forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
RF Interference Mitigation is a new feature targeted to handle the problem of interference between DDR memory and WiFi. The role of the driver is to configure FW with the table holding a mapping between problematic channels/bands and the corresponding frequencies. This patch adds RFI infrastructure and adds two debugfs hooks: - send RFI configuration command (currently with a default table) which will reset feature in the FW - read the table, used by the FW (which can be a subset of the table that driver sent). Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Link: https://lore.kernel.org/r/iwlwifi.20210210171218.2cea55a09bc7.I634b79795abad499ce442631d6672ffef8fc6d41@changeid Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
- Loading branch information
1 parent
3ce8824
commit 2125490
Showing
8 changed files
with
261 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ | ||
/* | ||
* Copyright (C) 2020 Intel Corporation | ||
*/ | ||
#ifndef __iwl_fw_api_rfi_h__ | ||
#define __iwl_fw_api_rfi_h__ | ||
|
||
#define IWL_RFI_LUT_ENTRY_CHANNELS_NUM 15 | ||
#define IWL_RFI_LUT_SIZE 24 | ||
#define IWL_RFI_LUT_INSTALLED_SIZE 4 | ||
|
||
/** | ||
* struct iwl_rfi_lut_entry - an entry in the RFI frequency LUT. | ||
* | ||
* @freq: frequency | ||
* @channels: channels that can be interfered at frequency freq (at most 15) | ||
* @bands: the corresponding bands | ||
*/ | ||
struct iwl_rfi_lut_entry { | ||
__le16 freq; | ||
u8 channels[IWL_RFI_LUT_ENTRY_CHANNELS_NUM]; | ||
u8 bands[IWL_RFI_LUT_ENTRY_CHANNELS_NUM]; | ||
} __packed; | ||
|
||
/** | ||
* struct iwl_rfi_config_cmd - RFI configuration table | ||
* | ||
* @entry: a table can have 24 frequency/channel mappings | ||
* @oem: specifies if this is the default table or set by OEM | ||
*/ | ||
struct iwl_rfi_config_cmd { | ||
struct iwl_rfi_lut_entry table[IWL_RFI_LUT_SIZE]; | ||
u8 oem; | ||
u8 reserved[3]; | ||
} __packed; /* RFI_CONFIG_CMD_API_S_VER_1 */ | ||
|
||
/** | ||
* iwl_rfi_freq_table_status - status of the frequency table query | ||
* @RFI_FREQ_TABLE_OK: can be used | ||
* @RFI_FREQ_TABLE_DVFS_NOT_READY: DVFS is not ready yet, should try later | ||
* @RFI_FREQ_TABLE_DISABLED: the feature is disabled in FW | ||
*/ | ||
enum iwl_rfi_freq_table_status { | ||
RFI_FREQ_TABLE_OK, | ||
RFI_FREQ_TABLE_DVFS_NOT_READY, | ||
RFI_FREQ_TABLE_DISABLED, | ||
}; | ||
|
||
/** | ||
* struct iwl_rfi_freq_table_resp_cmd - get the rfi freq table used by FW | ||
* | ||
* @table: table used by FW | ||
* @status: see &iwl_rfi_freq_table_status | ||
*/ | ||
struct iwl_rfi_freq_table_resp_cmd { | ||
struct iwl_rfi_lut_entry table[IWL_RFI_LUT_INSTALLED_SIZE]; | ||
__le32 status; | ||
} __packed; /* RFI_CONFIG_CMD_API_S_VER_1 */ | ||
|
||
#endif /* __iwl_fw_api_rfi_h__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause | ||
/* | ||
* Copyright (C) 2020 Intel Corporation | ||
*/ | ||
|
||
#include "mvm.h" | ||
#include "fw/api/commands.h" | ||
#include "fw/api/phy-ctxt.h" | ||
|
||
/** | ||
* DDR needs frequency in units of 16.666MHz, so provide FW with the | ||
* frequency values in the adjusted format. | ||
*/ | ||
const static struct iwl_rfi_lut_entry iwl_rfi_table[IWL_RFI_LUT_SIZE] = { | ||
/* LPDDR4 */ | ||
|
||
/* frequency 3733MHz */ | ||
{cpu_to_le16(223), {114, 116, 118, 120, 122,}, | ||
{PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5,}}, | ||
|
||
/* frequency 4267MHz */ | ||
{cpu_to_le16(256), {79, 83, 85, 87, 89, 91, 93,}, | ||
{PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, | ||
PHY_BAND_6, PHY_BAND_6,}}, | ||
|
||
/* DDR5ePOR */ | ||
|
||
/* frequency 4000MHz */ | ||
{cpu_to_le16(240), {3, 5, 7, 9, 11, 13, 15,}, | ||
{PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, | ||
PHY_BAND_6, PHY_BAND_6,}}, | ||
|
||
/* frequency 4400MHz */ | ||
{cpu_to_le16(264), {111, 119, 123, 125, 129, 131, 133, 135, 143,}, | ||
{PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, | ||
PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6,}}, | ||
|
||
/* LPDDR5iPOR */ | ||
|
||
/* frequency 5200MHz */ | ||
{cpu_to_le16(312), {36, 38, 40, 42, 50,}, | ||
{PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5, PHY_BAND_5,}}, | ||
|
||
/* frequency 6000MHz */ | ||
{cpu_to_le16(360), {3, 5, 7, 9, 11, 13, 15,}, | ||
{PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, | ||
PHY_BAND_6, PHY_BAND_6,}}, | ||
|
||
/* frequency 6400MHz */ | ||
{cpu_to_le16(384), {79, 83, 85, 87, 89, 91, 93,}, | ||
{PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, PHY_BAND_6, | ||
PHY_BAND_6, PHY_BAND_6,}}, | ||
}; | ||
|
||
int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm, struct iwl_rfi_lut_entry *rfi_table) | ||
{ | ||
int ret; | ||
struct iwl_rfi_config_cmd cmd; | ||
struct iwl_host_cmd hcmd = { | ||
.id = WIDE_ID(SYSTEM_GROUP, RFI_CONFIG_CMD), | ||
.dataflags[0] = IWL_HCMD_DFL_DUP, | ||
.data[0] = &cmd, | ||
.len[0] = sizeof(cmd), | ||
}; | ||
|
||
if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_RFIM_SUPPORT)) | ||
return -EOPNOTSUPP; | ||
|
||
/* in case no table is passed, use the default one */ | ||
if (!rfi_table) { | ||
memcpy(cmd.table, iwl_rfi_table, sizeof(cmd.table)); | ||
} else { | ||
memcpy(cmd.table, rfi_table, sizeof(cmd.table)); | ||
/* notify FW the table is not the default one */ | ||
cmd.oem = 1; | ||
} | ||
|
||
mutex_lock(&mvm->mutex); | ||
ret = iwl_mvm_send_cmd(mvm, &hcmd); | ||
mutex_unlock(&mvm->mutex); | ||
|
||
if (ret) | ||
IWL_ERR(mvm, "Failed to send RFI config cmd %d\n", ret); | ||
|
||
return ret; | ||
} | ||
|
||
struct iwl_rfi_freq_table_resp_cmd *iwl_rfi_get_freq_table(struct iwl_mvm *mvm) | ||
{ | ||
struct iwl_rfi_freq_table_resp_cmd *resp; | ||
int resp_size = sizeof(*resp); | ||
int ret; | ||
struct iwl_host_cmd cmd = { | ||
.id = WIDE_ID(SYSTEM_GROUP, RFI_GET_FREQ_TABLE_CMD), | ||
.flags = CMD_WANT_SKB, | ||
}; | ||
|
||
if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_RFIM_SUPPORT)) | ||
return ERR_PTR(-EOPNOTSUPP); | ||
|
||
mutex_lock(&mvm->mutex); | ||
ret = iwl_mvm_send_cmd(mvm, &cmd); | ||
mutex_unlock(&mvm->mutex); | ||
if (ret) | ||
return ERR_PTR(ret); | ||
|
||
if (WARN_ON_ONCE(iwl_rx_packet_payload_len(cmd.resp_pkt) != resp_size)) | ||
return ERR_PTR(-EIO); | ||
|
||
resp = kzalloc(resp_size, GFP_KERNEL); | ||
if (!resp) | ||
return ERR_PTR(-ENOMEM); | ||
|
||
memcpy(resp, cmd.resp_pkt->data, resp_size); | ||
|
||
iwl_free_resp(&cmd); | ||
return resp; | ||
} |