iwlwifi: mvm: support rss queues configuration command

9000 series supports multi-queue rx. The hardware needs
to be configured with the hash functions to perform and
indirection table that maps hash results to the relevant
CPUs\queues.
Support this configuration.
Add debugfs hook to configure the indirection table in
order to enable performance analysis. The configuration
is stateless, receives a partial or full pattern and sends
the command to the firmware.

Signed-off-by: Sara Sharon <sara.sharon@intel.com>
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
This commit is contained in:
Sara Sharon 2015-12-31 11:49:18 +02:00 committed by Emmanuel Grumbach
parent 6ad6c01fa7
commit 43413a975d
6 changed files with 111 additions and 2 deletions

View File

@ -7,6 +7,7 @@
* *
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
@ -943,6 +944,47 @@ iwl_dbgfs_scan_ant_rxchain_write(struct iwl_mvm *mvm, char *buf,
return count; return count;
} }
static ssize_t iwl_dbgfs_indirection_tbl_write(struct iwl_mvm *mvm,
char *buf, size_t count,
loff_t *ppos)
{
struct iwl_rss_config_cmd cmd = {
.flags = cpu_to_le32(IWL_RSS_ENABLE),
.hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP |
IWL_RSS_HASH_TYPE_IPV4_PAYLOAD |
IWL_RSS_HASH_TYPE_IPV6_TCP |
IWL_RSS_HASH_TYPE_IPV6_PAYLOAD,
};
int ret, i, num_repeats, nbytes = count / 2;
ret = hex2bin(cmd.indirection_table, buf, nbytes);
if (ret)
return ret;
/*
* The input is the redirection table, partial or full.
* Repeat the pattern if needed.
* For example, input of 01020F will be repeated 42 times,
* indirecting RSS hash results to queues 1, 2, 15 (skipping
* queues 3 - 14).
*/
num_repeats = ARRAY_SIZE(cmd.indirection_table) / nbytes;
for (i = 1; i < num_repeats; i++)
memcpy(&cmd.indirection_table[i * nbytes],
cmd.indirection_table, nbytes);
/* handle cut in the middle pattern for the last places */
memcpy(&cmd.indirection_table[i * nbytes], cmd.indirection_table,
ARRAY_SIZE(cmd.indirection_table) % nbytes);
memcpy(cmd.secret_key, mvm->secret_key, ARRAY_SIZE(cmd.secret_key));
mutex_lock(&mvm->mutex);
ret = iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd);
mutex_unlock(&mvm->mutex);
return ret ?: count;
}
static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file, static ssize_t iwl_dbgfs_fw_dbg_conf_read(struct file *file,
char __user *user_buf, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
@ -1455,6 +1497,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(fw_dbg_conf, 8);
MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64); MVM_DEBUGFS_WRITE_FILE_OPS(fw_dbg_collect, 64);
MVM_DEBUGFS_WRITE_FILE_OPS(cont_recording, 8); MVM_DEBUGFS_WRITE_FILE_OPS(cont_recording, 8);
MVM_DEBUGFS_WRITE_FILE_OPS(indirection_tbl, 16);
#ifdef CONFIG_IWLWIFI_BCAST_FILTERING #ifdef CONFIG_IWLWIFI_BCAST_FILTERING
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
@ -1499,6 +1542,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR); MVM_DEBUGFS_ADD_FILE(fw_dbg_collect, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, S_IWUSR); MVM_DEBUGFS_ADD_FILE(send_echo_cmd, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(cont_recording, mvm->debugfs_dir, S_IWUSR); MVM_DEBUGFS_ADD_FILE(cont_recording, mvm->debugfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE(indirection_tbl, mvm->debugfs_dir, S_IWUSR);
if (!debugfs_create_bool("enable_scan_iteration_notif", if (!debugfs_create_bool("enable_scan_iteration_notif",
S_IRUSR | S_IWUSR, S_IRUSR | S_IWUSR,
mvm->debugfs_dir, mvm->debugfs_dir,

View File

@ -7,7 +7,7 @@
* *
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
@ -34,7 +34,7 @@
* *
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2015 Intel Deutschland GmbH * Copyright(c) 2015 - 2016 Intel Deutschland GmbH
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -362,4 +362,33 @@ struct iwl_frame_release {
__le16 nssn; __le16 nssn;
}; };
enum iwl_rss_hash_func_en {
IWL_RSS_HASH_TYPE_IPV4_TCP,
IWL_RSS_HASH_TYPE_IPV4_UDP,
IWL_RSS_HASH_TYPE_IPV4_PAYLOAD,
IWL_RSS_HASH_TYPE_IPV6_TCP,
IWL_RSS_HASH_TYPE_IPV6_UDP,
IWL_RSS_HASH_TYPE_IPV6_PAYLOAD,
};
#define IWL_RSS_HASH_KEY_CNT 10
#define IWL_RSS_INDIRECTION_TABLE_SIZE 128
#define IWL_RSS_ENABLE 1
/**
* struct iwl_rss_config_cmd - RSS (Receive Side Scaling) configuration
*
* @flags: 1 - enable, 0 - disable
* @hash_mask: Type of RSS to use. Values are from %iwl_rss_hash_func_en
* @secret_key: 320 bit input of random key configuration from driver
* @indirection_table: indirection table
*/
struct iwl_rss_config_cmd {
__le32 flags;
u8 hash_mask;
u8 reserved[3];
__le32 secret_key[IWL_RSS_HASH_KEY_CNT];
u8 indirection_table[IWL_RSS_INDIRECTION_TABLE_SIZE];
} __packed; /* RSS_CONFIG_CMD_API_S_VER_1 */
#endif /* __fw_api_rx_h__ */ #endif /* __fw_api_rx_h__ */

View File

@ -213,6 +213,8 @@ enum {
MFUART_LOAD_NOTIFICATION = 0xb1, MFUART_LOAD_NOTIFICATION = 0xb1,
RSS_CONFIG_CMD = 0xb3,
REPLY_RX_PHY_CMD = 0xc0, REPLY_RX_PHY_CMD = 0xc0,
REPLY_RX_MPDU_CMD = 0xc1, REPLY_RX_MPDU_CMD = 0xc1,
FRAME_RELEASE = 0xc3, FRAME_RELEASE = 0xc3,

View File

@ -7,6 +7,7 @@
* *
* Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
* Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
* Copyright(c) 2016 Intel Deutschland GmbH
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of version 2 of the GNU General Public License as
@ -107,6 +108,24 @@ static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant)
sizeof(tx_ant_cmd), &tx_ant_cmd); sizeof(tx_ant_cmd), &tx_ant_cmd);
} }
static int iwl_send_rss_cfg_cmd(struct iwl_mvm *mvm)
{
int i;
struct iwl_rss_config_cmd cmd = {
.flags = cpu_to_le32(IWL_RSS_ENABLE),
.hash_mask = IWL_RSS_HASH_TYPE_IPV4_TCP |
IWL_RSS_HASH_TYPE_IPV4_PAYLOAD |
IWL_RSS_HASH_TYPE_IPV6_TCP |
IWL_RSS_HASH_TYPE_IPV6_PAYLOAD,
};
for (i = 0; i < ARRAY_SIZE(cmd.indirection_table); i++)
cmd.indirection_table[i] = i % mvm->trans->num_rx_queues;
memcpy(cmd.secret_key, mvm->secret_key, ARRAY_SIZE(cmd.secret_key));
return iwl_mvm_send_cmd_pdu(mvm, RSS_CONFIG_CMD, 0, sizeof(cmd), &cmd);
}
static void iwl_free_fw_paging(struct iwl_mvm *mvm) static void iwl_free_fw_paging(struct iwl_mvm *mvm)
{ {
int i; int i;
@ -894,6 +913,16 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
if (ret) if (ret)
goto error; goto error;
/* Init RSS configuration */
if (iwl_mvm_has_new_rx_api(mvm)) {
ret = iwl_send_rss_cfg_cmd(mvm);
if (ret) {
IWL_ERR(mvm, "Failed to configure RSS queues: %d\n",
ret);
goto error;
}
}
/* init the fw <-> mac80211 STA mapping */ /* init the fw <-> mac80211 STA mapping */
for (i = 0; i < IWL_MVM_STATION_COUNT; i++) for (i = 0; i < IWL_MVM_STATION_COUNT; i++)
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL); RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);

View File

@ -647,6 +647,7 @@ struct iwl_mvm {
atomic_t pending_frames[IWL_MVM_STATION_COUNT]; atomic_t pending_frames[IWL_MVM_STATION_COUNT];
u32 tfd_drained[IWL_MVM_STATION_COUNT]; u32 tfd_drained[IWL_MVM_STATION_COUNT];
u8 rx_ba_sessions; u8 rx_ba_sessions;
u32 secret_key[IWL_RSS_HASH_KEY_CNT];
/* configured by mac80211 */ /* configured by mac80211 */
u32 rts_threshold; u32 rts_threshold;

View File

@ -347,6 +347,7 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = {
HCMD_NAME(MAC_PM_POWER_TABLE), HCMD_NAME(MAC_PM_POWER_TABLE),
HCMD_NAME(TDLS_CHANNEL_SWITCH_NOTIFICATION), HCMD_NAME(TDLS_CHANNEL_SWITCH_NOTIFICATION),
HCMD_NAME(MFUART_LOAD_NOTIFICATION), HCMD_NAME(MFUART_LOAD_NOTIFICATION),
HCMD_NAME(RSS_CONFIG_CMD),
HCMD_NAME(SCAN_ITERATION_COMPLETE_UMAC), HCMD_NAME(SCAN_ITERATION_COMPLETE_UMAC),
HCMD_NAME(REPLY_RX_PHY_CMD), HCMD_NAME(REPLY_RX_PHY_CMD),
HCMD_NAME(REPLY_RX_MPDU_CMD), HCMD_NAME(REPLY_RX_MPDU_CMD),
@ -651,6 +652,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
iwl_mvm_tof_init(mvm); iwl_mvm_tof_init(mvm);
/* init RSS hash key */
get_random_bytes(mvm->secret_key, ARRAY_SIZE(mvm->secret_key));
return op_mode; return op_mode;
out_unregister: out_unregister: