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
This commit is contained in:
Коммит
3e75e25fbe
|
@ -185,7 +185,7 @@ int ath11k_core_suspend(struct ath11k_base *ab)
|
|||
ath11k_hif_ce_irq_disable(ab);
|
||||
|
||||
ret = ath11k_hif_suspend(ab);
|
||||
if (!ret) {
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to suspend hif: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -2294,6 +2294,7 @@ static void ath11k_dp_rx_h_ppdu(struct ath11k *ar, struct hal_rx_desc *rx_desc,
|
|||
{
|
||||
u8 channel_num;
|
||||
u32 center_freq;
|
||||
struct ieee80211_channel *channel;
|
||||
|
||||
rx_status->freq = 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,
|
|||
rx_status->band = NL80211_BAND_5GHZ;
|
||||
} else {
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
rx_status->band = ar->rx_channel->band;
|
||||
channel_num =
|
||||
ieee80211_frequency_to_channel(ar->rx_channel->center_freq);
|
||||
channel = ar->rx_channel;
|
||||
if (channel) {
|
||||
rx_status->band = channel->band;
|
||||
channel_num =
|
||||
ieee80211_frequency_to_channel(channel->center_freq);
|
||||
}
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
ath11k_dbg_dump(ar->ab, ATH11K_DBG_DATA, NULL, "rx_desc: ",
|
||||
rx_desc, sizeof(struct hal_rx_desc));
|
||||
|
|
|
@ -3021,6 +3021,7 @@ static int ath11k_mac_station_add(struct ath11k *ar,
|
|||
}
|
||||
|
||||
if (ab->hw_params.vdev_start_delay &&
|
||||
!arvif->is_started &&
|
||||
arvif->vdev_type != WMI_VDEV_TYPE_AP) {
|
||||
ret = ath11k_start_vdev_delay(ar->hw, vif);
|
||||
if (ret) {
|
||||
|
@ -5284,7 +5285,8 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
|
|||
/* for QCA6390 bss peer must be created before vdev_start */
|
||||
if (ab->hw_params.vdev_start_delay &&
|
||||
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));
|
||||
ret = 0;
|
||||
goto out;
|
||||
|
@ -5295,7 +5297,9 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
|
|||
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.peer_type = WMI_PEER_TYPE_DEFAULT;
|
||||
param.peer_addr = ar->mac_addr;
|
||||
|
|
|
@ -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_VAL,
|
||||
PCIE_QSERDES_COM_SYSCLK_EN_SEL_MSK);
|
||||
if (!ret) {
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to set sysclk: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -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_VAL,
|
||||
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG_MSK);
|
||||
if (!ret) {
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to set dtct config1 error: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -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_VAL,
|
||||
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG_MSK);
|
||||
if (!ret) {
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to set dtct config2: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -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_VAL,
|
||||
PCIE_USB3_PCS_MISC_OSC_DTCT_CONFIG_MSK);
|
||||
if (!ret) {
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to set dtct config4: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
@ -886,6 +886,32 @@ static void ath11k_pci_free_region(struct ath11k_pci *ab_pci)
|
|||
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)
|
||||
{
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(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);
|
||||
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);
|
||||
if (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)
|
|||
{
|
||||
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_mhi_stop(ab_pci);
|
||||
clear_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
|
||||
|
@ -965,6 +999,8 @@ static int ath11k_pci_start(struct ath11k_base *ab)
|
|||
|
||||
set_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags);
|
||||
|
||||
ath11k_pci_aspm_restore(ab_pci);
|
||||
|
||||
ath11k_pci_ce_irqs_enable(ab);
|
||||
ath11k_ce_rx_post_buf(ab);
|
||||
|
||||
|
|
|
@ -63,6 +63,7 @@ struct ath11k_msi_config {
|
|||
enum ath11k_pci_flags {
|
||||
ATH11K_PCI_FLAG_INIT_DONE,
|
||||
ATH11K_PCI_FLAG_IS_MSI_64,
|
||||
ATH11K_PCI_ASPM_RESTORE,
|
||||
};
|
||||
|
||||
struct ath11k_pci {
|
||||
|
@ -80,6 +81,7 @@ struct ath11k_pci {
|
|||
|
||||
/* enum ath11k_pci_flags */
|
||||
unsigned long flags;
|
||||
u16 link_ctl;
|
||||
};
|
||||
|
||||
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,
|
|||
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)
|
||||
{
|
||||
struct ath11k_peer *peer;
|
||||
|
|
|
@ -43,5 +43,7 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
|
|||
struct ieee80211_sta *sta, struct peer_create_params *param);
|
||||
int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id,
|
||||
const u8 *addr);
|
||||
struct ath11k_peer *ath11k_peer_find_by_vdev_id(struct ath11k_base *ab,
|
||||
int vdev_id);
|
||||
|
||||
#endif /* _PEER_H_ */
|
||||
|
|
|
@ -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_txn txn = {};
|
||||
int ret = 0, i;
|
||||
bool delayed;
|
||||
|
||||
req = kzalloc(sizeof(*req), GFP_KERNEL);
|
||||
if (!req)
|
||||
|
@ -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
|
||||
* 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",
|
||||
ab->qmi.mem_seg_count);
|
||||
memset(req, 0, sizeof(*req));
|
||||
} else {
|
||||
delayed = false;
|
||||
req->mem_seg_len = ab->qmi.mem_seg_count;
|
||||
|
||||
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)
|
|||
}
|
||||
|
||||
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",
|
||||
resp.resp.result, resp.resp.error);
|
||||
ret = -EINVAL;
|
||||
|
@ -1742,6 +1751,8 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
|
|||
int i;
|
||||
struct target_mem_chunk *chunk;
|
||||
|
||||
ab->qmi.target_mem_delayed = false;
|
||||
|
||||
for (i = 0; i < ab->qmi.mem_seg_count; i++) {
|
||||
chunk = &ab->qmi.target_mem[i];
|
||||
chunk->vaddr = dma_alloc_coherent(ab->dev,
|
||||
|
@ -1749,6 +1760,15 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
|
|||
&chunk->paddr,
|
||||
GFP_KERNEL);
|
||||
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",
|
||||
chunk->size,
|
||||
chunk->type);
|
||||
|
@ -2517,7 +2537,7 @@ static void ath11k_qmi_msg_mem_request_cb(struct qmi_handle *qmi_hdl,
|
|||
ret);
|
||||
return;
|
||||
}
|
||||
} else if (msg->mem_seg_len > 2) {
|
||||
} else {
|
||||
ret = ath11k_qmi_alloc_target_mem_chunk(ab);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "qmi failed to alloc target memory: %d\n",
|
||||
|
|
|
@ -125,6 +125,7 @@ struct ath11k_qmi {
|
|||
struct target_mem_chunk target_mem[ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01];
|
||||
u32 mem_seg_count;
|
||||
u32 target_mem_mode;
|
||||
bool target_mem_delayed;
|
||||
u8 cal_done;
|
||||
struct target_info target;
|
||||
struct m3_mem_region m3_mem;
|
||||
|
|
|
@ -3460,6 +3460,9 @@ int ath11k_wmi_set_hw_mode(struct ath11k_base *ab,
|
|||
len = sizeof(*cmd);
|
||||
|
||||
skb = ath11k_wmi_alloc_skb(wmi_ab, len);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
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) |
|
||||
|
|
Загрузка…
Ссылка в новой задаче