Commit 47cb759f authored by John W. Linville's avatar John W. Linville

Merge tag 'iwlwifi-next-for-john-2014-10-29' of...

Merge tag 'iwlwifi-next-for-john-2014-10-29' of git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next

Emmanuel Grumbach <egrumbach@gmail.com> says:

"The big new thing here is netdetect which allows the
firmware to wake up the platform when a specific network
is detected. Along with that I have fixes for d3 operation.
The usual amount of rate scaling stuff - we now support STBC.
The other commit that stands out is Johannes's work on
devcoredump. He basically starts to use the standard
infrastructure he built."
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parents 5ca06ebe 4ff78181
...@@ -59,6 +59,7 @@ config IWLDVM ...@@ -59,6 +59,7 @@ config IWLDVM
config IWLMVM config IWLMVM
tristate "Intel Wireless WiFi MVM Firmware support" tristate "Intel Wireless WiFi MVM Firmware support"
select BACKPORT_WANT_DEV_COREDUMP
help help
This is the driver that supports the MVM firmware which is This is the driver that supports the MVM firmware which is
currently only available for 7260 and 3160 devices. currently only available for 7260 and 3160 devices.
......
...@@ -418,7 +418,7 @@ void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena) ...@@ -418,7 +418,7 @@ void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena)
static bool iwlagn_bt_traffic_is_sco(struct iwl_bt_uart_msg *uart_msg) static bool iwlagn_bt_traffic_is_sco(struct iwl_bt_uart_msg *uart_msg)
{ {
return BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3 >> return (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >>
BT_UART_MSG_FRAME3SCOESCO_POS; BT_UART_MSG_FRAME3SCOESCO_POS;
} }
......
...@@ -1095,6 +1095,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ...@@ -1095,6 +1095,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop) u32 queues, bool drop)
{ {
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
u32 scd_queues;
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "enter\n"); IWL_DEBUG_MAC80211(priv, "enter\n");
...@@ -1108,18 +1109,19 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, ...@@ -1108,18 +1109,19 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
goto done; goto done;
} }
/* scd_queues = BIT(priv->cfg->base_params->num_of_queues) - 1;
* mac80211 will not push any more frames for transmit scd_queues &= ~(BIT(IWL_IPAN_CMD_QUEUE_NUM) |
* until the flush is completed BIT(IWL_DEFAULT_CMD_QUEUE_NUM));
*/
if (drop) { if (vif)
IWL_DEBUG_MAC80211(priv, "send flush command\n"); scd_queues &= ~BIT(vif->hw_queue[IEEE80211_AC_VO]);
if (iwlagn_txfifo_flush(priv, 0)) {
IWL_DEBUG_TX_QUEUES(priv, "Flushing SCD queues: 0x%x\n", scd_queues);
if (iwlagn_txfifo_flush(priv, scd_queues)) {
IWL_ERR(priv, "flush request fail\n"); IWL_ERR(priv, "flush request fail\n");
goto done; goto done;
} }
} IWL_DEBUG_TX_QUEUES(priv, "wait transmit/flush all frames\n");
IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n");
iwl_trans_wait_tx_queue_empty(priv->trans, 0xffffffff); iwl_trans_wait_tx_queue_empty(priv->trans, 0xffffffff);
done: done:
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
......
...@@ -82,7 +82,8 @@ ...@@ -82,7 +82,8 @@
#define IWL8000_TX_POWER_VERSION 0xffff /* meaningless */ #define IWL8000_TX_POWER_VERSION 0xffff /* meaningless */
#define IWL8000_FW_PRE "iwlwifi-8000" #define IWL8000_FW_PRE "iwlwifi-8000"
#define IWL8000_MODULE_FIRMWARE(api) IWL8000_FW_PRE __stringify(api) ".ucode" #define IWL8000_MODULE_FIRMWARE(api) \
IWL8000_FW_PRE "-" __stringify(api) ".ucode"
#define NVM_HW_SECTION_NUM_FAMILY_8000 10 #define NVM_HW_SECTION_NUM_FAMILY_8000 10
#define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000.bin" #define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000.bin"
...@@ -103,6 +104,7 @@ static const struct iwl_base_params iwl8000_base_params = { ...@@ -103,6 +104,7 @@ static const struct iwl_base_params iwl8000_base_params = {
}; };
static const struct iwl_ht_params iwl8000_ht_params = { static const struct iwl_ht_params iwl8000_ht_params = {
.stbc = true,
.ldpc = true, .ldpc = true,
.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
}; };
......
...@@ -87,6 +87,16 @@ enum iwl_device_family { ...@@ -87,6 +87,16 @@ enum iwl_device_family {
IWL_DEVICE_FAMILY_8000, IWL_DEVICE_FAMILY_8000,
}; };
static inline bool iwl_has_secure_boot(u32 hw_rev,
enum iwl_device_family family)
{
/* return 1 only for family 8000 B0 */
if ((family == IWL_DEVICE_FAMILY_8000) && (hw_rev & 0xC))
return 1;
return 0;
}
/* /*
* LED mode * LED mode
* IWL_LED_DEFAULT: use device default * IWL_LED_DEFAULT: use device default
...@@ -246,6 +256,7 @@ struct iwl_pwr_tx_backoff { ...@@ -246,6 +256,7 @@ struct iwl_pwr_tx_backoff {
* @nvm_hw_section_num: the ID of the HW NVM section * @nvm_hw_section_num: the ID of the HW NVM section
* @pwr_tx_backoffs: translation table between power limits and backoffs * @pwr_tx_backoffs: translation table between power limits and backoffs
* @max_rx_agg_size: max RX aggregation size of the ADDBA request/response * @max_rx_agg_size: max RX aggregation size of the ADDBA request/response
* @max_tx_agg_size: max TX aggregation size of the ADDBA request/response
* *
* We enable the driver to be backward compatible wrt. hardware features. * We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs * API differences in uCode shouldn't be handled here but through TLVs
...@@ -285,6 +296,7 @@ struct iwl_cfg { ...@@ -285,6 +296,7 @@ struct iwl_cfg {
const char *default_nvm_file; const char *default_nvm_file;
unsigned int max_rx_agg_size; unsigned int max_rx_agg_size;
bool disable_dummy_notification; bool disable_dummy_notification;
unsigned int max_tx_agg_size;
}; };
/* /*
......
...@@ -807,19 +807,16 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, ...@@ -807,19 +807,16 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR, iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR,
tlv_len); tlv_len);
drv->fw.mvm_fw = true; drv->fw.mvm_fw = true;
drv->fw.img[IWL_UCODE_REGULAR].is_secure = true;
break; break;
case IWL_UCODE_TLV_SECURE_SEC_INIT: case IWL_UCODE_TLV_SECURE_SEC_INIT:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_INIT, iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_INIT,
tlv_len); tlv_len);
drv->fw.mvm_fw = true; drv->fw.mvm_fw = true;
drv->fw.img[IWL_UCODE_INIT].is_secure = true;
break; break;
case IWL_UCODE_TLV_SECURE_SEC_WOWLAN: case IWL_UCODE_TLV_SECURE_SEC_WOWLAN:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_WOWLAN, iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_WOWLAN,
tlv_len); tlv_len);
drv->fw.mvm_fw = true; drv->fw.mvm_fw = true;
drv->fw.img[IWL_UCODE_WOWLAN].is_secure = true;
break; break;
case IWL_UCODE_TLV_NUM_OF_CPU: case IWL_UCODE_TLV_NUM_OF_CPU:
if (tlv_len != sizeof(u32)) if (tlv_len != sizeof(u32))
......
...@@ -227,7 +227,6 @@ struct fw_desc { ...@@ -227,7 +227,6 @@ struct fw_desc {
struct fw_img { struct fw_img {
struct fw_desc sec[IWL_UCODE_SECTION_MAX]; struct fw_desc sec[IWL_UCODE_SECTION_MAX];
bool is_secure;
bool is_dual_cpus; bool is_dual_cpus;
}; };
......
...@@ -535,9 +535,7 @@ struct iwl_trans_ops { ...@@ -535,9 +535,7 @@ struct iwl_trans_ops {
void (*ref)(struct iwl_trans *trans); void (*ref)(struct iwl_trans *trans);
void (*unref)(struct iwl_trans *trans); void (*unref)(struct iwl_trans *trans);
#ifdef CONFIG_IWLWIFI_DEBUGFS
struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans); struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans);
#endif
}; };
/** /**
...@@ -563,6 +561,7 @@ enum iwl_trans_state { ...@@ -563,6 +561,7 @@ enum iwl_trans_state {
* Set during transport allocation. * Set during transport allocation.
* @hw_id_str: a string with info about HW ID. Set during transport allocation. * @hw_id_str: a string with info about HW ID. Set during transport allocation.
* @pm_support: set to true in start_hw if link pm is supported * @pm_support: set to true in start_hw if link pm is supported
* @ltr_enabled: set to true if the LTR is enabled
* @dev_cmd_pool: pool for Tx cmd allocation - for internal use only. * @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
* The user should use iwl_trans_{alloc,free}_tx_cmd. * The user should use iwl_trans_{alloc,free}_tx_cmd.
* @dev_cmd_headroom: room needed for the transport's private use before the * @dev_cmd_headroom: room needed for the transport's private use before the
...@@ -589,6 +588,7 @@ struct iwl_trans { ...@@ -589,6 +588,7 @@ struct iwl_trans {
u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size; u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size;
bool pm_support; bool pm_support;
bool ltr_enabled;
/* The following fields are internal only */ /* The following fields are internal only */
struct kmem_cache *dev_cmd_pool; struct kmem_cache *dev_cmd_pool;
...@@ -702,7 +702,6 @@ static inline void iwl_trans_unref(struct iwl_trans *trans) ...@@ -702,7 +702,6 @@ static inline void iwl_trans_unref(struct iwl_trans *trans)
trans->ops->unref(trans); trans->ops->unref(trans);
} }
#ifdef CONFIG_IWLWIFI_DEBUGFS
static inline struct iwl_trans_dump_data * static inline struct iwl_trans_dump_data *
iwl_trans_dump_data(struct iwl_trans *trans) iwl_trans_dump_data(struct iwl_trans *trans)
{ {
...@@ -710,7 +709,6 @@ iwl_trans_dump_data(struct iwl_trans *trans) ...@@ -710,7 +709,6 @@ iwl_trans_dump_data(struct iwl_trans *trans)
return NULL; return NULL;
return trans->ops->dump_data(trans); return trans->ops->dump_data(trans);
} }
#endif
static inline int iwl_trans_send_cmd(struct iwl_trans *trans, static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd) struct iwl_host_cmd *cmd)
......
...@@ -72,8 +72,6 @@ ...@@ -72,8 +72,6 @@
#include "mvm.h" #include "mvm.h"
#include "iwl-debug.h" #include "iwl-debug.h"
#define BT_ANTENNA_COUPLING_THRESHOLD (30)
const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = { const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = {
[BT_KILL_MSK_DEFAULT] = 0xfffffc00, [BT_KILL_MSK_DEFAULT] = 0xfffffc00,
[BT_KILL_MSK_NEVER] = 0xffffffff, [BT_KILL_MSK_NEVER] = 0xffffffff,
...@@ -302,11 +300,6 @@ static const __le64 iwl_ci_mask[][3] = { ...@@ -302,11 +300,6 @@ static const __le64 iwl_ci_mask[][3] = {
}, },
}; };
static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = {
cpu_to_le32(0x28412201),
cpu_to_le32(0x11118451),
};
struct corunning_block_luts { struct corunning_block_luts {
u8 range; u8 range;
__le32 lut20[BT_COEX_CORUN_LUT_SIZE]; __le32 lut20[BT_COEX_CORUN_LUT_SIZE];
...@@ -605,7 +598,7 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) ...@@ -605,7 +598,7 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
bt_cmd->max_kill = cpu_to_le32(5); bt_cmd->max_kill = cpu_to_le32(5);
bt_cmd->bt4_antenna_isolation_thr = bt_cmd->bt4_antenna_isolation_thr =
cpu_to_le32(BT_ANTENNA_COUPLING_THRESHOLD); cpu_to_le32(IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS);
bt_cmd->bt4_tx_tx_delta_freq_thr = cpu_to_le32(15); bt_cmd->bt4_tx_tx_delta_freq_thr = cpu_to_le32(15);
bt_cmd->bt4_tx_rx_max_freq0 = cpu_to_le32(15); bt_cmd->bt4_tx_rx_max_freq0 = cpu_to_le32(15);
bt_cmd->override_primary_lut = cpu_to_le32(BT_COEX_INVALID_LUT); bt_cmd->override_primary_lut = cpu_to_le32(BT_COEX_INVALID_LUT);
...@@ -638,8 +631,8 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) ...@@ -638,8 +631,8 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
memcpy(&bt_cmd->mplut_prio_boost, iwl_bt_prio_boost, memcpy(&bt_cmd->mplut_prio_boost, iwl_bt_prio_boost,
sizeof(iwl_bt_prio_boost)); sizeof(iwl_bt_prio_boost));
memcpy(&bt_cmd->multiprio_lut, iwl_bt_mprio_lut, bt_cmd->multiprio_lut[0] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG0);
sizeof(iwl_bt_mprio_lut)); bt_cmd->multiprio_lut[1] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG1);
send_cmd: send_cmd:
memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
......
...@@ -102,8 +102,6 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { ...@@ -102,8 +102,6 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
#undef EVENT_PRIO_ANT #undef EVENT_PRIO_ANT
#define BT_ANTENNA_COUPLING_THRESHOLD (30)
static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
{ {
if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
...@@ -290,11 +288,6 @@ static const __le64 iwl_ci_mask[][3] = { ...@@ -290,11 +288,6 @@ static const __le64 iwl_ci_mask[][3] = {
}, },
}; };
static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = {
cpu_to_le32(0x28412201),
cpu_to_le32(0x11118451),
};
struct corunning_block_luts { struct corunning_block_luts {
u8 range; u8 range;
__le32 lut20[BT_COEX_CORUN_LUT_SIZE]; __le32 lut20[BT_COEX_CORUN_LUT_SIZE];
...@@ -593,7 +586,8 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm) ...@@ -593,7 +586,8 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm)
} }
bt_cmd->max_kill = 5; bt_cmd->max_kill = 5;
bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD; bt_cmd->bt4_antenna_isolation_thr =
IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS;
bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling; bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling;
bt_cmd->bt4_tx_tx_delta_freq_thr = 15; bt_cmd->bt4_tx_tx_delta_freq_thr = 15;
bt_cmd->bt4_tx_rx_max_freq0 = 15; bt_cmd->bt4_tx_rx_max_freq0 = 15;
...@@ -649,8 +643,8 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm) ...@@ -649,8 +643,8 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm)
memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost, memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost,
sizeof(iwl_bt_prio_boost)); sizeof(iwl_bt_prio_boost));
memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut, bt_cmd->bt4_multiprio_lut[0] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG0);
sizeof(iwl_bt_mprio_lut)); bt_cmd->bt4_multiprio_lut[1] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG1);
send_cmd: send_cmd:
memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old)); memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
......
...@@ -92,8 +92,13 @@ ...@@ -92,8 +92,13 @@
#define IWL_MVM_BT_COEX_SYNC2SCO 1 #define IWL_MVM_BT_COEX_SYNC2SCO 1
#define IWL_MVM_BT_COEX_CORUNNING 0 #define IWL_MVM_BT_COEX_CORUNNING 0
#define IWL_MVM_BT_COEX_MPLUT 1 #define IWL_MVM_BT_COEX_MPLUT 1
#define IWL_MVM_BT_COEX_MPLUT_REG0 0x2e402280
#define IWL_MVM_BT_COEX_MPLUT_REG1 0x7711a751
#define IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS 30
#define IWL_MVM_FW_MCAST_FILTER_PASS_ALL 0 #define IWL_MVM_FW_MCAST_FILTER_PASS_ALL 0
#define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0
#define IWL_MVM_QUOTA_THRESHOLD 8 #define IWL_MVM_QUOTA_THRESHOLD 8
#define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 #define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0
#define IWL_MVM_RS_DISABLE_MIMO 0
#endif /* __MVM_CONSTANTS_H */ #endif /* __MVM_CONSTANTS_H */
This diff is collapsed.
...@@ -121,78 +121,6 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf, ...@@ -121,78 +121,6 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf,
return ret; return ret;
} }
static int iwl_dbgfs_fw_error_dump_open(struct inode *inode, struct file *file)
{
struct iwl_mvm *mvm = inode->i_private;
int ret;
if (!mvm)
return -EINVAL;
mutex_lock(&mvm->mutex);
if (!mvm->fw_error_dump) {
ret = -ENODATA;
goto out;
}
file->private_data = mvm->fw_error_dump;
mvm->fw_error_dump = NULL;
ret = 0;
out:
mutex_unlock(&mvm->mutex);
return ret;
}
static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
ssize_t bytes_read = 0;
ssize_t bytes_read_trans = 0;
if (*ppos < dump_ptrs->op_mode_len)
bytes_read +=
simple_read_from_buffer(user_buf, count, ppos,
dump_ptrs->op_mode_ptr,
dump_ptrs->op_mode_len);
if (bytes_read < 0 || *ppos < dump_ptrs->op_mode_len)
return bytes_read;
if (dump_ptrs->trans_ptr) {
*ppos -= dump_ptrs->op_mode_len;
bytes_read_trans =
simple_read_from_buffer(user_buf + bytes_read,
count - bytes_read, ppos,
dump_ptrs->trans_ptr->data,
dump_ptrs->trans_ptr->len);
*ppos += dump_ptrs->op_mode_len;
if (bytes_read_trans >= 0)
bytes_read += bytes_read_trans;
else if (!bytes_read)
/* propagate the failure */
return bytes_read_trans;
}
return bytes_read;
}
static int iwl_dbgfs_fw_error_dump_release(struct inode *inode,
struct file *file)
{
struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
vfree(dump_ptrs->op_mode_ptr);
vfree(dump_ptrs->trans_ptr);
kfree(dump_ptrs);
return 0;
}
static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
...@@ -1250,6 +1178,126 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf, ...@@ -1250,6 +1178,126 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
return ret; return ret;
} }
#define MAX_NUM_ND_MATCHSETS 10
static ssize_t iwl_dbgfs_netdetect_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos)
{
const char *seps = ",\n";
char *buf_ptr = buf;
char *value_str = NULL;
int ret, i;
/* TODO: don't free if write is being called several times in one go */
if (mvm->nd_config) {
kfree(mvm->nd_config->match_sets);
kfree(mvm->nd_config);
mvm->nd_config = NULL;
kfree(mvm->nd_ies);
mvm->nd_ies = NULL;
}
mvm->nd_ies = kzalloc(sizeof(*mvm->nd_ies), GFP_KERNEL);
if (!mvm->nd_ies)
return -ENOMEM;
mvm->nd_config = kzalloc(sizeof(*mvm->nd_config) +
(11 * sizeof(struct ieee80211_channel *)),
GFP_KERNEL);
if (!mvm->nd_config) {
ret = -ENOMEM;
goto out_free;
}
mvm->nd_config->n_channels = 11;
mvm->nd_config->scan_width = NL80211_BSS_CHAN_WIDTH_20;
mvm->nd_config->interval = 5;
mvm->nd_config->min_rssi_thold = -80;
for (i = 0; i < mvm->nd_config->n_channels; i++)
mvm->nd_config->channels[i] = &mvm->nvm_data->channels[i];
mvm->nd_config->match_sets =
kcalloc(MAX_NUM_ND_MATCHSETS,
sizeof(*mvm->nd_config->match_sets),
GFP_KERNEL);
if (!mvm->nd_config->match_sets) {
ret = -ENOMEM;
goto out_free;
}
while ((value_str = strsep(&buf_ptr, seps)) &&
strlen(value_str)) {
struct cfg80211_match_set *set;
if (mvm->nd_config->n_match_sets >= MAX_NUM_ND_MATCHSETS) {
ret = -EINVAL;
goto out_free;
}
set = &mvm->nd_config->match_sets[mvm->nd_config->n_match_sets];
set->ssid.ssid_len = strlen(value_str);
if (set->ssid.ssid_len > IEEE80211_MAX_SSID_LEN) {
ret = -EINVAL;
goto out_free;
}
memcpy(set->ssid.ssid, value_str, set->ssid.ssid_len);
mvm->nd_config->n_match_sets++;
}
ret = count;
if (mvm->nd_config->n_match_sets)
goto out;
out_free:
if (mvm->nd_config)
kfree(mvm->nd_config->match_sets);
kfree(mvm->nd_config);
mvm->nd_config = NULL;
kfree(mvm->nd_ies);
mvm->nd_ies = NULL;
out:
return ret;
}
static ssize_t
iwl_dbgfs_netdetect_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
size_t bufsz, ret;
char *buf;
int i, n_match_sets, pos = 0;
n_match_sets = mvm->nd_config ? mvm->nd_config->n_match_sets : 0;
bufsz = n_match_sets * (IEEE80211_MAX_SSID_LEN + 1) + 1;
buf = kzalloc(bufsz, GFP_KERNEL);
if (!buf)
return -ENOMEM;
for (i = 0; i < n_match_sets; i++) {
if (pos +
mvm->nd_config->match_sets[i].ssid.ssid_len + 2 > bufsz) {
ret = -EIO;
goto out;
}
memcpy(buf + pos, mvm->nd_config->match_sets[i].ssid.ssid,
mvm->nd_config->match_sets[i].ssid.ssid_len);
pos += mvm->nd_config->match_sets[i].ssid.ssid_len;
buf[pos++] = '\n';
}
ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
out:
kfree(buf);
return ret;
}
#endif #endif
#define PRINT_MVM_REF(ref) do { \ #define PRINT_MVM_REF(ref) do { \
...@@ -1415,12 +1463,6 @@ MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10); ...@@ -1415,12 +1463,6 @@ MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
static const struct file_operations iwl_dbgfs_fw_error_dump_ops = {
.open = iwl_dbgfs_fw_error_dump_open,
.read = iwl_dbgfs_fw_error_dump_read,
.release = iwl_dbgfs_fw_error_dump_release,
};
#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);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256); MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
...@@ -1428,6 +1470,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256); ...@@ -1428,6 +1470,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8); MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(netdetect, 384);
#endif #endif
int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
...@@ -1446,7 +1489,6 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) ...@@ -1446,7 +1489,6 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
S_IWUSR | S_IRUSR); S_IWUSR | S_IRUSR);
MVM_DEBUGFS_ADD_FILE(nic_temp, dbgfs_dir, S_IRUSR); MVM_DEBUGFS_ADD_FILE(nic_temp, dbgfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR); MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(fw_error_dump, dbgfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR); MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir,
...@@ -1487,6 +1529,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) ...@@ -1487,6 +1529,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR | S_IWUSR, if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR | S_IWUSR,
mvm->debugfs_dir, &mvm->d3_wake_sysassert)) mvm->debugfs_dir, &mvm->d3_wake_sysassert))
goto err; goto err;
MVM_DEBUGFS_ADD_FILE(netdetect, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
#endif #endif
if (!debugfs_create_u8("low_latency_agg_frame_limit", S_IRUSR | S_IWUSR, if (!debugfs_create_u8("low_latency_agg_frame_limit", S_IRUSR | S_IWUSR,
......
...@@ -68,13 +68,46 @@ ...@@ -68,13 +68,46 @@
/* Power Management Commands, Responses, Notifications */ /* Power Management Commands, Responses, Notifications */
/**
* enum iwl_ltr_config_flags - masks for LTR config command flags
* @LTR_CFG_FLAG_FEATURE_ENABLE: Feature operational status
* @LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS: allow LTR change on shadow
* memory access
* @LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH: allow LTR msg send on ANY LTR
* reg change
* @LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3: allow LTR msg send on transition from
* D0 to D3
* @LTR_CFG_FLAG_SW_SET_SHORT: fixed static short LTR register
* @LTR_CFG_FLAG_SW_SET_LONG: fixed static short LONG register
* @LTR_CFG_FLAG_DENIE_C10_ON_PD: allow going into C10 on PD
*/
enum iwl_ltr_config_flags {
LTR_CFG_FLAG_FEATURE_ENABLE = BIT(0),
LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS = BIT(1),
LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH = BIT(2),
LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3 = BIT(3),
LTR_CFG_FLAG_SW_SET_SHORT = BIT(4),
LTR_CFG_FLAG_SW_SET_LONG = BIT(5),
LTR_CFG_FLAG_DENIE_C10_ON_PD = BIT(6),
};
/**
* struct iwl_ltr_config_cmd - configures the LTR
* @flags: See %enum iwl_ltr_config_flags
*/
struct iwl_ltr_config_cmd {
__le32 flags;
__le32 static_long;
__le32 static_short;
} __packed;
/* Radio LP RX Energy Threshold measured in dBm */ /* Radio LP RX Energy Threshold measured in dBm */
#define POWER_LPRX_RSSI_THRESHOLD 75 #define POWER_LPRX_RSSI_THRESHOLD 75
#define POWER_LPRX_RSSI_THRESHOLD_MAX 94 #define POWER_LPRX_RSSI_THRESHOLD_MAX 94
#define POWER_LPRX_RSSI_THRESHOLD_MIN 30 #define POWER_LPRX_RSSI_THRESHOLD_MIN 30
/** /**
* enum iwl_scan_flags - masks for power table command flags * enum iwl_power_flags - masks for power table command flags
* @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off * @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off
* receiver and transmitter. '0' - does not allow. * receiver and transmitter. '0' - does not allow.
* @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management, * @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management,
......
...@@ -157,6 +157,7 @@ enum { ...@@ -157,6 +157,7 @@ enum {
/* Power - legacy power table command */ /* Power - legacy power table command */
POWER_TABLE_CMD = 0x77, POWER_TABLE_CMD = 0x77,
PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78, PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78,
LTR_CONFIG = 0xee,
/* Thermal Throttling*/ /* Thermal Throttling*/
REPLY_THERMAL_MNG_BACKOFF = 0x7e, REPLY_THERMAL_MNG_BACKOFF = 0x7e,
......
...@@ -480,6 +480,15 @@ int iwl_mvm_up(struct iwl_mvm *mvm) ...@@ -480,6 +480,15 @@ int iwl_mvm_up(struct iwl_mvm *mvm)
/* Initialize tx backoffs to the minimal possible */ /* Initialize tx backoffs to the minimal possible */
iwl_mvm_tt_tx_backoff(mvm, 0); iwl_mvm_tt_tx_backoff(mvm, 0);
if (mvm->trans->ltr_enabled) {
struct iwl_ltr_config_cmd cmd = {
.flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE),
};
WARN_ON(iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0,
sizeof(cmd), &cmd));
}
ret = iwl_mvm_power_update_device(mvm); ret = iwl_mvm_power_update_device(mvm);
if (ret) if (ret)
goto error; goto error;
......
...@@ -197,8 +197,7 @@ static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac, ...@@ -197,8 +197,7 @@ static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac,
/* /*
* Get the mask of the queues used by the vif * Get the mask of the queues used by the vif
*/ */
u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm, u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif)
struct ieee80211_vif *vif)
{ {
u32 qmask = 0, ac; u32 qmask = 0, ac;
...@@ -227,7 +226,7 @@ static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac, ...@@ -227,7 +226,7 @@ static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
} }
/* Mark the queues used by the vif */ /* Mark the queues used by the vif */
data->used_hw_queues |= iwl_mvm_mac_get_queues_mask(data->mvm, vif); data->used_hw_queues |= iwl_mvm_mac_get_queues_mask(vif);
/* Mark MAC IDs as used by clearing the available bit, and /* Mark MAC IDs as used by clearing the available bit, and
* (below) mark TSFs as used if their existing use is not * (below) mark TSFs as used if their existing use is not
......
...@@ -69,6 +69,7 @@ ...@@ -69,6 +69,7 @@
#include <linux/etherdevice.h> #include <linux/etherdevice.h>
#include <linux/ip.h> #include <linux/ip.h>
#include <linux/if_arp.h> #include <linux/if_arp.h>
#include <linux/devcoredump.h>
#include <net/mac80211.h> #include <net/mac80211.h>
#include <net/ieee80211_radiotap.h> #include <net/ieee80211_radiotap.h>
#include <net/tcp.h> #include <net/tcp.h>
...@@ -526,7 +527,8 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw, ...@@ -526,7 +527,8 @@ static void iwl_mvm_mac_tx(struct ieee80211_hw *hw,
} }
if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE && if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
!test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status)) !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status) &&
!test_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status))
goto drop; goto drop;
/* treat non-bufferable MMPDUs as broadcast if sta is sleeping */ /* treat non-bufferable MMPDUs as broadcast if sta is sleeping */
...@@ -678,10 +680,51 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac, ...@@ -678,10 +680,51 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data)); memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
} }
#ifdef CONFIG_IWLWIFI_DEBUGFS static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count,
const void *data, size_t datalen)
{
const struct iwl_mvm_dump_ptrs *dump_ptrs = data;
ssize_t bytes_read;
ssize_t bytes_read_trans;
if (offset < dump_ptrs->op_mode_len) {
bytes_read = min_t(ssize_t, count,
dump_ptrs->op_mode_len - offset);
memcpy(buffer, (u8 *)dump_ptrs->op_mode_ptr + offset,
bytes_read);
offset += bytes_read;
count -= bytes_read;
if (count == 0)
return bytes_read;
} else {
bytes_read = 0;
}
if (!dump_ptrs->trans_ptr)
return bytes_read;
offset -= dump_ptrs->op_mode_len;
bytes_read_trans = min_t(ssize_t, count,
dump_ptrs->trans_ptr->len - offset);
memcpy(buffer + bytes_read,
(u8 *)dump_ptrs->trans_ptr->data + offset,
bytes_read_trans);
return bytes_read + bytes_read_trans;
}
static void iwl_mvm_free_coredump(const void *data)
{
const struct iwl_mvm_dump_ptrs *fw_error_dump = data;
vfree(fw_error_dump->op_mode_ptr);
vfree(fw_error_dump->trans_ptr);
kfree(fw_error_dump);
}
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
{ {
static char *env[] = { "DRIVER=iwlwifi", "EVENT=error_dump", NULL };
struct iwl_fw_error_dump_file *dump_file; struct iwl_fw_error_dump_file *dump_file;
struct iwl_fw_error_dump_data *dump_data; struct iwl_fw_error_dump_data *dump_data;
struct iwl_fw_error_dump_info *dump_info; struct iwl_fw_error_dump_info *dump_info;
...@@ -694,10 +737,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) ...@@ -694,10 +737,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
if (mvm->fw_error_dump) fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL);
return;
fw_error_dump = kzalloc(sizeof(*mvm->fw_error_dump), GFP_KERNEL);
if (!fw_error_dump) if (!fw_error_dump)
return; return;
...@@ -772,12 +812,10 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) ...@@ -772,12 +812,10 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
if (fw_error_dump->trans_ptr) if (fw_error_dump->trans_ptr)
file_len += fw_error_dump->trans_ptr->len; file_len += fw_error_dump->trans_ptr->len;
dump_file->file_len = cpu_to_le32(file_len); dump_file->file_len = cpu_to_le32(file_len);
mvm->fw_error_dump = fw_error_dump;
/* notify the userspace about the error we had */ dev_coredumpm(mvm->trans->dev, THIS_MODULE, fw_error_dump, 0,
kobject_uevent_env(&mvm->hw->wiphy->dev.kobj, KOBJ_CHANGE, env); GFP_KERNEL, iwl_mvm_read_coredump, iwl_mvm_free_coredump);
} }
#endif
static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
{ {
...@@ -1085,7 +1123,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, ...@@ -1085,7 +1123,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
struct ieee80211_vif *vif) struct ieee80211_vif *vif)
{ {
u32 tfd_msk = iwl_mvm_mac_get_queues_mask(mvm, vif); u32 tfd_msk = iwl_mvm_mac_get_queues_mask(vif);
if (tfd_msk) { if (tfd_msk) {
mutex_lock(&mvm->mutex); mutex_lock(&mvm->mutex);
...@@ -1381,6 +1419,9 @@ bool iwl_mvm_bcast_filter_build_cmd(struct iwl_mvm *mvm, ...@@ -1381,6 +1419,9 @@ bool iwl_mvm_bcast_filter_build_cmd(struct iwl_mvm *mvm,
.cmd = cmd, .cmd = cmd,
}; };
if (IWL_MVM_FW_BCAST_FILTER_PASS_ALL)
return false;
memset(cmd, 0, sizeof(*cmd)); memset(cmd, 0, sizeof(*cmd));
cmd->max_bcast_filters = ARRAY_SIZE(cmd->filters); cmd->max_bcast_filters = ARRAY_SIZE(cmd->filters);
cmd->max_macs = ARRAY_SIZE(cmd->macs); cmd->max_macs = ARRAY_SIZE(cmd->macs);
...@@ -1734,6 +1775,13 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm, ...@@ -1734,6 +1775,13 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
if (changes & BSS_CHANGED_BEACON && if (changes & BSS_CHANGED_BEACON &&
iwl_mvm_mac_ctxt_beacon_changed(mvm, vif)) iwl_mvm_mac_ctxt_beacon_changed(mvm, vif))
IWL_WARN(mvm, "Failed updating beacon data\n"); IWL_WARN(mvm, "Failed updating beacon data\n");
if (changes & BSS_CHANGED_TXPOWER) {
IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n",
bss_conf->txpower);
iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower);
}
} }
static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw, static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
...@@ -2162,24 +2210,8 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, ...@@ -2162,24 +2210,8 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
mvm->scan_status = IWL_MVM_SCAN_SCHED; mvm->scan_status = IWL_MVM_SCAN_SCHED;
if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) { ret = iwl_mvm_scan_offload_start(mvm, vif, req, ies);
ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies);
if (ret) if (ret)
goto err;
}
ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
if (ret)
goto err;
if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
ret = iwl_mvm_unified_sched_scan_lmac(mvm, vif, req, ies);
else
ret = iwl_mvm_sched_scan_start(mvm, req);
if (!ret)
goto out;
err:
mvm->scan_status = IWL_MVM_SCAN_NONE; mvm->scan_status = IWL_MVM_SCAN_NONE;
out: out:
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
...@@ -2367,14 +2399,19 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm, ...@@ -2367,14 +2399,19 @@ static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
/* Set the node address */ /* Set the node address */
memcpy(aux_roc_req.node_addr, vif->addr, ETH_ALEN); memcpy(aux_roc_req.node_addr, vif->addr, ETH_ALEN);
lockdep_assert_held(&mvm->mutex);
spin_lock_bh(&mvm->time_event_lock);
if (WARN_ON(te_data->id == HOT_SPOT_CMD)) {
spin_unlock_bh(&mvm->time_event_lock);
return -EIO;
}
te_data->vif = vif; te_data->vif = vif;
te_data->duration = duration; te_data->duration = duration;
te_data->id = HOT_SPOT_CMD; te_data->id = HOT_SPOT_CMD;
lockdep_assert_held(&mvm->mutex);
spin_lock_bh(&mvm->time_event_lock);
list_add_tail(&te_data->list, &mvm->time_event_list);
spin_unlock_bh(&mvm->time_event_lock); spin_unlock_bh(&mvm->time_event_lock);
/* /*
...@@ -2430,22 +2467,23 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, ...@@ -2430,22 +2467,23 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
duration, type); duration, type);
mutex_lock(&mvm->mutex);
switch (vif->type) { switch (vif->type) {
case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_STATION:
/* Use aux roc framework (HS20) */ /* Use aux roc framework (HS20) */
ret = iwl_mvm_send_aux_roc_cmd(mvm, channel, ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
vif, duration); vif, duration);
return ret; goto out_unlock;
case NL80211_IFTYPE_P2P_DEVICE: case NL80211_IFTYPE_P2P_DEVICE:
/* handle below */ /* handle below */
break; break;
default: default:
IWL_ERR(mvm, "vif isn't P2P_DEVICE: %d\n", vif->type); IWL_ERR(mvm, "vif isn't P2P_DEVICE: %d\n", vif->type);
return -EINVAL; ret = -EINVAL;
goto out_unlock;
} }
mutex_lock(&mvm->mutex);
for (i = 0; i < NUM_PHY_CTX; i++) { for (i = 0; i < NUM_PHY_CTX; i++) {
phy_ctxt = &mvm->phy_ctxts[i]; phy_ctxt = &mvm->phy_ctxts[i];
if (phy_ctxt->ref == 0 || mvmvif->phy_ctxt == phy_ctxt) if (phy_ctxt->ref == 0 || mvmvif->phy_ctxt == phy_ctxt)
...@@ -2996,18 +3034,24 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, ...@@ -2996,18 +3034,24 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
mvmvif = iwl_mvm_vif_from_mac80211(vif); mvmvif = iwl_mvm_vif_from_mac80211(vif);
mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id); mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id);
if (WARN_ON_ONCE(!mvmsta)) if (WARN_ON_ONCE(!mvmsta)) {
goto done; mutex_unlock(&mvm->mutex);
return;
}
if (drop) { if (drop) {
if (iwl_mvm_flush_tx_path(mvm, mvmsta->tfd_queue_msk, true)) if (iwl_mvm_flush_tx_path(mvm, mvmsta->tfd_queue_msk, true))
IWL_ERR(mvm, "flush request fail\n"); IWL_ERR(mvm, "flush request fail\n");
mutex_unlock(&mvm->mutex);
} else { } else {
iwl_trans_wait_tx_queue_empty(mvm->trans, u32 tfd_queue_msk = mvmsta->tfd_queue_msk;
mvmsta->tfd_queue_msk);
}
done:
mutex_unlock(&mvm->mutex); mutex_unlock(&mvm->mutex);
/* this can take a while, and we may need/want other operations
* to succeed while doing this, so do it without the mutex held
*/
iwl_trans_wait_tx_queue_empty(mvm->trans, tfd_queue_msk);
}
} }
const struct ieee80211_ops iwl_mvm_hw_ops = { const struct ieee80211_ops iwl_mvm_hw_ops = {
......
...@@ -648,7 +648,6 @@ struct iwl_mvm { ...@@ -648,7 +648,6 @@ struct iwl_mvm {
/* -1 for always, 0 for never, >0 for that many times */ /* -1 for always, 0 for never, >0 for that many times */
s8 restart_fw; s8 restart_fw;
struct work_struct fw_error_dump_wk; struct work_struct fw_error_dump_wk;
struct iwl_mvm_dump_ptrs *fw_error_dump;
#ifdef CONFIG_IWLWIFI_LEDS #ifdef CONFIG_IWLWIFI_LEDS
struct led_classdev led; struct led_classdev led;
...@@ -659,6 +658,10 @@ struct iwl_mvm { ...@@ -659,6 +658,10 @@ struct iwl_mvm {
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
struct wiphy_wowlan_support wowlan; struct wiphy_wowlan_support wowlan;
int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen;
/* sched scan settings for net detect */
struct cfg80211_sched_scan_request *nd_config;
struct ieee80211_scan_ies *nd_ies;
#ifdef CONFIG_IWLWIFI_DEBUGFS #ifdef CONFIG_IWLWIFI_DEBUGFS
u32 d3_wake_sysassert; /* must be u32 for debugfs_create_bool */ u32 d3_wake_sysassert; /* must be u32 for debugfs_create_bool */
bool d3_test_active; bool d3_test_active;
...@@ -905,8 +908,7 @@ int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif); ...@@ -905,8 +908,7 @@ int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool force_assoc_off, const u8 *bssid_override); bool force_assoc_off, const u8 *bssid_override);
int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm, u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif);
struct ieee80211_vif *vif);
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
struct ieee80211_vif *vif); struct ieee80211_vif *vif);
int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
...@@ -949,6 +951,10 @@ int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, ...@@ -949,6 +951,10 @@ int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req); struct cfg80211_sched_scan_request *req);
int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req); struct cfg80211_sched_scan_request *req);
int iwl_mvm_scan_offload_start(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
struct ieee80211_scan_ies *ies);
int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify); int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify);
int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm, int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb, struct iwl_rx_cmd_buffer *rxb,
...@@ -1206,11 +1212,9 @@ void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -1206,11 +1212,9 @@ void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw, void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
struct ieee80211_vif *vif); struct ieee80211_vif *vif);
struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm);
void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error); void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error);
#ifdef CONFIG_IWLWIFI_DEBUGFS
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm); void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm);
#else
static inline void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) {}
#endif
#endif /* __IWL_MVM_H__ */ #endif /* __IWL_MVM_H__ */
...@@ -336,6 +336,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = { ...@@ -336,6 +336,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD(DTS_MEASUREMENT_NOTIFICATION), CMD(DTS_MEASUREMENT_NOTIFICATION),
CMD(REPLY_THERMAL_MNG_BACKOFF), CMD(REPLY_THERMAL_MNG_BACKOFF),
CMD(MAC_PM_POWER_TABLE), CMD(MAC_PM_POWER_TABLE),
CMD(LTR_CONFIG),
CMD(BT_COEX_CI), CMD(BT_COEX_CI),
CMD(BT_COEX_UPDATE_SW_BOOST), CMD(BT_COEX_UPDATE_SW_BOOST),
CMD(BT_COEX_UPDATE_CORUN_LUT), CMD(BT_COEX_UPDATE_CORUN_LUT),
...@@ -402,6 +403,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, ...@@ -402,6 +403,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
if (cfg->max_rx_agg_size) if (cfg->max_rx_agg_size)
hw->max_rx_aggregation_subframes = cfg->max_rx_agg_size; hw->max_rx_aggregation_subframes = cfg->max_rx_agg_size;
if (cfg->max_tx_agg_size)
hw->max_tx_aggregation_subframes = cfg->max_tx_agg_size;
op_mode = hw->priv; op_mode = hw->priv;
op_mode->ops = &iwl_mvm_ops; op_mode->ops = &iwl_mvm_ops;
...@@ -583,16 +587,18 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) ...@@ -583,16 +587,18 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
ieee80211_unregister_hw(mvm->hw); ieee80211_unregister_hw(mvm->hw);
kfree(mvm->scan_cmd); kfree(mvm->scan_cmd);
if (mvm->fw_error_dump) {
vfree(mvm->fw_error_dump->op_mode_ptr);
vfree(mvm->fw_error_dump->trans_ptr);
kfree(mvm->fw_error_dump);
}
kfree(mvm->mcast_filter_cmd); kfree(mvm->mcast_filter_cmd);
mvm->mcast_filter_cmd = NULL; mvm->mcast_filter_cmd = NULL;
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS) #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS)
kfree(mvm->d3_resume_sram); kfree(mvm->d3_resume_sram);
if (mvm->nd_config) {
kfree(mvm->nd_config->match_sets);
kfree(mvm->nd_config);
mvm->nd_config = NULL;
kfree(mvm->nd_ies);
mvm->nd_ies = NULL;
}
#endif #endif
iwl_trans_op_mode_leave(mvm->trans); iwl_trans_op_mode_leave(mvm->trans);
......
...@@ -505,10 +505,11 @@ static const char *rs_pretty_lq_type(enum iwl_table_type type) ...@@ -505,10 +505,11 @@ static const char *rs_pretty_lq_type(enum iwl_table_type type)
static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate, static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate,
const char *prefix) const char *prefix)
{ {
IWL_DEBUG_RATE(mvm, "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d\n", IWL_DEBUG_RATE(mvm,
"%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d STBC %d\n",
prefix, rs_pretty_lq_type(rate->type), prefix, rs_pretty_lq_type(rate->type),
rate->index, rs_pretty_ant(rate->ant), rate->index, rs_pretty_ant(rate->ant),
rate->bw, rate->sgi, rate->ldpc); rate->bw, rate->sgi, rate->ldpc, rate->stbc);
} }
static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
...@@ -741,6 +742,12 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm, ...@@ -741,6 +742,12 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm,
IWL_ERR(mvm, "Invalid rate->type %d\n", rate->type); IWL_ERR(mvm, "Invalid rate->type %d\n", rate->type);
} }
if (is_siso(rate) && rate->stbc) {
/* To enable STBC we need to set both a flag and ANT_AB */
ucode_rate |= RATE_MCS_ANT_AB_MSK;
ucode_rate |= RATE_MCS_VHT_STBC_MSK;
}
ucode_rate |= rate->bw; ucode_rate |= rate->bw;
if (rate->sgi) if (rate->sgi)
ucode_rate |= RATE_MCS_SGI_MSK; ucode_rate |= RATE_MCS_SGI_MSK;
...@@ -785,6 +792,8 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, ...@@ -785,6 +792,8 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
rate->sgi = true; rate->sgi = true;
if (ucode_rate & RATE_MCS_LDPC_MSK) if (ucode_rate & RATE_MCS_LDPC_MSK)
rate->ldpc = true; rate->ldpc = true;
if (ucode_rate & RATE_MCS_VHT_STBC_MSK)
rate->stbc = true;
rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK; rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK;
...@@ -794,7 +803,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, ...@@ -794,7 +803,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate,
if (nss == 1) { if (nss == 1) {
rate->type = LQ_HT_SISO; rate->type = LQ_HT_SISO;
WARN_ON_ONCE(num_of_ant != 1); WARN_ON_ONCE(!rate->stbc && num_of_ant != 1);
} else if (nss == 2) { } else if (nss == 2) {
rate->type = LQ_HT_MIMO2; rate->type = LQ_HT_MIMO2;
WARN_ON_ONCE(num_of_ant != 2); WARN_ON_ONCE(num_of_ant != 2);
...@@ -992,7 +1001,15 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta, ...@@ -992,7 +1001,15 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
static inline bool rs_rate_match(struct rs_rate *a, static inline bool rs_rate_match(struct rs_rate *a,
struct rs_rate *b) struct rs_rate *b)
{ {
return (a->type == b->type) && (a->ant == b->ant) && (a->sgi == b->sgi); bool ant_match;
if (a->stbc)
ant_match = (b->ant == ANT_A || b->ant == ANT_B);
else
ant_match = (a->ant == b->ant);
return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi)
&& ant_match;
} }
static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags) static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags)
...@@ -1225,7 +1242,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, ...@@ -1225,7 +1242,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp); IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp);
done: done:
/* See if there's a better rate or modulation mode to try. */ /* See if there's a better rate or modulation mode to try. */
if (sta && sta->supp_rates[info->band]) if (sta->supp_rates[info->band])
rs_rate_scale_perform(mvm, sta, lq_sta, tid); rs_rate_scale_perform(mvm, sta, lq_sta, tid);
} }
...@@ -1623,6 +1640,8 @@ static int rs_switch_to_column(struct iwl_mvm *mvm, ...@@ -1623,6 +1640,8 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
else else
rate->type = LQ_LEGACY_G; rate->type = LQ_LEGACY_G;
rate->bw = RATE_MCS_CHAN_WIDTH_20;
rate->ldpc = false;
rate_mask = lq_sta->active_legacy_rate; rate_mask = lq_sta->active_legacy_rate;
} else if (column->mode == RS_SISO) { } else if (column->mode == RS_SISO) {
rate->type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO; rate->type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO;
...@@ -1634,8 +1653,11 @@ static int rs_switch_to_column(struct iwl_mvm *mvm, ...@@ -1634,8 +1653,11 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
WARN_ON_ONCE("Bad column mode"); WARN_ON_ONCE("Bad column mode");
} }
if (column->mode != RS_LEGACY) {
rate->bw = rs_bw_from_sta_bw(sta); rate->bw = rs_bw_from_sta_bw(sta);
rate->ldpc = lq_sta->ldpc; rate->ldpc = lq_sta->ldpc;
}
search_tbl->column = col_id; search_tbl->column = col_id;
rs_set_expected_tpt_table(lq_sta, search_tbl); rs_set_expected_tpt_table(lq_sta, search_tbl);
...@@ -1754,6 +1776,29 @@ static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm, ...@@ -1754,6 +1776,29 @@ static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm,
return action; return action;
} }
static bool rs_stbc_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta)
{
struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
struct ieee80211_vif *vif = mvmsta->vif;
bool sta_ps_disabled = (vif->type == NL80211_IFTYPE_STATION &&
!vif->bss_conf.ps);
/* Our chip supports Tx STBC and the peer is an HT/VHT STA which
* supports STBC of at least 1*SS
*/
if (!lq_sta->stbc)
return false;
if (!mvm->ps_disabled && !sta_ps_disabled)
return false;
if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta))
return false;
return true;
}
static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index, static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index,
int *weaker, int *stronger) int *weaker, int *stronger)
{ {
...@@ -2675,6 +2720,11 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, ...@@ -2675,6 +2720,11 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
if (mvm->cfg->ht_params->ldpc && if (mvm->cfg->ht_params->ldpc &&
(ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)) (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING))
lq_sta->ldpc = true; lq_sta->ldpc = true;
if (mvm->cfg->ht_params->stbc &&
(num_of_ant(mvm->fw->valid_tx_ant) > 1) &&
(ht_cap->cap & IEEE80211_HT_CAP_RX_STBC))
lq_sta->stbc = true;
} else { } else {
rs_vht_set_enabled_rates(sta, vht_cap, lq_sta); rs_vht_set_enabled_rates(sta, vht_cap, lq_sta);
lq_sta->is_vht = true; lq_sta->is_vht = true;
...@@ -2682,8 +2732,16 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, ...@@ -2682,8 +2732,16 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
if (mvm->cfg->ht_params->ldpc && if (mvm->cfg->ht_params->ldpc &&
(vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC)) (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC))
lq_sta->ldpc = true; lq_sta->ldpc = true;
if (mvm->cfg->ht_params->stbc &&
(num_of_ant(mvm->fw->valid_tx_ant) > 1) &&
(vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK))
lq_sta->stbc = true;
} }
if (IWL_MVM_RS_DISABLE_MIMO)
lq_sta->active_mimo2_rate = 0;
lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate, lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate,
BITS_PER_LONG); BITS_PER_LONG);
lq_sta->max_siso_rate_idx = find_last_bit(&lq_sta->active_siso_rate, lq_sta->max_siso_rate_idx = find_last_bit(&lq_sta->active_siso_rate,
...@@ -2692,11 +2750,11 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, ...@@ -2692,11 +2750,11 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
BITS_PER_LONG); BITS_PER_LONG);
IWL_DEBUG_RATE(mvm, IWL_DEBUG_RATE(mvm,
"RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d\n", "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d STBC%d\n",
lq_sta->active_legacy_rate, lq_sta->active_legacy_rate,
lq_sta->active_siso_rate, lq_sta->active_siso_rate,
lq_sta->active_mimo2_rate, lq_sta->active_mimo2_rate,
lq_sta->is_vht, lq_sta->ldpc); lq_sta->is_vht, lq_sta->ldpc, lq_sta->stbc);
IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n", IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n",
lq_sta->max_legacy_rate_idx, lq_sta->max_legacy_rate_idx,
lq_sta->max_siso_rate_idx, lq_sta->max_siso_rate_idx,
...@@ -2820,6 +2878,7 @@ static void rs_fill_rates_for_column(struct iwl_mvm *mvm, ...@@ -2820,6 +2878,7 @@ static void rs_fill_rates_for_column(struct iwl_mvm *mvm,
* rate[15] 0x800D Legacy | ANT: B Rate: 6 Mbps * rate[15] 0x800D Legacy | ANT: B Rate: 6 Mbps
*/ */
static void rs_build_rates_table(struct iwl_mvm *mvm, static void rs_build_rates_table(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta, struct iwl_lq_sta *lq_sta,
const struct rs_rate *initial_rate) const struct rs_rate *initial_rate)
{ {
...@@ -2832,6 +2891,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, ...@@ -2832,6 +2891,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm,
memcpy(&rate, initial_rate, sizeof(rate)); memcpy(&rate, initial_rate, sizeof(rate));
valid_tx_ant = mvm->fw->valid_tx_ant; valid_tx_ant = mvm->fw->valid_tx_ant;
rate.stbc = rs_stbc_allow(mvm, sta, lq_sta);
if (is_siso(&rate)) { if (is_siso(&rate)) {
num_rates = RS_INITIAL_SISO_NUM_RATES; num_rates = RS_INITIAL_SISO_NUM_RATES;
...@@ -2903,7 +2963,7 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm, ...@@ -2903,7 +2963,7 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm,
if (WARN_ON_ONCE(!sta || !initial_rate)) if (WARN_ON_ONCE(!sta || !initial_rate))
return; return;
rs_build_rates_table(mvm, lq_sta, initial_rate); rs_build_rates_table(mvm, sta, lq_sta, initial_rate);
if (num_of_ant(initial_rate->ant) == 1) if (num_of_ant(initial_rate->ant) == 1)
lq_cmd->single_stream_ant_msk = initial_rate->ant; lq_cmd->single_stream_ant_msk = initial_rate->ant;
......
...@@ -208,6 +208,7 @@ struct rs_rate { ...@@ -208,6 +208,7 @@ struct rs_rate {
u32 bw; u32 bw;
bool sgi; bool sgi;
bool ldpc; bool ldpc;
bool stbc;
}; };
...@@ -331,6 +332,7 @@ struct iwl_lq_sta { ...@@ -331,6 +332,7 @@ struct iwl_lq_sta {
u64 last_tx; u64 last_tx;
bool is_vht; bool is_vht;
bool ldpc; /* LDPC Rx is supported by the STA */ bool ldpc; /* LDPC Rx is supported by the STA */
bool stbc; /* Tx STBC is supported by chip and Rx by STA */
enum ieee80211_band band; enum ieee80211_band band;
/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
......
...@@ -270,7 +270,8 @@ static void iwl_mvm_scan_condition_iterator(void *data, u8 *mac, ...@@ -270,7 +270,8 @@ static void iwl_mvm_scan_condition_iterator(void *data, u8 *mac,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
bool *global_bound = data; bool *global_bound = data;
if (mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < MAX_PHYS) if (vif->type != NL80211_IFTYPE_P2P_DEVICE && mvmvif->phy_ctxt &&
mvmvif->phy_ctxt->id < MAX_PHYS)
*global_bound = true; *global_bound = true;
} }
...@@ -459,7 +460,8 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm, ...@@ -459,7 +460,8 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm,
basic_ssid ? 1 : 0); basic_ssid ? 1 : 0);
cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL | cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
TX_CMD_FLG_BT_DIS); 3 << TX_CMD_FLG_BT_PRIO_POS);
cmd->tx_cmd.sta_id = mvm->aux_sta.sta_id; cmd->tx_cmd.sta_id = mvm->aux_sta.sta_id;
cmd->tx_cmd.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE); cmd->tx_cmd.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
cmd->tx_cmd.rate_n_flags = cmd->tx_cmd.rate_n_flags =
...@@ -671,6 +673,7 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, ...@@ -671,6 +673,7 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm,
mvm->scan_status = IWL_MVM_SCAN_NONE; mvm->scan_status = IWL_MVM_SCAN_NONE;
ieee80211_scan_completed(mvm->hw, ieee80211_scan_completed(mvm->hw,
status == IWL_SCAN_OFFLOAD_ABORTED); status == IWL_SCAN_OFFLOAD_ABORTED);
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
} }
mvm->last_ebs_successful = !ebs_status; mvm->last_ebs_successful = !ebs_status;
...@@ -1006,6 +1009,31 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, ...@@ -1006,6 +1009,31 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
sizeof(scan_req), &scan_req); sizeof(scan_req), &scan_req);
} }
int iwl_mvm_scan_offload_start(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct cfg80211_sched_scan_request *req,
struct ieee80211_scan_ies *ies)
{
int ret;
if ((mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) {
ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
if (ret)
return ret;
ret = iwl_mvm_unified_sched_scan_lmac(mvm, vif, req, ies);
} else {
ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies);
if (ret)
return ret;
ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
if (ret)
return ret;
ret = iwl_mvm_sched_scan_start(mvm, req);
}
return ret;
}
static int iwl_mvm_send_scan_offload_abort(struct iwl_mvm *mvm) static int iwl_mvm_send_scan_offload_abort(struct iwl_mvm *mvm)
{ {
int ret; int ret;
...@@ -1080,8 +1108,12 @@ int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify) ...@@ -1080,8 +1108,12 @@ int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify)
/* /*
* Clear the scan status so the next scan requests will succeed. This * Clear the scan status so the next scan requests will succeed. This
* also ensures the Rx handler doesn't do anything, as the scan was * also ensures the Rx handler doesn't do anything, as the scan was
* stopped from above. * stopped from above. Since the rx handler won't do anything now,
* we have to release the scan reference here.
*/ */
if (mvm->scan_status == IWL_MVM_SCAN_OS)
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
mvm->scan_status = IWL_MVM_SCAN_NONE; mvm->scan_status = IWL_MVM_SCAN_NONE;
if (notify) { if (notify) {
......
...@@ -609,7 +609,7 @@ int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -609,7 +609,7 @@ int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
lockdep_assert_held(&mvm->mutex); lockdep_assert_held(&mvm->mutex);
qmask = iwl_mvm_mac_get_queues_mask(mvm, vif); qmask = iwl_mvm_mac_get_queues_mask(vif);
/* /*
* The firmware defines the TFD queue mask to only be relevant * The firmware defines the TFD queue mask to only be relevant
......
...@@ -305,8 +305,8 @@ static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm, ...@@ -305,8 +305,8 @@ static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
te_data->running = false; te_data->running = false;
te_data->vif = NULL; te_data->vif = NULL;
te_data->uid = 0; te_data->uid = 0;
te_data->id = TE_MAX;
} else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) { } else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) {
set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status); set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
te_data->running = true; te_data->running = true;
ieee80211_ready_on_channel(mvm->hw); /* Start TE */ ieee80211_ready_on_channel(mvm->hw); /* Start TE */
......
...@@ -64,10 +64,6 @@ ...@@ -64,10 +64,6 @@
*****************************************************************************/ *****************************************************************************/
#include "mvm.h" #include "mvm.h"
#include "iwl-config.h"
#include "iwl-io.h"
#include "iwl-csr.h"
#include "iwl-prph.h"
#define IWL_MVM_TEMP_NOTIF_WAIT_TIMEOUT HZ #define IWL_MVM_TEMP_NOTIF_WAIT_TIMEOUT HZ
......
...@@ -175,14 +175,10 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, ...@@ -175,14 +175,10 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
/* /*
* for data packets, rate info comes from the table inside the fw. This * for data packets, rate info comes from the table inside the fw. This
* table is controlled by LINK_QUALITY commands. Exclude ctrl port * table is controlled by LINK_QUALITY commands
* frames like EAPOLs which should be treated as mgmt frames. This
* avoids them being sent initially in high rates which increases the
* chances for completion of the 4-Way handshake.
*/ */
if (ieee80211_is_data(fc) && sta && if (ieee80211_is_data(fc) && sta) {
!(info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) {
tx_cmd->initial_rate_index = 0; tx_cmd->initial_rate_index = 0;
tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE); tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
return; return;
...@@ -193,8 +189,10 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, ...@@ -193,8 +189,10 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
/* HT rate doesn't make sense for a non data frame */ /* HT rate doesn't make sense for a non data frame */
WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS, WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS,
"Got an HT rate for a non data frame 0x%x\n", "Got an HT rate (flags:0x%x/mcs:%d) for a non data frame (fc:0x%x)\n",
info->control.rates[0].flags); info->control.rates[0].flags,
info->control.rates[0].idx,
le16_to_cpu(fc));
rate_idx = info->control.rates[0].idx; rate_idx = info->control.rates[0].idx;
/* if the rate isn't a well known legacy rate, take the lowest one */ /* if the rate isn't a well known legacy rate, take the lowest one */
......
...@@ -734,3 +734,40 @@ bool iwl_mvm_is_idle(struct iwl_mvm *mvm) ...@@ -734,3 +734,40 @@ bool iwl_mvm_is_idle(struct iwl_mvm *mvm)
return idle; return idle;
} }
struct iwl_bss_iter_data {
struct ieee80211_vif *vif;
bool error;
};
static void iwl_mvm_bss_iface_iterator(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
struct iwl_bss_iter_data *data = _data;
if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
return;
if (data->vif) {
data->error = true;
return;
}
data->vif = vif;
}
struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm)
{
struct iwl_bss_iter_data bss_iter_data = {};
ieee80211_iterate_active_interfaces_atomic(
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_bss_iface_iterator, &bss_iter_data);
if (bss_iter_data.error) {
IWL_ERR(mvm, "More than one managed interface active!\n");
return ERR_PTR(-EINVAL);
}
return bss_iter_data.vif;
}
...@@ -133,7 +133,7 @@ static void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans) ...@@ -133,7 +133,7 @@ static void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans)
break; break;
} }
if (!page) if (WARN_ON_ONCE(!page))
return; return;
trans_pcie->fw_mon_page = page; trans_pcie->fw_mon_page = page;
...@@ -174,6 +174,7 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans) ...@@ -174,6 +174,7 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans)
{ {
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
u16 lctl; u16 lctl;
u16 cap;
/* /*
* HW bug W/A for instability in PCIe bus L0S->L1 transition. * HW bug W/A for instability in PCIe bus L0S->L1 transition.
...@@ -184,16 +185,17 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans) ...@@ -184,16 +185,17 @@ static void iwl_pcie_apm_config(struct iwl_trans *trans)
* power savings, even without L1. * power savings, even without L1.
*/ */
pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl); pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl);
if (lctl & PCI_EXP_LNKCTL_ASPM_L1) { if (lctl & PCI_EXP_LNKCTL_ASPM_L1)
/* L1-ASPM enabled; disable(!) L0S */
iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
dev_info(trans->dev, "L1 Enabled; Disabling L0S\n"); else
} else {
/* L1-ASPM disabled; enable(!) L0S */
iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
dev_info(trans->dev, "L1 Disabled; Enabling L0S\n");
}
trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S); trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S);
pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_DEVCTL2, &cap);
trans->ltr_enabled = cap & PCI_EXP_DEVCTL2_LTR_EN;
dev_info(trans->dev, "L1 %sabled - LTR %sabled\n",
(lctl & PCI_EXP_LNKCTL_ASPM_L1) ? "En" : "Dis",
trans->ltr_enabled ? "En" : "Dis");
} }
/* /*
...@@ -428,7 +430,7 @@ static int iwl_pcie_apm_stop_master(struct iwl_trans *trans) ...@@ -428,7 +430,7 @@ static int iwl_pcie_apm_stop_master(struct iwl_trans *trans)
ret = iwl_poll_bit(trans, CSR_RESET, ret = iwl_poll_bit(trans, CSR_RESET,
CSR_RESET_REG_FLAG_MASTER_DISABLED, CSR_RESET_REG_FLAG_MASTER_DISABLED,
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
if (ret) if (ret < 0)
IWL_WARN(trans, "Master Disable Timed Out, 100 usec\n"); IWL_WARN(trans, "Master Disable Timed Out, 100 usec\n");
IWL_DEBUG_INFO(trans, "stop master\n"); IWL_DEBUG_INFO(trans, "stop master\n");
...@@ -544,7 +546,7 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans) ...@@ -544,7 +546,7 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
msleep(25); msleep(25);
} }
IWL_DEBUG_INFO(trans, "got NIC after %d iterations\n", iter); IWL_ERR(trans, "Couldn't prepare the card\n");
return ret; return ret;
} }
...@@ -744,15 +746,12 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, ...@@ -744,15 +746,12 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
int ret = 0; int ret = 0;
int first_ucode_section; int first_ucode_section;
IWL_DEBUG_FW(trans,
"working with %s image\n",
image->is_secure ? "Secured" : "Non Secured");
IWL_DEBUG_FW(trans, IWL_DEBUG_FW(trans,
"working with %s CPU\n", "working with %s CPU\n",
image->is_dual_cpus ? "Dual" : "Single"); image->is_dual_cpus ? "Dual" : "Single");
/* configure the ucode to be ready to get the secured image */ /* configure the ucode to be ready to get the secured image */
if (image->is_secure) { if (iwl_has_secure_boot(trans->hw_rev, trans->cfg->device_family)) {
/* set secure boot inspector addresses */ /* set secure boot inspector addresses */
iwl_write_prph(trans, iwl_write_prph(trans,
LMPM_SECURE_INSPECTOR_CODE_ADDR, LMPM_SECURE_INSPECTOR_CODE_ADDR,
...@@ -788,7 +787,8 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, ...@@ -788,7 +787,8 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
LMPM_SECURE_CPU2_HDR_MEM_SPACE); LMPM_SECURE_CPU2_HDR_MEM_SPACE);
/* load to FW the binary sections of CPU2 */ /* load to FW the binary sections of CPU2 */
if (image->is_secure) if (iwl_has_secure_boot(trans->hw_rev,
trans->cfg->device_family))
ret = iwl_pcie_load_cpu_secured_sections( ret = iwl_pcie_load_cpu_secured_sections(
trans, image, 2, trans, image, 2,
&first_ucode_section); &first_ucode_section);
...@@ -819,7 +819,7 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, ...@@ -819,7 +819,7 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
else else
iwl_write32(trans, CSR_RESET, 0); iwl_write32(trans, CSR_RESET, 0);
if (image->is_secure) { if (iwl_has_secure_boot(trans->hw_rev, trans->cfg->device_family)) {
/* wait for image verification to complete */ /* wait for image verification to complete */
ret = iwl_poll_prph_bit(trans, ret = iwl_poll_prph_bit(trans,
LMPM_SECURE_BOOT_CPU1_STATUS_ADDR, LMPM_SECURE_BOOT_CPU1_STATUS_ADDR,
...@@ -1021,14 +1021,6 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, ...@@ -1021,14 +1021,6 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
return 0; return 0;
} }
iwl_pcie_set_pwr(trans, false);
val = iwl_read32(trans, CSR_RESET);
if (val & CSR_RESET_REG_FLAG_NEVO_RESET) {
*status = IWL_D3_STATUS_RESET;
return 0;
}
/* /*
* Also enables interrupts - none will happen as the device doesn't * Also enables interrupts - none will happen as the device doesn't
* know we're waking it up, only when the opmode actually tells it * know we're waking it up, only when the opmode actually tells it
...@@ -1043,11 +1035,13 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, ...@@ -1043,11 +1035,13 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
25000); 25000);
if (ret) { if (ret < 0) {
IWL_ERR(trans, "Failed to resume the device (mac ready)\n"); IWL_ERR(trans, "Failed to resume the device (mac ready)\n");
return ret; return ret;
} }
iwl_pcie_set_pwr(trans, false);
iwl_trans_pcie_tx_reset(trans); iwl_trans_pcie_tx_reset(trans);
ret = iwl_pcie_rx_init(trans); ret = iwl_pcie_rx_init(trans);
...@@ -1056,7 +1050,12 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, ...@@ -1056,7 +1050,12 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
return ret; return ret;
} }
val = iwl_read32(trans, CSR_RESET);
if (val & CSR_RESET_REG_FLAG_NEVO_RESET)
*status = IWL_D3_STATUS_RESET;
else
*status = IWL_D3_STATUS_ALIVE; *status = IWL_D3_STATUS_ALIVE;
return 0; return 0;
} }
...@@ -1765,6 +1764,13 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, ...@@ -1765,6 +1764,13 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
IWL_ERR(trans, "failed to create the trans debugfs entry\n"); IWL_ERR(trans, "failed to create the trans debugfs entry\n");
return -ENOMEM; return -ENOMEM;
} }
#else
static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
struct dentry *dir)
{
return 0;
}
#endif /*CONFIG_IWLWIFI_DEBUGFS */
static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd) static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd)
{ {
...@@ -2043,13 +2049,6 @@ struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans) ...@@ -2043,13 +2049,6 @@ struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
return dump_data; return dump_data;
} }
#else
static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
struct dentry *dir)
{
return 0;
}
#endif /*CONFIG_IWLWIFI_DEBUGFS */
static const struct iwl_trans_ops trans_ops_pcie = { static const struct iwl_trans_ops trans_ops_pcie = {
.start_hw = iwl_trans_pcie_start_hw, .start_hw = iwl_trans_pcie_start_hw,
...@@ -2086,9 +2085,7 @@ static const struct iwl_trans_ops trans_ops_pcie = { ...@@ -2086,9 +2085,7 @@ static const struct iwl_trans_ops trans_ops_pcie = {
.release_nic_access = iwl_trans_pcie_release_nic_access, .release_nic_access = iwl_trans_pcie_release_nic_access,
.set_bits_mask = iwl_trans_pcie_set_bits_mask, .set_bits_mask = iwl_trans_pcie_set_bits_mask,
#ifdef CONFIG_IWLWIFI_DEBUGFS
.dump_data = iwl_trans_pcie_dump_data, .dump_data = iwl_trans_pcie_dump_data,
#endif
}; };
struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
......
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