Commit 43413a97 authored by Sara Sharon's avatar Sara Sharon Committed by Emmanuel Grumbach

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: default avatarSara Sharon <sara.sharon@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
parent 6ad6c01f
...@@ -7,6 +7,7 @@ ...@@ -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, ...@@ -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); ...@@ -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) ...@@ -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,
......
...@@ -7,7 +7,7 @@ ...@@ -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 @@ ...@@ -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 { ...@@ -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__ */
...@@ -213,6 +213,8 @@ enum { ...@@ -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,
......
...@@ -7,6 +7,7 @@ ...@@ -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) ...@@ -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) ...@@ -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);
......
...@@ -647,6 +647,7 @@ struct iwl_mvm { ...@@ -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;
......
...@@ -347,6 +347,7 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = { ...@@ -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, ...@@ -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:
......
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