Commit 3e75e25f authored by Kalle Valo's avatar Kalle Valo

Merge ath-current from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git

ath.git fixes for 5.11. Major changes:

ath11k

* add null check for skb allocation

* fix crash found during connect/disconnect stress testing

* fix for HT disabled case

* brown paperbag fixes for my bugs in suspend code

* fix an unnecessary qmi allocation during firmware bootup

* disable ASPM during firmware bootup to avoid issues
parents 4dfde294 e9603f4b
...@@ -185,7 +185,7 @@ int ath11k_core_suspend(struct ath11k_base *ab) ...@@ -185,7 +185,7 @@ int ath11k_core_suspend(struct ath11k_base *ab)
ath11k_hif_ce_irq_disable(ab); ath11k_hif_ce_irq_disable(ab);
ret = ath11k_hif_suspend(ab); ret = ath11k_hif_suspend(ab);
if (!ret) { if (ret) {
ath11k_warn(ab, "failed to suspend hif: %d\n", ret); ath11k_warn(ab, "failed to suspend hif: %d\n", ret);
return ret; return ret;
} }
......
...@@ -2294,6 +2294,7 @@ static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc, ...@@ -2294,6 +2294,7 @@ static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc,
{ {
u8 channel_num; u8 channel_num;
u32 center_freq; u32 center_freq;
struct ieee80211_channel *channel;
rx_status->freq = 0; rx_status->freq = 0;
rx_status->rate_idx = 0; rx_status->rate_idx = 0;
...@@ -2314,9 +2315,12 @@ static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc, ...@@ -2314,9 +2315,12 @@ static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc,
rx_status->band = NL80211_BAND_5GHZ; rx_status->band = NL80211_BAND_5GHZ;
} else { } else {
spin_lock_bh(&ar->data_lock); spin_lock_bh(&ar->data_lock);
rx_status->band = ar->rx_channel->band; channel = ar->rx_channel;
if (channel) {
rx_status->band = channel->band;
channel_num = channel_num =
ieee80211_frequency_to_channel(ar->rx_channel->center_freq); ieee80211_frequency_to_channel(channel->center_freq);
}
spin_unlock_bh(&ar->data_lock); spin_unlock_bh(&ar->data_lock);
ath11k_dbg_dump(ar->ab, ATH11K_DBG_DATA, NULL, "rx_desc: ", ath11k_dbg_dump(ar->ab, ATH11K_DBG_DATA, NULL, "rx_desc: ",
rx_desc, sizeof(struct hal_rx_desc)); rx_desc, sizeof(struct hal_rx_desc));
......
...@@ -3021,6 +3021,7 @@ static int ath11k_mac_station_add(struct ath11k *ar, ...@@ -3021,6 +3021,7 @@ static int ath11k_mac_station_add(struct ath11k *ar,
} }
if (ab->hw_params.vdev_start_delay && if (ab->hw_params.vdev_start_delay &&
!arvif->is_started &&
arvif->vdev_type != WMI_VDEV_TYPE_AP) { arvif->vdev_type != WMI_VDEV_TYPE_AP) {
ret = ath11k_start_vdev_delay(ar->hw, vif); ret = ath11k_start_vdev_delay(ar->hw, vif);
if (ret) { if (ret) {
...@@ -5284,7 +5285,8 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, ...@@ -5284,7 +5285,8 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
/* for QCA6390 bss peer must be created before vdev_start */ /* for QCA6390 bss peer must be created before vdev_start */
if (ab->hw_params.vdev_start_delay && if (ab->hw_params.vdev_start_delay &&
arvif->vdev_type != WMI_VDEV_TYPE_AP && arvif->vdev_type != WMI_VDEV_TYPE_AP &&
arvif->vdev_type != WMI_VDEV_TYPE_MONITOR) { arvif->vdev_type != WMI_VDEV_TYPE_MONITOR &&
!ath11k_peer_find_by_vdev_id(ab, arvif->vdev_id)) {
memcpy(&arvif->chanctx, ctx, sizeof(*ctx)); memcpy(&arvif->chanctx, ctx, sizeof(*ctx));
ret = 0; ret = 0;
goto out; goto out;
...@@ -5295,7 +5297,9 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, ...@@ -5295,7 +5297,9 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
goto out; goto out;
} }
if (ab->hw_params.vdev_start_delay) { if (ab->hw_params.vdev_start_delay &&
(arvif->vdev_type == WMI_VDEV_TYPE_AP ||
arvif->vdev_type == WMI_VDEV_TYPE_MONITOR)) {
param.vdev_id = arvif->vdev_id; param.vdev_id = arvif->vdev_id;
param.peer_type = WMI_PEER_TYPE_DEFAULT; param.peer_type = WMI_PEER_TYPE_DEFAULT;
param.peer_addr = ar->mac_addr; param.peer_addr = ar->mac_addr;
......
...@@ -274,7 +274,7 @@ static int ath11k_pci_fix_l1ss(struct ath11k_base *ab) ...@@ -274,7 +274,7 @@ static int ath11k_pci_fix_l1ss(struct ath11k_base *ab)
PCIE_QSERDES_COM_SYSCLK_EN_SEL_REG, PCIE_QSERDES_COM_SYSCLK_EN_SEL_REG,
PCIE_QSERDES_COM_SYSCLK_EN_SEL_VAL, PCIE_QSERDES_COM_SYSCLK_EN_SEL_VAL,
PCIE_QSERDES_COM_SYSCLK_EN_SEL_MSK); PCIE_QSERDES_COM_SYSCLK_EN_SEL_MSK);
if (!ret) { if (ret) {
ath11k_warn(ab, "failed to set sysclk: %d\n", ret); ath11k_warn(ab, "failed to set sysclk: %d\n", ret);
return ret; return ret;
} }
...@@ -283,7 +283,7 @@ static int ath11k_pci_fix_l1ss(struct ath11k_base *ab) ...@@ -283,7 +283,7 @@ static int ath11k_pci_fix_l1ss(struct ath11k_base *ab)
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG1_REG, PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG1_REG,
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG1_VAL, PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG1_VAL,
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG_MSK); PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG_MSK);
if (!ret) { if (ret) {
ath11k_warn(ab, "failed to set dtct config1 error: %d\n", ret); ath11k_warn(ab, "failed to set dtct config1 error: %d\n", ret);
return ret; return ret;
} }
...@@ -292,7 +292,7 @@ static int ath11k_pci_fix_l1ss(struct ath11k_base *ab) ...@@ -292,7 +292,7 @@ static int ath11k_pci_fix_l1ss(struct ath11k_base *ab)
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG2_REG, PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG2_REG,
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG2_VAL, PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG2_VAL,
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG_MSK); PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG_MSK);
if (!ret) { if (ret) {
ath11k_warn(ab, "failed to set dtct config2: %d\n", ret); ath11k_warn(ab, "failed to set dtct config2: %d\n", ret);
return ret; return ret;
} }
...@@ -301,7 +301,7 @@ static int ath11k_pci_fix_l1ss(struct ath11k_base *ab) ...@@ -301,7 +301,7 @@ static int ath11k_pci_fix_l1ss(struct ath11k_base *ab)
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG4_REG, PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG4_REG,
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG4_VAL, PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG4_VAL,
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG_MSK); PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG_MSK);
if (!ret) { if (ret) {
ath11k_warn(ab, "failed to set dtct config4: %d\n", ret); ath11k_warn(ab, "failed to set dtct config4: %d\n", ret);
return ret; return ret;
} }
...@@ -886,6 +886,32 @@ static void ath11k_pci_free_region(struct ath11k_pci *ab_pci) ...@@ -886,6 +886,32 @@ static void ath11k_pci_free_region(struct ath11k_pci *ab_pci)
pci_disable_device(pci_dev); pci_disable_device(pci_dev);
} }
static void ath11k_pci_aspm_disable(struct ath11k_pci *ab_pci)
{
struct ath11k_base *ab = ab_pci->ab;
pcie_capability_read_word(ab_pci->pdev, PCI_EXP_LNKCTL,
&ab_pci->link_ctl);
ath11k_dbg(ab, ATH11K_DBG_PCI, "pci link_ctl 0x%04x L0s %d L1 %d\n",
ab_pci->link_ctl,
u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L0S),
u16_get_bits(ab_pci->link_ctl, PCI_EXP_LNKCTL_ASPM_L1));
/* disable L0s and L1 */
pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
ab_pci->link_ctl & ~PCI_EXP_LNKCTL_ASPMC);
set_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags);
}
static void ath11k_pci_aspm_restore(struct ath11k_pci *ab_pci)
{
if (test_and_clear_bit(ATH11K_PCI_ASPM_RESTORE, &ab_pci->flags))
pcie_capability_write_word(ab_pci->pdev, PCI_EXP_LNKCTL,
ab_pci->link_ctl);
}
static int ath11k_pci_power_up(struct ath11k_base *ab) static int ath11k_pci_power_up(struct ath11k_base *ab)
{ {
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
...@@ -895,6 +921,11 @@ static int ath11k_pci_power_up(struct ath11k_base *ab) ...@@ -895,6 +921,11 @@ static int ath11k_pci_power_up(struct ath11k_base *ab)
clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags); clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
ath11k_pci_sw_reset(ab_pci->ab, true); ath11k_pci_sw_reset(ab_pci->ab, true);
/* Disable ASPM during firmware download due to problems switching
* to AMSS state.
*/
ath11k_pci_aspm_disable(ab_pci);
ret = ath11k_mhi_start(ab_pci); ret = ath11k_mhi_start(ab_pci);
if (ret) { if (ret) {
ath11k_err(ab, "failed to start mhi: %d\n", ret); ath11k_err(ab, "failed to start mhi: %d\n", ret);
...@@ -908,6 +939,9 @@ static void ath11k_pci_power_down(struct ath11k_base *ab) ...@@ -908,6 +939,9 @@ static void ath11k_pci_power_down(struct ath11k_base *ab)
{ {
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
/* restore aspm in case firmware bootup fails */
ath11k_pci_aspm_restore(ab_pci);
ath11k_pci_force_wake(ab_pci->ab); ath11k_pci_force_wake(ab_pci->ab);
ath11k_mhi_stop(ab_pci); ath11k_mhi_stop(ab_pci);
clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags); clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
...@@ -965,6 +999,8 @@ static int ath11k_pci_start(struct ath11k_base *ab) ...@@ -965,6 +999,8 @@ static int ath11k_pci_start(struct ath11k_base *ab)
set_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags); set_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
ath11k_pci_aspm_restore(ab_pci);
ath11k_pci_ce_irqs_enable(ab); ath11k_pci_ce_irqs_enable(ab);
ath11k_ce_rx_post_buf(ab); ath11k_ce_rx_post_buf(ab);
......
...@@ -63,6 +63,7 @@ struct ath11k_msi_config { ...@@ -63,6 +63,7 @@ struct ath11k_msi_config {
enum ath11k_pci_flags { enum ath11k_pci_flags {
ATH11K_PCI_FLAG_INIT_DONE, ATH11K_PCI_FLAG_INIT_DONE,
ATH11K_PCI_FLAG_IS_MSI_64, ATH11K_PCI_FLAG_IS_MSI_64,
ATH11K_PCI_ASPM_RESTORE,
}; };
struct ath11k_pci { struct ath11k_pci {
...@@ -80,6 +81,7 @@ struct ath11k_pci { ...@@ -80,6 +81,7 @@ struct ath11k_pci {
/* enum ath11k_pci_flags */ /* enum ath11k_pci_flags */
unsigned long flags; unsigned long flags;
u16 link_ctl;
}; };
static inline struct ath11k_pci *ath11k_pci_priv(struct ath11k_base *ab) static inline struct ath11k_pci *ath11k_pci_priv(struct ath11k_base *ab)
......
...@@ -76,6 +76,23 @@ struct ath11k_peer *ath11k_peer_find_by_id(struct ath11k_base *ab, ...@@ -76,6 +76,23 @@ struct ath11k_peer *ath11k_peer_find_by_id(struct ath11k_base *ab,
return NULL; return NULL;
} }
struct ath11k_peer *ath11k_peer_find_by_vdev_id(struct ath11k_base *ab,
int vdev_id)
{
struct ath11k_peer *peer;
spin_lock_bh(&ab->base_lock);
list_for_each_entry(peer, &ab->peers, list) {
if (vdev_id == peer->vdev_id) {
spin_unlock_bh(&ab->base_lock);
return peer;
}
}
spin_unlock_bh(&ab->base_lock);
return NULL;
}
void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id) void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id)
{ {
struct ath11k_peer *peer; struct ath11k_peer *peer;
......
...@@ -43,5 +43,7 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, ...@@ -43,5 +43,7 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
struct ieee80211_sta *sta, struct peer_create_params *param); struct ieee80211_sta *sta, struct peer_create_params *param);
int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id, int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id,
const u8 *addr); const u8 *addr);
struct ath11k_peer *ath11k_peer_find_by_vdev_id(struct ath11k_base *ab,
int vdev_id);
#endif /* _PEER_H_ */ #endif /* _PEER_H_ */
...@@ -1660,6 +1660,7 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab) ...@@ -1660,6 +1660,7 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
struct qmi_wlanfw_respond_mem_resp_msg_v01 resp; struct qmi_wlanfw_respond_mem_resp_msg_v01 resp;
struct qmi_txn txn = {}; struct qmi_txn txn = {};
int ret = 0, i; int ret = 0, i;
bool delayed;
req = kzalloc(sizeof(*req), GFP_KERNEL); req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req) if (!req)
...@@ -1672,11 +1673,13 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab) ...@@ -1672,11 +1673,13 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
* failure to FW and FW will then request mulitple blocks of small * failure to FW and FW will then request mulitple blocks of small
* chunk size memory. * chunk size memory.
*/ */
if (!ab->bus_params.fixed_mem_region && ab->qmi.mem_seg_count <= 2) { if (!ab->bus_params.fixed_mem_region && ab->qmi.target_mem_delayed) {
delayed = true;
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi delays mem_request %d\n", ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi delays mem_request %d\n",
ab->qmi.mem_seg_count); ab->qmi.mem_seg_count);
memset(req, 0, sizeof(*req)); memset(req, 0, sizeof(*req));
} else { } else {
delayed = false;
req->mem_seg_len = ab->qmi.mem_seg_count; req->mem_seg_len = ab->qmi.mem_seg_count;
for (i = 0; i < req->mem_seg_len ; i++) { for (i = 0; i < req->mem_seg_len ; i++) {
...@@ -1708,6 +1711,12 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab) ...@@ -1708,6 +1711,12 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
} }
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) { if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
/* the error response is expected when
* target_mem_delayed is true.
*/
if (delayed && resp.resp.error == 0)
goto out;
ath11k_warn(ab, "Respond mem req failed, result: %d, err: %d\n", ath11k_warn(ab, "Respond mem req failed, result: %d, err: %d\n",
resp.resp.result, resp.resp.error); resp.resp.result, resp.resp.error);
ret = -EINVAL; ret = -EINVAL;
...@@ -1742,6 +1751,8 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab) ...@@ -1742,6 +1751,8 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
int i; int i;
struct target_mem_chunk *chunk; struct target_mem_chunk *chunk;
ab->qmi.target_mem_delayed = false;
for (i = 0; i < ab->qmi.mem_seg_count; i++) { for (i = 0; i < ab->qmi.mem_seg_count; i++) {
chunk = &ab->qmi.target_mem[i]; chunk = &ab->qmi.target_mem[i];
chunk->vaddr = dma_alloc_coherent(ab->dev, chunk->vaddr = dma_alloc_coherent(ab->dev,
...@@ -1749,6 +1760,15 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab) ...@@ -1749,6 +1760,15 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
&chunk->paddr, &chunk->paddr,
GFP_KERNEL); GFP_KERNEL);
if (!chunk->vaddr) { if (!chunk->vaddr) {
if (ab->qmi.mem_seg_count <= 2) {
ath11k_dbg(ab, ATH11K_DBG_QMI,
"qmi dma allocation failed (%d B type %u), will try later with small size\n",
chunk->size,
chunk->type);
ath11k_qmi_free_target_mem_chunk(ab);
ab->qmi.target_mem_delayed = true;
return 0;
}
ath11k_err(ab, "failed to alloc memory, size: 0x%x, type: %u\n", ath11k_err(ab, "failed to alloc memory, size: 0x%x, type: %u\n",
chunk->size, chunk->size,
chunk->type); chunk->type);
...@@ -2517,7 +2537,7 @@ static void ath11k_qmi_msg_mem_request_cb(struct qmi_handle *qmi_hdl, ...@@ -2517,7 +2537,7 @@ static void ath11k_qmi_msg_mem_request_cb(struct qmi_handle *qmi_hdl,
ret); ret);
return; return;
} }
} else if (msg->mem_seg_len > 2) { } else {
ret = ath11k_qmi_alloc_target_mem_chunk(ab); ret = ath11k_qmi_alloc_target_mem_chunk(ab);
if (ret) { if (ret) {
ath11k_warn(ab, "qmi failed to alloc target memory: %d\n", ath11k_warn(ab, "qmi failed to alloc target memory: %d\n",
......
...@@ -125,6 +125,7 @@ struct ath11k_qmi { ...@@ -125,6 +125,7 @@ struct ath11k_qmi {
struct target_mem_chunk target_mem[ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01]; struct target_mem_chunk target_mem[ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01];
u32 mem_seg_count; u32 mem_seg_count;
u32 target_mem_mode; u32 target_mem_mode;
bool target_mem_delayed;
u8 cal_done; u8 cal_done;
struct target_info target; struct target_info target;
struct m3_mem_region m3_mem; struct m3_mem_region m3_mem;
......
...@@ -3460,6 +3460,9 @@ int ath11k_wmi_set_hw_mode(struct ath11k_base *ab, ...@@ -3460,6 +3460,9 @@ int ath11k_wmi_set_hw_mode(struct ath11k_base *ab,
len = sizeof(*cmd); len = sizeof(*cmd);
skb = ath11k_wmi_alloc_skb(wmi_ab, len); skb = ath11k_wmi_alloc_skb(wmi_ab, len);
if (!skb)
return -ENOMEM;
cmd = (struct wmi_pdev_set_hw_mode_cmd_param *)skb->data; cmd = (struct wmi_pdev_set_hw_mode_cmd_param *)skb->data;
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_PDEV_SET_HW_MODE_CMD) | cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_PDEV_SET_HW_MODE_CMD) |
......
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