提交 652dfb2b 编写于 作者: D David S. Miller

Merge tag 'wireless-drivers-for-davem-2018-03-08' of...

Merge tag 'wireless-drivers-for-davem-2018-03-08' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers

Kalle Valo:

====================
wireless-drivers fixes for 4.16

Quote a few fixes as I have not been able to send a pull request
earlier. Most of the fixes for iwlwifi but also few others, nothing
really standing out though.

iwlwifi

* fix a bogus warning when freeing a TFD

* fix severe throughput problem with 9000 series

* fix for a bug that caused queue hangs in certain situations

* fix for an issue with IBSS

* fix an issue with rate-scaling in AP-mode

* fix Channel Switch Announcement (CSA) issues with count 0 and 1

* some firmware debugging fixes

* remov a wrong error message when removing keys

* fix a firmware sysassert most usually triggered in IBSS

* a couple of fixes on multicast queues

* a fix with CCMP 256

rtlwifi

* fix loss of signal for rtl8723be

brcmfmac

* add possibility to obtain firmware error

* fix P2P_DEVICE ethernet address generation
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
...@@ -181,6 +181,7 @@ enum brcmf_netif_stop_reason { ...@@ -181,6 +181,7 @@ enum brcmf_netif_stop_reason {
* @netif_stop_lock: spinlock for update netif_stop from multiple sources. * @netif_stop_lock: spinlock for update netif_stop from multiple sources.
* @pend_8021x_cnt: tracks outstanding number of 802.1x frames. * @pend_8021x_cnt: tracks outstanding number of 802.1x frames.
* @pend_8021x_wait: used for signalling change in count. * @pend_8021x_wait: used for signalling change in count.
* @fwil_fwerr: flag indicating fwil layer should return firmware error codes.
*/ */
struct brcmf_if { struct brcmf_if {
struct brcmf_pub *drvr; struct brcmf_pub *drvr;
...@@ -198,6 +199,7 @@ struct brcmf_if { ...@@ -198,6 +199,7 @@ struct brcmf_if {
wait_queue_head_t pend_8021x_wait; wait_queue_head_t pend_8021x_wait;
struct in6_addr ipv6_addr_tbl[NDOL_MAX_ENTRIES]; struct in6_addr ipv6_addr_tbl[NDOL_MAX_ENTRIES];
u8 ipv6addr_idx; u8 ipv6addr_idx;
bool fwil_fwerr;
}; };
int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp); int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp);
......
...@@ -104,6 +104,9 @@ static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp, ...@@ -104,6 +104,9 @@ static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp,
u32 data; u32 data;
int err; int err;
/* we need to know firmware error */
ifp->fwil_fwerr = true;
err = brcmf_fil_iovar_int_get(ifp, name, &data); err = brcmf_fil_iovar_int_get(ifp, name, &data);
if (err == 0) { if (err == 0) {
brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]); brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
...@@ -112,6 +115,8 @@ static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp, ...@@ -112,6 +115,8 @@ static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp,
brcmf_dbg(TRACE, "%s feature check failed: %d\n", brcmf_dbg(TRACE, "%s feature check failed: %d\n",
brcmf_feat_names[id], err); brcmf_feat_names[id], err);
} }
ifp->fwil_fwerr = false;
} }
static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp, static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp,
...@@ -120,6 +125,9 @@ static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp, ...@@ -120,6 +125,9 @@ static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp,
{ {
int err; int err;
/* we need to know firmware error */
ifp->fwil_fwerr = true;
err = brcmf_fil_iovar_data_set(ifp, name, data, len); err = brcmf_fil_iovar_data_set(ifp, name, data, len);
if (err != -BRCMF_FW_UNSUPPORTED) { if (err != -BRCMF_FW_UNSUPPORTED) {
brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]); brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
...@@ -128,6 +136,8 @@ static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp, ...@@ -128,6 +136,8 @@ static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp,
brcmf_dbg(TRACE, "%s feature check failed: %d\n", brcmf_dbg(TRACE, "%s feature check failed: %d\n",
brcmf_feat_names[id], err); brcmf_feat_names[id], err);
} }
ifp->fwil_fwerr = false;
} }
#define MAX_CAPS_BUFFER_SIZE 512 #define MAX_CAPS_BUFFER_SIZE 512
......
...@@ -131,6 +131,9 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) ...@@ -131,6 +131,9 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
brcmf_fil_get_errstr((u32)(-fwerr)), fwerr); brcmf_fil_get_errstr((u32)(-fwerr)), fwerr);
err = -EBADE; err = -EBADE;
} }
if (ifp->fwil_fwerr)
return fwerr;
return err; return err;
} }
......
...@@ -462,25 +462,23 @@ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac) ...@@ -462,25 +462,23 @@ static int brcmf_p2p_set_firmware(struct brcmf_if *ifp, u8 *p2p_mac)
* @dev_addr: optional device address. * @dev_addr: optional device address.
* *
* P2P needs mac addresses for P2P device and interface. If no device * P2P needs mac addresses for P2P device and interface. If no device
* address it specified, these are derived from the primary net device, ie. * address it specified, these are derived from a random ethernet
* the permanent ethernet address of the device. * address.
*/ */
static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr) static void brcmf_p2p_generate_bss_mac(struct brcmf_p2p_info *p2p, u8 *dev_addr)
{ {
struct brcmf_if *pri_ifp = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; bool random_addr = false;
bool local_admin = false;
if (!dev_addr || is_zero_ether_addr(dev_addr)) { if (!dev_addr || is_zero_ether_addr(dev_addr))
dev_addr = pri_ifp->mac_addr; random_addr = true;
local_admin = true;
}
/* Generate the P2P Device Address. This consists of the device's /* Generate the P2P Device Address obtaining a random ethernet
* primary MAC address with the locally administered bit set. * address with the locally administered bit set.
*/ */
memcpy(p2p->dev_addr, dev_addr, ETH_ALEN); if (random_addr)
if (local_admin) eth_random_addr(p2p->dev_addr);
p2p->dev_addr[0] |= 0x02; else
memcpy(p2p->dev_addr, dev_addr, ETH_ALEN);
/* Generate the P2P Interface Address. If the discovery and connection /* Generate the P2P Interface Address. If the discovery and connection
* BSSCFGs need to simultaneously co-exist, then this address must be * BSSCFGs need to simultaneously co-exist, then this address must be
......
...@@ -91,7 +91,6 @@ config IWLWIFI_BCAST_FILTERING ...@@ -91,7 +91,6 @@ config IWLWIFI_BCAST_FILTERING
config IWLWIFI_PCIE_RTPM config IWLWIFI_PCIE_RTPM
bool "Enable runtime power management mode for PCIe devices" bool "Enable runtime power management mode for PCIe devices"
depends on IWLMVM && PM && EXPERT depends on IWLMVM && PM && EXPERT
default false
help help
Say Y here to enable runtime power management for PCIe Say Y here to enable runtime power management for PCIe
devices. If enabled, the device will go into low power mode devices. If enabled, the device will go into low power mode
......
...@@ -211,7 +211,7 @@ enum { ...@@ -211,7 +211,7 @@ enum {
* @TE_V2_NOTIF_HOST_FRAG_END:request/receive notification on frag end * @TE_V2_NOTIF_HOST_FRAG_END:request/receive notification on frag end
* @TE_V2_NOTIF_INTERNAL_FRAG_START: internal FW use. * @TE_V2_NOTIF_INTERNAL_FRAG_START: internal FW use.
* @TE_V2_NOTIF_INTERNAL_FRAG_END: internal FW use. * @TE_V2_NOTIF_INTERNAL_FRAG_END: internal FW use.
* @T2_V2_START_IMMEDIATELY: start time event immediately * @TE_V2_START_IMMEDIATELY: start time event immediately
* @TE_V2_DEP_OTHER: depends on another time event * @TE_V2_DEP_OTHER: depends on another time event
* @TE_V2_DEP_TSF: depends on a specific time * @TE_V2_DEP_TSF: depends on a specific time
* @TE_V2_EVENT_SOCIOPATHIC: can't co-exist with other events of tha same MAC * @TE_V2_EVENT_SOCIOPATHIC: can't co-exist with other events of tha same MAC
...@@ -230,7 +230,7 @@ enum iwl_time_event_policy { ...@@ -230,7 +230,7 @@ enum iwl_time_event_policy {
TE_V2_NOTIF_HOST_FRAG_END = BIT(5), TE_V2_NOTIF_HOST_FRAG_END = BIT(5),
TE_V2_NOTIF_INTERNAL_FRAG_START = BIT(6), TE_V2_NOTIF_INTERNAL_FRAG_START = BIT(6),
TE_V2_NOTIF_INTERNAL_FRAG_END = BIT(7), TE_V2_NOTIF_INTERNAL_FRAG_END = BIT(7),
T2_V2_START_IMMEDIATELY = BIT(11), TE_V2_START_IMMEDIATELY = BIT(11),
/* placement characteristics */ /* placement characteristics */
TE_V2_DEP_OTHER = BIT(TE_V2_PLACEMENT_POS), TE_V2_DEP_OTHER = BIT(TE_V2_PLACEMENT_POS),
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2008 - 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 - 2017 Intel Deutschland GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* *
* 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
...@@ -33,6 +34,7 @@ ...@@ -33,6 +34,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 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 - 2017 Intel Deutschland GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* 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
...@@ -942,7 +944,6 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt) ...@@ -942,7 +944,6 @@ void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt)
out: out:
iwl_fw_free_dump_desc(fwrt); iwl_fw_free_dump_desc(fwrt);
fwrt->dump.trig = NULL;
clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status); clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status);
IWL_DEBUG_INFO(fwrt, "WRT dump done\n"); IWL_DEBUG_INFO(fwrt, "WRT dump done\n");
} }
...@@ -1112,6 +1113,14 @@ void iwl_fw_error_dump_wk(struct work_struct *work) ...@@ -1112,6 +1113,14 @@ void iwl_fw_error_dump_wk(struct work_struct *work)
fwrt->ops->dump_start(fwrt->ops_ctx)) fwrt->ops->dump_start(fwrt->ops_ctx))
return; return;
if (fwrt->ops && fwrt->ops->fw_running &&
!fwrt->ops->fw_running(fwrt->ops_ctx)) {
IWL_ERR(fwrt, "Firmware not running - cannot dump error\n");
iwl_fw_free_dump_desc(fwrt);
clear_bit(IWL_FWRT_STATUS_DUMPING, &fwrt->status);
goto out;
}
if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) { if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
/* stop recording */ /* stop recording */
iwl_fw_dbg_stop_recording(fwrt); iwl_fw_dbg_stop_recording(fwrt);
...@@ -1145,7 +1154,7 @@ void iwl_fw_error_dump_wk(struct work_struct *work) ...@@ -1145,7 +1154,7 @@ void iwl_fw_error_dump_wk(struct work_struct *work)
iwl_write_prph(fwrt->trans, DBGC_OUT_CTRL, out_ctrl); iwl_write_prph(fwrt->trans, DBGC_OUT_CTRL, out_ctrl);
} }
} }
out:
if (fwrt->ops && fwrt->ops->dump_end) if (fwrt->ops && fwrt->ops->dump_end)
fwrt->ops->dump_end(fwrt->ops_ctx); fwrt->ops->dump_end(fwrt->ops_ctx);
} }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
* Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2008 - 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 - 2017 Intel Deutschland GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* *
* 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
...@@ -33,6 +34,7 @@ ...@@ -33,6 +34,7 @@
* Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2005 - 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 - 2017 Intel Deutschland GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* 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
...@@ -91,6 +93,7 @@ static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt) ...@@ -91,6 +93,7 @@ static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt)
if (fwrt->dump.desc != &iwl_dump_desc_assert) if (fwrt->dump.desc != &iwl_dump_desc_assert)
kfree(fwrt->dump.desc); kfree(fwrt->dump.desc);
fwrt->dump.desc = NULL; fwrt->dump.desc = NULL;
fwrt->dump.trig = NULL;
} }
void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt); void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt);
......
...@@ -75,6 +75,20 @@ static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt) ...@@ -75,6 +75,20 @@ static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt)
cancel_delayed_work_sync(&fwrt->timestamp.wk); cancel_delayed_work_sync(&fwrt->timestamp.wk);
} }
static inline void iwl_fw_suspend_timestamp(struct iwl_fw_runtime *fwrt)
{
cancel_delayed_work_sync(&fwrt->timestamp.wk);
}
static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt)
{
if (!fwrt->timestamp.delay)
return;
schedule_delayed_work(&fwrt->timestamp.wk,
round_jiffies_relative(fwrt->timestamp.delay));
}
#else #else
static inline int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, static inline int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt,
struct dentry *dbgfs_dir) struct dentry *dbgfs_dir)
...@@ -84,4 +98,8 @@ static inline int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, ...@@ -84,4 +98,8 @@ static inline int iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt,
static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt) {} static inline void iwl_fw_cancel_timestamp(struct iwl_fw_runtime *fwrt) {}
static inline void iwl_fw_suspend_timestamp(struct iwl_fw_runtime *fwrt) {}
static inline void iwl_fw_resume_timestamp(struct iwl_fw_runtime *fwrt) {}
#endif /* CONFIG_IWLWIFI_DEBUGFS */ #endif /* CONFIG_IWLWIFI_DEBUGFS */
...@@ -77,8 +77,14 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, ...@@ -77,8 +77,14 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
} }
IWL_EXPORT_SYMBOL(iwl_fw_runtime_init); IWL_EXPORT_SYMBOL(iwl_fw_runtime_init);
void iwl_fw_runtime_exit(struct iwl_fw_runtime *fwrt) void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt)
{ {
iwl_fw_cancel_timestamp(fwrt); iwl_fw_suspend_timestamp(fwrt);
} }
IWL_EXPORT_SYMBOL(iwl_fw_runtime_exit); IWL_EXPORT_SYMBOL(iwl_fw_runtime_suspend);
void iwl_fw_runtime_resume(struct iwl_fw_runtime *fwrt)
{
iwl_fw_resume_timestamp(fwrt);
}
IWL_EXPORT_SYMBOL(iwl_fw_runtime_resume);
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
* GPL LICENSE SUMMARY * GPL LICENSE SUMMARY
* *
* Copyright(c) 2017 Intel Deutschland GmbH * Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* *
* 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
...@@ -26,6 +27,7 @@ ...@@ -26,6 +27,7 @@
* BSD LICENSE * BSD LICENSE
* *
* Copyright(c) 2017 Intel Deutschland GmbH * Copyright(c) 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* 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
...@@ -68,6 +70,7 @@ ...@@ -68,6 +70,7 @@
struct iwl_fw_runtime_ops { struct iwl_fw_runtime_ops {
int (*dump_start)(void *ctx); int (*dump_start)(void *ctx);
void (*dump_end)(void *ctx); void (*dump_end)(void *ctx);
bool (*fw_running)(void *ctx);
}; };
#define MAX_NUM_LMAC 2 #define MAX_NUM_LMAC 2
...@@ -150,6 +153,10 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, ...@@ -150,6 +153,10 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
void iwl_fw_runtime_exit(struct iwl_fw_runtime *fwrt); void iwl_fw_runtime_exit(struct iwl_fw_runtime *fwrt);
void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt);
void iwl_fw_runtime_resume(struct iwl_fw_runtime *fwrt);
static inline void iwl_fw_set_current_image(struct iwl_fw_runtime *fwrt, static inline void iwl_fw_set_current_image(struct iwl_fw_runtime *fwrt,
enum iwl_ucode_type cur_fw_img) enum iwl_ucode_type cur_fw_img)
{ {
......
...@@ -1098,6 +1098,8 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) ...@@ -1098,6 +1098,8 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
/* make sure the d0i3 exit work is not pending */ /* make sure the d0i3 exit work is not pending */
flush_work(&mvm->d0i3_exit_work); flush_work(&mvm->d0i3_exit_work);
iwl_fw_runtime_suspend(&mvm->fwrt);
ret = iwl_trans_suspend(trans); ret = iwl_trans_suspend(trans);
if (ret) if (ret)
return ret; return ret;
...@@ -2012,6 +2014,8 @@ int iwl_mvm_resume(struct ieee80211_hw *hw) ...@@ -2012,6 +2014,8 @@ int iwl_mvm_resume(struct ieee80211_hw *hw)
mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED; mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
iwl_fw_runtime_resume(&mvm->fwrt);
return ret; return ret;
} }
...@@ -2038,6 +2042,8 @@ static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file) ...@@ -2038,6 +2042,8 @@ static int iwl_mvm_d3_test_open(struct inode *inode, struct file *file)
mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3; mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_D3;
iwl_fw_runtime_suspend(&mvm->fwrt);
/* start pseudo D3 */ /* start pseudo D3 */
rtnl_lock(); rtnl_lock();
err = __iwl_mvm_suspend(mvm->hw, mvm->hw->wiphy->wowlan_config, true); err = __iwl_mvm_suspend(mvm->hw, mvm->hw->wiphy->wowlan_config, true);
...@@ -2098,6 +2104,8 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file) ...@@ -2098,6 +2104,8 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file)
__iwl_mvm_resume(mvm, true); __iwl_mvm_resume(mvm, true);
rtnl_unlock(); rtnl_unlock();
iwl_fw_runtime_resume(&mvm->fwrt);
mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED; mvm->trans->system_pm_mode = IWL_PLAT_PM_MODE_DISABLED;
iwl_abort_notification_waits(&mvm->notif_wait); iwl_abort_notification_waits(&mvm->notif_wait);
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,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 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* *
* 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
...@@ -35,6 +36,7 @@ ...@@ -35,6 +36,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 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* 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
...@@ -1281,9 +1283,6 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm, ...@@ -1281,9 +1283,6 @@ static ssize_t iwl_dbgfs_fw_dbg_collect_write(struct iwl_mvm *mvm,
{ {
int ret; int ret;
if (!iwl_mvm_firmware_running(mvm))
return -EIO;
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE); ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE);
if (ret) if (ret)
return ret; return ret;
......
...@@ -438,7 +438,8 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -438,7 +438,8 @@ int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
} }
/* Allocate the CAB queue for softAP and GO interfaces */ /* Allocate the CAB queue for softAP and GO interfaces */
if (vif->type == NL80211_IFTYPE_AP) { if (vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_ADHOC) {
/* /*
* For TVQM this will be overwritten later with the FW assigned * For TVQM this will be overwritten later with the FW assigned
* queue value (when queue is enabled). * queue value (when queue is enabled).
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,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 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* *
* 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
...@@ -2106,15 +2107,40 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, ...@@ -2106,15 +2107,40 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
if (ret) if (ret)
goto out_remove; goto out_remove;
ret = iwl_mvm_add_mcast_sta(mvm, vif); /*
if (ret) * This is not very nice, but the simplest:
goto out_unbind; * For older FWs adding the mcast sta before the bcast station may
* cause assert 0x2b00.
/* Send the bcast station. At this stage the TBTT and DTIM time events * This is fixed in later FW so make the order of removal depend on
* are added and applied to the scheduler */ * the TLV
ret = iwl_mvm_send_add_bcast_sta(mvm, vif); */
if (ret) if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_STA_TYPE)) {
goto out_rm_mcast; ret = iwl_mvm_add_mcast_sta(mvm, vif);
if (ret)
goto out_unbind;
/*
* Send the bcast station. At this stage the TBTT and DTIM time
* events are added and applied to the scheduler
*/
ret = iwl_mvm_send_add_bcast_sta(mvm, vif);
if (ret) {
iwl_mvm_rm_mcast_sta(mvm, vif);
goto out_unbind;
}
} else {
/*
* Send the bcast station. At this stage the TBTT and DTIM time
* events are added and applied to the scheduler
*/
iwl_mvm_send_add_bcast_sta(mvm, vif);
if (ret)
goto out_unbind;
iwl_mvm_add_mcast_sta(mvm, vif);
if (ret) {
iwl_mvm_send_rm_bcast_sta(mvm, vif);
goto out_unbind;
}
}
/* must be set before quota calculations */ /* must be set before quota calculations */
mvmvif->ap_ibss_active = true; mvmvif->ap_ibss_active = true;
...@@ -2144,7 +2170,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw, ...@@ -2144,7 +2170,6 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
iwl_mvm_power_update_mac(mvm); iwl_mvm_power_update_mac(mvm);
mvmvif->ap_ibss_active = false; mvmvif->ap_ibss_active = false;
iwl_mvm_send_rm_bcast_sta(mvm, vif); iwl_mvm_send_rm_bcast_sta(mvm, vif);
out_rm_mcast:
iwl_mvm_rm_mcast_sta(mvm, vif); iwl_mvm_rm_mcast_sta(mvm, vif);
out_unbind: out_unbind:
iwl_mvm_binding_remove_vif(mvm, vif); iwl_mvm_binding_remove_vif(mvm, vif);
...@@ -2682,6 +2707,10 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, ...@@ -2682,6 +2707,10 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
/* enable beacon filtering */ /* enable beacon filtering */
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0)); WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
iwl_mvm_rs_rate_init(mvm, sta, mvmvif->phy_ctxt->channel->band,
false);
ret = 0; ret = 0;
} else if (old_state == IEEE80211_STA_AUTHORIZED && } else if (old_state == IEEE80211_STA_AUTHORIZED &&
new_state == IEEE80211_STA_ASSOC) { new_state == IEEE80211_STA_ASSOC) {
......
...@@ -90,6 +90,7 @@ ...@@ -90,6 +90,7 @@
#include "fw/runtime.h" #include "fw/runtime.h"
#include "fw/dbg.h" #include "fw/dbg.h"
#include "fw/acpi.h" #include "fw/acpi.h"
#include "fw/debugfs.h"
#define IWL_MVM_MAX_ADDRESSES 5 #define IWL_MVM_MAX_ADDRESSES 5
/* RSSI offset for WkP */ /* RSSI offset for WkP */
...@@ -1783,6 +1784,7 @@ static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm) ...@@ -1783,6 +1784,7 @@ static inline u32 iwl_mvm_flushable_queues(struct iwl_mvm *mvm)
static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm) static inline void iwl_mvm_stop_device(struct iwl_mvm *mvm)
{ {
iwl_fw_cancel_timestamp(&mvm->fwrt);
iwl_free_fw_paging(&mvm->fwrt); iwl_free_fw_paging(&mvm->fwrt);
clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status); clear_bit(IWL_MVM_STATUS_FIRMWARE_RUNNING, &mvm->status);
iwl_fw_dump_conf_clear(&mvm->fwrt); iwl_fw_dump_conf_clear(&mvm->fwrt);
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,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 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* *
* 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
...@@ -35,6 +36,7 @@ ...@@ -35,6 +36,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 - 2017 Intel Deutschland GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
* Copyright(c) 2018 Intel Corporation
* 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
...@@ -552,9 +554,15 @@ static void iwl_mvm_fwrt_dump_end(void *ctx) ...@@ -552,9 +554,15 @@ static void iwl_mvm_fwrt_dump_end(void *ctx)
iwl_mvm_unref(mvm, IWL_MVM_REF_FW_DBG_COLLECT); iwl_mvm_unref(mvm, IWL_MVM_REF_FW_DBG_COLLECT);
} }
static bool iwl_mvm_fwrt_fw_running(void *ctx)
{
return iwl_mvm_firmware_running(ctx);
}
static const struct iwl_fw_runtime_ops iwl_mvm_fwrt_ops = { static const struct iwl_fw_runtime_ops iwl_mvm_fwrt_ops = {
.dump_start = iwl_mvm_fwrt_dump_start, .dump_start = iwl_mvm_fwrt_dump_start,
.dump_end = iwl_mvm_fwrt_dump_end, .dump_end = iwl_mvm_fwrt_dump_end,
.fw_running = iwl_mvm_fwrt_fw_running,
}; };
static struct iwl_op_mode * static struct iwl_op_mode *
...@@ -802,7 +810,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, ...@@ -802,7 +810,6 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
iwl_mvm_leds_exit(mvm); iwl_mvm_leds_exit(mvm);
iwl_mvm_thermal_exit(mvm); iwl_mvm_thermal_exit(mvm);
out_free: out_free:
iwl_fw_runtime_exit(&mvm->fwrt);
iwl_fw_flush_dump(&mvm->fwrt); iwl_fw_flush_dump(&mvm->fwrt);
if (iwlmvm_mod_params.init_dbg) if (iwlmvm_mod_params.init_dbg)
...@@ -843,7 +850,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) ...@@ -843,7 +850,6 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
#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);
#endif #endif
iwl_fw_runtime_exit(&mvm->fwrt);
iwl_trans_op_mode_leave(mvm->trans); iwl_trans_op_mode_leave(mvm->trans);
iwl_phy_db_free(mvm->phy_db); iwl_phy_db_free(mvm->phy_db);
......
...@@ -2684,7 +2684,8 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm, ...@@ -2684,7 +2684,8 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm,
struct ieee80211_sta *sta, struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta, struct iwl_lq_sta *lq_sta,
enum nl80211_band band, enum nl80211_band band,
struct rs_rate *rate) struct rs_rate *rate,
bool init)
{ {
int i, nentries; int i, nentries;
unsigned long active_rate; unsigned long active_rate;
...@@ -2738,14 +2739,25 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm, ...@@ -2738,14 +2739,25 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm,
*/ */
if (sta->vht_cap.vht_supported && if (sta->vht_cap.vht_supported &&
best_rssi > IWL_RS_LOW_RSSI_THRESHOLD) { best_rssi > IWL_RS_LOW_RSSI_THRESHOLD) {
switch (sta->bandwidth) { /*
case IEEE80211_STA_RX_BW_160: * In AP mode, when a new station associates, rs is initialized
case IEEE80211_STA_RX_BW_80: * immediately upon association completion, before the phy
case IEEE80211_STA_RX_BW_40: * context is updated with the association parameters, so the
* sta bandwidth might be wider than the phy context allows.
* To avoid this issue, always initialize rs with 20mhz
* bandwidth rate, and after authorization, when the phy context
* is already up-to-date, re-init rs with the correct bw.
*/
u32 bw = init ? RATE_MCS_CHAN_WIDTH_20 : rs_bw_from_sta_bw(sta);
switch (bw) {
case RATE_MCS_CHAN_WIDTH_40:
case RATE_MCS_CHAN_WIDTH_80:
case RATE_MCS_CHAN_WIDTH_160:
initial_rates = rs_optimal_rates_vht; initial_rates = rs_optimal_rates_vht;
nentries = ARRAY_SIZE(rs_optimal_rates_vht); nentries = ARRAY_SIZE(rs_optimal_rates_vht);
break; break;
case IEEE80211_STA_RX_BW_20: case RATE_MCS_CHAN_WIDTH_20:
initial_rates = rs_optimal_rates_vht_20mhz; initial_rates = rs_optimal_rates_vht_20mhz;
nentries = ARRAY_SIZE(rs_optimal_rates_vht_20mhz); nentries = ARRAY_SIZE(rs_optimal_rates_vht_20mhz);
break; break;
...@@ -2756,7 +2768,7 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm, ...@@ -2756,7 +2768,7 @@ static void rs_get_initial_rate(struct iwl_mvm *mvm,
active_rate = lq_sta->active_siso_rate; active_rate = lq_sta->active_siso_rate;
rate->type = LQ_VHT_SISO; rate->type = LQ_VHT_SISO;
rate->bw = rs_bw_from_sta_bw(sta); rate->bw = bw;
} else if (sta->ht_cap.ht_supported && } else if (sta->ht_cap.ht_supported &&
best_rssi > IWL_RS_LOW_RSSI_THRESHOLD) { best_rssi > IWL_RS_LOW_RSSI_THRESHOLD) {
initial_rates = rs_optimal_rates_ht; initial_rates = rs_optimal_rates_ht;
...@@ -2839,7 +2851,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm, ...@@ -2839,7 +2851,7 @@ static void rs_initialize_lq(struct iwl_mvm *mvm,
tbl = &(lq_sta->lq_info[active_tbl]); tbl = &(lq_sta->lq_info[active_tbl]);
rate = &tbl->rate; rate = &tbl->rate;
rs_get_initial_rate(mvm, sta, lq_sta, band, rate); rs_get_initial_rate(mvm, sta, lq_sta, band, rate, init);
rs_init_optimal_rate(mvm, sta, lq_sta); rs_init_optimal_rate(mvm, sta, lq_sta);
WARN_ONCE(rate->ant != ANT_A && rate->ant != ANT_B, WARN_ONCE(rate->ant != ANT_A && rate->ant != ANT_B,
......
...@@ -71,6 +71,7 @@ static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -71,6 +71,7 @@ static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_rx_status *stats = IEEE80211_SKB_RXCB(skb); struct ieee80211_rx_status *stats = IEEE80211_SKB_RXCB(skb);
struct iwl_mvm_key_pn *ptk_pn; struct iwl_mvm_key_pn *ptk_pn;
int res;
u8 tid, keyidx; u8 tid, keyidx;
u8 pn[IEEE80211_CCMP_PN_LEN]; u8 pn[IEEE80211_CCMP_PN_LEN];
u8 *extiv; u8 *extiv;
...@@ -127,12 +128,13 @@ static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb, ...@@ -127,12 +128,13 @@ static inline int iwl_mvm_check_pn(struct iwl_mvm *mvm, struct sk_buff *skb,
pn[4] = extiv[1]; pn[4] = extiv[1];
pn[5] = extiv[0]; pn[5] = extiv[0];
if (memcmp(pn, ptk_pn->q[queue].pn[tid], res = memcmp(pn, ptk_pn->q[queue].pn[tid], IEEE80211_CCMP_PN_LEN);
IEEE80211_CCMP_PN_LEN) <= 0) if (res < 0)
return -1;
if (!res && !(stats->flag & RX_FLAG_ALLOW_SAME_PN))
return -1; return -1;
if (!(stats->flag & RX_FLAG_AMSDU_MORE)) memcpy(ptk_pn->q[queue].pn[tid], pn, IEEE80211_CCMP_PN_LEN);
memcpy(ptk_pn->q[queue].pn[tid], pn, IEEE80211_CCMP_PN_LEN);
stats->flag |= RX_FLAG_PN_VALIDATED; stats->flag |= RX_FLAG_PN_VALIDATED;
return 0; return 0;
...@@ -314,28 +316,21 @@ static void iwl_mvm_rx_csum(struct ieee80211_sta *sta, ...@@ -314,28 +316,21 @@ static void iwl_mvm_rx_csum(struct ieee80211_sta *sta,
} }
/* /*
* returns true if a packet outside BA session is a duplicate and * returns true if a packet is a duplicate and should be dropped.
* should be dropped * Updates AMSDU PN tracking info
*/ */
static bool iwl_mvm_is_nonagg_dup(struct ieee80211_sta *sta, int queue, static bool iwl_mvm_is_dup(struct ieee80211_sta *sta, int queue,
struct ieee80211_rx_status *rx_status, struct ieee80211_rx_status *rx_status,
struct ieee80211_hdr *hdr, struct ieee80211_hdr *hdr,
struct iwl_rx_mpdu_desc *desc) struct iwl_rx_mpdu_desc *desc)
{ {
struct iwl_mvm_sta *mvm_sta; struct iwl_mvm_sta *mvm_sta;
struct iwl_mvm_rxq_dup_data *dup_data; struct iwl_mvm_rxq_dup_data *dup_data;
u8 baid, tid, sub_frame_idx; u8 tid, sub_frame_idx;
if (WARN_ON(IS_ERR_OR_NULL(sta))) if (WARN_ON(IS_ERR_OR_NULL(sta)))
return false; return false;
baid = (le32_to_cpu(desc->reorder_data) &
IWL_RX_MPDU_REORDER_BAID_MASK) >>
IWL_RX_MPDU_REORDER_BAID_SHIFT;
if (baid != IWL_RX_REORDER_DATA_INVALID_BAID)
return false;
mvm_sta = iwl_mvm_sta_from_mac80211(sta); mvm_sta = iwl_mvm_sta_from_mac80211(sta);
dup_data = &mvm_sta->dup_data[queue]; dup_data = &mvm_sta->dup_data[queue];
...@@ -365,6 +360,12 @@ static bool iwl_mvm_is_nonagg_dup(struct ieee80211_sta *sta, int queue, ...@@ -365,6 +360,12 @@ static bool iwl_mvm_is_nonagg_dup(struct ieee80211_sta *sta, int queue,
dup_data->last_sub_frame[tid] >= sub_frame_idx)) dup_data->last_sub_frame[tid] >= sub_frame_idx))
return true; return true;
/* Allow same PN as the first subframe for following sub frames */
if (dup_data->last_seq[tid] == hdr->seq_ctrl &&
sub_frame_idx > dup_data->last_sub_frame[tid] &&
desc->mac_flags2 & IWL_RX_MPDU_MFLG2_AMSDU)
rx_status->flag |= RX_FLAG_ALLOW_SAME_PN;
dup_data->last_seq[tid] = hdr->seq_ctrl; dup_data->last_seq[tid] = hdr->seq_ctrl;
dup_data->last_sub_frame[tid] = sub_frame_idx; dup_data->last_sub_frame[tid] = sub_frame_idx;
...@@ -971,7 +972,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi, ...@@ -971,7 +972,7 @@ void iwl_mvm_rx_mpdu_mq(struct iwl_mvm *mvm, struct napi_struct *napi,
if (ieee80211_is_data(hdr->frame_control)) if (ieee80211_is_data(hdr->frame_control))
iwl_mvm_rx_csum(sta, skb, desc); iwl_mvm_rx_csum(sta, skb, desc);
if (iwl_mvm_is_nonagg_dup(sta, queue, rx_status, hdr, desc)) { if (iwl_mvm_is_dup(sta, queue, rx_status, hdr, desc)) {
kfree_skb(skb); kfree_skb(skb);
goto out; goto out;
} }
......
...@@ -2039,7 +2039,7 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -2039,7 +2039,7 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
struct iwl_trans_txq_scd_cfg cfg = { struct iwl_trans_txq_scd_cfg cfg = {
.fifo = IWL_MVM_TX_FIFO_MCAST, .fifo = IWL_MVM_TX_FIFO_MCAST,
.sta_id = msta->sta_id, .sta_id = msta->sta_id,
.tid = IWL_MAX_TID_COUNT, .tid = 0,
.aggregate = false, .aggregate = false,
.frame_limit = IWL_FRAME_LIMIT, .frame_limit = IWL_FRAME_LIMIT,
}; };
...@@ -2052,6 +2052,17 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -2052,6 +2052,17 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
vif->type != NL80211_IFTYPE_ADHOC)) vif->type != NL80211_IFTYPE_ADHOC))
return -ENOTSUPP; return -ENOTSUPP;
/*
* In IBSS, ieee80211_check_queues() sets the cab_queue to be
* invalid, so make sure we use the queue we want.
* Note that this is done here as we want to avoid making DQA
* changes in mac80211 layer.
*/
if (vif->type == NL80211_IFTYPE_ADHOC) {
vif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
mvmvif->cab_queue = vif->cab_queue;
}
/* /*
* While in previous FWs we had to exclude cab queue from TFD queue * While in previous FWs we had to exclude cab queue from TFD queue
* mask, now it is needed as any other queue. * mask, now it is needed as any other queue.
...@@ -2079,24 +2090,13 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -2079,24 +2090,13 @@ int iwl_mvm_add_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
if (iwl_mvm_has_new_tx_api(mvm)) { if (iwl_mvm_has_new_tx_api(mvm)) {
int queue = iwl_mvm_tvqm_enable_txq(mvm, vif->cab_queue, int queue = iwl_mvm_tvqm_enable_txq(mvm, vif->cab_queue,
msta->sta_id, msta->sta_id,
IWL_MAX_TID_COUNT, 0,
timeout); timeout);
mvmvif->cab_queue = queue; mvmvif->cab_queue = queue;
} else if (!fw_has_api(&mvm->fw->ucode_capa, } else if (!fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_STA_TYPE)) { IWL_UCODE_TLV_API_STA_TYPE))
/*
* In IBSS, ieee80211_check_queues() sets the cab_queue to be
* invalid, so make sure we use the queue we want.
* Note that this is done here as we want to avoid making DQA
* changes in mac80211 layer.
*/
if (vif->type == NL80211_IFTYPE_ADHOC) {
vif->cab_queue = IWL_MVM_DQA_GCAST_QUEUE;
mvmvif->cab_queue = vif->cab_queue;
}
iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0, iwl_mvm_enable_txq(mvm, vif->cab_queue, vif->cab_queue, 0,
&cfg, timeout); &cfg, timeout);
}
return 0; return 0;
} }
...@@ -2115,7 +2115,7 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) ...@@ -2115,7 +2115,7 @@ int iwl_mvm_rm_mcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
iwl_mvm_flush_sta(mvm, &mvmvif->mcast_sta, true, 0); iwl_mvm_flush_sta(mvm, &mvmvif->mcast_sta, true, 0);
iwl_mvm_disable_txq(mvm, mvmvif->cab_queue, vif->cab_queue, iwl_mvm_disable_txq(mvm, mvmvif->cab_queue, vif->cab_queue,
IWL_MAX_TID_COUNT, 0); 0, 0);
ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id); ret = iwl_mvm_rm_sta_common(mvm, mvmvif->mcast_sta.sta_id);
if (ret) if (ret)
...@@ -3170,8 +3170,9 @@ static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id, ...@@ -3170,8 +3170,9 @@ static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
int ret, size; int ret, size;
u32 status; u32 status;
/* This is a valid situation for GTK removal */
if (sta_id == IWL_MVM_INVALID_STA) if (sta_id == IWL_MVM_INVALID_STA)
return -EINVAL; return 0;
key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) & key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
STA_KEY_FLG_KEYID_MSK); STA_KEY_FLG_KEYID_MSK);
......
...@@ -616,7 +616,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm, ...@@ -616,7 +616,7 @@ void iwl_mvm_protect_session(struct iwl_mvm *mvm,
time_cmd.repeat = 1; time_cmd.repeat = 1;
time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START |
TE_V2_NOTIF_HOST_EVENT_END | TE_V2_NOTIF_HOST_EVENT_END |
T2_V2_START_IMMEDIATELY); TE_V2_START_IMMEDIATELY);
if (!wait_for_notif) { if (!wait_for_notif) {
iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
...@@ -803,7 +803,7 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, ...@@ -803,7 +803,7 @@ int iwl_mvm_start_p2p_roc(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
time_cmd.repeat = 1; time_cmd.repeat = 1;
time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START |
TE_V2_NOTIF_HOST_EVENT_END | TE_V2_NOTIF_HOST_EVENT_END |
T2_V2_START_IMMEDIATELY); TE_V2_START_IMMEDIATELY);
return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
} }
...@@ -913,6 +913,8 @@ int iwl_mvm_schedule_csa_period(struct iwl_mvm *mvm, ...@@ -913,6 +913,8 @@ int iwl_mvm_schedule_csa_period(struct iwl_mvm *mvm,
time_cmd.interval = cpu_to_le32(1); time_cmd.interval = cpu_to_le32(1);
time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START | time_cmd.policy = cpu_to_le16(TE_V2_NOTIF_HOST_EVENT_START |
TE_V2_ABSENCE); TE_V2_ABSENCE);
if (!apply_time)
time_cmd.policy |= cpu_to_le16(TE_V2_START_IMMEDIATELY);
return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd); return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
} }
...@@ -419,11 +419,11 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm, ...@@ -419,11 +419,11 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
{ {
struct ieee80211_key_conf *keyconf = info->control.hw_key; struct ieee80211_key_conf *keyconf = info->control.hw_key;
u8 *crypto_hdr = skb_frag->data + hdrlen; u8 *crypto_hdr = skb_frag->data + hdrlen;
enum iwl_tx_cmd_sec_ctrl type = TX_CMD_SEC_CCM;
u64 pn; u64 pn;
switch (keyconf->cipher) { switch (keyconf->cipher) {
case WLAN_CIPHER_SUITE_CCMP: case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_CCMP_256:
iwl_mvm_set_tx_cmd_ccmp(info, tx_cmd); iwl_mvm_set_tx_cmd_ccmp(info, tx_cmd);
iwl_mvm_set_tx_cmd_pn(info, crypto_hdr); iwl_mvm_set_tx_cmd_pn(info, crypto_hdr);
break; break;
...@@ -447,13 +447,16 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm, ...@@ -447,13 +447,16 @@ static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
break; break;
case WLAN_CIPHER_SUITE_GCMP: case WLAN_CIPHER_SUITE_GCMP:
case WLAN_CIPHER_SUITE_GCMP_256: case WLAN_CIPHER_SUITE_GCMP_256:
type = TX_CMD_SEC_GCMP;
/* Fall through */
case WLAN_CIPHER_SUITE_CCMP_256:
/* TODO: Taking the key from the table might introduce a race /* TODO: Taking the key from the table might introduce a race
* when PTK rekeying is done, having an old packets with a PN * when PTK rekeying is done, having an old packets with a PN
* based on the old key but the message encrypted with a new * based on the old key but the message encrypted with a new
* one. * one.
* Need to handle this. * Need to handle this.
*/ */
tx_cmd->sec_ctl |= TX_CMD_SEC_GCMP | TX_CMD_SEC_KEY_FROM_TABLE; tx_cmd->sec_ctl |= type | TX_CMD_SEC_KEY_FROM_TABLE;
tx_cmd->key[0] = keyconf->hw_key_idx; tx_cmd->key[0] = keyconf->hw_key_idx;
iwl_mvm_set_tx_cmd_pn(info, crypto_hdr); iwl_mvm_set_tx_cmd_pn(info, crypto_hdr);
break; break;
...@@ -645,7 +648,11 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb) ...@@ -645,7 +648,11 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
if (info.control.vif->type == NL80211_IFTYPE_P2P_DEVICE || if (info.control.vif->type == NL80211_IFTYPE_P2P_DEVICE ||
info.control.vif->type == NL80211_IFTYPE_AP || info.control.vif->type == NL80211_IFTYPE_AP ||
info.control.vif->type == NL80211_IFTYPE_ADHOC) { info.control.vif->type == NL80211_IFTYPE_ADHOC) {
sta_id = mvmvif->bcast_sta.sta_id; if (info.control.vif->type == NL80211_IFTYPE_P2P_DEVICE)
sta_id = mvmvif->bcast_sta.sta_id;
else
sta_id = mvmvif->mcast_sta.sta_id;
queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info, queue = iwl_mvm_get_ctrl_vif_queue(mvm, &info,
hdr->frame_control); hdr->frame_control);
if (queue < 0) if (queue < 0)
......
...@@ -147,7 +147,7 @@ static void iwl_pcie_gen2_tfd_unmap(struct iwl_trans *trans, ...@@ -147,7 +147,7 @@ static void iwl_pcie_gen2_tfd_unmap(struct iwl_trans *trans,
/* Sanity check on number of chunks */ /* Sanity check on number of chunks */
num_tbs = iwl_pcie_gen2_get_num_tbs(trans, tfd); num_tbs = iwl_pcie_gen2_get_num_tbs(trans, tfd);
if (num_tbs >= trans_pcie->max_tbs) { if (num_tbs > trans_pcie->max_tbs) {
IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); IWL_ERR(trans, "Too many chunks: %i\n", num_tbs);
return; return;
} }
......
...@@ -378,7 +378,7 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans, ...@@ -378,7 +378,7 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
/* Sanity check on number of chunks */ /* Sanity check on number of chunks */
num_tbs = iwl_pcie_tfd_get_num_tbs(trans, tfd); num_tbs = iwl_pcie_tfd_get_num_tbs(trans, tfd);
if (num_tbs >= trans_pcie->max_tbs) { if (num_tbs > trans_pcie->max_tbs) {
IWL_ERR(trans, "Too many chunks: %i\n", num_tbs); IWL_ERR(trans, "Too many chunks: %i\n", num_tbs);
/* @todo issue fatal error, it is quite serious situation */ /* @todo issue fatal error, it is quite serious situation */
return; return;
......
...@@ -1125,7 +1125,8 @@ static void _rtl8723be_enable_aspm_back_door(struct ieee80211_hw *hw) ...@@ -1125,7 +1125,8 @@ static void _rtl8723be_enable_aspm_back_door(struct ieee80211_hw *hw)
/* Configuration Space offset 0x70f BIT7 is used to control L0S */ /* Configuration Space offset 0x70f BIT7 is used to control L0S */
tmp8 = _rtl8723be_dbi_read(rtlpriv, 0x70f); tmp8 = _rtl8723be_dbi_read(rtlpriv, 0x70f);
_rtl8723be_dbi_write(rtlpriv, 0x70f, tmp8 | BIT(7)); _rtl8723be_dbi_write(rtlpriv, 0x70f, tmp8 | BIT(7) |
ASPM_L1_LATENCY << 3);
/* Configuration Space offset 0x719 Bit3 is for L1 /* Configuration Space offset 0x719 Bit3 is for L1
* BIT4 is for clock request * BIT4 is for clock request
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册