提交 eb77802e 编写于 作者: K Kalle Valo

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

ath.git patches for v5.10. Major changes:

ath11k

* add support for QCA6390 PCI devices

wcn36xx

* add support for TX ack

ath9k

* add support for NL80211_EXT_FEATURE_CAN_REPLACE_PTK0 to improve PTK0
  rekeying
...@@ -12,17 +12,9 @@ ...@@ -12,17 +12,9 @@
void ath10k_bmi_start(struct ath10k *ar) void ath10k_bmi_start(struct ath10k *ar)
{ {
int ret;
ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi start\n"); ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi start\n");
ar->bmi.done_sent = false; ar->bmi.done_sent = false;
/* Enable hardware clock to speed up firmware download */
if (ar->hw_params.hw_ops->enable_pll_clk) {
ret = ar->hw_params.hw_ops->enable_pll_clk(ar);
ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi enable pll ret %d\n", ret);
}
} }
int ath10k_bmi_done(struct ath10k *ar) int ath10k_bmi_done(struct ath10k *ar)
......
...@@ -481,6 +481,15 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar, ...@@ -481,6 +481,15 @@ static inline void ath10k_ce_engine_int_status_clear(struct ath10k *ar,
ath10k_ce_write32(ar, ce_ctrl_addr + wm_regs->addr, mask); ath10k_ce_write32(ar, ce_ctrl_addr + wm_regs->addr, mask);
} }
static inline bool ath10k_ce_engine_int_status_check(struct ath10k *ar,
u32 ce_ctrl_addr,
unsigned int mask)
{
struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
return ath10k_ce_read32(ar, ce_ctrl_addr + wm_regs->addr) & mask;
}
/* /*
* Guts of ath10k_ce_send. * Guts of ath10k_ce_send.
* The caller takes responsibility for any needed locking. * The caller takes responsibility for any needed locking.
...@@ -1301,19 +1310,22 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) ...@@ -1301,19 +1310,22 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
spin_lock_bh(&ce->ce_lock); spin_lock_bh(&ce->ce_lock);
/* Clear the copy-complete interrupts that will be handled here. */ if (ath10k_ce_engine_int_status_check(ar, ctrl_addr,
ath10k_ce_engine_int_status_clear(ar, ctrl_addr, wm_regs->cc_mask)) {
wm_regs->cc_mask); /* Clear before handling */
ath10k_ce_engine_int_status_clear(ar, ctrl_addr,
wm_regs->cc_mask);
spin_unlock_bh(&ce->ce_lock); spin_unlock_bh(&ce->ce_lock);
if (ce_state->recv_cb) if (ce_state->recv_cb)
ce_state->recv_cb(ce_state); ce_state->recv_cb(ce_state);
if (ce_state->send_cb) if (ce_state->send_cb)
ce_state->send_cb(ce_state); ce_state->send_cb(ce_state);
spin_lock_bh(&ce->ce_lock); spin_lock_bh(&ce->ce_lock);
}
/* /*
* Misc CE interrupts are not being handled, but still need * Misc CE interrupts are not being handled, but still need
...@@ -1555,7 +1567,7 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id, ...@@ -1555,7 +1567,7 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id,
ret = ath10k_ce_alloc_shadow_base(ar, src_ring, nentries); ret = ath10k_ce_alloc_shadow_base(ar, src_ring, nentries);
if (ret) { if (ret) {
dma_free_coherent(ar->dev, dma_free_coherent(ar->dev,
(nentries * sizeof(struct ce_desc_64) + (nentries * sizeof(struct ce_desc) +
CE_DESC_RING_ALIGN), CE_DESC_RING_ALIGN),
src_ring->base_addr_owner_space_unaligned, src_ring->base_addr_owner_space_unaligned,
base_addr); base_addr);
......
...@@ -334,6 +334,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { ...@@ -334,6 +334,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_filter_reset_required = true, .hw_filter_reset_required = true,
.fw_diag_ce_download = true, .fw_diag_ce_download = true,
.tx_stats_over_pktlog = false, .tx_stats_over_pktlog = false,
.supports_peer_stats_info = true,
}, },
{ {
.id = QCA99X0_HW_2_0_DEV_VERSION, .id = QCA99X0_HW_2_0_DEV_VERSION,
...@@ -2320,7 +2321,7 @@ static void ath10k_core_restart(struct work_struct *work) ...@@ -2320,7 +2321,7 @@ static void ath10k_core_restart(struct work_struct *work)
break; break;
case ATH10K_STATE_RESTARTED: case ATH10K_STATE_RESTARTED:
ar->state = ATH10K_STATE_WEDGED; ar->state = ATH10K_STATE_WEDGED;
/* fall through */ fallthrough;
case ATH10K_STATE_WEDGED: case ATH10K_STATE_WEDGED:
ath10k_warn(ar, "device is wedged, will not restart\n"); ath10k_warn(ar, "device is wedged, will not restart\n");
break; break;
...@@ -2614,6 +2615,13 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, ...@@ -2614,6 +2615,13 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
ar->running_fw->fw_file.fw_features)) { ar->running_fw->fw_file.fw_features)) {
ath10k_bmi_start(ar); ath10k_bmi_start(ar);
/* Enable hardware clock to speed up firmware download */
if (ar->hw_params.hw_ops->enable_pll_clk) {
status = ar->hw_params.hw_ops->enable_pll_clk(ar);
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot enable pll ret %d\n",
status);
}
if (ath10k_init_configure_target(ar)) { if (ath10k_init_configure_target(ar)) {
status = -EINVAL; status = -EINVAL;
goto err; goto err;
......
...@@ -142,6 +142,14 @@ static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num) ...@@ -142,6 +142,14 @@ static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num)
BUILD_BUG_ON(HTT_RX_RING_FILL_LEVEL >= HTT_RX_RING_SIZE / 2); BUILD_BUG_ON(HTT_RX_RING_FILL_LEVEL >= HTT_RX_RING_SIZE / 2);
idx = __le32_to_cpu(*htt->rx_ring.alloc_idx.vaddr); idx = __le32_to_cpu(*htt->rx_ring.alloc_idx.vaddr);
if (idx < 0 || idx >= htt->rx_ring.size) {
ath10k_err(htt->ar, "rx ring index is not valid, firmware malfunctioning?\n");
idx &= htt->rx_ring.size_mask;
ret = -ENOMEM;
goto fail;
}
while (num > 0) { while (num > 0) {
skb = dev_alloc_skb(HTT_RX_BUF_SIZE + HTT_RX_DESC_ALIGN); skb = dev_alloc_skb(HTT_RX_BUF_SIZE + HTT_RX_DESC_ALIGN);
if (!skb) { if (!skb) {
...@@ -941,6 +949,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, ...@@ -941,6 +949,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
u8 preamble = 0; u8 preamble = 0;
u8 group_id; u8 group_id;
u32 info1, info2, info3; u32 info1, info2, info3;
u32 stbc, nsts_su;
info1 = __le32_to_cpu(rxd->ppdu_start.info1); info1 = __le32_to_cpu(rxd->ppdu_start.info1);
info2 = __le32_to_cpu(rxd->ppdu_start.info2); info2 = __le32_to_cpu(rxd->ppdu_start.info2);
...@@ -985,11 +994,16 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, ...@@ -985,11 +994,16 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
*/ */
bw = info2 & 3; bw = info2 & 3;
sgi = info3 & 1; sgi = info3 & 1;
stbc = (info2 >> 3) & 1;
group_id = (info2 >> 4) & 0x3F; group_id = (info2 >> 4) & 0x3F;
if (GROUP_ID_IS_SU_MIMO(group_id)) { if (GROUP_ID_IS_SU_MIMO(group_id)) {
mcs = (info3 >> 4) & 0x0F; mcs = (info3 >> 4) & 0x0F;
nss = ((info2 >> 10) & 0x07) + 1; nsts_su = ((info2 >> 10) & 0x07);
if (stbc)
nss = (nsts_su >> 2) + 1;
else
nss = (nsts_su + 1);
} else { } else {
/* Hardware doesn't decode VHT-SIG-B into Rx descriptor /* Hardware doesn't decode VHT-SIG-B into Rx descriptor
* so it's impossible to decode MCS. Also since * so it's impossible to decode MCS. Also since
...@@ -3017,7 +3031,7 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) ...@@ -3017,7 +3031,7 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
ath10k_htt_rx_h_enqueue(ar, &amsdu, status); ath10k_htt_rx_h_enqueue(ar, &amsdu, status);
break; break;
case -EAGAIN: case -EAGAIN:
/* fall through */ fallthrough;
default: default:
/* Should not happen. */ /* Should not happen. */
ath10k_warn(ar, "failed to extract amsdu: %d\n", ret); ath10k_warn(ar, "failed to extract amsdu: %d\n", ret);
...@@ -3575,12 +3589,14 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar, ...@@ -3575,12 +3589,14 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
} }
if (ar->htt.disable_tx_comp) { if (ar->htt.disable_tx_comp) {
arsta->tx_retries += peer_stats->retry_pkts;
arsta->tx_failed += peer_stats->failed_pkts; arsta->tx_failed += peer_stats->failed_pkts;
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx retries %d tx failed %d\n", ath10k_dbg(ar, ATH10K_DBG_HTT, "tx failed %d\n",
arsta->tx_retries, arsta->tx_failed); arsta->tx_failed);
} }
arsta->tx_retries += peer_stats->retry_pkts;
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx retries %d", arsta->tx_retries);
if (ath10k_debug_is_extd_tx_stats_enabled(ar)) if (ath10k_debug_is_extd_tx_stats_enabled(ar))
ath10k_accumulate_per_peer_tx_stats(ar, arsta, peer_stats, ath10k_accumulate_per_peer_tx_stats(ar, arsta, peer_stats,
rate_idx); rate_idx);
......
...@@ -1314,7 +1314,7 @@ static int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txm ...@@ -1314,7 +1314,7 @@ static int ath10k_htt_tx_hl(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txm
case ATH10K_HW_TXRX_RAW: case ATH10K_HW_TXRX_RAW:
case ATH10K_HW_TXRX_NATIVE_WIFI: case ATH10K_HW_TXRX_NATIVE_WIFI:
flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT; flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
/* fall through */ fallthrough;
case ATH10K_HW_TXRX_ETHERNET: case ATH10K_HW_TXRX_ETHERNET:
flags0 |= SM(txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE); flags0 |= SM(txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
break; break;
...@@ -1460,7 +1460,7 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt, ...@@ -1460,7 +1460,7 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt,
case ATH10K_HW_TXRX_RAW: case ATH10K_HW_TXRX_RAW:
case ATH10K_HW_TXRX_NATIVE_WIFI: case ATH10K_HW_TXRX_NATIVE_WIFI:
flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT; flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
/* fall through */ fallthrough;
case ATH10K_HW_TXRX_ETHERNET: case ATH10K_HW_TXRX_ETHERNET:
if (ar->hw_params.continuous_frag_desc) { if (ar->hw_params.continuous_frag_desc) {
ext_desc_t = htt->frag_desc.vaddr_desc_32; ext_desc_t = htt->frag_desc.vaddr_desc_32;
...@@ -1662,7 +1662,7 @@ static int ath10k_htt_tx_64(struct ath10k_htt *htt, ...@@ -1662,7 +1662,7 @@ static int ath10k_htt_tx_64(struct ath10k_htt *htt,
case ATH10K_HW_TXRX_RAW: case ATH10K_HW_TXRX_RAW:
case ATH10K_HW_TXRX_NATIVE_WIFI: case ATH10K_HW_TXRX_NATIVE_WIFI:
flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT; flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
/* fall through */ fallthrough;
case ATH10K_HW_TXRX_ETHERNET: case ATH10K_HW_TXRX_ETHERNET:
if (ar->hw_params.continuous_frag_desc) { if (ar->hw_params.continuous_frag_desc) {
ext_desc_t = htt->frag_desc.vaddr_desc_64; ext_desc_t = htt->frag_desc.vaddr_desc_64;
......
...@@ -2468,17 +2468,17 @@ ath10k_peer_assoc_h_vht_limit(u16 tx_mcs_set, ...@@ -2468,17 +2468,17 @@ ath10k_peer_assoc_h_vht_limit(u16 tx_mcs_set,
idx_limit = -1; idx_limit = -1;
switch (idx_limit) { switch (idx_limit) {
case 0: /* fall through */ case 0:
case 1: /* fall through */ case 1:
case 2: /* fall through */ case 2:
case 3: /* fall through */ case 3:
case 4: /* fall through */ case 4:
case 5: /* fall through */ case 5:
case 6: /* fall through */ case 6:
default: default:
/* see ath10k_mac_can_set_bitrate_mask() */ /* see ath10k_mac_can_set_bitrate_mask() */
WARN_ON(1); WARN_ON(1);
/* fall through */ fallthrough;
case -1: case -1:
mcs = IEEE80211_VHT_MCS_NOT_SUPPORTED; mcs = IEEE80211_VHT_MCS_NOT_SUPPORTED;
break; break;
...@@ -4238,7 +4238,7 @@ void __ath10k_scan_finish(struct ath10k *ar) ...@@ -4238,7 +4238,7 @@ void __ath10k_scan_finish(struct ath10k *ar)
} else if (ar->scan.roc_notify) { } else if (ar->scan.roc_notify) {
ieee80211_remain_on_channel_expired(ar->hw); ieee80211_remain_on_channel_expired(ar->hw);
} }
/* fall through */ fallthrough;
case ATH10K_SCAN_STARTING: case ATH10K_SCAN_STARTING:
ar->scan.state = ATH10K_SCAN_IDLE; ar->scan.state = ATH10K_SCAN_IDLE;
ar->scan_channel = NULL; ar->scan_channel = NULL;
...@@ -7278,7 +7278,7 @@ ath10k_mac_update_bss_chan_survey(struct ath10k *ar, ...@@ -7278,7 +7278,7 @@ ath10k_mac_update_bss_chan_survey(struct ath10k *ar,
struct ieee80211_channel *channel) struct ieee80211_channel *channel)
{ {
int ret; int ret;
enum wmi_bss_survey_req_type type = WMI_BSS_SURVEY_REQ_TYPE_READ_CLEAR; enum wmi_bss_survey_req_type type = WMI_BSS_SURVEY_REQ_TYPE_READ;
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
...@@ -8363,19 +8363,32 @@ static void ath10k_mac_get_rate_flags_ht(struct ath10k *ar, u32 rate, u8 nss, u8 ...@@ -8363,19 +8363,32 @@ static void ath10k_mac_get_rate_flags_ht(struct ath10k *ar, u32 rate, u8 nss, u8
u8 *flags, u8 *bw) u8 *flags, u8 *bw)
{ {
struct ath10k_index_ht_data_rate_type *mcs_rate; struct ath10k_index_ht_data_rate_type *mcs_rate;
u8 index;
size_t len_nss1 = ARRAY_SIZE(supported_ht_mcs_rate_nss1);
size_t len_nss2 = ARRAY_SIZE(supported_ht_mcs_rate_nss2);
if (mcs >= (len_nss1 + len_nss2)) {
ath10k_warn(ar, "not supported mcs %d in current rate table", mcs);
return;
}
mcs_rate = (struct ath10k_index_ht_data_rate_type *) mcs_rate = (struct ath10k_index_ht_data_rate_type *)
((nss == 1) ? &supported_ht_mcs_rate_nss1 : ((nss == 1) ? &supported_ht_mcs_rate_nss1 :
&supported_ht_mcs_rate_nss2); &supported_ht_mcs_rate_nss2);
if (rate == mcs_rate[mcs].supported_rate[0]) { if (mcs >= len_nss1)
index = mcs - len_nss1;
else
index = mcs;
if (rate == mcs_rate[index].supported_rate[0]) {
*bw = RATE_INFO_BW_20; *bw = RATE_INFO_BW_20;
} else if (rate == mcs_rate[mcs].supported_rate[1]) { } else if (rate == mcs_rate[index].supported_rate[1]) {
*bw |= RATE_INFO_BW_40; *bw |= RATE_INFO_BW_40;
} else if (rate == mcs_rate[mcs].supported_rate[2]) { } else if (rate == mcs_rate[index].supported_rate[2]) {
*bw |= RATE_INFO_BW_20; *bw |= RATE_INFO_BW_20;
*flags |= RATE_INFO_FLAGS_SHORT_GI; *flags |= RATE_INFO_FLAGS_SHORT_GI;
} else if (rate == mcs_rate[mcs].supported_rate[3]) { } else if (rate == mcs_rate[index].supported_rate[3]) {
*bw |= RATE_INFO_BW_40; *bw |= RATE_INFO_BW_40;
*flags |= RATE_INFO_FLAGS_SHORT_GI; *flags |= RATE_INFO_FLAGS_SHORT_GI;
} else { } else {
...@@ -8436,6 +8449,9 @@ static void ath10k_mac_parse_bitrate(struct ath10k *ar, u32 rate_code, ...@@ -8436,6 +8449,9 @@ static void ath10k_mac_parse_bitrate(struct ath10k *ar, u32 rate_code,
u8 mcs = WMI_TLV_GET_HW_RC_RATE_V1(rate_code); u8 mcs = WMI_TLV_GET_HW_RC_RATE_V1(rate_code);
u8 flags = 0, bw = 0; u8 flags = 0, bw = 0;
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac parse rate code 0x%x bitrate %d kbps\n",
rate_code, bitrate_kbps);
if (preamble == WMI_RATE_PREAMBLE_HT) if (preamble == WMI_RATE_PREAMBLE_HT)
mode = ATH10K_PHY_MODE_HT; mode = ATH10K_PHY_MODE_HT;
else if (preamble == WMI_RATE_PREAMBLE_VHT) else if (preamble == WMI_RATE_PREAMBLE_VHT)
...@@ -8528,26 +8544,26 @@ static void ath10k_sta_statistics(struct ieee80211_hw *hw, ...@@ -8528,26 +8544,26 @@ static void ath10k_sta_statistics(struct ieee80211_hw *hw,
sinfo->rx_duration = arsta->rx_duration; sinfo->rx_duration = arsta->rx_duration;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION); sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
if (!arsta->txrate.legacy && !arsta->txrate.nss) if (arsta->txrate.legacy || arsta->txrate.nss) {
return; if (arsta->txrate.legacy) {
sinfo->txrate.legacy = arsta->txrate.legacy;
if (arsta->txrate.legacy) { } else {
sinfo->txrate.legacy = arsta->txrate.legacy; sinfo->txrate.mcs = arsta->txrate.mcs;
} else { sinfo->txrate.nss = arsta->txrate.nss;
sinfo->txrate.mcs = arsta->txrate.mcs; sinfo->txrate.bw = arsta->txrate.bw;
sinfo->txrate.nss = arsta->txrate.nss; }
sinfo->txrate.bw = arsta->txrate.bw; sinfo->txrate.flags = arsta->txrate.flags;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
} }
sinfo->txrate.flags = arsta->txrate.flags;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
if (ar->htt.disable_tx_comp) { if (ar->htt.disable_tx_comp) {
sinfo->tx_retries = arsta->tx_retries;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
sinfo->tx_failed = arsta->tx_failed; sinfo->tx_failed = arsta->tx_failed;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED); sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
} }
sinfo->tx_retries = arsta->tx_retries;
sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
ath10k_mac_sta_get_peer_stats_info(ar, sta, sinfo); ath10k_mac_sta_get_peer_stats_info(ar, sta, sinfo);
} }
......
...@@ -2184,7 +2184,7 @@ int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, ...@@ -2184,7 +2184,7 @@ int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
if (ret == 0 && resp_len) { if (ret == 0 && resp_len) {
*resp_len = min(*resp_len, xfer.resp_len); *resp_len = min(*resp_len, xfer.resp_len);
memcpy(resp, tresp, xfer.resp_len); memcpy(resp, tresp, *resp_len);
} }
err_dma: err_dma:
kfree(treq); kfree(treq);
......
...@@ -557,6 +557,10 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar, ...@@ -557,6 +557,10 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar,
le16_to_cpu(htc_hdr->len), le16_to_cpu(htc_hdr->len),
ATH10K_HTC_MBOX_MAX_PAYLOAD_LENGTH); ATH10K_HTC_MBOX_MAX_PAYLOAD_LENGTH);
ret = -ENOMEM; ret = -ENOMEM;
queue_work(ar->workqueue, &ar->restart_work);
ath10k_warn(ar, "exceeds length, start recovery\n");
goto err; goto err;
} }
......
...@@ -1772,9 +1772,18 @@ static int ath10k_snoc_remove(struct platform_device *pdev) ...@@ -1772,9 +1772,18 @@ static int ath10k_snoc_remove(struct platform_device *pdev)
return 0; return 0;
} }
static void ath10k_snoc_shutdown(struct platform_device *pdev)
{
struct ath10k *ar = platform_get_drvdata(pdev);
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc shutdown\n");
ath10k_snoc_remove(pdev);
}
static struct platform_driver ath10k_snoc_driver = { static struct platform_driver ath10k_snoc_driver = {
.probe = ath10k_snoc_probe, .probe = ath10k_snoc_probe,
.remove = ath10k_snoc_remove, .remove = ath10k_snoc_remove,
.shutdown = ath10k_snoc_shutdown,
.driver = { .driver = {
.name = "ath10k_snoc", .name = "ath10k_snoc",
.of_match_table = ath10k_snoc_dt_match, .of_match_table = ath10k_snoc_dt_match,
......
...@@ -1614,6 +1614,8 @@ wmi_tlv_svc_map(const __le32 *in, unsigned long *out, size_t len) ...@@ -1614,6 +1614,8 @@ wmi_tlv_svc_map(const __le32 *in, unsigned long *out, size_t len)
WMI_SERVICE_MESH_11S, len); WMI_SERVICE_MESH_11S, len);
SVCMAP(WMI_TLV_SERVICE_SYNC_DELETE_CMDS, SVCMAP(WMI_TLV_SERVICE_SYNC_DELETE_CMDS,
WMI_SERVICE_SYNC_DELETE_CMDS, len); WMI_SERVICE_SYNC_DELETE_CMDS, len);
SVCMAP(WMI_TLV_SERVICE_PEER_STATS_INFO,
WMI_SERVICE_PEER_STATS, len);
} }
static inline void static inline void
......
...@@ -275,7 +275,7 @@ static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif, ...@@ -275,7 +275,7 @@ static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif,
switch (arvif->vdev_type) { switch (arvif->vdev_type) {
case WMI_VDEV_TYPE_IBSS: case WMI_VDEV_TYPE_IBSS:
__set_bit(WOW_BEACON_EVENT, &wow_mask); __set_bit(WOW_BEACON_EVENT, &wow_mask);
/* fall through */ fallthrough;
case WMI_VDEV_TYPE_AP: case WMI_VDEV_TYPE_AP:
__set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask); __set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask);
__set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask); __set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask);
......
...@@ -2,9 +2,7 @@ ...@@ -2,9 +2,7 @@
config ATH11K config ATH11K
tristate "Qualcomm Technologies 802.11ax chipset support" tristate "Qualcomm Technologies 802.11ax chipset support"
depends on MAC80211 && HAS_DMA depends on MAC80211 && HAS_DMA
depends on REMOTEPROC
depends on CRYPTO_MICHAEL_MIC depends on CRYPTO_MICHAEL_MIC
depends on ARCH_QCOM || COMPILE_TEST
select ATH_COMMON select ATH_COMMON
select QCOM_QMI_HELPERS select QCOM_QMI_HELPERS
help help
...@@ -13,6 +11,22 @@ config ATH11K ...@@ -13,6 +11,22 @@ config ATH11K
If you choose to build a module, it'll be called ath11k. If you choose to build a module, it'll be called ath11k.
config ATH11K_AHB
tristate "Atheros ath11k AHB support"
depends on ATH11K
depends on REMOTEPROC
help
This module adds support for AHB bus
config ATH11K_PCI
tristate "Atheros ath11k PCI support"
depends on ATH11K && PCI
select MHI_BUS
select QRTR
select QRTR_MHI
help
This module adds support for PCIE bus
config ATH11K_DEBUG config ATH11K_DEBUG
bool "QCA ath11k debugging" bool "QCA ath11k debugging"
depends on ATH11K depends on ATH11K
......
...@@ -4,7 +4,6 @@ ath11k-y += core.o \ ...@@ -4,7 +4,6 @@ ath11k-y += core.o \
hal.o \ hal.o \
hal_tx.o \ hal_tx.o \
hal_rx.o \ hal_rx.o \
ahb.o \
wmi.o \ wmi.o \
mac.o \ mac.o \
reg.o \ reg.o \
...@@ -16,7 +15,8 @@ ath11k-y += core.o \ ...@@ -16,7 +15,8 @@ ath11k-y += core.o \
debug.o \ debug.o \
ce.o \ ce.o \
peer.o \ peer.o \
dbring.o dbring.o \
hw.o
ath11k-$(CONFIG_ATH11K_DEBUGFS) += debug_htt_stats.o debugfs_sta.o ath11k-$(CONFIG_ATH11K_DEBUGFS) += debug_htt_stats.o debugfs_sta.o
ath11k-$(CONFIG_NL80211_TESTMODE) += testmode.o ath11k-$(CONFIG_NL80211_TESTMODE) += testmode.o
...@@ -24,5 +24,11 @@ ath11k-$(CONFIG_ATH11K_TRACING) += trace.o ...@@ -24,5 +24,11 @@ ath11k-$(CONFIG_ATH11K_TRACING) += trace.o
ath11k-$(CONFIG_THERMAL) += thermal.o ath11k-$(CONFIG_THERMAL) += thermal.o
ath11k-$(CONFIG_ATH11K_SPECTRAL) += spectral.o ath11k-$(CONFIG_ATH11K_SPECTRAL) += spectral.o
obj-$(CONFIG_ATH11K_AHB) += ath11k_ahb.o
ath11k_ahb-y += ahb.o
obj-$(CONFIG_ATH11K_PCI) += ath11k_pci.o
ath11k_pci-y += mhi.o pci.o
# for tracing framework to find trace.h # for tracing framework to find trace.h
CFLAGS_trace.o := -I$(src) CFLAGS_trace.o := -I$(src)
...@@ -25,6 +25,13 @@ static const struct of_device_id ath11k_ahb_of_match[] = { ...@@ -25,6 +25,13 @@ static const struct of_device_id ath11k_ahb_of_match[] = {
MODULE_DEVICE_TABLE(of, ath11k_ahb_of_match); MODULE_DEVICE_TABLE(of, ath11k_ahb_of_match);
static const struct ath11k_bus_params ath11k_ahb_bus_params = {
.mhi_support = false,
.m3_fw_support = false,
.fixed_bdf_addr = true,
.fixed_mem_region = true,
};
/* Target firmware's Copy Engine configuration. */ /* Target firmware's Copy Engine configuration. */
static const struct ce_pipe_config target_ce_config_wlan[] = { static const struct ce_pipe_config target_ce_config_wlan[] = {
/* CE0: host->target HTC control and raw streams */ /* CE0: host->target HTC control and raw streams */
...@@ -321,78 +328,6 @@ static const char *irq_name[ATH11K_IRQ_NUM_MAX] = { ...@@ -321,78 +328,6 @@ static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
"tcl2host-status-ring", "tcl2host-status-ring",
}; };
#define ATH11K_TX_RING_MASK_0 0x1
#define ATH11K_TX_RING_MASK_1 0x2
#define ATH11K_TX_RING_MASK_2 0x4
#define ATH11K_RX_RING_MASK_0 0x1
#define ATH11K_RX_RING_MASK_1 0x2
#define ATH11K_RX_RING_MASK_2 0x4
#define ATH11K_RX_RING_MASK_3 0x8
#define ATH11K_RX_ERR_RING_MASK_0 0x1
#define ATH11K_RX_WBM_REL_RING_MASK_0 0x1
#define ATH11K_REO_STATUS_RING_MASK_0 0x1
#define ATH11K_RXDMA2HOST_RING_MASK_0 0x1
#define ATH11K_RXDMA2HOST_RING_MASK_1 0x2
#define ATH11K_RXDMA2HOST_RING_MASK_2 0x4
#define ATH11K_HOST2RXDMA_RING_MASK_0 0x1
#define ATH11K_HOST2RXDMA_RING_MASK_1 0x2
#define ATH11K_HOST2RXDMA_RING_MASK_2 0x4
#define ATH11K_RX_MON_STATUS_RING_MASK_0 0x1
#define ATH11K_RX_MON_STATUS_RING_MASK_1 0x2
#define ATH11K_RX_MON_STATUS_RING_MASK_2 0x4
const u8 ath11k_tx_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
ATH11K_TX_RING_MASK_0,
ATH11K_TX_RING_MASK_1,
ATH11K_TX_RING_MASK_2,
};
const u8 rx_mon_status_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
0, 0, 0, 0,
ATH11K_RX_MON_STATUS_RING_MASK_0,
ATH11K_RX_MON_STATUS_RING_MASK_1,
ATH11K_RX_MON_STATUS_RING_MASK_2,
};
const u8 ath11k_rx_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
0, 0, 0, 0, 0, 0, 0,
ATH11K_RX_RING_MASK_0,
ATH11K_RX_RING_MASK_1,
ATH11K_RX_RING_MASK_2,
ATH11K_RX_RING_MASK_3,
};
const u8 ath11k_rx_err_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
ATH11K_RX_ERR_RING_MASK_0,
};
const u8 ath11k_rx_wbm_rel_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
ATH11K_RX_WBM_REL_RING_MASK_0,
};
const u8 ath11k_reo_status_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
ATH11K_REO_STATUS_RING_MASK_0,
};
const u8 ath11k_rxdma2host_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
ATH11K_RXDMA2HOST_RING_MASK_0,
ATH11K_RXDMA2HOST_RING_MASK_1,
ATH11K_RXDMA2HOST_RING_MASK_2,
};
const u8 ath11k_host2rxdma_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX] = {
ATH11K_HOST2RXDMA_RING_MASK_0,
ATH11K_HOST2RXDMA_RING_MASK_1,
ATH11K_HOST2RXDMA_RING_MASK_2,
};
/* enum ext_irq_num - irq numbers that can be used by external modules /* enum ext_irq_num - irq numbers that can be used by external modules
* like datapath * like datapath
*/ */
...@@ -449,10 +384,10 @@ static void ath11k_ahb_kill_tasklets(struct ath11k_base *ab) ...@@ -449,10 +384,10 @@ static void ath11k_ahb_kill_tasklets(struct ath11k_base *ab)
{ {
int i; int i;
for (i = 0; i < CE_COUNT; i++) { for (i = 0; i < ab->hw_params.ce_count; i++) {
struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i]; struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR) if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
continue; continue;
tasklet_kill(&ce_pipe->intr_tq); tasklet_kill(&ce_pipe->intr_tq);
...@@ -540,8 +475,8 @@ static void ath11k_ahb_sync_ce_irqs(struct ath11k_base *ab) ...@@ -540,8 +475,8 @@ static void ath11k_ahb_sync_ce_irqs(struct ath11k_base *ab)
int i; int i;
int irq_idx; int irq_idx;
for (i = 0; i < CE_COUNT; i++) { for (i = 0; i < ab->hw_params.ce_count; i++) {
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR) if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
continue; continue;
irq_idx = ATH11K_IRQ_CE0_OFFSET + i; irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
...@@ -568,8 +503,8 @@ static void ath11k_ahb_ce_irqs_enable(struct ath11k_base *ab) ...@@ -568,8 +503,8 @@ static void ath11k_ahb_ce_irqs_enable(struct ath11k_base *ab)
{ {
int i; int i;
for (i = 0; i < CE_COUNT; i++) { for (i = 0; i < ab->hw_params.ce_count; i++) {
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR) if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
continue; continue;
ath11k_ahb_ce_irq_enable(ab, i); ath11k_ahb_ce_irq_enable(ab, i);
} }
...@@ -579,8 +514,8 @@ static void ath11k_ahb_ce_irqs_disable(struct ath11k_base *ab) ...@@ -579,8 +514,8 @@ static void ath11k_ahb_ce_irqs_disable(struct ath11k_base *ab)
{ {
int i; int i;
for (i = 0; i < CE_COUNT; i++) { for (i = 0; i < ab->hw_params.ce_count; i++) {
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR) if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
continue; continue;
ath11k_ahb_ce_irq_disable(ab, i); ath11k_ahb_ce_irq_disable(ab, i);
} }
...@@ -646,6 +581,7 @@ static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab) ...@@ -646,6 +581,7 @@ static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab)
cfg->tgt_ce = target_ce_config_wlan; cfg->tgt_ce = target_ce_config_wlan;
cfg->svc_to_ce_map_len = ARRAY_SIZE(target_service_to_ce_map_wlan); cfg->svc_to_ce_map_len = ARRAY_SIZE(target_service_to_ce_map_wlan);
cfg->svc_to_ce_map = target_service_to_ce_map_wlan; cfg->svc_to_ce_map = target_service_to_ce_map_wlan;
ab->qmi.service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074;
} }
static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab) static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab)
...@@ -665,8 +601,8 @@ static void ath11k_ahb_free_irq(struct ath11k_base *ab) ...@@ -665,8 +601,8 @@ static void ath11k_ahb_free_irq(struct ath11k_base *ab)
int irq_idx; int irq_idx;
int i; int i;
for (i = 0; i < CE_COUNT; i++) { for (i = 0; i < ab->hw_params.ce_count; i++) {
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR) if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
continue; continue;
irq_idx = ATH11K_IRQ_CE0_OFFSET + i; irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]); free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]);
...@@ -734,6 +670,7 @@ static irqreturn_t ath11k_ahb_ext_interrupt_handler(int irq, void *arg) ...@@ -734,6 +670,7 @@ static irqreturn_t ath11k_ahb_ext_interrupt_handler(int irq, void *arg)
static int ath11k_ahb_ext_irq_config(struct ath11k_base *ab) static int ath11k_ahb_ext_irq_config(struct ath11k_base *ab)
{ {
struct ath11k_hw_params *hw = &ab->hw_params;
int i, j; int i, j;
int irq; int irq;
int ret; int ret;
...@@ -749,45 +686,45 @@ static int ath11k_ahb_ext_irq_config(struct ath11k_base *ab) ...@@ -749,45 +686,45 @@ static int ath11k_ahb_ext_irq_config(struct ath11k_base *ab)
ath11k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT); ath11k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT);
for (j = 0; j < ATH11K_EXT_IRQ_NUM_MAX; j++) { for (j = 0; j < ATH11K_EXT_IRQ_NUM_MAX; j++) {
if (ath11k_tx_ring_mask[i] & BIT(j)) { if (ab->hw_params.ring_mask->tx[i] & BIT(j)) {
irq_grp->irqs[num_irq++] = irq_grp->irqs[num_irq++] =
wbm2host_tx_completions_ring1 - j; wbm2host_tx_completions_ring1 - j;
} }
if (ath11k_rx_ring_mask[i] & BIT(j)) { if (ab->hw_params.ring_mask->rx[i] & BIT(j)) {
irq_grp->irqs[num_irq++] = irq_grp->irqs[num_irq++] =
reo2host_destination_ring1 - j; reo2host_destination_ring1 - j;
} }
if (ath11k_rx_err_ring_mask[i] & BIT(j)) if (ab->hw_params.ring_mask->rx_err[i] & BIT(j))
irq_grp->irqs[num_irq++] = reo2host_exception; irq_grp->irqs[num_irq++] = reo2host_exception;
if (ath11k_rx_wbm_rel_ring_mask[i] & BIT(j)) if (ab->hw_params.ring_mask->rx_wbm_rel[i] & BIT(j))
irq_grp->irqs[num_irq++] = wbm2host_rx_release; irq_grp->irqs[num_irq++] = wbm2host_rx_release;
if (ath11k_reo_status_ring_mask[i] & BIT(j)) if (ab->hw_params.ring_mask->reo_status[i] & BIT(j))
irq_grp->irqs[num_irq++] = reo2host_status; irq_grp->irqs[num_irq++] = reo2host_status;
if (j < MAX_RADIOS) { if (j < ab->hw_params.max_radios) {
if (ath11k_rxdma2host_ring_mask[i] & BIT(j)) { if (ab->hw_params.ring_mask->rxdma2host[i] & BIT(j)) {
irq_grp->irqs[num_irq++] = irq_grp->irqs[num_irq++] =
rxdma2host_destination_ring_mac1 rxdma2host_destination_ring_mac1 -
- ath11k_core_get_hw_mac_id(ab, j); ath11k_hw_get_mac_from_pdev_id(hw, j);
} }
if (ath11k_host2rxdma_ring_mask[i] & BIT(j)) { if (ab->hw_params.ring_mask->host2rxdma[i] & BIT(j)) {
irq_grp->irqs[num_irq++] = irq_grp->irqs[num_irq++] =
host2rxdma_host_buf_ring_mac1 host2rxdma_host_buf_ring_mac1 -
- ath11k_core_get_hw_mac_id(ab, j); ath11k_hw_get_mac_from_pdev_id(hw, j);
} }
if (rx_mon_status_ring_mask[i] & BIT(j)) { if (ab->hw_params.ring_mask->rx_mon_status[i] & BIT(j)) {
irq_grp->irqs[num_irq++] = irq_grp->irqs[num_irq++] =
ppdu_end_interrupts_mac1 - ppdu_end_interrupts_mac1 -
ath11k_core_get_hw_mac_id(ab, j); ath11k_hw_get_mac_from_pdev_id(hw, j);
irq_grp->irqs[num_irq++] = irq_grp->irqs[num_irq++] =
rxdma2host_monitor_status_ring_mac1 - rxdma2host_monitor_status_ring_mac1 -
ath11k_core_get_hw_mac_id(ab, j); ath11k_hw_get_mac_from_pdev_id(hw, j);
} }
} }
} }
...@@ -819,10 +756,10 @@ static int ath11k_ahb_config_irq(struct ath11k_base *ab) ...@@ -819,10 +756,10 @@ static int ath11k_ahb_config_irq(struct ath11k_base *ab)
int ret; int ret;
/* Configure CE irqs */ /* Configure CE irqs */
for (i = 0; i < CE_COUNT; i++) { for (i = 0; i < ab->hw_params.ce_count; i++) {
struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i]; struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR) if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
continue; continue;
irq_idx = ATH11K_IRQ_CE0_OFFSET + i; irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
...@@ -926,7 +863,7 @@ static int ath11k_ahb_probe(struct platform_device *pdev) ...@@ -926,7 +863,7 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
return ret; return ret;
} }
ab = ath11k_core_alloc(&pdev->dev, 0, ATH11K_BUS_AHB); ab = ath11k_core_alloc(&pdev->dev, 0, ATH11K_BUS_AHB, &ath11k_ahb_bus_params);
if (!ab) { if (!ab) {
dev_err(&pdev->dev, "failed to allocate ath11k base\n"); dev_err(&pdev->dev, "failed to allocate ath11k base\n");
return -ENOMEM; return -ENOMEM;
...@@ -939,6 +876,10 @@ static int ath11k_ahb_probe(struct platform_device *pdev) ...@@ -939,6 +876,10 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
ab->mem_len = resource_size(mem_res); ab->mem_len = resource_size(mem_res);
platform_set_drvdata(pdev, ab); platform_set_drvdata(pdev, ab);
ret = ath11k_core_pre_init(ab);
if (ret)
goto err_core_free;
ret = ath11k_hal_srng_init(ab); ret = ath11k_hal_srng_init(ab);
if (ret) if (ret)
goto err_core_free; goto err_core_free;
...@@ -951,15 +892,15 @@ static int ath11k_ahb_probe(struct platform_device *pdev) ...@@ -951,15 +892,15 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
ath11k_ahb_init_qmi_ce_config(ab); ath11k_ahb_init_qmi_ce_config(ab);
ret = ath11k_ahb_config_irq(ab); ret = ath11k_core_init(ab);
if (ret) { if (ret) {
ath11k_err(ab, "failed to configure irq: %d\n", ret); ath11k_err(ab, "failed to init core: %d\n", ret);
goto err_ce_free; goto err_ce_free;
} }
ret = ath11k_core_init(ab); ret = ath11k_ahb_config_irq(ab);
if (ret) { if (ret) {
ath11k_err(ab, "failed to init core: %d\n", ret); ath11k_err(ab, "failed to configure irq: %d\n", ret);
goto err_ce_free; goto err_ce_free;
} }
...@@ -1023,5 +964,5 @@ static void ath11k_ahb_exit(void) ...@@ -1023,5 +964,5 @@ static void ath11k_ahb_exit(void)
} }
module_exit(ath11k_ahb_exit); module_exit(ath11k_ahb_exit);
MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax wireless chip"); MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN AHB devices");
MODULE_LICENSE("Dual BSD/GPL"); MODULE_LICENSE("Dual BSD/GPL");
...@@ -5,8 +5,9 @@ ...@@ -5,8 +5,9 @@
#include "dp_rx.h" #include "dp_rx.h"
#include "debug.h" #include "debug.h"
#include "hif.h"
static const struct ce_attr host_ce_config_wlan[] = { const struct ce_attr ath11k_host_ce_config_ipq8074[] = {
/* CE0: host->target HTC control and raw streams */ /* CE0: host->target HTC control and raw streams */
{ {
.flags = CE_ATTR_FLAGS, .flags = CE_ATTR_FLAGS,
...@@ -108,6 +109,84 @@ static const struct ce_attr host_ce_config_wlan[] = { ...@@ -108,6 +109,84 @@ static const struct ce_attr host_ce_config_wlan[] = {
}, },
}; };
const struct ce_attr ath11k_host_ce_config_qca6390[] = {
/* CE0: host->target HTC control and raw streams */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 16,
.src_sz_max = 2048,
.dest_nentries = 0,
},
/* CE1: target->host HTT + HTC control */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 512,
.recv_cb = ath11k_htc_rx_completion_handler,
},
/* CE2: target->host WMI */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 512,
.recv_cb = ath11k_htc_rx_completion_handler,
},
/* CE3: host->target WMI (mac0) */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 32,
.src_sz_max = 2048,
.dest_nentries = 0,
},
/* CE4: host->target HTT */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 2048,
.src_sz_max = 256,
.dest_nentries = 0,
},
/* CE5: target->host pktlog */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 2048,
.dest_nentries = 512,
.recv_cb = ath11k_dp_htt_htc_t2h_msg_handler,
},
/* CE6: target autonomous hif_memcpy */
{
.flags = CE_ATTR_FLAGS | CE_ATTR_DIS_INTR,
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
/* CE7: host->target WMI (mac1) */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 32,
.src_sz_max = 2048,
.dest_nentries = 0,
},
/* CE8: target autonomous hif_memcpy */
{
.flags = CE_ATTR_FLAGS,
.src_nentries = 0,
.src_sz_max = 0,
.dest_nentries = 0,
},
};
static int ath11k_ce_rx_buf_enqueue_pipe(struct ath11k_ce_pipe *pipe, static int ath11k_ce_rx_buf_enqueue_pipe(struct ath11k_ce_pipe *pipe,
struct sk_buff *skb, dma_addr_t paddr) struct sk_buff *skb, dma_addr_t paddr)
{ {
...@@ -352,6 +431,31 @@ static void ath11k_ce_send_done_cb(struct ath11k_ce_pipe *pipe) ...@@ -352,6 +431,31 @@ static void ath11k_ce_send_done_cb(struct ath11k_ce_pipe *pipe)
} }
} }
static void ath11k_ce_srng_msi_ring_params_setup(struct ath11k_base *ab, u32 ce_id,
struct hal_srng_params *ring_params)
{
u32 msi_data_start;
u32 msi_data_count;
u32 msi_irq_start;
u32 addr_lo;
u32 addr_hi;
int ret;
ret = ath11k_get_user_msi_vector(ab, "CE",
&msi_data_count, &msi_data_start,
&msi_irq_start);
if (ret)
return;
ath11k_get_msi_address(ab, &addr_lo, &addr_hi);
ring_params->msi_addr = addr_lo;
ring_params->msi_addr |= (dma_addr_t)(((uint64_t)addr_hi) << 32);
ring_params->msi_data = (ce_id % msi_data_count) + msi_data_start;
ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR;
}
static int ath11k_ce_init_ring(struct ath11k_base *ab, static int ath11k_ce_init_ring(struct ath11k_base *ab,
struct ath11k_ce_ring *ce_ring, struct ath11k_ce_ring *ce_ring,
int ce_id, enum hal_ring_type type) int ce_id, enum hal_ring_type type)
...@@ -363,21 +467,24 @@ static int ath11k_ce_init_ring(struct ath11k_base *ab, ...@@ -363,21 +467,24 @@ static int ath11k_ce_init_ring(struct ath11k_base *ab,
params.ring_base_vaddr = ce_ring->base_addr_owner_space; params.ring_base_vaddr = ce_ring->base_addr_owner_space;
params.num_entries = ce_ring->nentries; params.num_entries = ce_ring->nentries;
if (!(CE_ATTR_DIS_INTR & ab->hw_params.host_ce_config[ce_id].flags))
ath11k_ce_srng_msi_ring_params_setup(ab, ce_id, &params);
switch (type) { switch (type) {
case HAL_CE_SRC: case HAL_CE_SRC:
if (!(CE_ATTR_DIS_INTR & host_ce_config_wlan[ce_id].flags)) if (!(CE_ATTR_DIS_INTR & ab->hw_params.host_ce_config[ce_id].flags))
params.intr_batch_cntr_thres_entries = 1; params.intr_batch_cntr_thres_entries = 1;
break; break;
case HAL_CE_DST: case HAL_CE_DST:
params.max_buffer_len = host_ce_config_wlan[ce_id].src_sz_max; params.max_buffer_len = ab->hw_params.host_ce_config[ce_id].src_sz_max;
if (!(host_ce_config_wlan[ce_id].flags & CE_ATTR_DIS_INTR)) { if (!(ab->hw_params.host_ce_config[ce_id].flags & CE_ATTR_DIS_INTR)) {
params.intr_timer_thres_us = 1024; params.intr_timer_thres_us = 1024;
params.flags |= HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN; params.flags |= HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN;
params.low_threshold = ce_ring->nentries - 3; params.low_threshold = ce_ring->nentries - 3;
} }
break; break;
case HAL_CE_DST_STATUS: case HAL_CE_DST_STATUS:
if (!(host_ce_config_wlan[ce_id].flags & CE_ATTR_DIS_INTR)) { if (!(ab->hw_params.host_ce_config[ce_id].flags & CE_ATTR_DIS_INTR)) {
params.intr_batch_cntr_thres_entries = 1; params.intr_batch_cntr_thres_entries = 1;
params.intr_timer_thres_us = 0x1000; params.intr_timer_thres_us = 0x1000;
} }
...@@ -395,6 +502,7 @@ static int ath11k_ce_init_ring(struct ath11k_base *ab, ...@@ -395,6 +502,7 @@ static int ath11k_ce_init_ring(struct ath11k_base *ab,
ret, ce_id); ret, ce_id);
return ret; return ret;
} }
ce_ring->hal_ring_id = ret; ce_ring->hal_ring_id = ret;
return 0; return 0;
...@@ -440,7 +548,7 @@ ath11k_ce_alloc_ring(struct ath11k_base *ab, int nentries, int desc_sz) ...@@ -440,7 +548,7 @@ ath11k_ce_alloc_ring(struct ath11k_base *ab, int nentries, int desc_sz)
static int ath11k_ce_alloc_pipe(struct ath11k_base *ab, int ce_id) static int ath11k_ce_alloc_pipe(struct ath11k_base *ab, int ce_id)
{ {
struct ath11k_ce_pipe *pipe = &ab->ce.ce_pipe[ce_id]; struct ath11k_ce_pipe *pipe = &ab->ce.ce_pipe[ce_id];
const struct ce_attr *attr = &host_ce_config_wlan[ce_id]; const struct ce_attr *attr = &ab->hw_params.host_ce_config[ce_id];
struct ath11k_ce_ring *ring; struct ath11k_ce_ring *ring;
int nentries; int nentries;
int desc_sz; int desc_sz;
...@@ -494,6 +602,7 @@ void ath11k_ce_poll_send_completed(struct ath11k_base *ab, u8 pipe_id) ...@@ -494,6 +602,7 @@ void ath11k_ce_poll_send_completed(struct ath11k_base *ab, u8 pipe_id)
if ((pipe->attr_flags & CE_ATTR_DIS_INTR) && pipe->send_cb) if ((pipe->attr_flags & CE_ATTR_DIS_INTR) && pipe->send_cb)
pipe->send_cb(pipe); pipe->send_cb(pipe);
} }
EXPORT_SYMBOL(ath11k_ce_per_engine_service);
int ath11k_ce_send(struct ath11k_base *ab, struct sk_buff *skb, u8 pipe_id, int ath11k_ce_send(struct ath11k_base *ab, struct sk_buff *skb, u8 pipe_id,
u16 transfer_id) u16 transfer_id)
...@@ -609,7 +718,7 @@ void ath11k_ce_cleanup_pipes(struct ath11k_base *ab) ...@@ -609,7 +718,7 @@ void ath11k_ce_cleanup_pipes(struct ath11k_base *ab)
struct ath11k_ce_pipe *pipe; struct ath11k_ce_pipe *pipe;
int pipe_num; int pipe_num;
for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) { for (pipe_num = 0; pipe_num < ab->hw_params.ce_count; pipe_num++) {
pipe = &ab->ce.ce_pipe[pipe_num]; pipe = &ab->ce.ce_pipe[pipe_num];
ath11k_ce_rx_pipe_cleanup(pipe); ath11k_ce_rx_pipe_cleanup(pipe);
...@@ -619,6 +728,7 @@ void ath11k_ce_cleanup_pipes(struct ath11k_base *ab) ...@@ -619,6 +728,7 @@ void ath11k_ce_cleanup_pipes(struct ath11k_base *ab)
/* NOTE: Should we also clean up tx buffer in all pipes? */ /* NOTE: Should we also clean up tx buffer in all pipes? */
} }
} }
EXPORT_SYMBOL(ath11k_ce_cleanup_pipes);
void ath11k_ce_rx_post_buf(struct ath11k_base *ab) void ath11k_ce_rx_post_buf(struct ath11k_base *ab)
{ {
...@@ -626,7 +736,7 @@ void ath11k_ce_rx_post_buf(struct ath11k_base *ab) ...@@ -626,7 +736,7 @@ void ath11k_ce_rx_post_buf(struct ath11k_base *ab)
int i; int i;
int ret; int ret;
for (i = 0; i < CE_COUNT; i++) { for (i = 0; i < ab->hw_params.ce_count; i++) {
pipe = &ab->ce.ce_pipe[i]; pipe = &ab->ce.ce_pipe[i];
ret = ath11k_ce_rx_post_pipe(pipe); ret = ath11k_ce_rx_post_pipe(pipe);
if (ret) { if (ret) {
...@@ -642,6 +752,7 @@ void ath11k_ce_rx_post_buf(struct ath11k_base *ab) ...@@ -642,6 +752,7 @@ void ath11k_ce_rx_post_buf(struct ath11k_base *ab)
} }
} }
} }
EXPORT_SYMBOL(ath11k_ce_rx_post_buf);
void ath11k_ce_rx_replenish_retry(struct timer_list *t) void ath11k_ce_rx_replenish_retry(struct timer_list *t)
{ {
...@@ -656,7 +767,7 @@ int ath11k_ce_init_pipes(struct ath11k_base *ab) ...@@ -656,7 +767,7 @@ int ath11k_ce_init_pipes(struct ath11k_base *ab)
int i; int i;
int ret; int ret;
for (i = 0; i < CE_COUNT; i++) { for (i = 0; i < ab->hw_params.ce_count; i++) {
pipe = &ab->ce.ce_pipe[i]; pipe = &ab->ce.ce_pipe[i];
if (pipe->src_ring) { if (pipe->src_ring) {
...@@ -714,7 +825,7 @@ void ath11k_ce_free_pipes(struct ath11k_base *ab) ...@@ -714,7 +825,7 @@ void ath11k_ce_free_pipes(struct ath11k_base *ab)
int desc_sz; int desc_sz;
int i; int i;
for (i = 0; i < CE_COUNT; i++) { for (i = 0; i < ab->hw_params.ce_count; i++) {
pipe = &ab->ce.ce_pipe[i]; pipe = &ab->ce.ce_pipe[i];
if (pipe->src_ring) { if (pipe->src_ring) {
...@@ -752,6 +863,7 @@ void ath11k_ce_free_pipes(struct ath11k_base *ab) ...@@ -752,6 +863,7 @@ void ath11k_ce_free_pipes(struct ath11k_base *ab)
} }
} }
} }
EXPORT_SYMBOL(ath11k_ce_free_pipes);
int ath11k_ce_alloc_pipes(struct ath11k_base *ab) int ath11k_ce_alloc_pipes(struct ath11k_base *ab)
{ {
...@@ -762,8 +874,8 @@ int ath11k_ce_alloc_pipes(struct ath11k_base *ab) ...@@ -762,8 +874,8 @@ int ath11k_ce_alloc_pipes(struct ath11k_base *ab)
spin_lock_init(&ab->ce.ce_lock); spin_lock_init(&ab->ce.ce_lock);
for (i = 0; i < CE_COUNT; i++) { for (i = 0; i < ab->hw_params.ce_count; i++) {
attr = &host_ce_config_wlan[i]; attr = &ab->hw_params.host_ce_config[i];
pipe = &ab->ce.ce_pipe[i]; pipe = &ab->ce.ce_pipe[i];
pipe->pipe_num = i; pipe->pipe_num = i;
pipe->ab = ab; pipe->ab = ab;
...@@ -779,6 +891,7 @@ int ath11k_ce_alloc_pipes(struct ath11k_base *ab) ...@@ -779,6 +891,7 @@ int ath11k_ce_alloc_pipes(struct ath11k_base *ab)
return 0; return 0;
} }
EXPORT_SYMBOL(ath11k_ce_alloc_pipes);
/* For Big Endian Host, Copy Engine byte_swap is enabled /* For Big Endian Host, Copy Engine byte_swap is enabled
* When Copy Engine does byte_swap, need to byte swap again for the * When Copy Engine does byte_swap, need to byte swap again for the
...@@ -799,10 +912,11 @@ void ath11k_ce_byte_swap(void *mem, u32 len) ...@@ -799,10 +912,11 @@ void ath11k_ce_byte_swap(void *mem, u32 len)
} }
} }
int ath11k_ce_get_attr_flags(int ce_id) int ath11k_ce_get_attr_flags(struct ath11k_base *ab, int ce_id)
{ {
if (ce_id >= CE_COUNT) if (ce_id >= ab->hw_params.ce_count)
return -EINVAL; return -EINVAL;
return host_ce_config_wlan[ce_id].flags; return ab->hw_params.host_ce_config[ce_id].flags;
} }
EXPORT_SYMBOL(ath11k_ce_get_attr_flags);
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
#ifndef ATH11K_CE_H #ifndef ATH11K_CE_H
#define ATH11K_CE_H #define ATH11K_CE_H
#define CE_COUNT 12 #define CE_COUNT_MAX 12
/* Byte swap data words */ /* Byte swap data words */
#define CE_ATTR_BYTE_SWAP_DATA 2 #define CE_ATTR_BYTE_SWAP_DATA 2
...@@ -165,11 +165,14 @@ struct ath11k_ce_pipe { ...@@ -165,11 +165,14 @@ struct ath11k_ce_pipe {
}; };
struct ath11k_ce { struct ath11k_ce {
struct ath11k_ce_pipe ce_pipe[CE_COUNT]; struct ath11k_ce_pipe ce_pipe[CE_COUNT_MAX];
/* Protects rings of all ce pipes */ /* Protects rings of all ce pipes */
spinlock_t ce_lock; spinlock_t ce_lock;
}; };
extern const struct ce_attr ath11k_host_ce_config_ipq8074[];
extern const struct ce_attr ath11k_host_ce_config_qca6390[];
void ath11k_ce_cleanup_pipes(struct ath11k_base *ab); void ath11k_ce_cleanup_pipes(struct ath11k_base *ab);
void ath11k_ce_rx_replenish_retry(struct timer_list *t); void ath11k_ce_rx_replenish_retry(struct timer_list *t);
void ath11k_ce_per_engine_service(struct ath11k_base *ab, u16 ce_id); void ath11k_ce_per_engine_service(struct ath11k_base *ab, u16 ce_id);
...@@ -179,6 +182,9 @@ void ath11k_ce_rx_post_buf(struct ath11k_base *ab); ...@@ -179,6 +182,9 @@ void ath11k_ce_rx_post_buf(struct ath11k_base *ab);
int ath11k_ce_init_pipes(struct ath11k_base *ab); int ath11k_ce_init_pipes(struct ath11k_base *ab);
int ath11k_ce_alloc_pipes(struct ath11k_base *ab); int ath11k_ce_alloc_pipes(struct ath11k_base *ab);
void ath11k_ce_free_pipes(struct ath11k_base *ab); void ath11k_ce_free_pipes(struct ath11k_base *ab);
int ath11k_ce_get_attr_flags(int ce_id); int ath11k_ce_get_attr_flags(struct ath11k_base *ab, int ce_id);
void ath11k_ce_poll_send_completed(struct ath11k_base *ab, u8 pipe_id); void ath11k_ce_poll_send_completed(struct ath11k_base *ab, u8 pipe_id);
int ath11k_ce_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
u8 *ul_pipe, u8 *dl_pipe);
int ath11k_ce_attr_attach(struct ath11k_base *ab);
#endif #endif
...@@ -14,43 +14,69 @@ ...@@ -14,43 +14,69 @@
#include "hif.h" #include "hif.h"
unsigned int ath11k_debug_mask; unsigned int ath11k_debug_mask;
EXPORT_SYMBOL(ath11k_debug_mask);
module_param_named(debug_mask, ath11k_debug_mask, uint, 0644); module_param_named(debug_mask, ath11k_debug_mask, uint, 0644);
MODULE_PARM_DESC(debug_mask, "Debugging mask"); MODULE_PARM_DESC(debug_mask, "Debugging mask");
static const struct ath11k_hw_params ath11k_hw_params = { static const struct ath11k_hw_params ath11k_hw_params[] = {
.name = "ipq8074", {
.fw = { .hw_rev = ATH11K_HW_IPQ8074,
.dir = IPQ8074_FW_DIR, .name = "ipq8074 hw2.0",
.board_size = IPQ8074_MAX_BOARD_DATA_SZ, .fw = {
.cal_size = IPQ8074_MAX_CAL_DATA_SZ, .dir = "IPQ8074/hw2.0",
.board_size = 256 * 1024,
.cal_size = 256 * 1024,
},
.max_radios = 3,
.bdf_addr = 0x4B0C0000,
.hw_ops = &ipq8074_ops,
.ring_mask = &ath11k_hw_ring_mask_ipq8074,
.internal_sleep_clock = false,
.regs = &ipq8074_regs,
.host_ce_config = ath11k_host_ce_config_ipq8074,
.ce_count = 12,
.single_pdev_only = false,
.needs_band_to_mac = true,
.rxdma1_enable = true,
.num_rxmda_per_pdev = 1,
.rx_mac_buf_ring = false,
.vdev_start_delay = false,
.htt_peer_map_v2 = true,
.tcl_0_only = false,
},
{
.name = "qca6390 hw2.0",
.hw_rev = ATH11K_HW_QCA6390_HW20,
.fw = {
.dir = "QCA6390/hw2.0",
.board_size = 256 * 1024,
.cal_size = 256 * 1024,
},
.max_radios = 3,
.bdf_addr = 0x4B0C0000,
.hw_ops = &qca6390_ops,
.ring_mask = &ath11k_hw_ring_mask_qca6390,
.internal_sleep_clock = true,
.regs = &qca6390_regs,
.host_ce_config = ath11k_host_ce_config_qca6390,
.ce_count = 9,
.single_pdev_only = true,
.needs_band_to_mac = false,
.rxdma1_enable = false,
.num_rxmda_per_pdev = 2,
.rx_mac_buf_ring = true,
.vdev_start_delay = true,
.htt_peer_map_v2 = false,
.tcl_0_only = true,
}, },
}; };
/* Map from pdev index to hw mac index */
u8 ath11k_core_get_hw_mac_id(struct ath11k_base *ab, int pdev_idx)
{
switch (pdev_idx) {
case 0:
return 0;
case 1:
return 2;
case 2:
return 1;
default:
ath11k_warn(ab, "Invalid pdev idx %d\n", pdev_idx);
return ATH11K_INVALID_HW_MAC_ID;
}
}
EXPORT_SYMBOL(ath11k_core_get_hw_mac_id);
static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name, static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
size_t name_len) size_t name_len)
{ {
/* Note: bus is fixed to ahb. When other bus type supported,
* make it to dynamic.
*/
scnprintf(name, name_len, scnprintf(name, name_len,
"bus=ahb,qmi-chip-id=%d,qmi-board-id=%d", "bus=%s,qmi-chip-id=%d,qmi-board-id=%d",
ath11k_bus_str(ab->hif.bus),
ab->qmi.target.chip_id, ab->qmi.target.chip_id,
ab->qmi.target.board_id); ab->qmi.target.board_id);
...@@ -59,29 +85,24 @@ static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name, ...@@ -59,29 +85,24 @@ static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
return 0; return 0;
} }
static const struct firmware *ath11k_fetch_fw_file(struct ath11k_base *ab, const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
const char *dir, const char *file)
const char *file)
{ {
char filename[100];
const struct firmware *fw; const struct firmware *fw;
char path[100];
int ret; int ret;
if (file == NULL) if (file == NULL)
return ERR_PTR(-ENOENT); return ERR_PTR(-ENOENT);
if (dir == NULL) ath11k_core_create_firmware_path(ab, file, path, sizeof(path));
dir = ".";
snprintf(filename, sizeof(filename), "%s/%s", dir, file);
ret = firmware_request_nowarn(&fw, filename, ab->dev);
ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot fw request '%s': %d\n",
filename, ret);
ret = firmware_request_nowarn(&fw, path, ab->dev);
if (ret) if (ret)
return ERR_PTR(ret); return ERR_PTR(ret);
ath11k_warn(ab, "Downloading BDF: %s, size: %zu\n",
filename, fw->size); ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot firmware request %s size %zu\n",
path, fw->size);
return fw; return fw;
} }
...@@ -181,26 +202,30 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab, ...@@ -181,26 +202,30 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab,
{ {
size_t len, magic_len; size_t len, magic_len;
const u8 *data; const u8 *data;
char *filename = ATH11K_BOARD_API2_FILE; char *filename, filepath[100];
size_t ie_len; size_t ie_len;
struct ath11k_fw_ie *hdr; struct ath11k_fw_ie *hdr;
int ret, ie_id; int ret, ie_id;
filename = ATH11K_BOARD_API2_FILE;
if (!bd->fw) if (!bd->fw)
bd->fw = ath11k_fetch_fw_file(ab, bd->fw = ath11k_core_firmware_request(ab, filename);
ab->hw_params.fw.dir,
filename);
if (IS_ERR(bd->fw)) if (IS_ERR(bd->fw))
return PTR_ERR(bd->fw); return PTR_ERR(bd->fw);
data = bd->fw->data; data = bd->fw->data;
len = bd->fw->size; len = bd->fw->size;
ath11k_core_create_firmware_path(ab, filename,
filepath, sizeof(filepath));
/* magic has extra null byte padded */ /* magic has extra null byte padded */
magic_len = strlen(ATH11K_BOARD_MAGIC) + 1; magic_len = strlen(ATH11K_BOARD_MAGIC) + 1;
if (len < magic_len) { if (len < magic_len) {
ath11k_err(ab, "failed to find magic value in %s/%s, file too short: %zu\n", ath11k_err(ab, "failed to find magic value in %s, file too short: %zu\n",
ab->hw_params.fw.dir, filename, len); filepath, len);
ret = -EINVAL; ret = -EINVAL;
goto err; goto err;
} }
...@@ -214,8 +239,8 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab, ...@@ -214,8 +239,8 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab,
/* magic is padded to 4 bytes */ /* magic is padded to 4 bytes */
magic_len = ALIGN(magic_len, 4); magic_len = ALIGN(magic_len, 4);
if (len < magic_len) { if (len < magic_len) {
ath11k_err(ab, "failed: %s/%s too small to contain board data, len: %zu\n", ath11k_err(ab, "failed: %s too small to contain board data, len: %zu\n",
ab->hw_params.fw.dir, filename, len); filepath, len);
ret = -EINVAL; ret = -EINVAL;
goto err; goto err;
} }
...@@ -263,8 +288,8 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab, ...@@ -263,8 +288,8 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab,
out: out:
if (!bd->data || !bd->len) { if (!bd->data || !bd->len) {
ath11k_err(ab, ath11k_err(ab,
"failed to fetch board data for %s from %s/%s\n", "failed to fetch board data for %s from %s\n",
boardname, ab->hw_params.fw.dir, filename); boardname, filepath);
ret = -ENODATA; ret = -ENODATA;
goto err; goto err;
} }
...@@ -279,9 +304,7 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab, ...@@ -279,9 +304,7 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab,
static int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab, static int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab,
struct ath11k_board_data *bd) struct ath11k_board_data *bd)
{ {
bd->fw = ath11k_fetch_fw_file(ab, bd->fw = ath11k_core_firmware_request(ab, ATH11K_DEFAULT_BOARD_FILE);
ab->hw_params.fw.dir,
ATH11K_DEFAULT_BOARD_FILE);
if (IS_ERR(bd->fw)) if (IS_ERR(bd->fw))
return PTR_ERR(bd->fw); return PTR_ERR(bd->fw);
...@@ -706,7 +729,7 @@ static void ath11k_core_restart(struct work_struct *work) ...@@ -706,7 +729,7 @@ static void ath11k_core_restart(struct work_struct *work)
break; break;
case ATH11K_STATE_RESTARTED: case ATH11K_STATE_RESTARTED:
ar->state = ATH11K_STATE_WEDGED; ar->state = ATH11K_STATE_WEDGED;
/* fall through */ fallthrough;
case ATH11K_STATE_WEDGED: case ATH11K_STATE_WEDGED:
ath11k_warn(ab, ath11k_warn(ab,
"device is wedged, will not restart radio %d\n", i); "device is wedged, will not restart radio %d\n", i);
...@@ -717,12 +740,52 @@ static void ath11k_core_restart(struct work_struct *work) ...@@ -717,12 +740,52 @@ static void ath11k_core_restart(struct work_struct *work)
complete(&ab->driver_recovery); complete(&ab->driver_recovery);
} }
int ath11k_core_init(struct ath11k_base *ab) static int ath11k_init_hw_params(struct ath11k_base *ab)
{
const struct ath11k_hw_params *hw_params = NULL;
int i;
for (i = 0; i < ARRAY_SIZE(ath11k_hw_params); i++) {
hw_params = &ath11k_hw_params[i];
if (hw_params->hw_rev == ab->hw_rev)
break;
}
if (i == ARRAY_SIZE(ath11k_hw_params)) {
ath11k_err(ab, "Unsupported hardware version: 0x%x\n", ab->hw_rev);
return -EINVAL;
}
ab->hw_params = *hw_params;
ath11k_dbg(ab, ATH11K_DBG_BOOT, "Hardware name %s\n", ab->hw_params.name);
return 0;
}
int ath11k_core_pre_init(struct ath11k_base *ab)
{
int ret;
ret = ath11k_init_hw_params(ab);
if (ret) {
ath11k_err(ab, "failed to get hw params: %d\n", ret);
return ret;
}
return 0;
}
EXPORT_SYMBOL(ath11k_core_pre_init);
static int ath11k_core_get_rproc(struct ath11k_base *ab)
{ {
struct device *dev = ab->dev; struct device *dev = ab->dev;
struct rproc *prproc; struct rproc *prproc;
phandle rproc_phandle; phandle rproc_phandle;
int ret;
if (ab->bus_params.mhi_support)
return 0;
if (of_property_read_u32(dev->of_node, "qcom,rproc", &rproc_phandle)) { if (of_property_read_u32(dev->of_node, "qcom,rproc", &rproc_phandle)) {
ath11k_err(ab, "failed to get q6_rproc handle\n"); ath11k_err(ab, "failed to get q6_rproc handle\n");
...@@ -735,7 +798,25 @@ int ath11k_core_init(struct ath11k_base *ab) ...@@ -735,7 +798,25 @@ int ath11k_core_init(struct ath11k_base *ab)
return -EINVAL; return -EINVAL;
} }
ab->tgt_rproc = prproc; ab->tgt_rproc = prproc;
ab->hw_params = ath11k_hw_params;
return 0;
}
int ath11k_core_init(struct ath11k_base *ab)
{
int ret;
ret = ath11k_core_get_rproc(ab);
if (ret) {
ath11k_err(ab, "failed to get rproc: %d\n", ret);
return ret;
}
ret = ath11k_init_hw_params(ab);
if (ret) {
ath11k_err(ab, "failed to get hw params %d\n", ret);
return ret;
}
ret = ath11k_core_soc_create(ab); ret = ath11k_core_soc_create(ab);
if (ret) { if (ret) {
...@@ -745,6 +826,7 @@ int ath11k_core_init(struct ath11k_base *ab) ...@@ -745,6 +826,7 @@ int ath11k_core_init(struct ath11k_base *ab)
return 0; return 0;
} }
EXPORT_SYMBOL(ath11k_core_init);
void ath11k_core_deinit(struct ath11k_base *ab) void ath11k_core_deinit(struct ath11k_base *ab)
{ {
...@@ -759,14 +841,17 @@ void ath11k_core_deinit(struct ath11k_base *ab) ...@@ -759,14 +841,17 @@ void ath11k_core_deinit(struct ath11k_base *ab)
ath11k_mac_destroy(ab); ath11k_mac_destroy(ab);
ath11k_core_soc_destroy(ab); ath11k_core_soc_destroy(ab);
} }
EXPORT_SYMBOL(ath11k_core_deinit);
void ath11k_core_free(struct ath11k_base *ab) void ath11k_core_free(struct ath11k_base *ab)
{ {
kfree(ab); kfree(ab);
} }
EXPORT_SYMBOL(ath11k_core_free);
struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size, struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
enum ath11k_bus bus) enum ath11k_bus bus,
const struct ath11k_bus_params *bus_params)
{ {
struct ath11k_base *ab; struct ath11k_base *ab;
...@@ -789,6 +874,8 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size, ...@@ -789,6 +874,8 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
INIT_WORK(&ab->restart_work, ath11k_core_restart); INIT_WORK(&ab->restart_work, ath11k_core_restart);
timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0); timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0);
ab->dev = dev; ab->dev = dev;
ab->bus_params = *bus_params;
ab->hif.bus = bus;
return ab; return ab;
...@@ -796,3 +883,7 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size, ...@@ -796,3 +883,7 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
kfree(ab); kfree(ab);
return NULL; return NULL;
} }
EXPORT_SYMBOL(ath11k_core_alloc);
MODULE_DESCRIPTION("Core module for Qualcomm Atheros 802.11ax wireless LAN cards.");
MODULE_LICENSE("Dual BSD/GPL");
...@@ -90,6 +90,7 @@ struct ath11k_skb_rxcb { ...@@ -90,6 +90,7 @@ struct ath11k_skb_rxcb {
enum ath11k_hw_rev { enum ath11k_hw_rev {
ATH11K_HW_IPQ8074, ATH11K_HW_IPQ8074,
ATH11K_HW_QCA6390_HW20,
}; };
enum ath11k_firmware_mode { enum ath11k_firmware_mode {
...@@ -101,18 +102,8 @@ enum ath11k_firmware_mode { ...@@ -101,18 +102,8 @@ enum ath11k_firmware_mode {
}; };
#define ATH11K_IRQ_NUM_MAX 52 #define ATH11K_IRQ_NUM_MAX 52
#define ATH11K_EXT_IRQ_GRP_NUM_MAX 11
#define ATH11K_EXT_IRQ_NUM_MAX 16 #define ATH11K_EXT_IRQ_NUM_MAX 16
extern const u8 ath11k_reo_status_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX];
extern const u8 ath11k_tx_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX];
extern const u8 ath11k_rx_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX];
extern const u8 ath11k_rx_err_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX];
extern const u8 ath11k_rx_wbm_rel_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX];
extern const u8 ath11k_rxdma2host_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX];
extern const u8 ath11k_host2rxdma_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX];
extern const u8 rx_mon_status_ring_mask[ATH11K_EXT_IRQ_GRP_NUM_MAX];
struct ath11k_ext_irq_grp { struct ath11k_ext_irq_grp {
struct ath11k_base *ab; struct ath11k_base *ab;
u32 irqs[ATH11K_EXT_IRQ_NUM_MAX]; u32 irqs[ATH11K_EXT_IRQ_NUM_MAX];
...@@ -226,6 +217,7 @@ struct ath11k_vif { ...@@ -226,6 +217,7 @@ struct ath11k_vif {
int txpower; int txpower;
bool rsnie_present; bool rsnie_present;
bool wpaie_present; bool wpaie_present;
struct ieee80211_chanctx_conf chanctx;
}; };
struct ath11k_vif_iter { struct ath11k_vif_iter {
...@@ -554,6 +546,7 @@ struct ath11k { ...@@ -554,6 +546,7 @@ struct ath11k {
}; };
struct ath11k_band_cap { struct ath11k_band_cap {
u32 phy_id;
u32 max_bw_supported; u32 max_bw_supported;
u32 ht_cap_info; u32 ht_cap_info;
u32 he_cap_info[2]; u32 he_cap_info[2];
...@@ -589,6 +582,13 @@ struct ath11k_board_data { ...@@ -589,6 +582,13 @@ struct ath11k_board_data {
size_t len; size_t len;
}; };
struct ath11k_bus_params {
bool mhi_support;
bool m3_fw_support;
bool fixed_bdf_addr;
bool fixed_mem_region;
};
/* IPQ8074 HW channel counters frequency value in hertz */ /* IPQ8074 HW channel counters frequency value in hertz */
#define IPQ8074_CC_FREQ_HERTZ 320000 #define IPQ8074_CC_FREQ_HERTZ 320000
...@@ -651,6 +651,7 @@ struct ath11k_base { ...@@ -651,6 +651,7 @@ struct ath11k_base {
unsigned long mem_len; unsigned long mem_len;
struct { struct {
enum ath11k_bus bus;
const struct ath11k_hif_ops *ops; const struct ath11k_hif_ops *ops;
} hif; } hif;
...@@ -677,7 +678,10 @@ struct ath11k_base { ...@@ -677,7 +678,10 @@ struct ath11k_base {
u32 ext_service_bitmap[WMI_SERVICE_EXT_BM_SIZE]; u32 ext_service_bitmap[WMI_SERVICE_EXT_BM_SIZE];
bool pdevs_macaddr_valid; bool pdevs_macaddr_valid;
int bd_api; int bd_api;
struct ath11k_hw_params hw_params; struct ath11k_hw_params hw_params;
struct ath11k_bus_params bus_params;
const struct firmware *cal_file; const struct firmware *cal_file;
/* Below regd's are protected by ab->data_lock */ /* Below regd's are protected by ab->data_lock */
...@@ -850,17 +854,21 @@ struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab, ...@@ -850,17 +854,21 @@ struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab,
const u8 *addr); const u8 *addr);
struct ath11k_peer *ath11k_peer_find_by_id(struct ath11k_base *ab, int peer_id); struct ath11k_peer *ath11k_peer_find_by_id(struct ath11k_base *ab, int peer_id);
int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab); int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab);
int ath11k_core_pre_init(struct ath11k_base *ab);
int ath11k_core_init(struct ath11k_base *ath11k); int ath11k_core_init(struct ath11k_base *ath11k);
void ath11k_core_deinit(struct ath11k_base *ath11k); void ath11k_core_deinit(struct ath11k_base *ath11k);
struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size, struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
enum ath11k_bus bus); enum ath11k_bus bus,
const struct ath11k_bus_params *bus_params);
void ath11k_core_free(struct ath11k_base *ath11k); void ath11k_core_free(struct ath11k_base *ath11k);
int ath11k_core_fetch_bdf(struct ath11k_base *ath11k, int ath11k_core_fetch_bdf(struct ath11k_base *ath11k,
struct ath11k_board_data *bd); struct ath11k_board_data *bd);
void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd); void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd);
void ath11k_core_halt(struct ath11k *ar); void ath11k_core_halt(struct ath11k *ar);
u8 ath11k_core_get_hw_mac_id(struct ath11k_base *ab, int pdev_idx);
const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
const char *filename);
static inline const char *ath11k_scan_state_str(enum ath11k_scan_state state) static inline const char *ath11k_scan_state_str(enum ath11k_scan_state state)
{ {
...@@ -894,4 +902,30 @@ static inline struct ath11k_vif *ath11k_vif_to_arvif(struct ieee80211_vif *vif) ...@@ -894,4 +902,30 @@ static inline struct ath11k_vif *ath11k_vif_to_arvif(struct ieee80211_vif *vif)
return (struct ath11k_vif *)vif->drv_priv; return (struct ath11k_vif *)vif->drv_priv;
} }
static inline struct ath11k *ath11k_ab_to_ar(struct ath11k_base *ab,
int mac_id)
{
return ab->pdevs[ath11k_hw_mac_id_to_pdev_id(&ab->hw_params, mac_id)].ar;
}
static inline void ath11k_core_create_firmware_path(struct ath11k_base *ab,
const char *filename,
void *buf, size_t buf_len)
{
snprintf(buf, buf_len, "%s/%s/%s", ATH11K_FW_DIR,
ab->hw_params.fw.dir, filename);
}
static inline const char *ath11k_bus_str(enum ath11k_bus bus)
{
switch (bus) {
case ATH11K_BUS_PCI:
return "pci";
case ATH11K_BUS_AHB:
return "ahb";
}
return "unknown";
}
#endif /* _CORE_H_ */ #endif /* _CORE_H_ */
...@@ -168,7 +168,7 @@ int ath11k_dbring_buf_setup(struct ath11k *ar, ...@@ -168,7 +168,7 @@ int ath11k_dbring_buf_setup(struct ath11k *ar,
srng = &ab->hal.srng_list[ring->refill_srng.ring_id]; srng = &ab->hal.srng_list[ring->refill_srng.ring_id];
ring->bufs_max = ring->refill_srng.size / ring->bufs_max = ring->refill_srng.size /
ath11k_hal_srng_get_entrysize(HAL_RXDMA_DIR_BUF); ath11k_hal_srng_get_entrysize(ab, HAL_RXDMA_DIR_BUF);
ring->buf_sz = db_cap->min_buf_sz; ring->buf_sz = db_cap->min_buf_sz;
ring->buf_align = db_cap->min_buf_align; ring->buf_align = db_cap->min_buf_align;
......
...@@ -62,6 +62,7 @@ void ath11k_info(struct ath11k_base *ab, const char *fmt, ...) ...@@ -62,6 +62,7 @@ void ath11k_info(struct ath11k_base *ab, const char *fmt, ...)
/* TODO: Trace the log */ /* TODO: Trace the log */
va_end(args); va_end(args);
} }
EXPORT_SYMBOL(ath11k_info);
void ath11k_err(struct ath11k_base *ab, const char *fmt, ...) void ath11k_err(struct ath11k_base *ab, const char *fmt, ...)
{ {
...@@ -76,6 +77,7 @@ void ath11k_err(struct ath11k_base *ab, const char *fmt, ...) ...@@ -76,6 +77,7 @@ void ath11k_err(struct ath11k_base *ab, const char *fmt, ...)
/* TODO: Trace the log */ /* TODO: Trace the log */
va_end(args); va_end(args);
} }
EXPORT_SYMBOL(ath11k_err);
void ath11k_warn(struct ath11k_base *ab, const char *fmt, ...) void ath11k_warn(struct ath11k_base *ab, const char *fmt, ...)
{ {
...@@ -90,6 +92,7 @@ void ath11k_warn(struct ath11k_base *ab, const char *fmt, ...) ...@@ -90,6 +92,7 @@ void ath11k_warn(struct ath11k_base *ab, const char *fmt, ...)
/* TODO: Trace the log */ /* TODO: Trace the log */
va_end(args); va_end(args);
} }
EXPORT_SYMBOL(ath11k_warn);
#ifdef CONFIG_ATH11K_DEBUG #ifdef CONFIG_ATH11K_DEBUG
void __ath11k_dbg(struct ath11k_base *ab, enum ath11k_debug_mask mask, void __ath11k_dbg(struct ath11k_base *ab, enum ath11k_debug_mask mask,
...@@ -110,6 +113,7 @@ void __ath11k_dbg(struct ath11k_base *ab, enum ath11k_debug_mask mask, ...@@ -110,6 +113,7 @@ void __ath11k_dbg(struct ath11k_base *ab, enum ath11k_debug_mask mask,
va_end(args); va_end(args);
} }
EXPORT_SYMBOL(__ath11k_dbg);
void ath11k_dbg_dump(struct ath11k_base *ab, void ath11k_dbg_dump(struct ath11k_base *ab,
enum ath11k_debug_mask mask, enum ath11k_debug_mask mask,
...@@ -138,6 +142,7 @@ void ath11k_dbg_dump(struct ath11k_base *ab, ...@@ -138,6 +142,7 @@ void ath11k_dbg_dump(struct ath11k_base *ab,
} }
} }
} }
EXPORT_SYMBOL(ath11k_dbg_dump);
#endif #endif
...@@ -693,8 +698,10 @@ static ssize_t ath11k_write_extd_rx_stats(struct file *file, ...@@ -693,8 +698,10 @@ static ssize_t ath11k_write_extd_rx_stats(struct file *file,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct ath11k *ar = file->private_data; struct ath11k *ar = file->private_data;
struct ath11k_base *ab = ar->ab;
struct htt_rx_ring_tlv_filter tlv_filter = {0}; struct htt_rx_ring_tlv_filter tlv_filter = {0};
u32 enable, rx_filter = 0, ring_id; u32 enable, rx_filter = 0, ring_id;
int i;
int ret; int ret;
if (kstrtouint_from_user(ubuf, count, 0, &enable)) if (kstrtouint_from_user(ubuf, count, 0, &enable))
...@@ -737,14 +744,16 @@ static ssize_t ath11k_write_extd_rx_stats(struct file *file, ...@@ -737,14 +744,16 @@ static ssize_t ath11k_write_extd_rx_stats(struct file *file,
ar->debug.rx_filter = tlv_filter.rx_filter; ar->debug.rx_filter = tlv_filter.rx_filter;
ring_id = ar->dp.rx_mon_status_refill_ring.refill_buf_ring.ring_id; for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id, ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
HAL_RXDMA_MONITOR_STATUS, ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
DP_RX_BUFFER_SIZE, &tlv_filter); HAL_RXDMA_MONITOR_STATUS,
DP_RX_BUFFER_SIZE, &tlv_filter);
if (ret) { if (ret) {
ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n"); ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
goto exit; goto exit;
}
} }
ar->debug.extd_rx_stats = enable; ar->debug.extd_rx_stats = enable;
...@@ -995,10 +1004,11 @@ static ssize_t ath11k_write_pktlog_filter(struct file *file, ...@@ -995,10 +1004,11 @@ static ssize_t ath11k_write_pktlog_filter(struct file *file,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct ath11k *ar = file->private_data; struct ath11k *ar = file->private_data;
struct ath11k_base *ab = ar->ab;
struct htt_rx_ring_tlv_filter tlv_filter = {0}; struct htt_rx_ring_tlv_filter tlv_filter = {0};
u32 rx_filter = 0, ring_id, filter, mode; u32 rx_filter = 0, ring_id, filter, mode;
u8 buf[128] = {0}; u8 buf[128] = {0};
int ret; int i, ret;
ssize_t rc; ssize_t rc;
mutex_lock(&ar->conf_mutex); mutex_lock(&ar->conf_mutex);
...@@ -1079,16 +1089,20 @@ static ssize_t ath11k_write_pktlog_filter(struct file *file, ...@@ -1079,16 +1089,20 @@ static ssize_t ath11k_write_pktlog_filter(struct file *file,
HTT_RX_FP_DATA_FILTER_FLASG3; HTT_RX_FP_DATA_FILTER_FLASG3;
} }
ring_id = ar->dp.rx_mon_status_refill_ring.refill_buf_ring.ring_id; for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id, ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
HAL_RXDMA_MONITOR_STATUS, ret = ath11k_dp_tx_htt_rx_filter_setup(ab, ring_id,
DP_RX_BUFFER_SIZE, &tlv_filter); ar->dp.mac_id + i,
if (ret) { HAL_RXDMA_MONITOR_STATUS,
ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n"); DP_RX_BUFFER_SIZE, &tlv_filter);
goto out;
if (ret) {
ath11k_warn(ab, "failed to set rx filter for moniter status ring\n");
goto out;
}
} }
ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "pktlog filter %d mode %s\n", ath11k_dbg(ab, ATH11K_DBG_WMI, "pktlog filter %d mode %s\n",
filter, ((mode == ATH11K_PKTLOG_MODE_FULL) ? "full" : "lite")); filter, ((mode == ATH11K_PKTLOG_MODE_FULL) ? "full" : "lite"));
ar->debug.pktlog_filter = filter; ar->debug.pktlog_filter = filter;
......
...@@ -25,6 +25,7 @@ enum ath11k_debug_mask { ...@@ -25,6 +25,7 @@ enum ath11k_debug_mask {
ATH11K_DBG_REG = 0x00000200, ATH11K_DBG_REG = 0x00000200,
ATH11K_DBG_TESTMODE = 0x00000400, ATH11K_DBG_TESTMODE = 0x00000400,
ATH11k_DBG_HAL = 0x00000800, ATH11k_DBG_HAL = 0x00000800,
ATH11K_DBG_PCI = 0x00001000,
ATH11K_DBG_ANY = 0xffffffff, ATH11K_DBG_ANY = 0xffffffff,
}; };
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "core.h" #include "core.h"
#include "dp_tx.h" #include "dp_tx.h"
#include "hal_tx.h" #include "hal_tx.h"
#include "hif.h"
#include "debug.h" #include "debug.h"
#include "dp_rx.h" #include "dp_rx.h"
#include "peer.h" #include "peer.h"
...@@ -106,13 +107,120 @@ void ath11k_dp_srng_cleanup(struct ath11k_base *ab, struct dp_srng *ring) ...@@ -106,13 +107,120 @@ void ath11k_dp_srng_cleanup(struct ath11k_base *ab, struct dp_srng *ring)
ring->vaddr_unaligned = NULL; ring->vaddr_unaligned = NULL;
} }
static int ath11k_dp_srng_find_ring_in_mask(int ring_num, const u8 *grp_mask)
{
int ext_group_num;
u8 mask = 1 << ring_num;
for (ext_group_num = 0; ext_group_num < ATH11K_EXT_IRQ_GRP_NUM_MAX;
ext_group_num++) {
if (mask & grp_mask[ext_group_num])
return ext_group_num;
}
return -ENOENT;
}
static int ath11k_dp_srng_calculate_msi_group(struct ath11k_base *ab,
enum hal_ring_type type, int ring_num)
{
const u8 *grp_mask;
switch (type) {
case HAL_WBM2SW_RELEASE:
if (ring_num < 3) {
grp_mask = &ab->hw_params.ring_mask->tx[0];
} else if (ring_num == 3) {
grp_mask = &ab->hw_params.ring_mask->rx_wbm_rel[0];
ring_num = 0;
} else {
return -ENOENT;
}
break;
case HAL_REO_EXCEPTION:
grp_mask = &ab->hw_params.ring_mask->rx_err[0];
break;
case HAL_REO_DST:
grp_mask = &ab->hw_params.ring_mask->rx[0];
break;
case HAL_REO_STATUS:
grp_mask = &ab->hw_params.ring_mask->reo_status[0];
break;
case HAL_RXDMA_MONITOR_STATUS:
case HAL_RXDMA_MONITOR_DST:
grp_mask = &ab->hw_params.ring_mask->rx_mon_status[0];
break;
case HAL_RXDMA_DST:
grp_mask = &ab->hw_params.ring_mask->rxdma2host[0];
break;
case HAL_RXDMA_BUF:
grp_mask = &ab->hw_params.ring_mask->host2rxdma[0];
break;
case HAL_RXDMA_MONITOR_BUF:
case HAL_TCL_DATA:
case HAL_TCL_CMD:
case HAL_REO_CMD:
case HAL_SW2WBM_RELEASE:
case HAL_WBM_IDLE_LINK:
case HAL_TCL_STATUS:
case HAL_REO_REINJECT:
case HAL_CE_SRC:
case HAL_CE_DST:
case HAL_CE_DST_STATUS:
default:
return -ENOENT;
}
return ath11k_dp_srng_find_ring_in_mask(ring_num, grp_mask);
}
static void ath11k_dp_srng_msi_setup(struct ath11k_base *ab,
struct hal_srng_params *ring_params,
enum hal_ring_type type, int ring_num)
{
int msi_group_number, msi_data_count;
u32 msi_data_start, msi_irq_start, addr_lo, addr_hi;
int ret;
ret = ath11k_get_user_msi_vector(ab, "DP",
&msi_data_count, &msi_data_start,
&msi_irq_start);
if (ret)
return;
msi_group_number = ath11k_dp_srng_calculate_msi_group(ab, type,
ring_num);
if (msi_group_number < 0) {
ath11k_dbg(ab, ATH11K_DBG_PCI,
"ring not part of an ext_group; ring_type: %d,ring_num %d",
type, ring_num);
ring_params->msi_addr = 0;
ring_params->msi_data = 0;
return;
}
if (msi_group_number > msi_data_count) {
ath11k_dbg(ab, ATH11K_DBG_PCI,
"multiple msi_groups share one msi, msi_group_num %d",
msi_group_number);
}
ath11k_get_msi_address(ab, &addr_lo, &addr_hi);
ring_params->msi_addr = addr_lo;
ring_params->msi_addr |= (dma_addr_t)(((uint64_t)addr_hi) << 32);
ring_params->msi_data = (msi_group_number % msi_data_count)
+ msi_data_start;
ring_params->flags |= HAL_SRNG_FLAGS_MSI_INTR;
}
int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring, int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring,
enum hal_ring_type type, int ring_num, enum hal_ring_type type, int ring_num,
int mac_id, int num_entries) int mac_id, int num_entries)
{ {
struct hal_srng_params params = { 0 }; struct hal_srng_params params = { 0 };
int entry_sz = ath11k_hal_srng_get_entrysize(type); int entry_sz = ath11k_hal_srng_get_entrysize(ab, type);
int max_entries = ath11k_hal_srng_get_max_entries(type); int max_entries = ath11k_hal_srng_get_max_entries(ab, type);
int ret; int ret;
if (max_entries < 0 || entry_sz < 0) if (max_entries < 0 || entry_sz < 0)
...@@ -135,6 +243,7 @@ int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring, ...@@ -135,6 +243,7 @@ int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring,
params.ring_base_vaddr = ring->vaddr; params.ring_base_vaddr = ring->vaddr;
params.ring_base_paddr = ring->paddr; params.ring_base_paddr = ring->paddr;
params.num_entries = num_entries; params.num_entries = num_entries;
ath11k_dp_srng_msi_setup(ab, &params, type, ring_num + mac_id);
switch (type) { switch (type) {
case HAL_REO_DST: case HAL_REO_DST:
...@@ -159,7 +268,7 @@ int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring, ...@@ -159,7 +268,7 @@ int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring,
break; break;
} }
/* follow through when ring_num >= 3 */ /* follow through when ring_num >= 3 */
/* fall through */ fallthrough;
case HAL_REO_EXCEPTION: case HAL_REO_EXCEPTION:
case HAL_REO_REINJECT: case HAL_REO_REINJECT:
case HAL_REO_CMD: case HAL_REO_CMD:
...@@ -367,7 +476,7 @@ static int ath11k_dp_scatter_idle_link_desc_setup(struct ath11k_base *ab, ...@@ -367,7 +476,7 @@ static int ath11k_dp_scatter_idle_link_desc_setup(struct ath11k_base *ab,
u32 end_offset; u32 end_offset;
n_entries_per_buf = HAL_WBM_IDLE_SCATTER_BUF_SIZE / n_entries_per_buf = HAL_WBM_IDLE_SCATTER_BUF_SIZE /
ath11k_hal_srng_get_entrysize(HAL_WBM_IDLE_LINK); ath11k_hal_srng_get_entrysize(ab, HAL_WBM_IDLE_LINK);
num_scatter_buf = DIV_ROUND_UP(size, HAL_WBM_IDLE_SCATTER_BUF_SIZE); num_scatter_buf = DIV_ROUND_UP(size, HAL_WBM_IDLE_SCATTER_BUF_SIZE);
if (num_scatter_buf > DP_IDLE_SCATTER_BUFS_MAX) if (num_scatter_buf > DP_IDLE_SCATTER_BUFS_MAX)
...@@ -565,7 +674,7 @@ int ath11k_dp_link_desc_setup(struct ath11k_base *ab, ...@@ -565,7 +674,7 @@ int ath11k_dp_link_desc_setup(struct ath11k_base *ab,
return ret; return ret;
/* Setup link desc idle list for HW internal usage */ /* Setup link desc idle list for HW internal usage */
entry_sz = ath11k_hal_srng_get_entrysize(ring_type); entry_sz = ath11k_hal_srng_get_entrysize(ab, ring_type);
tot_mem_sz = entry_sz * n_link_desc; tot_mem_sz = entry_sz * n_link_desc;
/* Setup scatter desc list when the total memory requirement is more */ /* Setup scatter desc list when the total memory requirement is more */
...@@ -622,16 +731,16 @@ int ath11k_dp_service_srng(struct ath11k_base *ab, ...@@ -622,16 +731,16 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
struct napi_struct *napi = &irq_grp->napi; struct napi_struct *napi = &irq_grp->napi;
int grp_id = irq_grp->grp_id; int grp_id = irq_grp->grp_id;
int work_done = 0; int work_done = 0;
int i = 0; int i = 0, j;
int tot_work_done = 0; int tot_work_done = 0;
while (ath11k_tx_ring_mask[grp_id] >> i) { while (ab->hw_params.ring_mask->tx[grp_id] >> i) {
if (ath11k_tx_ring_mask[grp_id] & BIT(i)) if (ab->hw_params.ring_mask->tx[grp_id] & BIT(i))
ath11k_dp_tx_completion_handler(ab, i); ath11k_dp_tx_completion_handler(ab, i);
i++; i++;
} }
if (ath11k_rx_err_ring_mask[grp_id]) { if (ab->hw_params.ring_mask->rx_err[grp_id]) {
work_done = ath11k_dp_process_rx_err(ab, napi, budget); work_done = ath11k_dp_process_rx_err(ab, napi, budget);
budget -= work_done; budget -= work_done;
tot_work_done += work_done; tot_work_done += work_done;
...@@ -639,7 +748,7 @@ int ath11k_dp_service_srng(struct ath11k_base *ab, ...@@ -639,7 +748,7 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
goto done; goto done;
} }
if (ath11k_rx_wbm_rel_ring_mask[grp_id]) { if (ab->hw_params.ring_mask->rx_wbm_rel[grp_id]) {
work_done = ath11k_dp_rx_process_wbm_err(ab, work_done = ath11k_dp_rx_process_wbm_err(ab,
napi, napi,
budget); budget);
...@@ -650,8 +759,8 @@ int ath11k_dp_service_srng(struct ath11k_base *ab, ...@@ -650,8 +759,8 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
goto done; goto done;
} }
if (ath11k_rx_ring_mask[grp_id]) { if (ab->hw_params.ring_mask->rx[grp_id]) {
i = fls(ath11k_rx_ring_mask[grp_id]) - 1; i = fls(ab->hw_params.ring_mask->rx[grp_id]) - 1;
work_done = ath11k_dp_process_rx(ab, i, napi, work_done = ath11k_dp_process_rx(ab, i, napi,
budget); budget);
budget -= work_done; budget -= work_done;
...@@ -660,41 +769,52 @@ int ath11k_dp_service_srng(struct ath11k_base *ab, ...@@ -660,41 +769,52 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
goto done; goto done;
} }
if (rx_mon_status_ring_mask[grp_id]) { if (ab->hw_params.ring_mask->rx_mon_status[grp_id]) {
for (i = 0; i < ab->num_radios; i++) { for (i = 0; i < ab->num_radios; i++) {
if (rx_mon_status_ring_mask[grp_id] & BIT(i)) { for (j = 0; j < ab->hw_params.num_rxmda_per_pdev; j++) {
work_done = int id = i * ab->hw_params.num_rxmda_per_pdev + j;
ath11k_dp_rx_process_mon_rings(ab,
i, napi, if (ab->hw_params.ring_mask->rx_mon_status[grp_id] &
budget); BIT(id)) {
budget -= work_done; work_done =
tot_work_done += work_done; ath11k_dp_rx_process_mon_rings(ab,
id,
napi, budget);
budget -= work_done;
tot_work_done += work_done;
if (budget <= 0)
goto done;
}
} }
if (budget <= 0)
goto done;
} }
} }
if (ath11k_reo_status_ring_mask[grp_id]) if (ab->hw_params.ring_mask->reo_status[grp_id])
ath11k_dp_process_reo_status(ab); ath11k_dp_process_reo_status(ab);
for (i = 0; i < ab->num_radios; i++) { for (i = 0; i < ab->num_radios; i++) {
if (ath11k_rxdma2host_ring_mask[grp_id] & BIT(i)) { for (j = 0; j < ab->hw_params.num_rxmda_per_pdev; j++) {
work_done = ath11k_dp_process_rxdma_err(ab, i, budget); int id = i * ab->hw_params.num_rxmda_per_pdev + j;
budget -= work_done;
tot_work_done += work_done;
}
if (budget <= 0) if (ab->hw_params.ring_mask->rxdma2host[grp_id] & BIT(id)) {
goto done; work_done = ath11k_dp_process_rxdma_err(ab, id, budget);
budget -= work_done;
tot_work_done += work_done;
}
if (budget <= 0)
goto done;
if (ath11k_host2rxdma_ring_mask[grp_id] & BIT(i)) { if (ab->hw_params.ring_mask->host2rxdma[grp_id] & BIT(id)) {
struct ath11k_pdev_dp *dp = &ab->pdevs[i].ar->dp; struct ath11k *ar = ath11k_ab_to_ar(ab, id);
struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring; struct ath11k_pdev_dp *dp = &ar->dp;
struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
ath11k_dp_rxbufs_replenish(ab, i, rx_ring, 0, ath11k_dp_rxbufs_replenish(ab, id, rx_ring, 0,
HAL_RX_BUF_RBM_SW3_BM, HAL_RX_BUF_RBM_SW3_BM,
GFP_ATOMIC); GFP_ATOMIC);
}
} }
} }
/* TODO: Implement handler for other interrupts */ /* TODO: Implement handler for other interrupts */
...@@ -722,6 +842,7 @@ void ath11k_dp_pdev_pre_alloc(struct ath11k_base *ab) ...@@ -722,6 +842,7 @@ void ath11k_dp_pdev_pre_alloc(struct ath11k_base *ab)
struct ath11k *ar; struct ath11k *ar;
struct ath11k_pdev_dp *dp; struct ath11k_pdev_dp *dp;
int i; int i;
int j;
for (i = 0; i < ab->num_radios; i++) { for (i = 0; i < ab->num_radios; i++) {
ar = ab->pdevs[i].ar; ar = ab->pdevs[i].ar;
...@@ -731,8 +852,10 @@ void ath11k_dp_pdev_pre_alloc(struct ath11k_base *ab) ...@@ -731,8 +852,10 @@ void ath11k_dp_pdev_pre_alloc(struct ath11k_base *ab)
spin_lock_init(&dp->rx_refill_buf_ring.idr_lock); spin_lock_init(&dp->rx_refill_buf_ring.idr_lock);
atomic_set(&dp->num_tx_pending, 0); atomic_set(&dp->num_tx_pending, 0);
init_waitqueue_head(&dp->tx_empty_waitq); init_waitqueue_head(&dp->tx_empty_waitq);
idr_init(&dp->rx_mon_status_refill_ring.bufs_idr); for (j = 0; j < ab->hw_params.num_rxmda_per_pdev; j++) {
spin_lock_init(&dp->rx_mon_status_refill_ring.idr_lock); idr_init(&dp->rx_mon_status_refill_ring[j].bufs_idr);
spin_lock_init(&dp->rx_mon_status_refill_ring[j].idr_lock);
}
idr_init(&dp->rxdma_mon_buf_ring.bufs_idr); idr_init(&dp->rxdma_mon_buf_ring.bufs_idr);
spin_lock_init(&dp->rxdma_mon_buf_ring.idr_lock); spin_lock_init(&dp->rxdma_mon_buf_ring.idr_lock);
} }
...@@ -797,13 +920,20 @@ int ath11k_dp_htt_connect(struct ath11k_dp *dp) ...@@ -797,13 +920,20 @@ int ath11k_dp_htt_connect(struct ath11k_dp *dp)
static void ath11k_dp_update_vdev_search(struct ath11k_vif *arvif) static void ath11k_dp_update_vdev_search(struct ath11k_vif *arvif)
{ {
/* For STA mode, enable address search index, /* When v2_map_support is true:for STA mode, enable address
* tcl uses ast_hash value in the descriptor. * search index, tcl uses ast_hash value in the descriptor.
* When v2_map_support is false: for STA mode, dont' enable
* address search index.
*/ */
switch (arvif->vdev_type) { switch (arvif->vdev_type) {
case WMI_VDEV_TYPE_STA: case WMI_VDEV_TYPE_STA:
arvif->hal_addr_search_flags = HAL_TX_ADDRX_EN; if (arvif->ar->ab->hw_params.htt_peer_map_v2) {
arvif->search_type = HAL_TX_ADDR_SEARCH_INDEX; arvif->hal_addr_search_flags = HAL_TX_ADDRX_EN;
arvif->search_type = HAL_TX_ADDR_SEARCH_INDEX;
} else {
arvif->hal_addr_search_flags = HAL_TX_ADDRY_EN;
arvif->search_type = HAL_TX_ADDR_SEARCH_DEFAULT;
}
break; break;
case WMI_VDEV_TYPE_AP: case WMI_VDEV_TYPE_AP:
case WMI_VDEV_TYPE_IBSS: case WMI_VDEV_TYPE_IBSS:
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include "hal_rx.h" #include "hal_rx.h"
#define MAX_RXDMA_PER_PDEV 2
struct ath11k_base; struct ath11k_base;
struct ath11k_peer; struct ath11k_peer;
struct ath11k_dp; struct ath11k_dp;
...@@ -142,12 +144,13 @@ struct ath11k_pdev_dp { ...@@ -142,12 +144,13 @@ struct ath11k_pdev_dp {
atomic_t num_tx_pending; atomic_t num_tx_pending;
wait_queue_head_t tx_empty_waitq; wait_queue_head_t tx_empty_waitq;
struct dp_rxdma_ring rx_refill_buf_ring; struct dp_rxdma_ring rx_refill_buf_ring;
struct dp_srng rxdma_err_dst_ring; struct dp_srng rx_mac_buf_ring[MAX_RXDMA_PER_PDEV];
struct dp_srng rxdma_err_dst_ring[MAX_RXDMA_PER_PDEV];
struct dp_srng rxdma_mon_dst_ring; struct dp_srng rxdma_mon_dst_ring;
struct dp_srng rxdma_mon_desc_ring; struct dp_srng rxdma_mon_desc_ring;
struct dp_rxdma_ring rxdma_mon_buf_ring; struct dp_rxdma_ring rxdma_mon_buf_ring;
struct dp_rxdma_ring rx_mon_status_refill_ring; struct dp_rxdma_ring rx_mon_status_refill_ring[MAX_RXDMA_PER_PDEV];
struct ieee80211_rx_status rx_status; struct ieee80211_rx_status rx_status;
struct ath11k_mon_data mon_data; struct ath11k_mon_data mon_data;
}; };
...@@ -936,11 +939,13 @@ struct htt_rx_ring_tlv_filter { ...@@ -936,11 +939,13 @@ struct htt_rx_ring_tlv_filter {
enum htt_t2h_msg_type { enum htt_t2h_msg_type {
HTT_T2H_MSG_TYPE_VERSION_CONF, HTT_T2H_MSG_TYPE_VERSION_CONF,
HTT_T2H_MSG_TYPE_PEER_MAP = 0x3,
HTT_T2H_MSG_TYPE_PEER_UNMAP = 0x4,
HTT_T2H_MSG_TYPE_RX_ADDBA = 0x5, HTT_T2H_MSG_TYPE_RX_ADDBA = 0x5,
HTT_T2H_MSG_TYPE_PKTLOG = 0x8, HTT_T2H_MSG_TYPE_PKTLOG = 0x8,
HTT_T2H_MSG_TYPE_SEC_IND = 0xb, HTT_T2H_MSG_TYPE_SEC_IND = 0xb,
HTT_T2H_MSG_TYPE_PEER_MAP = 0x1e, HTT_T2H_MSG_TYPE_PEER_MAP2 = 0x1e,
HTT_T2H_MSG_TYPE_PEER_UNMAP = 0x1f, HTT_T2H_MSG_TYPE_PEER_UNMAP2 = 0x1f,
HTT_T2H_MSG_TYPE_PPDU_STATS_IND = 0x1d, HTT_T2H_MSG_TYPE_PPDU_STATS_IND = 0x1d,
HTT_T2H_MSG_TYPE_EXT_STATS_CONF = 0x1c, HTT_T2H_MSG_TYPE_EXT_STATS_CONF = 0x1c,
HTT_T2H_MSG_TYPE_BKPRESSURE_EVENT_IND = 0x24, HTT_T2H_MSG_TYPE_BKPRESSURE_EVENT_IND = 0x24,
......
...@@ -375,7 +375,13 @@ static int ath11k_dp_rxdma_buf_ring_free(struct ath11k *ar, ...@@ -375,7 +375,13 @@ static int ath11k_dp_rxdma_buf_ring_free(struct ath11k *ar,
idr_destroy(&rx_ring->bufs_idr); idr_destroy(&rx_ring->bufs_idr);
spin_unlock_bh(&rx_ring->idr_lock); spin_unlock_bh(&rx_ring->idr_lock);
rx_ring = &dp->rx_mon_status_refill_ring; /* if rxdma1_enable is false, mon_status_refill_ring
* isn't setup, so don't clean.
*/
if (!ar->ab->hw_params.rxdma1_enable)
return 0;
rx_ring = &dp->rx_mon_status_refill_ring[0];
spin_lock_bh(&rx_ring->idr_lock); spin_lock_bh(&rx_ring->idr_lock);
idr_for_each_entry(&rx_ring->bufs_idr, skb, buf_id) { idr_for_each_entry(&rx_ring->bufs_idr, skb, buf_id) {
...@@ -390,21 +396,27 @@ static int ath11k_dp_rxdma_buf_ring_free(struct ath11k *ar, ...@@ -390,21 +396,27 @@ static int ath11k_dp_rxdma_buf_ring_free(struct ath11k *ar,
idr_destroy(&rx_ring->bufs_idr); idr_destroy(&rx_ring->bufs_idr);
spin_unlock_bh(&rx_ring->idr_lock); spin_unlock_bh(&rx_ring->idr_lock);
return 0; return 0;
} }
static int ath11k_dp_rxdma_pdev_buf_free(struct ath11k *ar) static int ath11k_dp_rxdma_pdev_buf_free(struct ath11k *ar)
{ {
struct ath11k_pdev_dp *dp = &ar->dp; struct ath11k_pdev_dp *dp = &ar->dp;
struct ath11k_base *ab = ar->ab;
struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring; struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
int i;
ath11k_dp_rxdma_buf_ring_free(ar, rx_ring); ath11k_dp_rxdma_buf_ring_free(ar, rx_ring);
rx_ring = &dp->rxdma_mon_buf_ring; rx_ring = &dp->rxdma_mon_buf_ring;
ath11k_dp_rxdma_buf_ring_free(ar, rx_ring); ath11k_dp_rxdma_buf_ring_free(ar, rx_ring);
rx_ring = &dp->rx_mon_status_refill_ring; for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
ath11k_dp_rxdma_buf_ring_free(ar, rx_ring); rx_ring = &dp->rx_mon_status_refill_ring[i];
ath11k_dp_rxdma_buf_ring_free(ar, rx_ring);
}
return 0; return 0;
} }
...@@ -416,7 +428,7 @@ static int ath11k_dp_rxdma_ring_buf_setup(struct ath11k *ar, ...@@ -416,7 +428,7 @@ static int ath11k_dp_rxdma_ring_buf_setup(struct ath11k *ar,
int num_entries; int num_entries;
num_entries = rx_ring->refill_buf_ring.size / num_entries = rx_ring->refill_buf_ring.size /
ath11k_hal_srng_get_entrysize(ringtype); ath11k_hal_srng_get_entrysize(ar->ab, ringtype);
rx_ring->bufs_max = num_entries; rx_ring->bufs_max = num_entries;
ath11k_dp_rxbufs_replenish(ar->ab, dp->mac_id, rx_ring, num_entries, ath11k_dp_rxbufs_replenish(ar->ab, dp->mac_id, rx_ring, num_entries,
...@@ -427,15 +439,21 @@ static int ath11k_dp_rxdma_ring_buf_setup(struct ath11k *ar, ...@@ -427,15 +439,21 @@ static int ath11k_dp_rxdma_ring_buf_setup(struct ath11k *ar,
static int ath11k_dp_rxdma_pdev_buf_setup(struct ath11k *ar) static int ath11k_dp_rxdma_pdev_buf_setup(struct ath11k *ar)
{ {
struct ath11k_pdev_dp *dp = &ar->dp; struct ath11k_pdev_dp *dp = &ar->dp;
struct ath11k_base *ab = ar->ab;
struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring; struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
int i;
ath11k_dp_rxdma_ring_buf_setup(ar, rx_ring, HAL_RXDMA_BUF); ath11k_dp_rxdma_ring_buf_setup(ar, rx_ring, HAL_RXDMA_BUF);
rx_ring = &dp->rxdma_mon_buf_ring; if (ar->ab->hw_params.rxdma1_enable) {
ath11k_dp_rxdma_ring_buf_setup(ar, rx_ring, HAL_RXDMA_MONITOR_BUF); rx_ring = &dp->rxdma_mon_buf_ring;
ath11k_dp_rxdma_ring_buf_setup(ar, rx_ring, HAL_RXDMA_MONITOR_BUF);
}
rx_ring = &dp->rx_mon_status_refill_ring; for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
ath11k_dp_rxdma_ring_buf_setup(ar, rx_ring, HAL_RXDMA_MONITOR_STATUS); rx_ring = &dp->rx_mon_status_refill_ring[i];
ath11k_dp_rxdma_ring_buf_setup(ar, rx_ring, HAL_RXDMA_MONITOR_STATUS);
}
return 0; return 0;
} }
...@@ -443,11 +461,21 @@ static int ath11k_dp_rxdma_pdev_buf_setup(struct ath11k *ar) ...@@ -443,11 +461,21 @@ static int ath11k_dp_rxdma_pdev_buf_setup(struct ath11k *ar)
static void ath11k_dp_rx_pdev_srng_free(struct ath11k *ar) static void ath11k_dp_rx_pdev_srng_free(struct ath11k *ar)
{ {
struct ath11k_pdev_dp *dp = &ar->dp; struct ath11k_pdev_dp *dp = &ar->dp;
struct ath11k_base *ab = ar->ab;
int i;
ath11k_dp_srng_cleanup(ab, &dp->rx_refill_buf_ring.refill_buf_ring);
for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
if (ab->hw_params.rx_mac_buf_ring)
ath11k_dp_srng_cleanup(ab, &dp->rx_mac_buf_ring[i]);
ath11k_dp_srng_cleanup(ar->ab, &dp->rx_refill_buf_ring.refill_buf_ring); ath11k_dp_srng_cleanup(ab, &dp->rxdma_err_dst_ring[i]);
ath11k_dp_srng_cleanup(ar->ab, &dp->rxdma_err_dst_ring); ath11k_dp_srng_cleanup(ab,
ath11k_dp_srng_cleanup(ar->ab, &dp->rx_mon_status_refill_ring.refill_buf_ring); &dp->rx_mon_status_refill_ring[i].refill_buf_ring);
ath11k_dp_srng_cleanup(ar->ab, &dp->rxdma_mon_buf_ring.refill_buf_ring); }
ath11k_dp_srng_cleanup(ab, &dp->rxdma_mon_buf_ring.refill_buf_ring);
} }
void ath11k_dp_pdev_reo_cleanup(struct ath11k_base *ab) void ath11k_dp_pdev_reo_cleanup(struct ath11k_base *ab)
...@@ -486,7 +514,9 @@ int ath11k_dp_pdev_reo_setup(struct ath11k_base *ab) ...@@ -486,7 +514,9 @@ int ath11k_dp_pdev_reo_setup(struct ath11k_base *ab)
static int ath11k_dp_rx_pdev_srng_alloc(struct ath11k *ar) static int ath11k_dp_rx_pdev_srng_alloc(struct ath11k *ar)
{ {
struct ath11k_pdev_dp *dp = &ar->dp; struct ath11k_pdev_dp *dp = &ar->dp;
struct ath11k_base *ab = ar->ab;
struct dp_srng *srng = NULL; struct dp_srng *srng = NULL;
int i;
int ret; int ret;
ret = ath11k_dp_srng_setup(ar->ab, ret = ath11k_dp_srng_setup(ar->ab,
...@@ -498,24 +528,50 @@ static int ath11k_dp_rx_pdev_srng_alloc(struct ath11k *ar) ...@@ -498,24 +528,50 @@ static int ath11k_dp_rx_pdev_srng_alloc(struct ath11k *ar)
return ret; return ret;
} }
ret = ath11k_dp_srng_setup(ar->ab, &dp->rxdma_err_dst_ring, if (ar->ab->hw_params.rx_mac_buf_ring) {
HAL_RXDMA_DST, 0, dp->mac_id, for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
DP_RXDMA_ERR_DST_RING_SIZE); ret = ath11k_dp_srng_setup(ar->ab,
if (ret) { &dp->rx_mac_buf_ring[i],
ath11k_warn(ar->ab, "failed to setup rxdma_err_dst_ring\n"); HAL_RXDMA_BUF, 1,
return ret; dp->mac_id + i, 1024);
if (ret) {
ath11k_warn(ar->ab, "failed to setup rx_mac_buf_ring %d\n",
i);
return ret;
}
}
} }
srng = &dp->rx_mon_status_refill_ring.refill_buf_ring; for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
ret = ath11k_dp_srng_setup(ar->ab, ret = ath11k_dp_srng_setup(ar->ab, &dp->rxdma_err_dst_ring[i],
srng, HAL_RXDMA_DST, 0, dp->mac_id + i,
HAL_RXDMA_MONITOR_STATUS, 0, dp->mac_id, DP_RXDMA_ERR_DST_RING_SIZE);
DP_RXDMA_MON_STATUS_RING_SIZE); if (ret) {
if (ret) { ath11k_warn(ar->ab, "failed to setup rxdma_err_dst_ring %d\n", i);
ath11k_warn(ar->ab, return ret;
"failed to setup rx_mon_status_refill_ring\n"); }
return ret;
} }
for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
srng = &dp->rx_mon_status_refill_ring[i].refill_buf_ring;
ret = ath11k_dp_srng_setup(ar->ab,
srng,
HAL_RXDMA_MONITOR_STATUS, 0, dp->mac_id + i,
DP_RXDMA_MON_STATUS_RING_SIZE);
if (ret) {
ath11k_warn(ar->ab,
"failed to setup rx_mon_status_refill_ring %d\n", i);
return ret;
}
}
/* if rxdma1_enable is false, then it doesn't need
* to setup rxdam_mon_buf_ring, rxdma_mon_dst_ring
* and rxdma_mon_desc_ring.
*/
if (!ar->ab->hw_params.rxdma1_enable)
return 0;
ret = ath11k_dp_srng_setup(ar->ab, ret = ath11k_dp_srng_setup(ar->ab,
&dp->rxdma_mon_buf_ring.refill_buf_ring, &dp->rxdma_mon_buf_ring.refill_buf_ring,
HAL_RXDMA_MONITOR_BUF, 0, dp->mac_id, HAL_RXDMA_MONITOR_BUF, 0, dp->mac_id,
...@@ -1569,6 +1625,17 @@ void ath11k_dp_htt_htc_t2h_msg_handler(struct ath11k_base *ab, ...@@ -1569,6 +1625,17 @@ void ath11k_dp_htt_htc_t2h_msg_handler(struct ath11k_base *ab,
complete(&dp->htt_tgt_version_received); complete(&dp->htt_tgt_version_received);
break; break;
case HTT_T2H_MSG_TYPE_PEER_MAP: case HTT_T2H_MSG_TYPE_PEER_MAP:
vdev_id = FIELD_GET(HTT_T2H_PEER_MAP_INFO_VDEV_ID,
resp->peer_map_ev.info);
peer_id = FIELD_GET(HTT_T2H_PEER_MAP_INFO_PEER_ID,
resp->peer_map_ev.info);
peer_mac_h16 = FIELD_GET(HTT_T2H_PEER_MAP_INFO1_MAC_ADDR_H16,
resp->peer_map_ev.info1);
ath11k_dp_get_mac_addr(resp->peer_map_ev.mac_addr_l32,
peer_mac_h16, mac_addr);
ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, 0);
break;
case HTT_T2H_MSG_TYPE_PEER_MAP2:
vdev_id = FIELD_GET(HTT_T2H_PEER_MAP_INFO_VDEV_ID, vdev_id = FIELD_GET(HTT_T2H_PEER_MAP_INFO_VDEV_ID,
resp->peer_map_ev.info); resp->peer_map_ev.info);
peer_id = FIELD_GET(HTT_T2H_PEER_MAP_INFO_PEER_ID, peer_id = FIELD_GET(HTT_T2H_PEER_MAP_INFO_PEER_ID,
...@@ -1582,6 +1649,7 @@ void ath11k_dp_htt_htc_t2h_msg_handler(struct ath11k_base *ab, ...@@ -1582,6 +1649,7 @@ void ath11k_dp_htt_htc_t2h_msg_handler(struct ath11k_base *ab,
ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash); ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash);
break; break;
case HTT_T2H_MSG_TYPE_PEER_UNMAP: case HTT_T2H_MSG_TYPE_PEER_UNMAP:
case HTT_T2H_MSG_TYPE_PEER_UNMAP2:
peer_id = FIELD_GET(HTT_T2H_PEER_UNMAP_INFO_PEER_ID, peer_id = FIELD_GET(HTT_T2H_PEER_UNMAP_INFO_PEER_ID,
resp->peer_unmap_ev.info); resp->peer_unmap_ev.info);
ath11k_peer_unmap_event(ab, peer_id); ath11k_peer_unmap_event(ab, peer_id);
...@@ -2719,20 +2787,25 @@ int ath11k_dp_rx_mon_status_bufs_replenish(struct ath11k_base *ab, int mac_id, ...@@ -2719,20 +2787,25 @@ int ath11k_dp_rx_mon_status_bufs_replenish(struct ath11k_base *ab, int mac_id,
static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id, static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id,
int *budget, struct sk_buff_head *skb_list) int *budget, struct sk_buff_head *skb_list)
{ {
struct ath11k *ar = ab->pdevs[mac_id].ar; struct ath11k *ar;
struct ath11k_pdev_dp *dp = &ar->dp; struct ath11k_pdev_dp *dp;
struct dp_rxdma_ring *rx_ring = &dp->rx_mon_status_refill_ring; struct dp_rxdma_ring *rx_ring;
struct hal_srng *srng; struct hal_srng *srng;
void *rx_mon_status_desc; void *rx_mon_status_desc;
struct sk_buff *skb; struct sk_buff *skb;
struct ath11k_skb_rxcb *rxcb; struct ath11k_skb_rxcb *rxcb;
struct hal_tlv_hdr *tlv; struct hal_tlv_hdr *tlv;
u32 cookie; u32 cookie;
int buf_id; int buf_id, srng_id;
dma_addr_t paddr; dma_addr_t paddr;
u8 rbm; u8 rbm;
int num_buffs_reaped = 0; int num_buffs_reaped = 0;
ar = ab->pdevs[ath11k_hw_mac_id_to_pdev_id(&ab->hw_params, mac_id)].ar;
dp = &ar->dp;
srng_id = ath11k_hw_mac_id_to_srng_id(&ab->hw_params, mac_id);
rx_ring = &dp->rx_mon_status_refill_ring[srng_id];
srng = &ab->hal.srng_list[rx_ring->refill_buf_ring.ring_id]; srng = &ab->hal.srng_list[rx_ring->refill_buf_ring.ring_id];
spin_lock_bh(&srng->lock); spin_lock_bh(&srng->lock);
...@@ -2813,7 +2886,7 @@ static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id, ...@@ -2813,7 +2886,7 @@ static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id,
int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id, int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
struct napi_struct *napi, int budget) struct napi_struct *napi, int budget)
{ {
struct ath11k *ar = ab->pdevs[mac_id].ar; struct ath11k *ar = ath11k_ab_to_ar(ab, mac_id);
enum hal_rx_mon_status hal_status; enum hal_rx_mon_status hal_status;
struct sk_buff *skb; struct sk_buff *skb;
struct sk_buff_head skb_list; struct sk_buff_head skb_list;
...@@ -3709,8 +3782,7 @@ static bool ath11k_dp_rx_h_reo_err(struct ath11k *ar, struct sk_buff *msdu, ...@@ -3709,8 +3782,7 @@ static bool ath11k_dp_rx_h_reo_err(struct ath11k *ar, struct sk_buff *msdu,
* instead, it is good to drop such packets in mac80211 * instead, it is good to drop such packets in mac80211
* after incrementing the replay counters. * after incrementing the replay counters.
*/ */
fallthrough;
/* fall through */
default: default:
/* TODO: Review other errors and process them to mac80211 /* TODO: Review other errors and process them to mac80211
* as appropriate. * as appropriate.
...@@ -3820,7 +3892,7 @@ int ath11k_dp_rx_process_wbm_err(struct ath11k_base *ab, ...@@ -3820,7 +3892,7 @@ int ath11k_dp_rx_process_wbm_err(struct ath11k_base *ab,
int total_num_buffs_reaped = 0; int total_num_buffs_reaped = 0;
int ret, i; int ret, i;
for (i = 0; i < MAX_RADIOS; i++) for (i = 0; i < ab->num_radios; i++)
__skb_queue_head_init(&msdu_list[i]); __skb_queue_head_init(&msdu_list[i]);
srng = &ab->hal.srng_list[dp->rx_rel_ring.ring_id]; srng = &ab->hal.srng_list[dp->rx_rel_ring.ring_id];
...@@ -3923,9 +3995,9 @@ int ath11k_dp_rx_process_wbm_err(struct ath11k_base *ab, ...@@ -3923,9 +3995,9 @@ int ath11k_dp_rx_process_wbm_err(struct ath11k_base *ab,
int ath11k_dp_process_rxdma_err(struct ath11k_base *ab, int mac_id, int budget) int ath11k_dp_process_rxdma_err(struct ath11k_base *ab, int mac_id, int budget)
{ {
struct ath11k *ar = ab->pdevs[mac_id].ar; struct ath11k *ar;
struct dp_srng *err_ring = &ar->dp.rxdma_err_dst_ring; struct dp_srng *err_ring;
struct dp_rxdma_ring *rx_ring = &ar->dp.rx_refill_buf_ring; struct dp_rxdma_ring *rx_ring;
struct dp_link_desc_bank *link_desc_banks = ab->dp.link_desc_banks; struct dp_link_desc_bank *link_desc_banks = ab->dp.link_desc_banks;
struct hal_srng *srng; struct hal_srng *srng;
u32 msdu_cookies[HAL_NUM_RX_MSDUS_PER_LINK_DESC]; u32 msdu_cookies[HAL_NUM_RX_MSDUS_PER_LINK_DESC];
...@@ -3944,6 +4016,11 @@ int ath11k_dp_process_rxdma_err(struct ath11k_base *ab, int mac_id, int budget) ...@@ -3944,6 +4016,11 @@ int ath11k_dp_process_rxdma_err(struct ath11k_base *ab, int mac_id, int budget)
int i; int i;
int buf_id; int buf_id;
ar = ab->pdevs[ath11k_hw_mac_id_to_pdev_id(&ab->hw_params, mac_id)].ar;
err_ring = &ar->dp.rxdma_err_dst_ring[ath11k_hw_mac_id_to_srng_id(&ab->hw_params,
mac_id)];
rx_ring = &ar->dp.rx_refill_buf_ring;
srng = &ab->hal.srng_list[err_ring->ring_id]; srng = &ab->hal.srng_list[err_ring->ring_id];
spin_lock_bh(&srng->lock); spin_lock_bh(&srng->lock);
...@@ -4097,6 +4174,7 @@ int ath11k_dp_rx_pdev_alloc(struct ath11k_base *ab, int mac_id) ...@@ -4097,6 +4174,7 @@ int ath11k_dp_rx_pdev_alloc(struct ath11k_base *ab, int mac_id)
struct ath11k *ar = ab->pdevs[mac_id].ar; struct ath11k *ar = ab->pdevs[mac_id].ar;
struct ath11k_pdev_dp *dp = &ar->dp; struct ath11k_pdev_dp *dp = &ar->dp;
u32 ring_id; u32 ring_id;
int i;
int ret; int ret;
ret = ath11k_dp_rx_pdev_srng_alloc(ar); ret = ath11k_dp_rx_pdev_srng_alloc(ar);
...@@ -4119,14 +4197,33 @@ int ath11k_dp_rx_pdev_alloc(struct ath11k_base *ab, int mac_id) ...@@ -4119,14 +4197,33 @@ int ath11k_dp_rx_pdev_alloc(struct ath11k_base *ab, int mac_id)
return ret; return ret;
} }
ring_id = dp->rxdma_err_dst_ring.ring_id; if (ab->hw_params.rx_mac_buf_ring) {
ret = ath11k_dp_tx_htt_srng_setup(ab, ring_id, mac_id, HAL_RXDMA_DST); for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
if (ret) { ring_id = dp->rx_mac_buf_ring[i].ring_id;
ath11k_warn(ab, "failed to configure rxdma_err_dest_ring %d\n", ret = ath11k_dp_tx_htt_srng_setup(ab, ring_id,
ret); mac_id + i, HAL_RXDMA_BUF);
return ret; if (ret) {
ath11k_warn(ab, "failed to configure rx_mac_buf_ring%d %d\n",
i, ret);
return ret;
}
}
}
for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
ring_id = dp->rxdma_err_dst_ring[i].ring_id;
ret = ath11k_dp_tx_htt_srng_setup(ab, ring_id,
mac_id + i, HAL_RXDMA_DST);
if (ret) {
ath11k_warn(ab, "failed to configure rxdma_err_dest_ring%d %d\n",
i, ret);
return ret;
}
} }
if (!ab->hw_params.rxdma1_enable)
goto config_refill_ring;
ring_id = dp->rxdma_mon_buf_ring.refill_buf_ring.ring_id; ring_id = dp->rxdma_mon_buf_ring.refill_buf_ring.ring_id;
ret = ath11k_dp_tx_htt_srng_setup(ab, ring_id, ret = ath11k_dp_tx_htt_srng_setup(ab, ring_id,
mac_id, HAL_RXDMA_MONITOR_BUF); mac_id, HAL_RXDMA_MONITOR_BUF);
...@@ -4151,15 +4248,20 @@ int ath11k_dp_rx_pdev_alloc(struct ath11k_base *ab, int mac_id) ...@@ -4151,15 +4248,20 @@ int ath11k_dp_rx_pdev_alloc(struct ath11k_base *ab, int mac_id)
ret); ret);
return ret; return ret;
} }
ring_id = dp->rx_mon_status_refill_ring.refill_buf_ring.ring_id;
ret = ath11k_dp_tx_htt_srng_setup(ab, ring_id, mac_id, config_refill_ring:
HAL_RXDMA_MONITOR_STATUS); for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
if (ret) { ring_id = dp->rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
ath11k_warn(ab, ret = ath11k_dp_tx_htt_srng_setup(ab, ring_id, mac_id + i,
"failed to configure mon_status_refill_ring %d\n", HAL_RXDMA_MONITOR_STATUS);
ret); if (ret) {
return ret; ath11k_warn(ab,
"failed to configure mon_status_refill_ring%d %d\n",
i, ret);
return ret;
}
} }
return 0; return 0;
} }
...@@ -4777,7 +4879,7 @@ static void ath11k_dp_rx_mon_status_process_tlv(struct ath11k *ar, ...@@ -4777,7 +4879,7 @@ static void ath11k_dp_rx_mon_status_process_tlv(struct ath11k *ar,
static int ath11k_dp_mon_process_rx(struct ath11k_base *ab, int mac_id, static int ath11k_dp_mon_process_rx(struct ath11k_base *ab, int mac_id,
struct napi_struct *napi, int budget) struct napi_struct *napi, int budget)
{ {
struct ath11k *ar = ab->pdevs[mac_id].ar; struct ath11k *ar = ath11k_ab_to_ar(ab, mac_id);
struct ath11k_pdev_dp *dp = &ar->dp; struct ath11k_pdev_dp *dp = &ar->dp;
struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data; struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data;
int num_buffs_reaped = 0; int num_buffs_reaped = 0;
...@@ -4793,7 +4895,7 @@ static int ath11k_dp_mon_process_rx(struct ath11k_base *ab, int mac_id, ...@@ -4793,7 +4895,7 @@ static int ath11k_dp_mon_process_rx(struct ath11k_base *ab, int mac_id,
int ath11k_dp_rx_process_mon_rings(struct ath11k_base *ab, int mac_id, int ath11k_dp_rx_process_mon_rings(struct ath11k_base *ab, int mac_id,
struct napi_struct *napi, int budget) struct napi_struct *napi, int budget)
{ {
struct ath11k *ar = ab->pdevs[mac_id].ar; struct ath11k *ar = ath11k_ab_to_ar(ab, mac_id);
int ret = 0; int ret = 0;
if (test_bit(ATH11K_FLAG_MONITOR_ENABLED, &ar->monitor_flags)) if (test_bit(ATH11K_FLAG_MONITOR_ENABLED, &ar->monitor_flags))
...@@ -4832,9 +4934,15 @@ int ath11k_dp_rx_pdev_mon_attach(struct ath11k *ar) ...@@ -4832,9 +4934,15 @@ int ath11k_dp_rx_pdev_mon_attach(struct ath11k *ar)
return ret; return ret;
} }
/* if rxdma1_enable is false, no need to setup
* rxdma_mon_desc_ring.
*/
if (!ar->ab->hw_params.rxdma1_enable)
return 0;
dp_srng = &dp->rxdma_mon_desc_ring; dp_srng = &dp->rxdma_mon_desc_ring;
n_link_desc = dp_srng->size / n_link_desc = dp_srng->size /
ath11k_hal_srng_get_entrysize(HAL_RXDMA_MONITOR_DESC); ath11k_hal_srng_get_entrysize(ar->ab, HAL_RXDMA_MONITOR_DESC);
mon_desc_srng = mon_desc_srng =
&ar->ab->hal.srng_list[dp->rxdma_mon_desc_ring.ring_id]; &ar->ab->hal.srng_list[dp->rxdma_mon_desc_ring.ring_id];
...@@ -4848,6 +4956,7 @@ int ath11k_dp_rx_pdev_mon_attach(struct ath11k *ar) ...@@ -4848,6 +4956,7 @@ int ath11k_dp_rx_pdev_mon_attach(struct ath11k *ar)
pmon->mon_last_linkdesc_paddr = 0; pmon->mon_last_linkdesc_paddr = 0;
pmon->mon_last_buf_cookie = DP_RX_DESC_COOKIE_MAX + 1; pmon->mon_last_buf_cookie = DP_RX_DESC_COOKIE_MAX + 1;
spin_lock_init(&pmon->mon_lock); spin_lock_init(&pmon->mon_lock);
return 0; return 0;
} }
......
...@@ -110,7 +110,12 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif, ...@@ -110,7 +110,12 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
tcl_ring_sel: tcl_ring_sel:
tcl_ring_retry = false; tcl_ring_retry = false;
ti.ring_id = ring_selector % DP_TCL_NUM_RING_MAX; /* For some chip, it can only use tcl0 to tx */
if (ar->ab->hw_params.tcl_0_only)
ti.ring_id = 0;
else
ti.ring_id = ring_selector % DP_TCL_NUM_RING_MAX;
ring_map |= BIT(ti.ring_id); ring_map |= BIT(ti.ring_id);
tx_ring = &dp->tx_ring[ti.ring_id]; tx_ring = &dp->tx_ring[ti.ring_id];
...@@ -221,7 +226,8 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif, ...@@ -221,7 +226,8 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
* checking this ring earlier for each pkt tx. * checking this ring earlier for each pkt tx.
* Restart ring selection if some rings are not checked yet. * Restart ring selection if some rings are not checked yet.
*/ */
if (ring_map != (BIT(DP_TCL_NUM_RING_MAX) - 1)) { if (ring_map != (BIT(DP_TCL_NUM_RING_MAX) - 1) &&
!ar->ab->hw_params.tcl_0_only) {
tcl_ring_retry = true; tcl_ring_retry = true;
ring_selector++; ring_selector++;
} }
...@@ -633,14 +639,28 @@ ath11k_dp_tx_get_ring_id_type(struct ath11k_base *ab, ...@@ -633,14 +639,28 @@ ath11k_dp_tx_get_ring_id_type(struct ath11k_base *ab,
switch (ring_type) { switch (ring_type) {
case HAL_RXDMA_BUF: case HAL_RXDMA_BUF:
lmac_ring_id_offset = mac_id * HAL_SRNG_RINGS_PER_LMAC; lmac_ring_id_offset = mac_id * HAL_SRNG_RINGS_PER_LMAC;
if (!(ring_id == (HAL_SRNG_RING_ID_WMAC1_SW2RXDMA0_BUF +
lmac_ring_id_offset) || /* for QCA6390, host fills rx buffer to fw and fw fills to
ring_id == (HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_BUF + * rxbuf ring for each rxdma
lmac_ring_id_offset))) { */
ret = -EINVAL; if (!ab->hw_params.rx_mac_buf_ring) {
if (!(ring_id == (HAL_SRNG_RING_ID_WMAC1_SW2RXDMA0_BUF +
lmac_ring_id_offset) ||
ring_id == (HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_BUF +
lmac_ring_id_offset))) {
ret = -EINVAL;
}
*htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
*htt_ring_type = HTT_SW_TO_HW_RING;
} else {
if (ring_id == HAL_SRNG_RING_ID_WMAC1_SW2RXDMA0_BUF) {
*htt_ring_id = HTT_HOST1_TO_FW_RXBUF_RING;
*htt_ring_type = HTT_SW_TO_SW_RING;
} else {
*htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
*htt_ring_type = HTT_SW_TO_HW_RING;
}
} }
*htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
*htt_ring_type = HTT_SW_TO_HW_RING;
break; break;
case HAL_RXDMA_DST: case HAL_RXDMA_DST:
*htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING; *htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING;
...@@ -720,7 +740,7 @@ int ath11k_dp_tx_htt_srng_setup(struct ath11k_base *ab, u32 ring_id, ...@@ -720,7 +740,7 @@ int ath11k_dp_tx_htt_srng_setup(struct ath11k_base *ab, u32 ring_id,
cmd->ring_base_addr_hi = (u64)params.ring_base_paddr >> cmd->ring_base_addr_hi = (u64)params.ring_base_paddr >>
HAL_ADDR_MSB_REG_SHIFT; HAL_ADDR_MSB_REG_SHIFT;
ret = ath11k_hal_srng_get_entrysize(ring_type); ret = ath11k_hal_srng_get_entrysize(ab, ring_type);
if (ret < 0) if (ret < 0)
goto err_free; goto err_free;
...@@ -968,8 +988,9 @@ ath11k_dp_tx_htt_h2t_ext_stats_req(struct ath11k *ar, u8 type, ...@@ -968,8 +988,9 @@ ath11k_dp_tx_htt_h2t_ext_stats_req(struct ath11k *ar, u8 type,
int ath11k_dp_tx_htt_monitor_mode_ring_config(struct ath11k *ar, bool reset) int ath11k_dp_tx_htt_monitor_mode_ring_config(struct ath11k *ar, bool reset)
{ {
struct ath11k_pdev_dp *dp = &ar->dp; struct ath11k_pdev_dp *dp = &ar->dp;
struct ath11k_base *ab = ar->ab;
struct htt_rx_ring_tlv_filter tlv_filter = {0}; struct htt_rx_ring_tlv_filter tlv_filter = {0};
int ret = 0, ring_id = 0; int ret = 0, ring_id = 0, i;
ring_id = dp->rxdma_mon_buf_ring.refill_buf_ring.ring_id; ring_id = dp->rxdma_mon_buf_ring.refill_buf_ring.ring_id;
...@@ -998,16 +1019,20 @@ int ath11k_dp_tx_htt_monitor_mode_ring_config(struct ath11k *ar, bool reset) ...@@ -998,16 +1019,20 @@ int ath11k_dp_tx_htt_monitor_mode_ring_config(struct ath11k *ar, bool reset)
if (ret) if (ret)
return ret; return ret;
ring_id = dp->rx_mon_status_refill_ring.refill_buf_ring.ring_id; for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
if (!reset) ring_id = dp->rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
tlv_filter.rx_filter = if (!reset)
HTT_RX_MON_FILTER_TLV_FLAGS_MON_STATUS_RING; tlv_filter.rx_filter =
else HTT_RX_MON_FILTER_TLV_FLAGS_MON_STATUS_RING;
tlv_filter = ath11k_mac_mon_status_filter_default; else
tlv_filter = ath11k_mac_mon_status_filter_default;
ret = ath11k_dp_tx_htt_rx_filter_setup(ab, ring_id,
dp->mac_id + i,
HAL_RXDMA_MONITOR_STATUS,
DP_RXDMA_REFILL_RING_SIZE,
&tlv_filter);
}
ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, dp->mac_id,
HAL_RXDMA_MONITOR_STATUS,
DP_RXDMA_REFILL_RING_SIZE,
&tlv_filter);
return ret; return ret;
} }
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include "hal_desc.h" #include "hal_desc.h"
#include "hif.h" #include "hif.h"
static const struct hal_srng_config hw_srng_config[] = { static const struct hal_srng_config hw_srng_config_template[] = {
/* TODO: max_rings can populated by querying HW capabilities */ /* TODO: max_rings can populated by querying HW capabilities */
{ /* REO_DST */ { /* REO_DST */
.start_ring_id = HAL_SRNG_RING_ID_REO2SW1, .start_ring_id = HAL_SRNG_RING_ID_REO2SW1,
...@@ -16,14 +16,6 @@ static const struct hal_srng_config hw_srng_config[] = { ...@@ -16,14 +16,6 @@ static const struct hal_srng_config hw_srng_config[] = {
.entry_size = sizeof(struct hal_reo_dest_ring) >> 2, .entry_size = sizeof(struct hal_reo_dest_ring) >> 2,
.lmac_ring = false, .lmac_ring = false,
.ring_dir = HAL_SRNG_DIR_DST, .ring_dir = HAL_SRNG_DIR_DST,
.reg_start = {
HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_BASE_LSB,
HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_HP,
},
.reg_size = {
HAL_REO2_RING_BASE_LSB - HAL_REO1_RING_BASE_LSB,
HAL_REO2_RING_HP - HAL_REO1_RING_HP,
},
.max_size = HAL_REO_REO2SW1_RING_BASE_MSB_RING_SIZE, .max_size = HAL_REO_REO2SW1_RING_BASE_MSB_RING_SIZE,
}, },
{ /* REO_EXCEPTION */ { /* REO_EXCEPTION */
...@@ -36,10 +28,6 @@ static const struct hal_srng_config hw_srng_config[] = { ...@@ -36,10 +28,6 @@ static const struct hal_srng_config hw_srng_config[] = {
.entry_size = sizeof(struct hal_reo_dest_ring) >> 2, .entry_size = sizeof(struct hal_reo_dest_ring) >> 2,
.lmac_ring = false, .lmac_ring = false,
.ring_dir = HAL_SRNG_DIR_DST, .ring_dir = HAL_SRNG_DIR_DST,
.reg_start = {
HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_TCL_RING_BASE_LSB,
HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_TCL_RING_HP,
},
.max_size = HAL_REO_REO2TCL_RING_BASE_MSB_RING_SIZE, .max_size = HAL_REO_REO2TCL_RING_BASE_MSB_RING_SIZE,
}, },
{ /* REO_REINJECT */ { /* REO_REINJECT */
...@@ -48,10 +36,6 @@ static const struct hal_srng_config hw_srng_config[] = { ...@@ -48,10 +36,6 @@ static const struct hal_srng_config hw_srng_config[] = {
.entry_size = sizeof(struct hal_reo_entrance_ring) >> 2, .entry_size = sizeof(struct hal_reo_entrance_ring) >> 2,
.lmac_ring = false, .lmac_ring = false,
.ring_dir = HAL_SRNG_DIR_SRC, .ring_dir = HAL_SRNG_DIR_SRC,
.reg_start = {
HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_BASE_LSB,
HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_HP,
},
.max_size = HAL_REO_SW2REO_RING_BASE_MSB_RING_SIZE, .max_size = HAL_REO_SW2REO_RING_BASE_MSB_RING_SIZE,
}, },
{ /* REO_CMD */ { /* REO_CMD */
...@@ -61,10 +45,6 @@ static const struct hal_srng_config hw_srng_config[] = { ...@@ -61,10 +45,6 @@ static const struct hal_srng_config hw_srng_config[] = {
sizeof(struct hal_reo_get_queue_stats)) >> 2, sizeof(struct hal_reo_get_queue_stats)) >> 2,
.lmac_ring = false, .lmac_ring = false,
.ring_dir = HAL_SRNG_DIR_SRC, .ring_dir = HAL_SRNG_DIR_SRC,
.reg_start = {
HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_RING_BASE_LSB,
HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_HP,
},
.max_size = HAL_REO_CMD_RING_BASE_MSB_RING_SIZE, .max_size = HAL_REO_CMD_RING_BASE_MSB_RING_SIZE,
}, },
{ /* REO_STATUS */ { /* REO_STATUS */
...@@ -74,11 +54,6 @@ static const struct hal_srng_config hw_srng_config[] = { ...@@ -74,11 +54,6 @@ static const struct hal_srng_config hw_srng_config[] = {
sizeof(struct hal_reo_get_queue_stats_status)) >> 2, sizeof(struct hal_reo_get_queue_stats_status)) >> 2,
.lmac_ring = false, .lmac_ring = false,
.ring_dir = HAL_SRNG_DIR_DST, .ring_dir = HAL_SRNG_DIR_DST,
.reg_start = {
HAL_SEQ_WCSS_UMAC_REO_REG +
HAL_REO_STATUS_RING_BASE_LSB,
HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_HP,
},
.max_size = HAL_REO_STATUS_RING_BASE_MSB_RING_SIZE, .max_size = HAL_REO_STATUS_RING_BASE_MSB_RING_SIZE,
}, },
{ /* TCL_DATA */ { /* TCL_DATA */
...@@ -88,14 +63,6 @@ static const struct hal_srng_config hw_srng_config[] = { ...@@ -88,14 +63,6 @@ static const struct hal_srng_config hw_srng_config[] = {
sizeof(struct hal_tcl_data_cmd)) >> 2, sizeof(struct hal_tcl_data_cmd)) >> 2,
.lmac_ring = false, .lmac_ring = false,
.ring_dir = HAL_SRNG_DIR_SRC, .ring_dir = HAL_SRNG_DIR_SRC,
.reg_start = {
HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB,
HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_HP,
},
.reg_size = {
HAL_TCL2_RING_BASE_LSB - HAL_TCL1_RING_BASE_LSB,
HAL_TCL2_RING_HP - HAL_TCL1_RING_HP,
},
.max_size = HAL_SW2TCL1_RING_BASE_MSB_RING_SIZE, .max_size = HAL_SW2TCL1_RING_BASE_MSB_RING_SIZE,
}, },
{ /* TCL_CMD */ { /* TCL_CMD */
...@@ -105,10 +72,6 @@ static const struct hal_srng_config hw_srng_config[] = { ...@@ -105,10 +72,6 @@ static const struct hal_srng_config hw_srng_config[] = {
sizeof(struct hal_tcl_gse_cmd)) >> 2, sizeof(struct hal_tcl_gse_cmd)) >> 2,
.lmac_ring = false, .lmac_ring = false,
.ring_dir = HAL_SRNG_DIR_SRC, .ring_dir = HAL_SRNG_DIR_SRC,
.reg_start = {
HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_RING_BASE_LSB,
HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_RING_HP,
},
.max_size = HAL_SW2TCL1_CMD_RING_BASE_MSB_RING_SIZE, .max_size = HAL_SW2TCL1_CMD_RING_BASE_MSB_RING_SIZE,
}, },
{ /* TCL_STATUS */ { /* TCL_STATUS */
...@@ -118,11 +81,6 @@ static const struct hal_srng_config hw_srng_config[] = { ...@@ -118,11 +81,6 @@ static const struct hal_srng_config hw_srng_config[] = {
sizeof(struct hal_tcl_status_ring)) >> 2, sizeof(struct hal_tcl_status_ring)) >> 2,
.lmac_ring = false, .lmac_ring = false,
.ring_dir = HAL_SRNG_DIR_DST, .ring_dir = HAL_SRNG_DIR_DST,
.reg_start = {
HAL_SEQ_WCSS_UMAC_TCL_REG +
HAL_TCL_STATUS_RING_BASE_LSB,
HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_HP,
},
.max_size = HAL_TCL_STATUS_RING_BASE_MSB_RING_SIZE, .max_size = HAL_TCL_STATUS_RING_BASE_MSB_RING_SIZE,
}, },
{ /* CE_SRC */ { /* CE_SRC */
...@@ -344,7 +302,7 @@ static void ath11k_hal_free_cont_wrp(struct ath11k_base *ab) ...@@ -344,7 +302,7 @@ static void ath11k_hal_free_cont_wrp(struct ath11k_base *ab)
static void ath11k_hal_ce_dst_setup(struct ath11k_base *ab, static void ath11k_hal_ce_dst_setup(struct ath11k_base *ab,
struct hal_srng *srng, int ring_num) struct hal_srng *srng, int ring_num)
{ {
const struct hal_srng_config *srng_config = &hw_srng_config[HAL_CE_DST]; struct hal_srng_config *srng_config = &ab->hal.srng_config[HAL_CE_DST];
u32 addr; u32 addr;
u32 val; u32 val;
...@@ -371,7 +329,7 @@ static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab, ...@@ -371,7 +329,7 @@ static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab,
if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) { if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) {
ath11k_hif_write32(ab, reg_base + ath11k_hif_write32(ab, reg_base +
HAL_REO1_RING_MSI1_BASE_LSB_OFFSET, HAL_REO1_RING_MSI1_BASE_LSB_OFFSET(ab),
(u32)srng->msi_addr); (u32)srng->msi_addr);
val = FIELD_PREP(HAL_REO1_RING_MSI1_BASE_MSB_ADDR, val = FIELD_PREP(HAL_REO1_RING_MSI1_BASE_MSB_ADDR,
...@@ -379,10 +337,10 @@ static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab, ...@@ -379,10 +337,10 @@ static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab,
HAL_ADDR_MSB_REG_SHIFT)) | HAL_ADDR_MSB_REG_SHIFT)) |
HAL_REO1_RING_MSI1_BASE_MSB_MSI1_ENABLE; HAL_REO1_RING_MSI1_BASE_MSB_MSI1_ENABLE;
ath11k_hif_write32(ab, reg_base + ath11k_hif_write32(ab, reg_base +
HAL_REO1_RING_MSI1_BASE_MSB_OFFSET, val); HAL_REO1_RING_MSI1_BASE_MSB_OFFSET(ab), val);
ath11k_hif_write32(ab, ath11k_hif_write32(ab,
reg_base + HAL_REO1_RING_MSI1_DATA_OFFSET, reg_base + HAL_REO1_RING_MSI1_DATA_OFFSET(ab),
srng->msi_data); srng->msi_data);
} }
...@@ -393,11 +351,11 @@ static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab, ...@@ -393,11 +351,11 @@ static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab,
HAL_ADDR_MSB_REG_SHIFT)) | HAL_ADDR_MSB_REG_SHIFT)) |
FIELD_PREP(HAL_REO1_RING_BASE_MSB_RING_SIZE, FIELD_PREP(HAL_REO1_RING_BASE_MSB_RING_SIZE,
(srng->entry_size * srng->num_entries)); (srng->entry_size * srng->num_entries));
ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_BASE_MSB_OFFSET, val); ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_BASE_MSB_OFFSET(ab), val);
val = FIELD_PREP(HAL_REO1_RING_ID_RING_ID, srng->ring_id) | val = FIELD_PREP(HAL_REO1_RING_ID_RING_ID, srng->ring_id) |
FIELD_PREP(HAL_REO1_RING_ID_ENTRY_SIZE, srng->entry_size); FIELD_PREP(HAL_REO1_RING_ID_ENTRY_SIZE, srng->entry_size);
ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_ID_OFFSET, val); ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_ID_OFFSET(ab), val);
/* interrupt setup */ /* interrupt setup */
val = FIELD_PREP(HAL_REO1_RING_PRDR_INT_SETUP_INTR_TMR_THOLD, val = FIELD_PREP(HAL_REO1_RING_PRDR_INT_SETUP_INTR_TMR_THOLD,
...@@ -408,21 +366,21 @@ static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab, ...@@ -408,21 +366,21 @@ static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab,
srng->entry_size)); srng->entry_size));
ath11k_hif_write32(ab, ath11k_hif_write32(ab,
reg_base + HAL_REO1_RING_PRODUCER_INT_SETUP_OFFSET, reg_base + HAL_REO1_RING_PRODUCER_INT_SETUP_OFFSET(ab),
val); val);
hp_addr = hal->rdp.paddr + hp_addr = hal->rdp.paddr +
((unsigned long)srng->u.dst_ring.hp_addr - ((unsigned long)srng->u.dst_ring.hp_addr -
(unsigned long)hal->rdp.vaddr); (unsigned long)hal->rdp.vaddr);
ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_HP_ADDR_LSB_OFFSET, ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_HP_ADDR_LSB_OFFSET(ab),
hp_addr & HAL_ADDR_LSB_REG_MASK); hp_addr & HAL_ADDR_LSB_REG_MASK);
ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_HP_ADDR_MSB_OFFSET, ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_HP_ADDR_MSB_OFFSET(ab),
hp_addr >> HAL_ADDR_MSB_REG_SHIFT); hp_addr >> HAL_ADDR_MSB_REG_SHIFT);
/* Initialize head and tail pointers to indicate ring is empty */ /* Initialize head and tail pointers to indicate ring is empty */
reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2]; reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2];
ath11k_hif_write32(ab, reg_base, 0); ath11k_hif_write32(ab, reg_base, 0);
ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_TP_OFFSET, 0); ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_TP_OFFSET(ab), 0);
*srng->u.dst_ring.hp_addr = 0; *srng->u.dst_ring.hp_addr = 0;
reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0]; reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R0];
...@@ -435,7 +393,7 @@ static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab, ...@@ -435,7 +393,7 @@ static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab,
val |= HAL_REO1_RING_MISC_MSI_SWAP; val |= HAL_REO1_RING_MISC_MSI_SWAP;
val |= HAL_REO1_RING_MISC_SRNG_ENABLE; val |= HAL_REO1_RING_MISC_SRNG_ENABLE;
ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_MISC_OFFSET, val); ath11k_hif_write32(ab, reg_base + HAL_REO1_RING_MISC_OFFSET(ab), val);
} }
static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab, static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab,
...@@ -450,7 +408,7 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab, ...@@ -450,7 +408,7 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab,
if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) { if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) {
ath11k_hif_write32(ab, reg_base + ath11k_hif_write32(ab, reg_base +
HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET, HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET(ab),
(u32)srng->msi_addr); (u32)srng->msi_addr);
val = FIELD_PREP(HAL_TCL1_RING_MSI1_BASE_MSB_ADDR, val = FIELD_PREP(HAL_TCL1_RING_MSI1_BASE_MSB_ADDR,
...@@ -458,11 +416,11 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab, ...@@ -458,11 +416,11 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab,
HAL_ADDR_MSB_REG_SHIFT)) | HAL_ADDR_MSB_REG_SHIFT)) |
HAL_TCL1_RING_MSI1_BASE_MSB_MSI1_ENABLE; HAL_TCL1_RING_MSI1_BASE_MSB_MSI1_ENABLE;
ath11k_hif_write32(ab, reg_base + ath11k_hif_write32(ab, reg_base +
HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET, HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET(ab),
val); val);
ath11k_hif_write32(ab, reg_base + ath11k_hif_write32(ab, reg_base +
HAL_TCL1_RING_MSI1_DATA_OFFSET, HAL_TCL1_RING_MSI1_DATA_OFFSET(ab),
srng->msi_data); srng->msi_data);
} }
...@@ -473,10 +431,10 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab, ...@@ -473,10 +431,10 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab,
HAL_ADDR_MSB_REG_SHIFT)) | HAL_ADDR_MSB_REG_SHIFT)) |
FIELD_PREP(HAL_TCL1_RING_BASE_MSB_RING_SIZE, FIELD_PREP(HAL_TCL1_RING_BASE_MSB_RING_SIZE,
(srng->entry_size * srng->num_entries)); (srng->entry_size * srng->num_entries));
ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_BASE_MSB_OFFSET, val); ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_BASE_MSB_OFFSET(ab), val);
val = FIELD_PREP(HAL_REO1_RING_ID_ENTRY_SIZE, srng->entry_size); val = FIELD_PREP(HAL_REO1_RING_ID_ENTRY_SIZE, srng->entry_size);
ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_ID_OFFSET, val); ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_ID_OFFSET(ab), val);
/* interrupt setup */ /* interrupt setup */
/* NOTE: IPQ8074 v2 requires the interrupt timer threshold in the /* NOTE: IPQ8074 v2 requires the interrupt timer threshold in the
...@@ -490,7 +448,7 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab, ...@@ -490,7 +448,7 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab,
srng->entry_size)); srng->entry_size));
ath11k_hif_write32(ab, ath11k_hif_write32(ab,
reg_base + HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET, reg_base + HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET(ab),
val); val);
val = 0; val = 0;
...@@ -499,7 +457,7 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab, ...@@ -499,7 +457,7 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab,
srng->u.src_ring.low_threshold); srng->u.src_ring.low_threshold);
} }
ath11k_hif_write32(ab, ath11k_hif_write32(ab,
reg_base + HAL_TCL1_RING_CONSR_INT_SETUP_IX1_OFFSET, reg_base + HAL_TCL1_RING_CONSR_INT_SETUP_IX1_OFFSET(ab),
val); val);
if (srng->ring_id != HAL_SRNG_RING_ID_WBM_IDLE_LINK) { if (srng->ring_id != HAL_SRNG_RING_ID_WBM_IDLE_LINK) {
...@@ -507,10 +465,10 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab, ...@@ -507,10 +465,10 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab,
((unsigned long)srng->u.src_ring.tp_addr - ((unsigned long)srng->u.src_ring.tp_addr -
(unsigned long)hal->rdp.vaddr); (unsigned long)hal->rdp.vaddr);
ath11k_hif_write32(ab, ath11k_hif_write32(ab,
reg_base + HAL_TCL1_RING_TP_ADDR_LSB_OFFSET, reg_base + HAL_TCL1_RING_TP_ADDR_LSB_OFFSET(ab),
tp_addr & HAL_ADDR_LSB_REG_MASK); tp_addr & HAL_ADDR_LSB_REG_MASK);
ath11k_hif_write32(ab, ath11k_hif_write32(ab,
reg_base + HAL_TCL1_RING_TP_ADDR_MSB_OFFSET, reg_base + HAL_TCL1_RING_TP_ADDR_MSB_OFFSET(ab),
tp_addr >> HAL_ADDR_MSB_REG_SHIFT); tp_addr >> HAL_ADDR_MSB_REG_SHIFT);
} }
...@@ -534,7 +492,7 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab, ...@@ -534,7 +492,7 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab,
val |= HAL_TCL1_RING_MISC_SRNG_ENABLE; val |= HAL_TCL1_RING_MISC_SRNG_ENABLE;
ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_MISC_OFFSET, val); ath11k_hif_write32(ab, reg_base + HAL_TCL1_RING_MISC_OFFSET(ab), val);
} }
static void ath11k_hal_srng_hw_init(struct ath11k_base *ab, static void ath11k_hal_srng_hw_init(struct ath11k_base *ab,
...@@ -550,7 +508,7 @@ static int ath11k_hal_srng_get_ring_id(struct ath11k_base *ab, ...@@ -550,7 +508,7 @@ static int ath11k_hal_srng_get_ring_id(struct ath11k_base *ab,
enum hal_ring_type type, enum hal_ring_type type,
int ring_num, int mac_id) int ring_num, int mac_id)
{ {
const struct hal_srng_config *srng_config = &hw_srng_config[type]; struct hal_srng_config *srng_config = &ab->hal.srng_config[type];
int ring_id; int ring_id;
if (ring_num >= srng_config->max_rings) { if (ring_num >= srng_config->max_rings) {
...@@ -568,26 +526,26 @@ static int ath11k_hal_srng_get_ring_id(struct ath11k_base *ab, ...@@ -568,26 +526,26 @@ static int ath11k_hal_srng_get_ring_id(struct ath11k_base *ab,
return ring_id; return ring_id;
} }
int ath11k_hal_srng_get_entrysize(u32 ring_type) int ath11k_hal_srng_get_entrysize(struct ath11k_base *ab, u32 ring_type)
{ {
const struct hal_srng_config *srng_config; struct hal_srng_config *srng_config;
if (WARN_ON(ring_type >= HAL_MAX_RING_TYPES)) if (WARN_ON(ring_type >= HAL_MAX_RING_TYPES))
return -EINVAL; return -EINVAL;
srng_config = &hw_srng_config[ring_type]; srng_config = &ab->hal.srng_config[ring_type];
return (srng_config->entry_size << 2); return (srng_config->entry_size << 2);
} }
int ath11k_hal_srng_get_max_entries(u32 ring_type) int ath11k_hal_srng_get_max_entries(struct ath11k_base *ab, u32 ring_type)
{ {
const struct hal_srng_config *srng_config; struct hal_srng_config *srng_config;
if (WARN_ON(ring_type >= HAL_MAX_RING_TYPES)) if (WARN_ON(ring_type >= HAL_MAX_RING_TYPES))
return -EINVAL; return -EINVAL;
srng_config = &hw_srng_config[ring_type]; srng_config = &ab->hal.srng_config[ring_type];
return (srng_config->max_size / srng_config->entry_size); return (srng_config->max_size / srng_config->entry_size);
} }
...@@ -1003,7 +961,7 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type, ...@@ -1003,7 +961,7 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type,
struct hal_srng_params *params) struct hal_srng_params *params)
{ {
struct ath11k_hal *hal = &ab->hal; struct ath11k_hal *hal = &ab->hal;
const struct hal_srng_config *srng_config = &hw_srng_config[type]; struct hal_srng_config *srng_config = &ab->hal.srng_config[type];
struct hal_srng *srng; struct hal_srng *srng;
int ring_id; int ring_id;
u32 lmac_idx; u32 lmac_idx;
...@@ -1027,6 +985,8 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type, ...@@ -1027,6 +985,8 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type,
params->intr_batch_cntr_thres_entries; params->intr_batch_cntr_thres_entries;
srng->intr_timer_thres_us = params->intr_timer_thres_us; srng->intr_timer_thres_us = params->intr_timer_thres_us;
srng->flags = params->flags; srng->flags = params->flags;
srng->msi_addr = params->msi_addr;
srng->msi_data = params->msi_data;
srng->initialized = 1; srng->initialized = 1;
spin_lock_init(&srng->lock); spin_lock_init(&srng->lock);
...@@ -1085,7 +1045,7 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type, ...@@ -1085,7 +1045,7 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type,
} else { } else {
srng->u.dst_ring.tp_addr = srng->u.dst_ring.tp_addr =
(u32 *)((unsigned long)ab->mem + reg_base + (u32 *)((unsigned long)ab->mem + reg_base +
(HAL_REO1_RING_TP - HAL_REO1_RING_HP)); (HAL_REO1_RING_TP(ab) - HAL_REO1_RING_HP(ab)));
} }
} }
...@@ -1102,6 +1062,56 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type, ...@@ -1102,6 +1062,56 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type,
return ring_id; return ring_id;
} }
static int ath11k_hal_srng_create_config(struct ath11k_base *ab)
{
struct ath11k_hal *hal = &ab->hal;
struct hal_srng_config *s;
hal->srng_config = kmemdup(hw_srng_config_template,
sizeof(hw_srng_config_template),
GFP_KERNEL);
if (!hal->srng_config)
return -ENOMEM;
s = &hal->srng_config[HAL_REO_DST];
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_BASE_LSB(ab);
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_RING_HP(ab);
s->reg_size[0] = HAL_REO2_RING_BASE_LSB(ab) - HAL_REO1_RING_BASE_LSB(ab);
s->reg_size[1] = HAL_REO2_RING_HP(ab) - HAL_REO1_RING_HP(ab);
s = &hal->srng_config[HAL_REO_EXCEPTION];
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_TCL_RING_BASE_LSB(ab);
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_TCL_RING_HP(ab);
s = &hal->srng_config[HAL_REO_REINJECT];
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_BASE_LSB;
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_SW2REO_RING_HP;
s = &hal->srng_config[HAL_REO_CMD];
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_RING_BASE_LSB;
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_CMD_HP;
s = &hal->srng_config[HAL_REO_STATUS];
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_RING_BASE_LSB(ab);
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO_STATUS_HP(ab);
s = &hal->srng_config[HAL_TCL_DATA];
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_BASE_LSB(ab);
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL1_RING_HP;
s->reg_size[0] = HAL_TCL2_RING_BASE_LSB(ab) - HAL_TCL1_RING_BASE_LSB(ab);
s->reg_size[1] = HAL_TCL2_RING_HP - HAL_TCL1_RING_HP;
s = &hal->srng_config[HAL_TCL_CMD];
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_RING_BASE_LSB(ab);
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_RING_HP;
s = &hal->srng_config[HAL_TCL_STATUS];
s->reg_start[0] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_BASE_LSB(ab);
s->reg_start[1] = HAL_SEQ_WCSS_UMAC_TCL_REG + HAL_TCL_STATUS_RING_HP;
return 0;
}
int ath11k_hal_srng_init(struct ath11k_base *ab) int ath11k_hal_srng_init(struct ath11k_base *ab)
{ {
struct ath11k_hal *hal = &ab->hal; struct ath11k_hal *hal = &ab->hal;
...@@ -1109,7 +1119,9 @@ int ath11k_hal_srng_init(struct ath11k_base *ab) ...@@ -1109,7 +1119,9 @@ int ath11k_hal_srng_init(struct ath11k_base *ab)
memset(hal, 0, sizeof(*hal)); memset(hal, 0, sizeof(*hal));
hal->srng_config = hw_srng_config; ret = ath11k_hal_srng_create_config(ab);
if (ret)
goto err_hal;
ret = ath11k_hal_alloc_cont_rdp(ab); ret = ath11k_hal_alloc_cont_rdp(ab);
if (ret) if (ret)
...@@ -1127,12 +1139,17 @@ int ath11k_hal_srng_init(struct ath11k_base *ab) ...@@ -1127,12 +1139,17 @@ int ath11k_hal_srng_init(struct ath11k_base *ab)
err_hal: err_hal:
return ret; return ret;
} }
EXPORT_SYMBOL(ath11k_hal_srng_init);
void ath11k_hal_srng_deinit(struct ath11k_base *ab) void ath11k_hal_srng_deinit(struct ath11k_base *ab)
{ {
struct ath11k_hal *hal = &ab->hal;
ath11k_hal_free_cont_rdp(ab); ath11k_hal_free_cont_rdp(ab);
ath11k_hal_free_cont_wrp(ab); ath11k_hal_free_cont_wrp(ab);
kfree(hal->srng_config);
} }
EXPORT_SYMBOL(ath11k_hal_srng_deinit);
void ath11k_hal_dump_srng_stats(struct ath11k_base *ab) void ath11k_hal_dump_srng_stats(struct ath11k_base *ab)
{ {
...@@ -1142,10 +1159,10 @@ void ath11k_hal_dump_srng_stats(struct ath11k_base *ab) ...@@ -1142,10 +1159,10 @@ void ath11k_hal_dump_srng_stats(struct ath11k_base *ab)
int i; int i;
ath11k_err(ab, "Last interrupt received for each CE:\n"); ath11k_err(ab, "Last interrupt received for each CE:\n");
for (i = 0; i < CE_COUNT; i++) { for (i = 0; i < ab->hw_params.ce_count; i++) {
ce_pipe = &ab->ce.ce_pipe[i]; ce_pipe = &ab->ce.ce_pipe[i];
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR) if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
continue; continue;
ath11k_err(ab, "CE_id %d pipe_num %d %ums before\n", ath11k_err(ab, "CE_id %d pipe_num %d %ums before\n",
......
...@@ -46,40 +46,47 @@ struct ath11k_base; ...@@ -46,40 +46,47 @@ struct ath11k_base;
/* SW2TCL(x) R0 ring configuration address */ /* SW2TCL(x) R0 ring configuration address */
#define HAL_TCL1_RING_CMN_CTRL_REG 0x00000014 #define HAL_TCL1_RING_CMN_CTRL_REG 0x00000014
#define HAL_TCL1_RING_DSCP_TID_MAP 0x0000002c #define HAL_TCL1_RING_DSCP_TID_MAP 0x0000002c
#define HAL_TCL1_RING_BASE_LSB 0x00000510 #define HAL_TCL1_RING_BASE_LSB(ab) ab->hw_params.regs->hal_tcl1_ring_base_lsb
#define HAL_TCL1_RING_BASE_MSB 0x00000514 #define HAL_TCL1_RING_BASE_MSB(ab) ab->hw_params.regs->hal_tcl1_ring_base_msb
#define HAL_TCL1_RING_ID 0x00000518 #define HAL_TCL1_RING_ID(ab) ab->hw_params.regs->hal_tcl1_ring_id
#define HAL_TCL1_RING_MISC 0x00000520 #define HAL_TCL1_RING_MISC(ab) ab->hw_params.regs->hal_tcl1_ring_misc
#define HAL_TCL1_RING_TP_ADDR_LSB 0x0000052c #define HAL_TCL1_RING_TP_ADDR_LSB(ab) \
#define HAL_TCL1_RING_TP_ADDR_MSB 0x00000530 ab->hw_params.regs->hal_tcl1_ring_tp_addr_lsb
#define HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0 0x00000540 #define HAL_TCL1_RING_TP_ADDR_MSB(ab) \
#define HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1 0x00000544 ab->hw_params.regs->hal_tcl1_ring_tp_addr_msb
#define HAL_TCL1_RING_MSI1_BASE_LSB 0x00000558 #define HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0(ab) \
#define HAL_TCL1_RING_MSI1_BASE_MSB 0x0000055c ab->hw_params.regs->hal_tcl1_ring_consumer_int_setup_ix0
#define HAL_TCL1_RING_MSI1_DATA 0x00000560 #define HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1(ab) \
#define HAL_TCL2_RING_BASE_LSB 0x00000568 ab->hw_params.regs->hal_tcl1_ring_consumer_int_setup_ix1
#define HAL_TCL_RING_BASE_LSB 0x00000618 #define HAL_TCL1_RING_MSI1_BASE_LSB(ab) \
ab->hw_params.regs->hal_tcl1_ring_msi1_base_lsb
#define HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET \ #define HAL_TCL1_RING_MSI1_BASE_MSB(ab) \
(HAL_TCL1_RING_MSI1_BASE_LSB - HAL_TCL1_RING_BASE_LSB) ab->hw_params.regs->hal_tcl1_ring_msi1_base_msb
#define HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET \ #define HAL_TCL1_RING_MSI1_DATA(ab) \
(HAL_TCL1_RING_MSI1_BASE_MSB - HAL_TCL1_RING_BASE_LSB) ab->hw_params.regs->hal_tcl1_ring_msi1_data
#define HAL_TCL1_RING_MSI1_DATA_OFFSET \ #define HAL_TCL2_RING_BASE_LSB(ab) ab->hw_params.regs->hal_tcl2_ring_base_lsb
(HAL_TCL1_RING_MSI1_DATA - HAL_TCL1_RING_BASE_LSB) #define HAL_TCL_RING_BASE_LSB(ab) ab->hw_params.regs->hal_tcl_ring_base_lsb
#define HAL_TCL1_RING_BASE_MSB_OFFSET \
(HAL_TCL1_RING_BASE_MSB - HAL_TCL1_RING_BASE_LSB) #define HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET(ab) \
#define HAL_TCL1_RING_ID_OFFSET \ (HAL_TCL1_RING_MSI1_BASE_LSB(ab) - HAL_TCL1_RING_BASE_LSB(ab))
(HAL_TCL1_RING_ID - HAL_TCL1_RING_BASE_LSB) #define HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET(ab) \
#define HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET \ (HAL_TCL1_RING_MSI1_BASE_MSB(ab) - HAL_TCL1_RING_BASE_LSB(ab))
(HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0 - HAL_TCL1_RING_BASE_LSB) #define HAL_TCL1_RING_MSI1_DATA_OFFSET(ab) \
#define HAL_TCL1_RING_CONSR_INT_SETUP_IX1_OFFSET \ (HAL_TCL1_RING_MSI1_DATA(ab) - HAL_TCL1_RING_BASE_LSB(ab))
(HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1 - HAL_TCL1_RING_BASE_LSB) #define HAL_TCL1_RING_BASE_MSB_OFFSET(ab) \
#define HAL_TCL1_RING_TP_ADDR_LSB_OFFSET \ (HAL_TCL1_RING_BASE_MSB(ab) - HAL_TCL1_RING_BASE_LSB(ab))
(HAL_TCL1_RING_TP_ADDR_LSB - HAL_TCL1_RING_BASE_LSB) #define HAL_TCL1_RING_ID_OFFSET(ab) \
#define HAL_TCL1_RING_TP_ADDR_MSB_OFFSET \ (HAL_TCL1_RING_ID(ab) - HAL_TCL1_RING_BASE_LSB(ab))
(HAL_TCL1_RING_TP_ADDR_MSB - HAL_TCL1_RING_BASE_LSB) #define HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET(ab) \
#define HAL_TCL1_RING_MISC_OFFSET \ (HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0(ab) - HAL_TCL1_RING_BASE_LSB(ab))
(HAL_TCL1_RING_MISC - HAL_TCL1_RING_BASE_LSB) #define HAL_TCL1_RING_CONSR_INT_SETUP_IX1_OFFSET(ab) \
(HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1(ab) - HAL_TCL1_RING_BASE_LSB(ab))
#define HAL_TCL1_RING_TP_ADDR_LSB_OFFSET(ab) \
(HAL_TCL1_RING_TP_ADDR_LSB(ab) - HAL_TCL1_RING_BASE_LSB(ab))
#define HAL_TCL1_RING_TP_ADDR_MSB_OFFSET(ab) \
(HAL_TCL1_RING_TP_ADDR_MSB(ab) - HAL_TCL1_RING_BASE_LSB(ab))
#define HAL_TCL1_RING_MISC_OFFSET(ab) \
(HAL_TCL1_RING_MISC(ab) - HAL_TCL1_RING_BASE_LSB(ab))
/* SW2TCL(x) R2 ring pointers (head/tail) address */ /* SW2TCL(x) R2 ring pointers (head/tail) address */
#define HAL_TCL1_RING_HP 0x00002000 #define HAL_TCL1_RING_HP 0x00002000
...@@ -91,7 +98,8 @@ struct ath11k_base; ...@@ -91,7 +98,8 @@ struct ath11k_base;
(HAL_TCL1_RING_TP - HAL_TCL1_RING_HP) (HAL_TCL1_RING_TP - HAL_TCL1_RING_HP)
/* TCL STATUS ring address */ /* TCL STATUS ring address */
#define HAL_TCL_STATUS_RING_BASE_LSB 0x00000720 #define HAL_TCL_STATUS_RING_BASE_LSB(ab) \
ab->hw_params.regs->hal_tcl_status_ring_base_lsb
#define HAL_TCL_STATUS_RING_HP 0x00002030 #define HAL_TCL_STATUS_RING_HP 0x00002030
/* REO2SW(x) R0 ring configuration address */ /* REO2SW(x) R0 ring configuration address */
...@@ -100,51 +108,63 @@ struct ath11k_base; ...@@ -100,51 +108,63 @@ struct ath11k_base;
#define HAL_REO1_DEST_RING_CTRL_IX_1 0x00000008 #define HAL_REO1_DEST_RING_CTRL_IX_1 0x00000008
#define HAL_REO1_DEST_RING_CTRL_IX_2 0x0000000c #define HAL_REO1_DEST_RING_CTRL_IX_2 0x0000000c
#define HAL_REO1_DEST_RING_CTRL_IX_3 0x00000010 #define HAL_REO1_DEST_RING_CTRL_IX_3 0x00000010
#define HAL_REO1_RING_BASE_LSB 0x0000029c #define HAL_REO1_RING_BASE_LSB(ab) ab->hw_params.regs->hal_reo1_ring_base_lsb
#define HAL_REO1_RING_BASE_MSB 0x000002a0 #define HAL_REO1_RING_BASE_MSB(ab) ab->hw_params.regs->hal_reo1_ring_base_msb
#define HAL_REO1_RING_ID 0x000002a4 #define HAL_REO1_RING_ID(ab) ab->hw_params.regs->hal_reo1_ring_id
#define HAL_REO1_RING_MISC 0x000002ac #define HAL_REO1_RING_MISC(ab) ab->hw_params.regs->hal_reo1_ring_misc
#define HAL_REO1_RING_HP_ADDR_LSB 0x000002b0 #define HAL_REO1_RING_HP_ADDR_LSB(ab) \
#define HAL_REO1_RING_HP_ADDR_MSB 0x000002b4 ab->hw_params.regs->hal_reo1_ring_hp_addr_lsb
#define HAL_REO1_RING_PRODUCER_INT_SETUP 0x000002c0 #define HAL_REO1_RING_HP_ADDR_MSB(ab) \
#define HAL_REO1_RING_MSI1_BASE_LSB 0x000002e4 ab->hw_params.regs->hal_reo1_ring_hp_addr_msb
#define HAL_REO1_RING_MSI1_BASE_MSB 0x000002e8 #define HAL_REO1_RING_PRODUCER_INT_SETUP(ab) \
#define HAL_REO1_RING_MSI1_DATA 0x000002ec ab->hw_params.regs->hal_reo1_ring_producer_int_setup
#define HAL_REO2_RING_BASE_LSB 0x000002f4 #define HAL_REO1_RING_MSI1_BASE_LSB(ab) \
#define HAL_REO1_AGING_THRESH_IX_0 0x00000564 ab->hw_params.regs->hal_reo1_ring_msi1_base_lsb
#define HAL_REO1_AGING_THRESH_IX_1 0x00000568 #define HAL_REO1_RING_MSI1_BASE_MSB(ab) \
#define HAL_REO1_AGING_THRESH_IX_2 0x0000056c ab->hw_params.regs->hal_reo1_ring_msi1_base_msb
#define HAL_REO1_AGING_THRESH_IX_3 0x00000570 #define HAL_REO1_RING_MSI1_DATA(ab) \
ab->hw_params.regs->hal_reo1_ring_msi1_data
#define HAL_REO1_RING_MSI1_BASE_LSB_OFFSET \ #define HAL_REO2_RING_BASE_LSB(ab) ab->hw_params.regs->hal_reo2_ring_base_lsb
(HAL_REO1_RING_MSI1_BASE_LSB - HAL_REO1_RING_BASE_LSB) #define HAL_REO1_AGING_THRESH_IX_0(ab) \
#define HAL_REO1_RING_MSI1_BASE_MSB_OFFSET \ ab->hw_params.regs->hal_reo1_aging_thresh_ix_0
(HAL_REO1_RING_MSI1_BASE_MSB - HAL_REO1_RING_BASE_LSB) #define HAL_REO1_AGING_THRESH_IX_1(ab) \
#define HAL_REO1_RING_MSI1_DATA_OFFSET \ ab->hw_params.regs->hal_reo1_aging_thresh_ix_1
(HAL_REO1_RING_MSI1_DATA - HAL_REO1_RING_BASE_LSB) #define HAL_REO1_AGING_THRESH_IX_2(ab) \
#define HAL_REO1_RING_BASE_MSB_OFFSET \ ab->hw_params.regs->hal_reo1_aging_thresh_ix_2
(HAL_REO1_RING_BASE_MSB - HAL_REO1_RING_BASE_LSB) #define HAL_REO1_AGING_THRESH_IX_3(ab) \
#define HAL_REO1_RING_ID_OFFSET (HAL_REO1_RING_ID - HAL_REO1_RING_BASE_LSB) ab->hw_params.regs->hal_reo1_aging_thresh_ix_3
#define HAL_REO1_RING_PRODUCER_INT_SETUP_OFFSET \
(HAL_REO1_RING_PRODUCER_INT_SETUP - HAL_REO1_RING_BASE_LSB) #define HAL_REO1_RING_MSI1_BASE_LSB_OFFSET(ab) \
#define HAL_REO1_RING_HP_ADDR_LSB_OFFSET \ (HAL_REO1_RING_MSI1_BASE_LSB(ab) - HAL_REO1_RING_BASE_LSB(ab))
(HAL_REO1_RING_HP_ADDR_LSB - HAL_REO1_RING_BASE_LSB) #define HAL_REO1_RING_MSI1_BASE_MSB_OFFSET(ab) \
#define HAL_REO1_RING_HP_ADDR_MSB_OFFSET \ (HAL_REO1_RING_MSI1_BASE_MSB(ab) - HAL_REO1_RING_BASE_LSB(ab))
(HAL_REO1_RING_HP_ADDR_MSB - HAL_REO1_RING_BASE_LSB) #define HAL_REO1_RING_MSI1_DATA_OFFSET(ab) \
#define HAL_REO1_RING_MISC_OFFSET (HAL_REO1_RING_MISC - HAL_REO1_RING_BASE_LSB) (HAL_REO1_RING_MSI1_DATA(ab) - HAL_REO1_RING_BASE_LSB(ab))
#define HAL_REO1_RING_BASE_MSB_OFFSET(ab) \
(HAL_REO1_RING_BASE_MSB(ab) - HAL_REO1_RING_BASE_LSB(ab))
#define HAL_REO1_RING_ID_OFFSET(ab) (HAL_REO1_RING_ID(ab) - HAL_REO1_RING_BASE_LSB(ab))
#define HAL_REO1_RING_PRODUCER_INT_SETUP_OFFSET(ab) \
(HAL_REO1_RING_PRODUCER_INT_SETUP(ab) - HAL_REO1_RING_BASE_LSB(ab))
#define HAL_REO1_RING_HP_ADDR_LSB_OFFSET(ab) \
(HAL_REO1_RING_HP_ADDR_LSB(ab) - HAL_REO1_RING_BASE_LSB(ab))
#define HAL_REO1_RING_HP_ADDR_MSB_OFFSET(ab) \
(HAL_REO1_RING_HP_ADDR_MSB(ab) - HAL_REO1_RING_BASE_LSB(ab))
#define HAL_REO1_RING_MISC_OFFSET(ab) \
(HAL_REO1_RING_MISC(ab) - HAL_REO1_RING_BASE_LSB(ab))
/* REO2SW(x) R2 ring pointers (head/tail) address */ /* REO2SW(x) R2 ring pointers (head/tail) address */
#define HAL_REO1_RING_HP 0x00003038 #define HAL_REO1_RING_HP(ab) ab->hw_params.regs->hal_reo1_ring_hp
#define HAL_REO1_RING_TP 0x0000303c #define HAL_REO1_RING_TP(ab) ab->hw_params.regs->hal_reo1_ring_tp
#define HAL_REO2_RING_HP 0x00003040 #define HAL_REO2_RING_HP(ab) ab->hw_params.regs->hal_reo2_ring_hp
#define HAL_REO1_RING_TP_OFFSET (HAL_REO1_RING_TP - HAL_REO1_RING_HP) #define HAL_REO1_RING_TP_OFFSET(ab) (HAL_REO1_RING_TP(ab) - HAL_REO1_RING_HP(ab))
/* REO2TCL R0 ring configuration address */ /* REO2TCL R0 ring configuration address */
#define HAL_REO_TCL_RING_BASE_LSB 0x000003fc #define HAL_REO_TCL_RING_BASE_LSB(ab) \
ab->hw_params.regs->hal_reo_tcl_ring_base_lsb
/* REO2TCL R2 ring pointer (head/tail) address */ /* REO2TCL R2 ring pointer (head/tail) address */
#define HAL_REO_TCL_RING_HP 0x00003058 #define HAL_REO_TCL_RING_HP(ab) ab->hw_params.regs->hal_reo_tcl_ring_hp
/* REO CMD R0 address */ /* REO CMD R0 address */
#define HAL_REO_CMD_RING_BASE_LSB 0x00000194 #define HAL_REO_CMD_RING_BASE_LSB 0x00000194
...@@ -168,8 +188,9 @@ struct ath11k_base; ...@@ -168,8 +188,9 @@ struct ath11k_base;
#define HAL_CE_DST_STATUS_RING_HP 0x00000408 #define HAL_CE_DST_STATUS_RING_HP 0x00000408
/* REO status address */ /* REO status address */
#define HAL_REO_STATUS_RING_BASE_LSB 0x00000504 #define HAL_REO_STATUS_RING_BASE_LSB(ab) \
#define HAL_REO_STATUS_HP 0x00003070 ab->hw_params.regs->hal_reo_status_ring_base_lsb
#define HAL_REO_STATUS_HP(ab) ab->hw_params.regs->hal_reo_status_hp
/* WBM Idle R0 address */ /* WBM Idle R0 address */
#define HAL_WBM_IDLE_LINK_RING_BASE_LSB 0x00000860 #define HAL_WBM_IDLE_LINK_RING_BASE_LSB 0x00000860
...@@ -458,6 +479,8 @@ struct hal_srng_params { ...@@ -458,6 +479,8 @@ struct hal_srng_params {
u32 flags; u32 flags;
u32 max_buffer_len; u32 max_buffer_len;
u32 low_threshold; u32 low_threshold;
dma_addr_t msi_addr;
u32 msi_data;
/* Add more params as needed */ /* Add more params as needed */
}; };
...@@ -839,7 +862,7 @@ struct ath11k_hal { ...@@ -839,7 +862,7 @@ struct ath11k_hal {
struct hal_srng srng_list[HAL_SRNG_RING_ID_MAX]; struct hal_srng srng_list[HAL_SRNG_RING_ID_MAX];
/* SRNG configuration table */ /* SRNG configuration table */
const struct hal_srng_config *srng_config; struct hal_srng_config *srng_config;
/* Remote pointer memory for HW/FW updates */ /* Remote pointer memory for HW/FW updates */
struct { struct {
...@@ -885,8 +908,8 @@ void ath11k_hal_ce_src_set_desc(void *buf, dma_addr_t paddr, u32 len, u32 id, ...@@ -885,8 +908,8 @@ void ath11k_hal_ce_src_set_desc(void *buf, dma_addr_t paddr, u32 len, u32 id,
u8 byte_swap_data); u8 byte_swap_data);
void ath11k_hal_ce_dst_set_desc(void *buf, dma_addr_t paddr); void ath11k_hal_ce_dst_set_desc(void *buf, dma_addr_t paddr);
u32 ath11k_hal_ce_dst_status_get_length(void *buf); u32 ath11k_hal_ce_dst_status_get_length(void *buf);
int ath11k_hal_srng_get_entrysize(u32 ring_type); int ath11k_hal_srng_get_entrysize(struct ath11k_base *ab, u32 ring_type);
int ath11k_hal_srng_get_max_entries(u32 ring_type); int ath11k_hal_srng_get_max_entries(struct ath11k_base *ab, u32 ring_type);
void ath11k_hal_srng_get_params(struct ath11k_base *ab, struct hal_srng *srng, void ath11k_hal_srng_get_params(struct ath11k_base *ab, struct hal_srng *srng,
struct hal_srng_params *params); struct hal_srng_params *params);
u32 *ath11k_hal_srng_dst_get_next_entry(struct ath11k_base *ab, u32 *ath11k_hal_srng_dst_get_next_entry(struct ath11k_base *ab,
......
...@@ -786,7 +786,7 @@ void ath11k_hal_reo_init_cmd_ring(struct ath11k_base *ab, ...@@ -786,7 +786,7 @@ void ath11k_hal_reo_init_cmd_ring(struct ath11k_base *ab,
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
entry_size = ath11k_hal_srng_get_entrysize(HAL_REO_CMD); entry_size = ath11k_hal_srng_get_entrysize(ab, HAL_REO_CMD);
ath11k_hal_srng_get_params(ab, srng, &params); ath11k_hal_srng_get_params(ab, srng, &params);
entry = (u8 *)params.ring_base_vaddr; entry = (u8 *)params.ring_base_vaddr;
...@@ -813,13 +813,13 @@ void ath11k_hal_reo_hw_setup(struct ath11k_base *ab, u32 ring_hash_map) ...@@ -813,13 +813,13 @@ void ath11k_hal_reo_hw_setup(struct ath11k_base *ab, u32 ring_hash_map)
FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE, 1); FIELD_PREP(HAL_REO1_GEN_ENABLE_AGING_FLUSH_ENABLE, 1);
ath11k_hif_write32(ab, reo_base + HAL_REO1_GEN_ENABLE, val); ath11k_hif_write32(ab, reo_base + HAL_REO1_GEN_ENABLE, val);
ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0, ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_0(ab),
HAL_DEFAULT_REO_TIMEOUT_USEC); HAL_DEFAULT_REO_TIMEOUT_USEC);
ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_1, ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_1(ab),
HAL_DEFAULT_REO_TIMEOUT_USEC); HAL_DEFAULT_REO_TIMEOUT_USEC);
ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_2, ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_2(ab),
HAL_DEFAULT_REO_TIMEOUT_USEC); HAL_DEFAULT_REO_TIMEOUT_USEC);
ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_3, ath11k_hif_write32(ab, reo_base + HAL_REO1_AGING_THRESH_IX_3(ab),
HAL_DEFAULT_REO_TIMEOUT_USEC); HAL_DEFAULT_REO_TIMEOUT_USEC);
ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_0, ath11k_hif_write32(ab, reo_base + HAL_REO1_DEST_RING_CTRL_IX_0,
......
...@@ -141,7 +141,7 @@ void ath11k_hal_tx_init_data_ring(struct ath11k_base *ab, struct hal_srng *srng) ...@@ -141,7 +141,7 @@ void ath11k_hal_tx_init_data_ring(struct ath11k_base *ab, struct hal_srng *srng)
memset(&params, 0, sizeof(params)); memset(&params, 0, sizeof(params));
entry_size = ath11k_hal_srng_get_entrysize(HAL_TCL_DATA); entry_size = ath11k_hal_srng_get_entrysize(ab, HAL_TCL_DATA);
ath11k_hal_srng_get_params(ab, srng, &params); ath11k_hal_srng_get_params(ab, srng, &params);
desc = (u8 *)params.ring_base_vaddr; desc = (u8 *)params.ring_base_vaddr;
......
...@@ -3,6 +3,9 @@ ...@@ -3,6 +3,9 @@
* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
*/ */
#ifndef _HIF_H_
#define _HIF_H_
#include "core.h" #include "core.h"
struct ath11k_hif_ops { struct ath11k_hif_ops {
...@@ -16,6 +19,11 @@ struct ath11k_hif_ops { ...@@ -16,6 +19,11 @@ struct ath11k_hif_ops {
void (*power_down)(struct ath11k_base *sc); void (*power_down)(struct ath11k_base *sc);
int (*map_service_to_pipe)(struct ath11k_base *sc, u16 service_id, int (*map_service_to_pipe)(struct ath11k_base *sc, u16 service_id,
u8 *ul_pipe, u8 *dl_pipe); u8 *ul_pipe, u8 *dl_pipe);
int (*get_user_msi_vector)(struct ath11k_base *ab, char *user_name,
int *num_vectors, u32 *user_base_data,
u32 *base_vector);
void (*get_msi_address)(struct ath11k_base *ab, u32 *msi_addr_lo,
u32 *msi_addr_hi);
}; };
static inline int ath11k_hif_start(struct ath11k_base *sc) static inline int ath11k_hif_start(struct ath11k_base *sc)
...@@ -63,3 +71,25 @@ static inline int ath11k_hif_map_service_to_pipe(struct ath11k_base *sc, u16 ser ...@@ -63,3 +71,25 @@ static inline int ath11k_hif_map_service_to_pipe(struct ath11k_base *sc, u16 ser
{ {
return sc->hif.ops->map_service_to_pipe(sc, service_id, ul_pipe, dl_pipe); return sc->hif.ops->map_service_to_pipe(sc, service_id, ul_pipe, dl_pipe);
} }
static inline int ath11k_get_user_msi_vector(struct ath11k_base *ab, char *user_name,
int *num_vectors, u32 *user_base_data,
u32 *base_vector)
{
if (!ab->hif.ops->get_user_msi_vector)
return -EOPNOTSUPP;
return ab->hif.ops->get_user_msi_vector(ab, user_name, num_vectors,
user_base_data,
base_vector);
}
static inline void ath11k_get_msi_address(struct ath11k_base *ab, u32 *msi_addr_lo,
u32 *msi_addr_hi)
{
if (!ab->hif.ops->get_msi_address)
return;
ab->hif.ops->get_msi_address(ab, msi_addr_lo, msi_addr_hi);
}
#endif /* _HIF_H_ */
...@@ -478,7 +478,7 @@ int ath11k_htc_wait_target(struct ath11k_htc *htc) ...@@ -478,7 +478,7 @@ int ath11k_htc_wait_target(struct ath11k_htc *htc)
if (!time_left) { if (!time_left) {
ath11k_warn(ab, "failed to receive control response completion, polling..\n"); ath11k_warn(ab, "failed to receive control response completion, polling..\n");
for (i = 0; i < CE_COUNT; i++) for (i = 0; i < ab->hw_params.ce_count; i++)
ath11k_ce_per_engine_service(htc->ab, i); ath11k_ce_per_engine_service(htc->ab, i);
time_left = time_left =
...@@ -748,7 +748,7 @@ int ath11k_htc_init(struct ath11k_base *ab) ...@@ -748,7 +748,7 @@ int ath11k_htc_init(struct ath11k_base *ab)
htc->wmi_ep_count = 3; htc->wmi_ep_count = 3;
break; break;
default: default:
htc->wmi_ep_count = 3; htc->wmi_ep_count = ab->hw_params.max_radios;
break; break;
} }
......
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2020 The Linux Foundation. All rights reserved.
*/
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/bitfield.h>
#include "hw.h"
#include "core.h"
#include "ce.h"
/* Map from pdev index to hw mac index */
static u8 ath11k_hw_ipq8074_mac_from_pdev_id(int pdev_idx)
{
switch (pdev_idx) {
case 0:
return 0;
case 1:
return 2;
case 2:
return 1;
default:
return ATH11K_INVALID_HW_MAC_ID;
}
}
static u8 ath11k_hw_ipq6018_mac_from_pdev_id(int pdev_idx)
{
return pdev_idx;
}
static void ath11k_init_wmi_config_qca6390(struct ath11k_base *ab,
struct target_resource_config *config)
{
config->num_vdevs = 4;
config->num_peers = 16;
config->num_tids = 32;
config->num_offload_peers = 3;
config->num_offload_reorder_buffs = 3;
config->num_peer_keys = TARGET_NUM_PEER_KEYS;
config->ast_skid_limit = TARGET_AST_SKID_LIMIT;
config->tx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;
config->rx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;
config->rx_timeout_pri[0] = TARGET_RX_TIMEOUT_LO_PRI;
config->rx_timeout_pri[1] = TARGET_RX_TIMEOUT_LO_PRI;
config->rx_timeout_pri[2] = TARGET_RX_TIMEOUT_LO_PRI;
config->rx_timeout_pri[3] = TARGET_RX_TIMEOUT_HI_PRI;
config->rx_decap_mode = TARGET_DECAP_MODE_NATIVE_WIFI;
config->scan_max_pending_req = TARGET_SCAN_MAX_PENDING_REQS;
config->bmiss_offload_max_vdev = TARGET_BMISS_OFFLOAD_MAX_VDEV;
config->roam_offload_max_vdev = TARGET_ROAM_OFFLOAD_MAX_VDEV;
config->roam_offload_max_ap_profiles = TARGET_ROAM_OFFLOAD_MAX_AP_PROFILES;
config->num_mcast_groups = 0;
config->num_mcast_table_elems = 0;
config->mcast2ucast_mode = 0;
config->tx_dbg_log_size = TARGET_TX_DBG_LOG_SIZE;
config->num_wds_entries = 0;
config->dma_burst_size = 0;
config->rx_skip_defrag_timeout_dup_detection_check = 0;
config->vow_config = TARGET_VOW_CONFIG;
config->gtk_offload_max_vdev = 2;
config->num_msdu_desc = 0x400;
config->beacon_tx_offload_max_vdev = 2;
config->rx_batchmode = TARGET_RX_BATCHMODE;
config->peer_map_unmap_v2_support = 0;
config->use_pdev_id = 1;
config->max_frag_entries = 0xa;
config->num_tdls_vdevs = 0x1;
config->num_tdls_conn_table_entries = 8;
config->beacon_tx_offload_max_vdev = 0x2;
config->num_multicast_filter_entries = 0x20;
config->num_wow_filters = 0x16;
config->num_keep_alive_pattern = 0x1;
config->num_keep_alive_pattern = 0;
}
static void ath11k_init_wmi_config_ipq8074(struct ath11k_base *ab,
struct target_resource_config *config)
{
config->num_vdevs = ab->num_radios * TARGET_NUM_VDEVS;
if (ab->num_radios == 2) {
config->num_peers = TARGET_NUM_PEERS(DBS);
config->num_tids = TARGET_NUM_TIDS(DBS);
} else if (ab->num_radios == 3) {
config->num_peers = TARGET_NUM_PEERS(DBS_SBS);
config->num_tids = TARGET_NUM_TIDS(DBS_SBS);
} else {
/* Control should not reach here */
config->num_peers = TARGET_NUM_PEERS(SINGLE);
config->num_tids = TARGET_NUM_TIDS(SINGLE);
}
config->num_offload_peers = TARGET_NUM_OFFLD_PEERS;
config->num_offload_reorder_buffs = TARGET_NUM_OFFLD_REORDER_BUFFS;
config->num_peer_keys = TARGET_NUM_PEER_KEYS;
config->ast_skid_limit = TARGET_AST_SKID_LIMIT;
config->tx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;
config->rx_chain_mask = (1 << ab->target_caps.num_rf_chains) - 1;
config->rx_timeout_pri[0] = TARGET_RX_TIMEOUT_LO_PRI;
config->rx_timeout_pri[1] = TARGET_RX_TIMEOUT_LO_PRI;
config->rx_timeout_pri[2] = TARGET_RX_TIMEOUT_LO_PRI;
config->rx_timeout_pri[3] = TARGET_RX_TIMEOUT_HI_PRI;
config->rx_decap_mode = TARGET_DECAP_MODE_NATIVE_WIFI;
config->scan_max_pending_req = TARGET_SCAN_MAX_PENDING_REQS;
config->bmiss_offload_max_vdev = TARGET_BMISS_OFFLOAD_MAX_VDEV;
config->roam_offload_max_vdev = TARGET_ROAM_OFFLOAD_MAX_VDEV;
config->roam_offload_max_ap_profiles = TARGET_ROAM_OFFLOAD_MAX_AP_PROFILES;
config->num_mcast_groups = TARGET_NUM_MCAST_GROUPS;
config->num_mcast_table_elems = TARGET_NUM_MCAST_TABLE_ELEMS;
config->mcast2ucast_mode = TARGET_MCAST2UCAST_MODE;
config->tx_dbg_log_size = TARGET_TX_DBG_LOG_SIZE;
config->num_wds_entries = TARGET_NUM_WDS_ENTRIES;
config->dma_burst_size = TARGET_DMA_BURST_SIZE;
config->rx_skip_defrag_timeout_dup_detection_check =
TARGET_RX_SKIP_DEFRAG_TIMEOUT_DUP_DETECTION_CHECK;
config->vow_config = TARGET_VOW_CONFIG;
config->gtk_offload_max_vdev = TARGET_GTK_OFFLOAD_MAX_VDEV;
config->num_msdu_desc = TARGET_NUM_MSDU_DESC;
config->beacon_tx_offload_max_vdev = ab->num_radios * TARGET_MAX_BCN_OFFLD;
config->rx_batchmode = TARGET_RX_BATCHMODE;
config->peer_map_unmap_v2_support = 1;
config->twt_ap_pdev_count = 2;
config->twt_ap_sta_count = 1000;
}
static int ath11k_hw_mac_id_to_pdev_id_ipq8074(struct ath11k_hw_params *hw,
int mac_id)
{
return mac_id;
}
static int ath11k_hw_mac_id_to_srng_id_ipq8074(struct ath11k_hw_params *hw,
int mac_id)
{
return 0;
}
static int ath11k_hw_mac_id_to_pdev_id_qca6390(struct ath11k_hw_params *hw,
int mac_id)
{
return 0;
}
static int ath11k_hw_mac_id_to_srng_id_qca6390(struct ath11k_hw_params *hw,
int mac_id)
{
return mac_id;
}
const struct ath11k_hw_ops ipq8074_ops = {
.get_hw_mac_from_pdev_id = ath11k_hw_ipq8074_mac_from_pdev_id,
.wmi_init_config = ath11k_init_wmi_config_qca6390,
.mac_id_to_pdev_id = ath11k_hw_mac_id_to_pdev_id_ipq8074,
.mac_id_to_srng_id = ath11k_hw_mac_id_to_srng_id_ipq8074,
};
const struct ath11k_hw_ops ipq6018_ops = {
.get_hw_mac_from_pdev_id = ath11k_hw_ipq6018_mac_from_pdev_id,
.wmi_init_config = ath11k_init_wmi_config_ipq8074,
.mac_id_to_pdev_id = ath11k_hw_mac_id_to_pdev_id_ipq8074,
.mac_id_to_srng_id = ath11k_hw_mac_id_to_srng_id_ipq8074,
};
const struct ath11k_hw_ops qca6390_ops = {
.get_hw_mac_from_pdev_id = ath11k_hw_ipq8074_mac_from_pdev_id,
.wmi_init_config = ath11k_init_wmi_config_qca6390,
.mac_id_to_pdev_id = ath11k_hw_mac_id_to_pdev_id_qca6390,
.mac_id_to_srng_id = ath11k_hw_mac_id_to_srng_id_qca6390,
};
#define ATH11K_TX_RING_MASK_0 0x1
#define ATH11K_TX_RING_MASK_1 0x2
#define ATH11K_TX_RING_MASK_2 0x4
#define ATH11K_RX_RING_MASK_0 0x1
#define ATH11K_RX_RING_MASK_1 0x2
#define ATH11K_RX_RING_MASK_2 0x4
#define ATH11K_RX_RING_MASK_3 0x8
#define ATH11K_RX_ERR_RING_MASK_0 0x1
#define ATH11K_RX_WBM_REL_RING_MASK_0 0x1
#define ATH11K_REO_STATUS_RING_MASK_0 0x1
#define ATH11K_RXDMA2HOST_RING_MASK_0 0x1
#define ATH11K_RXDMA2HOST_RING_MASK_1 0x2
#define ATH11K_RXDMA2HOST_RING_MASK_2 0x4
#define ATH11K_HOST2RXDMA_RING_MASK_0 0x1
#define ATH11K_HOST2RXDMA_RING_MASK_1 0x2
#define ATH11K_HOST2RXDMA_RING_MASK_2 0x4
#define ATH11K_RX_MON_STATUS_RING_MASK_0 0x1
#define ATH11K_RX_MON_STATUS_RING_MASK_1 0x2
#define ATH11K_RX_MON_STATUS_RING_MASK_2 0x4
const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_ipq8074 = {
.tx = {
ATH11K_TX_RING_MASK_0,
ATH11K_TX_RING_MASK_1,
ATH11K_TX_RING_MASK_2,
},
.rx_mon_status = {
0, 0, 0, 0,
ATH11K_RX_MON_STATUS_RING_MASK_0,
ATH11K_RX_MON_STATUS_RING_MASK_1,
ATH11K_RX_MON_STATUS_RING_MASK_2,
},
.rx = {
0, 0, 0, 0, 0, 0, 0,
ATH11K_RX_RING_MASK_0,
ATH11K_RX_RING_MASK_1,
ATH11K_RX_RING_MASK_2,
ATH11K_RX_RING_MASK_3,
},
.rx_err = {
ATH11K_RX_ERR_RING_MASK_0,
},
.rx_wbm_rel = {
ATH11K_RX_WBM_REL_RING_MASK_0,
},
.reo_status = {
ATH11K_REO_STATUS_RING_MASK_0,
},
.rxdma2host = {
ATH11K_RXDMA2HOST_RING_MASK_0,
ATH11K_RXDMA2HOST_RING_MASK_1,
ATH11K_RXDMA2HOST_RING_MASK_2,
},
.host2rxdma = {
ATH11K_HOST2RXDMA_RING_MASK_0,
ATH11K_HOST2RXDMA_RING_MASK_1,
ATH11K_HOST2RXDMA_RING_MASK_2,
},
};
const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qca6390 = {
.tx = {
ATH11K_TX_RING_MASK_0,
ATH11K_TX_RING_MASK_1,
ATH11K_TX_RING_MASK_2,
},
.rx_mon_status = {
0, 0, 0, 0,
ATH11K_RX_MON_STATUS_RING_MASK_0,
ATH11K_RX_MON_STATUS_RING_MASK_1,
ATH11K_RX_MON_STATUS_RING_MASK_2,
},
.rx = {
0, 0, 0, 0, 0, 0, 0,
ATH11K_RX_RING_MASK_0,
ATH11K_RX_RING_MASK_1,
ATH11K_RX_RING_MASK_2,
ATH11K_RX_RING_MASK_3,
},
.rx_err = {
ATH11K_RX_ERR_RING_MASK_0,
},
.rx_wbm_rel = {
ATH11K_RX_WBM_REL_RING_MASK_0,
},
.reo_status = {
ATH11K_REO_STATUS_RING_MASK_0,
},
.rxdma2host = {
ATH11K_RXDMA2HOST_RING_MASK_0,
ATH11K_RXDMA2HOST_RING_MASK_1,
ATH11K_RXDMA2HOST_RING_MASK_2,
},
.host2rxdma = {
},
};
const struct ath11k_hw_regs ipq8074_regs = {
/* SW2TCL(x) R0 ring configuration address */
.hal_tcl1_ring_base_lsb = 0x00000510,
.hal_tcl1_ring_base_msb = 0x00000514,
.hal_tcl1_ring_id = 0x00000518,
.hal_tcl1_ring_misc = 0x00000520,
.hal_tcl1_ring_tp_addr_lsb = 0x0000052c,
.hal_tcl1_ring_tp_addr_msb = 0x00000530,
.hal_tcl1_ring_consumer_int_setup_ix0 = 0x00000540,
.hal_tcl1_ring_consumer_int_setup_ix1 = 0x00000544,
.hal_tcl1_ring_msi1_base_lsb = 0x00000558,
.hal_tcl1_ring_msi1_base_msb = 0x0000055c,
.hal_tcl1_ring_msi1_data = 0x00000560,
.hal_tcl2_ring_base_lsb = 0x00000568,
.hal_tcl_ring_base_lsb = 0x00000618,
/* TCL STATUS ring address */
.hal_tcl_status_ring_base_lsb = 0x00000720,
/* REO2SW(x) R0 ring configuration address */
.hal_reo1_ring_base_lsb = 0x0000029c,
.hal_reo1_ring_base_msb = 0x000002a0,
.hal_reo1_ring_id = 0x000002a4,
.hal_reo1_ring_misc = 0x000002ac,
.hal_reo1_ring_hp_addr_lsb = 0x000002b0,
.hal_reo1_ring_hp_addr_msb = 0x000002b4,
.hal_reo1_ring_producer_int_setup = 0x000002c0,
.hal_reo1_ring_msi1_base_lsb = 0x000002e4,
.hal_reo1_ring_msi1_base_msb = 0x000002e8,
.hal_reo1_ring_msi1_data = 0x000002ec,
.hal_reo2_ring_base_lsb = 0x000002f4,
.hal_reo1_aging_thresh_ix_0 = 0x00000564,
.hal_reo1_aging_thresh_ix_1 = 0x00000568,
.hal_reo1_aging_thresh_ix_2 = 0x0000056c,
.hal_reo1_aging_thresh_ix_3 = 0x00000570,
/* REO2SW(x) R2 ring pointers (head/tail) address */
.hal_reo1_ring_hp = 0x00003038,
.hal_reo1_ring_tp = 0x0000303c,
.hal_reo2_ring_hp = 0x00003040,
/* REO2TCL R0 ring configuration address */
.hal_reo_tcl_ring_base_lsb = 0x000003fc,
.hal_reo_tcl_ring_hp = 0x00003058,
/* REO status address */
.hal_reo_status_ring_base_lsb = 0x00000504,
.hal_reo_status_hp = 0x00003070,
};
const struct ath11k_hw_regs qca6390_regs = {
/* SW2TCL(x) R0 ring configuration address */
.hal_tcl1_ring_base_lsb = 0x00000684,
.hal_tcl1_ring_base_msb = 0x00000688,
.hal_tcl1_ring_id = 0x0000068c,
.hal_tcl1_ring_misc = 0x00000694,
.hal_tcl1_ring_tp_addr_lsb = 0x000006a0,
.hal_tcl1_ring_tp_addr_msb = 0x000006a4,
.hal_tcl1_ring_consumer_int_setup_ix0 = 0x000006b4,
.hal_tcl1_ring_consumer_int_setup_ix1 = 0x000006b8,
.hal_tcl1_ring_msi1_base_lsb = 0x000006cc,
.hal_tcl1_ring_msi1_base_msb = 0x000006d0,
.hal_tcl1_ring_msi1_data = 0x000006d4,
.hal_tcl2_ring_base_lsb = 0x000006dc,
.hal_tcl_ring_base_lsb = 0x0000078c,
/* TCL STATUS ring address */
.hal_tcl_status_ring_base_lsb = 0x00000894,
/* REO2SW(x) R0 ring configuration address */
.hal_reo1_ring_base_lsb = 0x00000244,
.hal_reo1_ring_base_msb = 0x00000248,
.hal_reo1_ring_id = 0x0000024c,
.hal_reo1_ring_misc = 0x00000254,
.hal_reo1_ring_hp_addr_lsb = 0x00000258,
.hal_reo1_ring_hp_addr_msb = 0x0000025c,
.hal_reo1_ring_producer_int_setup = 0x00000268,
.hal_reo1_ring_msi1_base_lsb = 0x0000028c,
.hal_reo1_ring_msi1_base_msb = 0x00000290,
.hal_reo1_ring_msi1_data = 0x00000294,
.hal_reo2_ring_base_lsb = 0x0000029c,
.hal_reo1_aging_thresh_ix_0 = 0x0000050c,
.hal_reo1_aging_thresh_ix_1 = 0x00000510,
.hal_reo1_aging_thresh_ix_2 = 0x00000514,
.hal_reo1_aging_thresh_ix_3 = 0x00000518,
/* REO2SW(x) R2 ring pointers (head/tail) address */
.hal_reo1_ring_hp = 0x00003030,
.hal_reo1_ring_tp = 0x00003034,
.hal_reo2_ring_hp = 0x00003038,
/* REO2TCL R0 ring configuration address */
.hal_reo_tcl_ring_base_lsb = 0x000003a4,
.hal_reo_tcl_ring_hp = 0x00003050,
/* REO status address */
.hal_reo_status_ring_base_lsb = 0x000004ac,
.hal_reo_status_hp = 0x00003068,
};
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#ifndef ATH11K_HW_H #ifndef ATH11K_HW_H
#define ATH11K_HW_H #define ATH11K_HW_H
#include "wmi.h"
/* Target configuration defines */ /* Target configuration defines */
/* Num VDEVS per radio */ /* Num VDEVS per radio */
...@@ -68,15 +70,12 @@ ...@@ -68,15 +70,12 @@
#define ATH11K_FW_DIR "ath11k" #define ATH11K_FW_DIR "ath11k"
/* IPQ8074 definitions */
#define IPQ8074_FW_DIR "IPQ8074"
#define IPQ8074_MAX_BOARD_DATA_SZ (256 * 1024)
#define IPQ8074_MAX_CAL_DATA_SZ IPQ8074_MAX_BOARD_DATA_SZ
#define ATH11K_BOARD_MAGIC "QCA-ATH11K-BOARD" #define ATH11K_BOARD_MAGIC "QCA-ATH11K-BOARD"
#define ATH11K_BOARD_API2_FILE "board-2.bin" #define ATH11K_BOARD_API2_FILE "board-2.bin"
#define ATH11K_DEFAULT_BOARD_FILE "bdwlan.bin" #define ATH11K_DEFAULT_BOARD_FILE "board.bin"
#define ATH11K_DEFAULT_CAL_FILE "caldata.bin" #define ATH11K_DEFAULT_CAL_FILE "caldata.bin"
#define ATH11K_AMSS_FILE "amss.bin"
#define ATH11K_M3_FILE "m3.bin"
enum ath11k_hw_rate_cck { enum ath11k_hw_rate_cck {
ATH11K_HW_RATE_CCK_LP_11M = 0, ATH11K_HW_RATE_CCK_LP_11M = 0,
...@@ -104,15 +103,100 @@ enum ath11k_bus { ...@@ -104,15 +103,100 @@ enum ath11k_bus {
ATH11K_BUS_PCI, ATH11K_BUS_PCI,
}; };
#define ATH11K_EXT_IRQ_GRP_NUM_MAX 11
struct ath11k_hw_ring_mask {
u8 tx[ATH11K_EXT_IRQ_GRP_NUM_MAX];
u8 rx_mon_status[ATH11K_EXT_IRQ_GRP_NUM_MAX];
u8 rx[ATH11K_EXT_IRQ_GRP_NUM_MAX];
u8 rx_err[ATH11K_EXT_IRQ_GRP_NUM_MAX];
u8 rx_wbm_rel[ATH11K_EXT_IRQ_GRP_NUM_MAX];
u8 reo_status[ATH11K_EXT_IRQ_GRP_NUM_MAX];
u8 rxdma2host[ATH11K_EXT_IRQ_GRP_NUM_MAX];
u8 host2rxdma[ATH11K_EXT_IRQ_GRP_NUM_MAX];
};
struct ath11k_hw_params { struct ath11k_hw_params {
const char *name; const char *name;
u16 hw_rev;
u8 max_radios;
u32 bdf_addr;
struct { struct {
const char *dir; const char *dir;
size_t board_size; size_t board_size;
size_t cal_size; size_t cal_size;
} fw; } fw;
const struct ath11k_hw_ops *hw_ops;
const struct ath11k_hw_ring_mask *ring_mask;
bool internal_sleep_clock;
const struct ath11k_hw_regs *regs;
const struct ce_attr *host_ce_config;
u32 ce_count;
bool single_pdev_only;
/* For example on QCA6390 struct
* wmi_init_cmd_param::band_to_mac_config needs to be false as the
* firmware creates the mapping.
*/
bool needs_band_to_mac;
bool rxdma1_enable;
int num_rxmda_per_pdev;
bool rx_mac_buf_ring;
bool vdev_start_delay;
bool htt_peer_map_v2;
bool tcl_0_only;
};
struct ath11k_hw_ops {
u8 (*get_hw_mac_from_pdev_id)(int pdev_id);
void (*wmi_init_config)(struct ath11k_base *ab,
struct target_resource_config *config);
int (*mac_id_to_pdev_id)(struct ath11k_hw_params *hw, int mac_id);
int (*mac_id_to_srng_id)(struct ath11k_hw_params *hw, int mac_id);
}; };
extern const struct ath11k_hw_ops ipq8074_ops;
extern const struct ath11k_hw_ops ipq6018_ops;
extern const struct ath11k_hw_ops qca6390_ops;
extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_ipq8074;
extern const struct ath11k_hw_ring_mask ath11k_hw_ring_mask_qca6390;
static inline
int ath11k_hw_get_mac_from_pdev_id(struct ath11k_hw_params *hw,
int pdev_idx)
{
if (hw->hw_ops->get_hw_mac_from_pdev_id)
return hw->hw_ops->get_hw_mac_from_pdev_id(pdev_idx);
return 0;
}
static inline int ath11k_hw_mac_id_to_pdev_id(struct ath11k_hw_params *hw,
int mac_id)
{
if (hw->hw_ops->mac_id_to_pdev_id)
return hw->hw_ops->mac_id_to_pdev_id(hw, mac_id);
return 0;
}
static inline int ath11k_hw_mac_id_to_srng_id(struct ath11k_hw_params *hw,
int mac_id)
{
if (hw->hw_ops->mac_id_to_srng_id)
return hw->hw_ops->mac_id_to_srng_id(hw, mac_id);
return 0;
}
struct ath11k_fw_ie { struct ath11k_fw_ie {
__le32 id; __le32 id;
__le32 len; __le32 len;
...@@ -130,4 +214,51 @@ enum ath11k_bd_ie_type { ...@@ -130,4 +214,51 @@ enum ath11k_bd_ie_type {
ATH11K_BD_IE_BOARD_EXT = 1, ATH11K_BD_IE_BOARD_EXT = 1,
}; };
struct ath11k_hw_regs {
u32 hal_tcl1_ring_base_lsb;
u32 hal_tcl1_ring_base_msb;
u32 hal_tcl1_ring_id;
u32 hal_tcl1_ring_misc;
u32 hal_tcl1_ring_tp_addr_lsb;
u32 hal_tcl1_ring_tp_addr_msb;
u32 hal_tcl1_ring_consumer_int_setup_ix0;
u32 hal_tcl1_ring_consumer_int_setup_ix1;
u32 hal_tcl1_ring_msi1_base_lsb;
u32 hal_tcl1_ring_msi1_base_msb;
u32 hal_tcl1_ring_msi1_data;
u32 hal_tcl2_ring_base_lsb;
u32 hal_tcl_ring_base_lsb;
u32 hal_tcl_status_ring_base_lsb;
u32 hal_reo1_ring_base_lsb;
u32 hal_reo1_ring_base_msb;
u32 hal_reo1_ring_id;
u32 hal_reo1_ring_misc;
u32 hal_reo1_ring_hp_addr_lsb;
u32 hal_reo1_ring_hp_addr_msb;
u32 hal_reo1_ring_producer_int_setup;
u32 hal_reo1_ring_msi1_base_lsb;
u32 hal_reo1_ring_msi1_base_msb;
u32 hal_reo1_ring_msi1_data;
u32 hal_reo2_ring_base_lsb;
u32 hal_reo1_aging_thresh_ix_0;
u32 hal_reo1_aging_thresh_ix_1;
u32 hal_reo1_aging_thresh_ix_2;
u32 hal_reo1_aging_thresh_ix_3;
u32 hal_reo1_ring_hp;
u32 hal_reo1_ring_tp;
u32 hal_reo2_ring_hp;
u32 hal_reo_tcl_ring_base_lsb;
u32 hal_reo_tcl_ring_hp;
u32 hal_reo_status_ring_base_lsb;
u32 hal_reo_status_hp;
};
extern const struct ath11k_hw_regs ipq8074_regs;
extern const struct ath11k_hw_regs qca6390_regs;
#endif #endif
...@@ -244,6 +244,9 @@ static const u32 ath11k_smps_map[] = { ...@@ -244,6 +244,9 @@ static const u32 ath11k_smps_map[] = {
[WLAN_HT_CAP_SM_PS_DISABLED] = WMI_PEER_SMPS_PS_NONE, [WLAN_HT_CAP_SM_PS_DISABLED] = WMI_PEER_SMPS_PS_NONE,
}; };
static int ath11k_start_vdev_delay(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
u8 ath11k_mac_bw_to_mac80211_bw(u8 bw) u8 ath11k_mac_bw_to_mac80211_bw(u8 bw)
{ {
u8 ret = 0; u8 ret = 0;
...@@ -521,6 +524,11 @@ struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id) ...@@ -521,6 +524,11 @@ struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id)
int i; int i;
struct ath11k_pdev *pdev; struct ath11k_pdev *pdev;
if (ab->hw_params.single_pdev_only) {
pdev = rcu_dereference(ab->pdevs_active[0]);
return pdev ? pdev->ar : NULL;
}
if (WARN_ON(pdev_id > ab->num_radios)) if (WARN_ON(pdev_id > ab->num_radios))
return NULL; return NULL;
...@@ -1138,13 +1146,13 @@ ath11k_peer_assoc_h_vht_limit(u16 tx_mcs_set, ...@@ -1138,13 +1146,13 @@ ath11k_peer_assoc_h_vht_limit(u16 tx_mcs_set,
idx_limit = -1; idx_limit = -1;
switch (idx_limit) { switch (idx_limit) {
case 0: /* fall through */ case 0:
case 1: /* fall through */ case 1:
case 2: /* fall through */ case 2:
case 3: /* fall through */ case 3:
case 4: /* fall through */ case 4:
case 5: /* fall through */ case 5:
case 6: /* fall through */ case 6:
case 7: case 7:
mcs = IEEE80211_VHT_MCS_SUPPORT_0_7; mcs = IEEE80211_VHT_MCS_SUPPORT_0_7;
break; break;
...@@ -1156,7 +1164,7 @@ ath11k_peer_assoc_h_vht_limit(u16 tx_mcs_set, ...@@ -1156,7 +1164,7 @@ ath11k_peer_assoc_h_vht_limit(u16 tx_mcs_set,
break; break;
default: default:
WARN_ON(1); WARN_ON(1);
/* fall through */ fallthrough;
case -1: case -1:
mcs = IEEE80211_VHT_MCS_NOT_SUPPORTED; mcs = IEEE80211_VHT_MCS_NOT_SUPPORTED;
break; break;
...@@ -1339,7 +1347,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar, ...@@ -1339,7 +1347,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v; arg->peer_he_tx_mcs_set[WMI_HECAP_TXRX_MCS_NSS_IDX_160] = v;
arg->peer_he_mcs_count++; arg->peer_he_mcs_count++;
/* fall through */ fallthrough;
default: default:
v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80); v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
...@@ -2114,7 +2122,7 @@ void __ath11k_mac_scan_finish(struct ath11k *ar) ...@@ -2114,7 +2122,7 @@ void __ath11k_mac_scan_finish(struct ath11k *ar)
} else if (ar->scan.roc_notify) { } else if (ar->scan.roc_notify) {
ieee80211_remain_on_channel_expired(ar->hw); ieee80211_remain_on_channel_expired(ar->hw);
} }
/* fall through */ fallthrough;
case ATH11K_SCAN_STARTING: case ATH11K_SCAN_STARTING:
ar->scan.state = ATH11K_SCAN_IDLE; ar->scan.state = ATH11K_SCAN_IDLE;
ar->scan_channel = NULL; ar->scan_channel = NULL;
...@@ -2955,6 +2963,14 @@ static int ath11k_mac_station_add(struct ath11k *ar, ...@@ -2955,6 +2963,14 @@ static int ath11k_mac_station_add(struct ath11k *ar,
goto free_tx_stats; goto free_tx_stats;
} }
if (ab->hw_params.vdev_start_delay) {
ret = ath11k_start_vdev_delay(ar->hw, vif);
if (ret) {
ath11k_warn(ab, "failed to delay vdev start: %d\n", ret);
goto free_tx_stats;
}
}
return 0; return 0;
free_tx_stats: free_tx_stats:
...@@ -3039,10 +3055,6 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw, ...@@ -3039,10 +3055,6 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
if (ret) if (ret)
ath11k_warn(ar->ab, "Failed to associate station: %pM\n", ath11k_warn(ar->ab, "Failed to associate station: %pM\n",
sta->addr); sta->addr);
else
ath11k_info(ar->ab,
"Station %pM moved to assoc state\n",
sta->addr);
} else if (old_state == IEEE80211_STA_ASSOC && } else if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTH && new_state == IEEE80211_STA_AUTH &&
(vif->type == NL80211_IFTYPE_AP || (vif->type == NL80211_IFTYPE_AP ||
...@@ -3052,10 +3064,6 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw, ...@@ -3052,10 +3064,6 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
if (ret) if (ret)
ath11k_warn(ar->ab, "Failed to disassociate station: %pM\n", ath11k_warn(ar->ab, "Failed to disassociate station: %pM\n",
sta->addr); sta->addr);
else
ath11k_info(ar->ab,
"Station %pM moved to disassociated state\n",
sta->addr);
} }
mutex_unlock(&ar->conf_mutex); mutex_unlock(&ar->conf_mutex);
...@@ -4057,6 +4065,8 @@ void ath11k_mac_drain_tx(struct ath11k *ar) ...@@ -4057,6 +4065,8 @@ void ath11k_mac_drain_tx(struct ath11k *ar)
static int ath11k_mac_config_mon_status_default(struct ath11k *ar, bool enable) static int ath11k_mac_config_mon_status_default(struct ath11k *ar, bool enable)
{ {
struct htt_rx_ring_tlv_filter tlv_filter = {0}; struct htt_rx_ring_tlv_filter tlv_filter = {0};
struct ath11k_base *ab = ar->ab;
int i, ret = 0;
u32 ring_id; u32 ring_id;
if (enable) { if (enable) {
...@@ -4064,11 +4074,16 @@ static int ath11k_mac_config_mon_status_default(struct ath11k *ar, bool enable) ...@@ -4064,11 +4074,16 @@ static int ath11k_mac_config_mon_status_default(struct ath11k *ar, bool enable)
tlv_filter.rx_filter = ath11k_debug_rx_filter(ar); tlv_filter.rx_filter = ath11k_debug_rx_filter(ar);
} }
ring_id = ar->dp.rx_mon_status_refill_ring.refill_buf_ring.ring_id; for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
ring_id = ar->dp.rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id,
ar->dp.mac_id + i,
HAL_RXDMA_MONITOR_STATUS,
DP_RX_BUFFER_SIZE,
&tlv_filter);
}
return ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id, return ret;
HAL_RXDMA_MONITOR_STATUS,
DP_RX_BUFFER_SIZE, &tlv_filter);
} }
static int ath11k_mac_op_start(struct ieee80211_hw *hw) static int ath11k_mac_op_start(struct ieee80211_hw *hw)
...@@ -4368,7 +4383,7 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, ...@@ -4368,7 +4383,7 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
break; break;
case NL80211_IFTYPE_MESH_POINT: case NL80211_IFTYPE_MESH_POINT:
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S; arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S;
/* fall through */ fallthrough;
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
arvif->vdev_type = WMI_VDEV_TYPE_AP; arvif->vdev_type = WMI_VDEV_TYPE_AP;
break; break;
...@@ -5112,6 +5127,39 @@ static void ath11k_mac_op_change_chanctx(struct ieee80211_hw *hw, ...@@ -5112,6 +5127,39 @@ static void ath11k_mac_op_change_chanctx(struct ieee80211_hw *hw,
mutex_unlock(&ar->conf_mutex); mutex_unlock(&ar->conf_mutex);
} }
static int ath11k_start_vdev_delay(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ath11k *ar = hw->priv;
struct ath11k_base *ab = ar->ab;
struct ath11k_vif *arvif = (void *)vif->drv_priv;
int ret;
if (WARN_ON(arvif->is_started))
return -EBUSY;
ret = ath11k_mac_vdev_start(arvif, &arvif->chanctx.def);
if (ret) {
ath11k_warn(ab, "failed to start vdev %i addr %pM on freq %d: %d\n",
arvif->vdev_id, vif->addr,
arvif->chanctx.def.chan->center_freq, ret);
return ret;
}
if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
ret = ath11k_monitor_vdev_up(ar, arvif->vdev_id);
if (ret) {
ath11k_warn(ab, "failed put monitor up: %d\n", ret);
return ret;
}
}
arvif->is_started = true;
/* TODO: Setup ps and cts/rts protection */
return 0;
}
static int static int
ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, struct ieee80211_vif *vif,
...@@ -5128,6 +5176,13 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw, ...@@ -5128,6 +5176,13 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
"mac chanctx assign ptr %pK vdev_id %i\n", "mac chanctx assign ptr %pK vdev_id %i\n",
ctx, arvif->vdev_id); ctx, arvif->vdev_id);
/* for QCA6390 bss peer must be created before vdev_start */
if (ab->hw_params.vdev_start_delay) {
memcpy(&arvif->chanctx, ctx, sizeof(*ctx));
mutex_unlock(&ar->conf_mutex);
return 0;
}
if (WARN_ON(arvif->is_started)) { if (WARN_ON(arvif->is_started)) {
mutex_unlock(&ar->conf_mutex); mutex_unlock(&ar->conf_mutex);
return -EBUSY; return -EBUSY;
...@@ -5829,12 +5884,29 @@ static void ath11k_mac_update_ch_list(struct ath11k *ar, ...@@ -5829,12 +5884,29 @@ static void ath11k_mac_update_ch_list(struct ath11k *ar,
} }
} }
static u32 ath11k_get_phy_id(struct ath11k *ar, u32 band)
{
struct ath11k_pdev *pdev = ar->pdev;
struct ath11k_pdev_cap *pdev_cap = &pdev->cap;
if (band == WMI_HOST_WLAN_2G_CAP)
return pdev_cap->band[NL80211_BAND_2GHZ].phy_id;
if (band == WMI_HOST_WLAN_5G_CAP)
return pdev_cap->band[NL80211_BAND_5GHZ].phy_id;
ath11k_warn(ar->ab, "unsupported phy cap:%d\n", band);
return 0;
}
static int ath11k_mac_setup_channels_rates(struct ath11k *ar, static int ath11k_mac_setup_channels_rates(struct ath11k *ar,
u32 supported_bands) u32 supported_bands)
{ {
struct ieee80211_supported_band *band; struct ieee80211_supported_band *band;
struct ath11k_hal_reg_capabilities_ext *reg_cap; struct ath11k_hal_reg_capabilities_ext *reg_cap;
void *channels; void *channels;
u32 phy_id;
BUILD_BUG_ON((ARRAY_SIZE(ath11k_2ghz_channels) + BUILD_BUG_ON((ARRAY_SIZE(ath11k_2ghz_channels) +
ARRAY_SIZE(ath11k_5ghz_channels) + ARRAY_SIZE(ath11k_5ghz_channels) +
...@@ -5857,6 +5929,11 @@ static int ath11k_mac_setup_channels_rates(struct ath11k *ar, ...@@ -5857,6 +5929,11 @@ static int ath11k_mac_setup_channels_rates(struct ath11k *ar,
band->n_bitrates = ath11k_g_rates_size; band->n_bitrates = ath11k_g_rates_size;
band->bitrates = ath11k_g_rates; band->bitrates = ath11k_g_rates;
ar->hw->wiphy->bands[NL80211_BAND_2GHZ] = band; ar->hw->wiphy->bands[NL80211_BAND_2GHZ] = band;
if (ar->ab->hw_params.single_pdev_only) {
phy_id = ath11k_get_phy_id(ar, WMI_HOST_WLAN_2G_CAP);
reg_cap = &ar->ab->hal_reg_cap[phy_id];
}
ath11k_mac_update_ch_list(ar, band, ath11k_mac_update_ch_list(ar, band,
reg_cap->low_2ghz_chan, reg_cap->low_2ghz_chan,
reg_cap->high_2ghz_chan); reg_cap->high_2ghz_chan);
...@@ -5901,6 +5978,12 @@ static int ath11k_mac_setup_channels_rates(struct ath11k *ar, ...@@ -5901,6 +5978,12 @@ static int ath11k_mac_setup_channels_rates(struct ath11k *ar,
band->n_bitrates = ath11k_a_rates_size; band->n_bitrates = ath11k_a_rates_size;
band->bitrates = ath11k_a_rates; band->bitrates = ath11k_a_rates;
ar->hw->wiphy->bands[NL80211_BAND_5GHZ] = band; ar->hw->wiphy->bands[NL80211_BAND_5GHZ] = band;
if (ar->ab->hw_params.single_pdev_only) {
phy_id = ath11k_get_phy_id(ar, WMI_HOST_WLAN_5G_CAP);
reg_cap = &ar->ab->hal_reg_cap[phy_id];
}
ath11k_mac_update_ch_list(ar, band, ath11k_mac_update_ch_list(ar, band,
reg_cap->low_5ghz_chan, reg_cap->low_5ghz_chan,
reg_cap->high_5ghz_chan); reg_cap->high_5ghz_chan);
...@@ -6194,7 +6277,7 @@ int ath11k_mac_allocate(struct ath11k_base *ab) ...@@ -6194,7 +6277,7 @@ int ath11k_mac_allocate(struct ath11k_base *ab)
ar->ab = ab; ar->ab = ab;
ar->pdev = pdev; ar->pdev = pdev;
ar->pdev_idx = i; ar->pdev_idx = i;
ar->lmac_id = ath11k_core_get_hw_mac_id(ab, i); ar->lmac_id = ath11k_hw_get_mac_from_pdev_id(&ab->hw_params, i);
ar->wmi = &ab->wmi_ab.wmi[i]; ar->wmi = &ab->wmi_ab.wmi[i];
/* FIXME wmi[0] is already initialized during attach, /* FIXME wmi[0] is already initialized during attach,
......
// SPDX-License-Identifier: BSD-3-Clause-Clear
/* Copyright (c) 2020 The Linux Foundation. All rights reserved. */
#include <linux/msi.h>
#include <linux/pci.h>
#include "core.h"
#include "debug.h"
#include "mhi.h"
#define MHI_TIMEOUT_DEFAULT_MS 90000
static struct mhi_channel_config ath11k_mhi_channels[] = {
{
.num = 0,
.name = "LOOPBACK",
.num_elements = 32,
.event_ring = 0,
.dir = DMA_TO_DEVICE,
.ee_mask = 0x4,
.pollcfg = 0,
.doorbell = MHI_DB_BRST_DISABLE,
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.auto_start = false,
},
{
.num = 1,
.name = "LOOPBACK",
.num_elements = 32,
.event_ring = 0,
.dir = DMA_FROM_DEVICE,
.ee_mask = 0x4,
.pollcfg = 0,
.doorbell = MHI_DB_BRST_DISABLE,
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.auto_start = false,
},
{
.num = 20,
.name = "IPCR",
.num_elements = 64,
.event_ring = 1,
.dir = DMA_TO_DEVICE,
.ee_mask = 0x4,
.pollcfg = 0,
.doorbell = MHI_DB_BRST_DISABLE,
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = false,
.auto_start = true,
},
{
.num = 21,
.name = "IPCR",
.num_elements = 64,
.event_ring = 1,
.dir = DMA_FROM_DEVICE,
.ee_mask = 0x4,
.pollcfg = 0,
.doorbell = MHI_DB_BRST_DISABLE,
.lpm_notify = false,
.offload_channel = false,
.doorbell_mode_switch = false,
.auto_queue = true,
.auto_start = true,
},
};
static struct mhi_event_config ath11k_mhi_events[] = {
{
.num_elements = 32,
.irq_moderation_ms = 0,
.irq = 1,
.mode = MHI_DB_BRST_DISABLE,
.data_type = MHI_ER_CTRL,
.hardware_event = false,
.client_managed = false,
.offload_channel = false,
},
{
.num_elements = 256,
.irq_moderation_ms = 1,
.irq = 2,
.mode = MHI_DB_BRST_DISABLE,
.priority = 1,
.hardware_event = false,
.client_managed = false,
.offload_channel = false,
},
};
static struct mhi_controller_config ath11k_mhi_config = {
.max_channels = 128,
.timeout_ms = 2000,
.use_bounce_buf = false,
.buf_len = 0,
.num_channels = ARRAY_SIZE(ath11k_mhi_channels),
.ch_cfg = ath11k_mhi_channels,
.num_events = ARRAY_SIZE(ath11k_mhi_events),
.event_cfg = ath11k_mhi_events,
};
void ath11k_mhi_set_mhictrl_reset(struct ath11k_base *ab)
{
u32 val;
val = ath11k_pci_read32(ab, MHISTATUS);
ath11k_dbg(ab, ATH11K_DBG_PCI, "MHISTATUS 0x%x\n", val);
/* Observed on QCA6390 that after SOC_GLOBAL_RESET, MHISTATUS
* has SYSERR bit set and thus need to set MHICTRL_RESET
* to clear SYSERR.
*/
ath11k_pci_write32(ab, MHICTRL, MHICTRL_RESET_MASK);
mdelay(10);
}
static void ath11k_mhi_reset_txvecdb(struct ath11k_base *ab)
{
ath11k_pci_write32(ab, PCIE_TXVECDB, 0);
}
static void ath11k_mhi_reset_txvecstatus(struct ath11k_base *ab)
{
ath11k_pci_write32(ab, PCIE_TXVECSTATUS, 0);
}
static void ath11k_mhi_reset_rxvecdb(struct ath11k_base *ab)
{
ath11k_pci_write32(ab, PCIE_RXVECDB, 0);
}
static void ath11k_mhi_reset_rxvecstatus(struct ath11k_base *ab)
{
ath11k_pci_write32(ab, PCIE_RXVECSTATUS, 0);
}
void ath11k_mhi_clear_vector(struct ath11k_base *ab)
{
ath11k_mhi_reset_txvecdb(ab);
ath11k_mhi_reset_txvecstatus(ab);
ath11k_mhi_reset_rxvecdb(ab);
ath11k_mhi_reset_rxvecstatus(ab);
}
static int ath11k_mhi_get_msi(struct ath11k_pci *ab_pci)
{
struct ath11k_base *ab = ab_pci->ab;
u32 user_base_data, base_vector;
int ret, num_vectors, i;
int *irq;
ret = ath11k_pci_get_user_msi_assignment(ab_pci,
"MHI", &num_vectors,
&user_base_data, &base_vector);
if (ret)
return ret;
ath11k_dbg(ab, ATH11K_DBG_PCI, "Number of assigned MSI for MHI is %d, base vector is %d\n",
num_vectors, base_vector);
irq = kcalloc(num_vectors, sizeof(int), GFP_KERNEL);
if (!irq)
return -ENOMEM;
for (i = 0; i < num_vectors; i++)
irq[i] = ath11k_pci_get_msi_irq(ab->dev,
base_vector + i);
ab_pci->mhi_ctrl->irq = irq;
ab_pci->mhi_ctrl->nr_irqs = num_vectors;
return 0;
}
static int ath11k_mhi_op_runtime_get(struct mhi_controller *mhi_cntrl)
{
return 0;
}
static void ath11k_mhi_op_runtime_put(struct mhi_controller *mhi_cntrl)
{
}
static void ath11k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl,
enum mhi_callback cb)
{
}
static int ath11k_mhi_op_read_reg(struct mhi_controller *mhi_cntrl,
void __iomem *addr,
u32 *out)
{
*out = readl(addr);
return 0;
}
static void ath11k_mhi_op_write_reg(struct mhi_controller *mhi_cntrl,
void __iomem *addr,
u32 val)
{
writel(val, addr);
}
int ath11k_mhi_register(struct ath11k_pci *ab_pci)
{
struct ath11k_base *ab = ab_pci->ab;
struct mhi_controller *mhi_ctrl;
int ret;
mhi_ctrl = kzalloc(sizeof(*mhi_ctrl), GFP_KERNEL);
if (!mhi_ctrl)
return PTR_ERR(mhi_ctrl);
ath11k_core_create_firmware_path(ab, ATH11K_AMSS_FILE,
ab_pci->amss_path,
sizeof(ab_pci->amss_path));
ab_pci->mhi_ctrl = mhi_ctrl;
mhi_ctrl->cntrl_dev = ab->dev;
mhi_ctrl->fw_image = ab_pci->amss_path;
mhi_ctrl->regs = ab->mem;
ret = ath11k_mhi_get_msi(ab_pci);
if (ret) {
ath11k_err(ab, "failed to get msi for mhi\n");
kfree(mhi_ctrl);
return ret;
}
mhi_ctrl->iova_start = 0;
mhi_ctrl->iova_stop = 0xffffffff;
mhi_ctrl->sbl_size = SZ_512K;
mhi_ctrl->seg_len = SZ_512K;
mhi_ctrl->fbc_download = true;
mhi_ctrl->runtime_get = ath11k_mhi_op_runtime_get;
mhi_ctrl->runtime_put = ath11k_mhi_op_runtime_put;
mhi_ctrl->status_cb = ath11k_mhi_op_status_cb;
mhi_ctrl->read_reg = ath11k_mhi_op_read_reg;
mhi_ctrl->write_reg = ath11k_mhi_op_write_reg;
ret = mhi_register_controller(mhi_ctrl, &ath11k_mhi_config);
if (ret) {
ath11k_err(ab, "failed to register to mhi bus, err = %d\n", ret);
kfree(mhi_ctrl);
return ret;
}
return 0;
}
void ath11k_mhi_unregister(struct ath11k_pci *ab_pci)
{
struct mhi_controller *mhi_ctrl = ab_pci->mhi_ctrl;
mhi_unregister_controller(mhi_ctrl);
kfree(mhi_ctrl->irq);
}
static char *ath11k_mhi_state_to_str(enum ath11k_mhi_state mhi_state)
{
switch (mhi_state) {
case ATH11K_MHI_INIT:
return "INIT";
case ATH11K_MHI_DEINIT:
return "DEINIT";
case ATH11K_MHI_POWER_ON:
return "POWER_ON";
case ATH11K_MHI_POWER_OFF:
return "POWER_OFF";
case ATH11K_MHI_FORCE_POWER_OFF:
return "FORCE_POWER_OFF";
case ATH11K_MHI_SUSPEND:
return "SUSPEND";
case ATH11K_MHI_RESUME:
return "RESUME";
case ATH11K_MHI_TRIGGER_RDDM:
return "TRIGGER_RDDM";
case ATH11K_MHI_RDDM_DONE:
return "RDDM_DONE";
default:
return "UNKNOWN";
}
};
static void ath11k_mhi_set_state_bit(struct ath11k_pci *ab_pci,
enum ath11k_mhi_state mhi_state)
{
struct ath11k_base *ab = ab_pci->ab;
switch (mhi_state) {
case ATH11K_MHI_INIT:
set_bit(ATH11K_MHI_INIT, &ab_pci->mhi_state);
break;
case ATH11K_MHI_DEINIT:
clear_bit(ATH11K_MHI_INIT, &ab_pci->mhi_state);
break;
case ATH11K_MHI_POWER_ON:
set_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state);
break;
case ATH11K_MHI_POWER_OFF:
case ATH11K_MHI_FORCE_POWER_OFF:
clear_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state);
clear_bit(ATH11K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state);
clear_bit(ATH11K_MHI_RDDM_DONE, &ab_pci->mhi_state);
break;
case ATH11K_MHI_SUSPEND:
set_bit(ATH11K_MHI_SUSPEND, &ab_pci->mhi_state);
break;
case ATH11K_MHI_RESUME:
clear_bit(ATH11K_MHI_SUSPEND, &ab_pci->mhi_state);
break;
case ATH11K_MHI_TRIGGER_RDDM:
set_bit(ATH11K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state);
break;
case ATH11K_MHI_RDDM_DONE:
set_bit(ATH11K_MHI_RDDM_DONE, &ab_pci->mhi_state);
break;
default:
ath11k_err(ab, "unhandled mhi state (%d)\n", mhi_state);
}
}
static int ath11k_mhi_check_state_bit(struct ath11k_pci *ab_pci,
enum ath11k_mhi_state mhi_state)
{
struct ath11k_base *ab = ab_pci->ab;
switch (mhi_state) {
case ATH11K_MHI_INIT:
if (!test_bit(ATH11K_MHI_INIT, &ab_pci->mhi_state))
return 0;
break;
case ATH11K_MHI_DEINIT:
case ATH11K_MHI_POWER_ON:
if (test_bit(ATH11K_MHI_INIT, &ab_pci->mhi_state) &&
!test_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state))
return 0;
break;
case ATH11K_MHI_FORCE_POWER_OFF:
if (test_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state))
return 0;
break;
case ATH11K_MHI_POWER_OFF:
case ATH11K_MHI_SUSPEND:
if (test_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state) &&
!test_bit(ATH11K_MHI_SUSPEND, &ab_pci->mhi_state))
return 0;
break;
case ATH11K_MHI_RESUME:
if (test_bit(ATH11K_MHI_SUSPEND, &ab_pci->mhi_state))
return 0;
break;
case ATH11K_MHI_TRIGGER_RDDM:
if (test_bit(ATH11K_MHI_POWER_ON, &ab_pci->mhi_state) &&
!test_bit(ATH11K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state))
return 0;
break;
case ATH11K_MHI_RDDM_DONE:
return 0;
default:
ath11k_err(ab, "unhandled mhi state: %s(%d)\n",
ath11k_mhi_state_to_str(mhi_state), mhi_state);
}
ath11k_err(ab, "failed to set mhi state %s(%d) in current mhi state (0x%lx)\n",
ath11k_mhi_state_to_str(mhi_state), mhi_state,
ab_pci->mhi_state);
return -EINVAL;
}
static int ath11k_mhi_set_state(struct ath11k_pci *ab_pci,
enum ath11k_mhi_state mhi_state)
{
struct ath11k_base *ab = ab_pci->ab;
int ret;
ret = ath11k_mhi_check_state_bit(ab_pci, mhi_state);
if (ret)
goto out;
ath11k_dbg(ab, ATH11K_DBG_PCI, "setting mhi state: %s(%d)\n",
ath11k_mhi_state_to_str(mhi_state), mhi_state);
switch (mhi_state) {
case ATH11K_MHI_INIT:
ret = mhi_prepare_for_power_up(ab_pci->mhi_ctrl);
break;
case ATH11K_MHI_DEINIT:
mhi_unprepare_after_power_down(ab_pci->mhi_ctrl);
ret = 0;
break;
case ATH11K_MHI_POWER_ON:
ret = mhi_async_power_up(ab_pci->mhi_ctrl);
break;
case ATH11K_MHI_POWER_OFF:
mhi_power_down(ab_pci->mhi_ctrl, true);
ret = 0;
break;
case ATH11K_MHI_FORCE_POWER_OFF:
mhi_power_down(ab_pci->mhi_ctrl, false);
ret = 0;
break;
case ATH11K_MHI_SUSPEND:
break;
case ATH11K_MHI_RESUME:
break;
case ATH11K_MHI_TRIGGER_RDDM:
ret = mhi_force_rddm_mode(ab_pci->mhi_ctrl);
break;
case ATH11K_MHI_RDDM_DONE:
break;
default:
ath11k_err(ab, "unhandled MHI state (%d)\n", mhi_state);
ret = -EINVAL;
}
if (ret)
goto out;
ath11k_mhi_set_state_bit(ab_pci, mhi_state);
return 0;
out:
ath11k_err(ab, "failed to set mhi state: %s(%d)\n",
ath11k_mhi_state_to_str(mhi_state), mhi_state);
return ret;
}
int ath11k_mhi_start(struct ath11k_pci *ab_pci)
{
int ret;
ab_pci->mhi_ctrl->timeout_ms = MHI_TIMEOUT_DEFAULT_MS;
ret = ath11k_mhi_set_state(ab_pci, ATH11K_MHI_INIT);
if (ret)
goto out;
ret = ath11k_mhi_set_state(ab_pci, ATH11K_MHI_POWER_ON);
if (ret)
goto out;
return 0;
out:
return ret;
}
void ath11k_mhi_stop(struct ath11k_pci *ab_pci)
{
ath11k_mhi_set_state(ab_pci, ATH11K_MHI_POWER_OFF);
ath11k_mhi_set_state(ab_pci, ATH11K_MHI_DEINIT);
}
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
*/
#ifndef _ATH11K_MHI_H
#define _ATH11K_MHI_H
#include "pci.h"
#define PCIE_TXVECDB 0x360
#define PCIE_TXVECSTATUS 0x368
#define PCIE_RXVECDB 0x394
#define PCIE_RXVECSTATUS 0x39C
#define MHISTATUS 0x48
#define MHICTRL 0x38
#define MHICTRL_RESET_MASK 0x2
enum ath11k_mhi_state {
ATH11K_MHI_INIT,
ATH11K_MHI_DEINIT,
ATH11K_MHI_POWER_ON,
ATH11K_MHI_POWER_OFF,
ATH11K_MHI_FORCE_POWER_OFF,
ATH11K_MHI_SUSPEND,
ATH11K_MHI_RESUME,
ATH11K_MHI_TRIGGER_RDDM,
ATH11K_MHI_RDDM,
ATH11K_MHI_RDDM_DONE,
};
int ath11k_mhi_start(struct ath11k_pci *ar_pci);
void ath11k_mhi_stop(struct ath11k_pci *ar_pci);
int ath11k_mhi_register(struct ath11k_pci *ar_pci);
void ath11k_mhi_unregister(struct ath11k_pci *ar_pci);
void ath11k_mhi_set_mhictrl_reset(struct ath11k_base *ab);
void ath11k_mhi_clear_vector(struct ath11k_base *ab);
#endif
此差异已折叠。
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
*/
#ifndef _ATH11K_PCI_H
#define _ATH11K_PCI_H
#include <linux/mhi.h>
#include "core.h"
#define PCIE_SOC_GLOBAL_RESET 0x3008
#define PCIE_SOC_GLOBAL_RESET_V 1
#define WLAON_WARM_SW_ENTRY 0x1f80504
#define WLAON_SOC_RESET_CAUSE_REG 0x01f8060c
#define PCIE_Q6_COOKIE_ADDR 0x01f80500
#define PCIE_Q6_COOKIE_DATA 0xc0000000
/* register to wake the UMAC from power collapse */
#define PCIE_SCRATCH_0_SOC_PCIE_REG 0x4040
/* register used for handshake mechanism to validate UMAC is awake */
#define PCIE_SOC_WAKE_PCIE_LOCAL_REG 0x3004
struct ath11k_msi_user {
char *name;
int num_vectors;
u32 base_vector;
};
struct ath11k_msi_config {
int total_vectors;
int total_users;
struct ath11k_msi_user *users;
};
struct ath11k_pci {
struct pci_dev *pdev;
struct ath11k_base *ab;
u16 dev_id;
char amss_path[100];
u32 msi_ep_base_data;
struct mhi_controller *mhi_ctrl;
unsigned long mhi_state;
u32 register_window;
/* protects register_window above */
spinlock_t window_lock;
};
static inline struct ath11k_pci *ath11k_pci_priv(struct ath11k_base *ab)
{
return (struct ath11k_pci *)ab->drv_priv;
}
int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ar_pci, char *user_name,
int *num_vectors, u32 *user_base_data,
u32 *base_vector);
int ath11k_pci_get_msi_irq(struct device *dev, unsigned int vector);
void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value);
u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset);
#endif
...@@ -223,9 +223,6 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, ...@@ -223,9 +223,6 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,
peer = ath11k_peer_find_by_pdev_idx(ar->ab, ar->pdev_idx, param->peer_addr); peer = ath11k_peer_find_by_pdev_idx(ar->ab, ar->pdev_idx, param->peer_addr);
if (peer) { if (peer) {
spin_unlock_bh(&ar->ab->base_lock); spin_unlock_bh(&ar->ab->base_lock);
ath11k_info(ar->ab,
"ignoring the peer %pM creation on same pdev idx %d\n",
param->peer_addr, ar->pdev_idx);
return -EINVAL; return -EINVAL;
} }
spin_unlock_bh(&ar->ab->base_lock); spin_unlock_bh(&ar->ab->base_lock);
......
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/firmware.h> #include <linux/firmware.h>
#define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02
#define HOST_CSTATE_BIT 0x04
static struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = { static struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = {
{ {
.data_type = QMI_OPT_FLAG, .data_type = QMI_OPT_FLAG,
...@@ -1516,15 +1519,35 @@ static int ath11k_qmi_host_cap_send(struct ath11k_base *ab) ...@@ -1516,15 +1519,35 @@ static int ath11k_qmi_host_cap_send(struct ath11k_base *ab)
req.bdf_support_valid = 1; req.bdf_support_valid = 1;
req.bdf_support = 1; req.bdf_support = 1;
req.m3_support_valid = 0; if (ab->bus_params.m3_fw_support) {
req.m3_support = 0; req.m3_support_valid = 1;
req.m3_support = 1;
req.m3_cache_support_valid = 0; req.m3_cache_support_valid = 1;
req.m3_cache_support = 0; req.m3_cache_support = 1;
} else {
req.m3_support_valid = 0;
req.m3_support = 0;
req.m3_cache_support_valid = 0;
req.m3_cache_support = 0;
}
req.cal_done_valid = 1; req.cal_done_valid = 1;
req.cal_done = ab->qmi.cal_done; req.cal_done = ab->qmi.cal_done;
if (ab->hw_params.internal_sleep_clock) {
req.nm_modem_valid = 1;
/* Notify firmware that this is non-qualcomm platform. */
req.nm_modem |= HOST_CSTATE_BIT;
/* Notify firmware about the sleep clock selection,
* nm_modem_bit[1] is used for this purpose. Host driver on
* non-qualcomm platforms should select internal sleep
* clock.
*/
req.nm_modem |= SLEEP_CLOCK_SELECT_INTERNAL_BIT;
}
ret = qmi_txn_init(&ab->qmi.handle, &txn, ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_host_cap_resp_msg_v01_ei, &resp); qmi_wlanfw_host_cap_resp_msg_v01_ei, &resp);
if (ret < 0) if (ret < 0)
...@@ -1634,19 +1657,30 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab) ...@@ -1634,19 +1657,30 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
memset(&resp, 0, sizeof(resp)); memset(&resp, 0, sizeof(resp));
req->mem_seg_len = ab->qmi.mem_seg_count; /* For QCA6390 by default FW requests a block of ~4M contiguous
* DMA memory, it's hard to allocate from OS. So host returns
* 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) {
ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi delays mem_request %d\n",
ab->qmi.mem_seg_count);
memset(req, 0, sizeof(*req));
} else {
req->mem_seg_len = ab->qmi.mem_seg_count;
for (i = 0; i < req->mem_seg_len ; i++) {
req->mem_seg[i].addr = ab->qmi.target_mem[i].paddr;
req->mem_seg[i].size = ab->qmi.target_mem[i].size;
req->mem_seg[i].type = ab->qmi.target_mem[i].type;
}
}
ret = qmi_txn_init(&ab->qmi.handle, &txn, ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_respond_mem_resp_msg_v01_ei, &resp); qmi_wlanfw_respond_mem_resp_msg_v01_ei, &resp);
if (ret < 0) if (ret < 0)
goto out; goto out;
for (i = 0; i < req->mem_seg_len ; i++) {
req->mem_seg[i].addr = ab->qmi.target_mem[i].paddr;
req->mem_seg[i].size = ab->qmi.target_mem[i].size;
req->mem_seg[i].type = ab->qmi.target_mem[i].type;
}
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn, ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_RESPOND_MEM_REQ_V01, QMI_WLANFW_RESPOND_MEM_REQ_V01,
QMI_WLANFW_RESPOND_MEM_REQ_MSG_V01_MAX_LEN, QMI_WLANFW_RESPOND_MEM_REQ_MSG_V01_MAX_LEN,
...@@ -1674,15 +1708,56 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab) ...@@ -1674,15 +1708,56 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
return ret; return ret;
} }
static void ath11k_qmi_free_target_mem_chunk(struct ath11k_base *ab)
{
int i;
if (ab->bus_params.fixed_mem_region)
return;
for (i = 0; i < ab->qmi.mem_seg_count; i++) {
if (!ab->qmi.target_mem[i].vaddr)
continue;
dma_free_coherent(ab->dev,
ab->qmi.target_mem[i].size,
ab->qmi.target_mem[i].vaddr,
ab->qmi.target_mem[i].paddr);
ab->qmi.target_mem[i].vaddr = NULL;
}
}
static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab) static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
{
int i;
struct target_mem_chunk *chunk;
for (i = 0; i < ab->qmi.mem_seg_count; i++) {
chunk = &ab->qmi.target_mem[i];
chunk->vaddr = dma_alloc_coherent(ab->dev,
chunk->size,
&chunk->paddr,
GFP_KERNEL);
if (!chunk->vaddr) {
ath11k_err(ab, "failed to alloc memory, size: 0x%x, type: %u\n",
chunk->size,
chunk->type);
return -EINVAL;
}
}
return 0;
}
static int ath11k_qmi_assign_target_mem_chunk(struct ath11k_base *ab)
{ {
int i, idx; int i, idx;
for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) { for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) {
switch (ab->qmi.target_mem[i].type) { switch (ab->qmi.target_mem[i].type) {
case BDF_MEM_REGION_TYPE: case BDF_MEM_REGION_TYPE:
ab->qmi.target_mem[idx].paddr = ATH11K_QMI_BDF_ADDRESS; ab->qmi.target_mem[idx].paddr = ab->hw_params.bdf_addr;
ab->qmi.target_mem[idx].vaddr = ATH11K_QMI_BDF_ADDRESS; ab->qmi.target_mem[idx].vaddr = NULL;
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size; ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type; ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
idx++; idx++;
...@@ -1694,7 +1769,7 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab) ...@@ -1694,7 +1769,7 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
} }
/* TODO ath11k does not support cold boot calibration */ /* TODO ath11k does not support cold boot calibration */
ab->qmi.target_mem[idx].paddr = 0; ab->qmi.target_mem[idx].paddr = 0;
ab->qmi.target_mem[idx].vaddr = 0; ab->qmi.target_mem[idx].vaddr = NULL;
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size; ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type; ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
idx++; idx++;
...@@ -1772,11 +1847,11 @@ static int ath11k_qmi_request_target_cap(struct ath11k_base *ab) ...@@ -1772,11 +1847,11 @@ static int ath11k_qmi_request_target_cap(struct ath11k_base *ab)
strlcpy(ab->qmi.target.fw_build_id, resp.fw_build_id, strlcpy(ab->qmi.target.fw_build_id, resp.fw_build_id,
sizeof(ab->qmi.target.fw_build_id)); sizeof(ab->qmi.target.fw_build_id));
ath11k_info(ab, "qmi target: chip_id: 0x%x, chip_family: 0x%x, board_id: 0x%x, soc_id: 0x%x\n", ath11k_info(ab, "chip_id 0x%x chip_family 0x%x board_id 0x%x soc_id 0x%x\n",
ab->qmi.target.chip_id, ab->qmi.target.chip_family, ab->qmi.target.chip_id, ab->qmi.target.chip_family,
ab->qmi.target.board_id, ab->qmi.target.soc_id); ab->qmi.target.board_id, ab->qmi.target.soc_id);
ath11k_info(ab, "qmi fw_version: 0x%x fw_build_timestamp: %s fw_build_id: %s", ath11k_info(ab, "fw_version 0x%x fw_build_timestamp %s fw_build_id %s",
ab->qmi.target.fw_version, ab->qmi.target.fw_version,
ab->qmi.target.fw_build_timestamp, ab->qmi.target.fw_build_timestamp,
ab->qmi.target.fw_build_id); ab->qmi.target.fw_build_id);
...@@ -1790,8 +1865,6 @@ ath11k_qmi_prepare_bdf_download(struct ath11k_base *ab, int type, ...@@ -1790,8 +1865,6 @@ ath11k_qmi_prepare_bdf_download(struct ath11k_base *ab, int type,
struct qmi_wlanfw_bdf_download_req_msg_v01 *req, struct qmi_wlanfw_bdf_download_req_msg_v01 *req,
void __iomem *bdf_addr) void __iomem *bdf_addr)
{ {
struct device *dev = ab->dev;
char filename[ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE];
const struct firmware *fw_entry; const struct firmware *fw_entry;
struct ath11k_board_data bd; struct ath11k_board_data bd;
u32 fw_size; u32 fw_size;
...@@ -1812,11 +1885,10 @@ ath11k_qmi_prepare_bdf_download(struct ath11k_base *ab, int type, ...@@ -1812,11 +1885,10 @@ ath11k_qmi_prepare_bdf_download(struct ath11k_base *ab, int type,
ath11k_core_free_bdf(ab, &bd); ath11k_core_free_bdf(ab, &bd);
break; break;
case ATH11K_QMI_FILE_TYPE_CALDATA: case ATH11K_QMI_FILE_TYPE_CALDATA:
snprintf(filename, sizeof(filename), fw_entry = ath11k_core_firmware_request(ab, ATH11K_DEFAULT_CAL_FILE);
"%s/%s", ab->hw_params.fw.dir, ATH11K_QMI_DEFAULT_CAL_FILE_NAME);
ret = request_firmware(&fw_entry, filename, dev);
if (ret) { if (ret) {
ath11k_warn(ab, "qmi failed to load CAL: %s\n", filename); ath11k_warn(ab, "failed to load %s: %d\n",
ATH11K_DEFAULT_CAL_FILE, ret);
goto out; goto out;
} }
...@@ -1825,8 +1897,6 @@ ath11k_qmi_prepare_bdf_download(struct ath11k_base *ab, int type, ...@@ -1825,8 +1897,6 @@ ath11k_qmi_prepare_bdf_download(struct ath11k_base *ab, int type,
memcpy_toio(bdf_addr + ATH11K_QMI_CALDATA_OFFSET, memcpy_toio(bdf_addr + ATH11K_QMI_CALDATA_OFFSET,
fw_entry->data, fw_size); fw_entry->data, fw_size);
ath11k_info(ab, "qmi downloading BDF: %s, size: %zu\n",
filename, fw_entry->size);
release_firmware(fw_entry); release_firmware(fw_entry);
break; break;
...@@ -1841,7 +1911,7 @@ ath11k_qmi_prepare_bdf_download(struct ath11k_base *ab, int type, ...@@ -1841,7 +1911,7 @@ ath11k_qmi_prepare_bdf_download(struct ath11k_base *ab, int type,
return ret; return ret;
} }
static int ath11k_qmi_load_bdf(struct ath11k_base *ab) static int ath11k_qmi_load_bdf_fixed_addr(struct ath11k_base *ab)
{ {
struct qmi_wlanfw_bdf_download_req_msg_v01 *req; struct qmi_wlanfw_bdf_download_req_msg_v01 *req;
struct qmi_wlanfw_bdf_download_resp_msg_v01 resp; struct qmi_wlanfw_bdf_download_resp_msg_v01 resp;
...@@ -1854,7 +1924,7 @@ static int ath11k_qmi_load_bdf(struct ath11k_base *ab) ...@@ -1854,7 +1924,7 @@ static int ath11k_qmi_load_bdf(struct ath11k_base *ab)
return -ENOMEM; return -ENOMEM;
memset(&resp, 0, sizeof(resp)); memset(&resp, 0, sizeof(resp));
bdf_addr = ioremap(ATH11K_QMI_BDF_ADDRESS, ATH11K_QMI_BDF_MAX_SIZE); bdf_addr = ioremap(ab->hw_params.bdf_addr, ATH11K_QMI_BDF_MAX_SIZE);
if (!bdf_addr) { if (!bdf_addr) {
ath11k_warn(ab, "qmi ioremap error for BDF\n"); ath11k_warn(ab, "qmi ioremap error for BDF\n");
ret = -EIO; ret = -EIO;
...@@ -1905,7 +1975,6 @@ static int ath11k_qmi_load_bdf(struct ath11k_base *ab) ...@@ -1905,7 +1975,6 @@ static int ath11k_qmi_load_bdf(struct ath11k_base *ab)
goto out_qmi_bdf; goto out_qmi_bdf;
} }
} }
ath11k_info(ab, "qmi BDF downloaded\n");
out_qmi_bdf: out_qmi_bdf:
iounmap(bdf_addr); iounmap(bdf_addr);
...@@ -1914,8 +1983,143 @@ static int ath11k_qmi_load_bdf(struct ath11k_base *ab) ...@@ -1914,8 +1983,143 @@ static int ath11k_qmi_load_bdf(struct ath11k_base *ab)
return ret; return ret;
} }
static int ath11k_qmi_load_bdf_qmi(struct ath11k_base *ab)
{
struct qmi_wlanfw_bdf_download_req_msg_v01 *req;
struct qmi_wlanfw_bdf_download_resp_msg_v01 resp;
struct ath11k_board_data bd;
unsigned int remaining;
struct qmi_txn txn = {};
int ret;
const u8 *temp;
req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
memset(&resp, 0, sizeof(resp));
memset(&bd, 0, sizeof(bd));
ret = ath11k_core_fetch_bdf(ab, &bd);
if (ret) {
ath11k_warn(ab, "qmi failed to load bdf:\n");
goto out;
}
temp = bd.data;
remaining = bd.len;
while (remaining) {
req->valid = 1;
req->file_id_valid = 1;
req->file_id = ab->qmi.target.board_id;
req->total_size_valid = 1;
req->total_size = bd.len;
req->seg_id_valid = 1;
req->data_valid = 1;
req->data_len = ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE;
req->bdf_type = ATH11K_QMI_BDF_TYPE_BIN;
req->bdf_type_valid = 1;
req->end_valid = 1;
req->end = 0;
if (remaining > QMI_WLANFW_MAX_DATA_SIZE_V01) {
req->data_len = QMI_WLANFW_MAX_DATA_SIZE_V01;
} else {
req->data_len = remaining;
req->end = 1;
}
memcpy(req->data, temp, req->data_len);
ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_bdf_download_resp_msg_v01_ei,
&resp);
if (ret < 0)
goto out_qmi_bdf;
ret = qmi_send_request(&ab->qmi.handle, NULL, &txn,
QMI_WLANFW_BDF_DOWNLOAD_REQ_V01,
QMI_WLANFW_BDF_DOWNLOAD_REQ_MSG_V01_MAX_LEN,
qmi_wlanfw_bdf_download_req_msg_v01_ei, req);
if (ret < 0) {
qmi_txn_cancel(&txn);
goto out_qmi_bdf;
}
ret = qmi_txn_wait(&txn, msecs_to_jiffies(ATH11K_QMI_WLANFW_TIMEOUT_MS));
if (ret < 0)
goto out_qmi_bdf;
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
ath11k_warn(ab, "qmi BDF download failed, result: %d, err: %d\n",
resp.resp.result, resp.resp.error);
ret = resp.resp.result;
goto out_qmi_bdf;
}
remaining -= req->data_len;
temp += req->data_len;
req->seg_id++;
}
out_qmi_bdf:
ath11k_core_free_bdf(ab, &bd);
out:
kfree(req);
return ret;
}
static int ath11k_qmi_m3_load(struct ath11k_base *ab)
{
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
const struct firmware *fw;
char path[100];
int ret;
if (m3_mem->vaddr || m3_mem->size)
return 0;
fw = ath11k_core_firmware_request(ab, ATH11K_M3_FILE);
if (IS_ERR(fw)) {
ret = PTR_ERR(fw);
ath11k_core_create_firmware_path(ab, ATH11K_M3_FILE,
path, sizeof(path));
ath11k_err(ab, "failed to load %s: %d\n", path, ret);
return ret;
}
m3_mem->vaddr = dma_alloc_coherent(ab->dev,
fw->size, &m3_mem->paddr,
GFP_KERNEL);
if (!m3_mem->vaddr) {
ath11k_err(ab, "failed to allocate memory for M3 with size %zu\n",
fw->size);
release_firmware(fw);
return -ENOMEM;
}
memcpy(m3_mem->vaddr, fw->data, fw->size);
m3_mem->size = fw->size;
release_firmware(fw);
return 0;
}
static void ath11k_qmi_m3_free(struct ath11k_base *ab)
{
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
if (!ab->bus_params.m3_fw_support || !m3_mem->vaddr)
return;
dma_free_coherent(ab->dev, m3_mem->size,
m3_mem->vaddr, m3_mem->paddr);
m3_mem->vaddr = NULL;
}
static int ath11k_qmi_wlanfw_m3_info_send(struct ath11k_base *ab) static int ath11k_qmi_wlanfw_m3_info_send(struct ath11k_base *ab)
{ {
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
struct qmi_wlanfw_m3_info_req_msg_v01 req; struct qmi_wlanfw_m3_info_req_msg_v01 req;
struct qmi_wlanfw_m3_info_resp_msg_v01 resp; struct qmi_wlanfw_m3_info_resp_msg_v01 resp;
struct qmi_txn txn = {}; struct qmi_txn txn = {};
...@@ -1923,8 +2127,20 @@ static int ath11k_qmi_wlanfw_m3_info_send(struct ath11k_base *ab) ...@@ -1923,8 +2127,20 @@ static int ath11k_qmi_wlanfw_m3_info_send(struct ath11k_base *ab)
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
memset(&resp, 0, sizeof(resp)); memset(&resp, 0, sizeof(resp));
req.addr = 0;
req.size = 0; if (ab->bus_params.m3_fw_support) {
ret = ath11k_qmi_m3_load(ab);
if (ret) {
ath11k_err(ab, "failed to load m3 firmware: %d", ret);
return ret;
}
req.addr = m3_mem->paddr;
req.size = m3_mem->size;
} else {
req.addr = 0;
req.size = 0;
}
ret = qmi_txn_init(&ab->qmi.handle, &txn, ret = qmi_txn_init(&ab->qmi.handle, &txn,
qmi_wlanfw_m3_info_resp_msg_v01_ei, &resp); qmi_wlanfw_m3_info_resp_msg_v01_ei, &resp);
...@@ -2034,7 +2250,7 @@ static int ath11k_qmi_wlanfw_wlan_cfg_send(struct ath11k_base *ab) ...@@ -2034,7 +2250,7 @@ static int ath11k_qmi_wlanfw_wlan_cfg_send(struct ath11k_base *ab)
req->tgt_cfg_valid = 1; req->tgt_cfg_valid = 1;
/* This is number of CE configs */ /* This is number of CE configs */
req->tgt_cfg_len = ab->qmi.ce_cfg.tgt_ce_len; req->tgt_cfg_len = ab->qmi.ce_cfg.tgt_ce_len;
for (pipe_num = 0; pipe_num <= req->tgt_cfg_len ; pipe_num++) { for (pipe_num = 0; pipe_num < req->tgt_cfg_len ; pipe_num++) {
req->tgt_cfg[pipe_num].pipe_num = ce_cfg[pipe_num].pipenum; req->tgt_cfg[pipe_num].pipe_num = ce_cfg[pipe_num].pipenum;
req->tgt_cfg[pipe_num].pipe_dir = ce_cfg[pipe_num].pipedir; req->tgt_cfg[pipe_num].pipe_dir = ce_cfg[pipe_num].pipedir;
req->tgt_cfg[pipe_num].nentries = ce_cfg[pipe_num].nentries; req->tgt_cfg[pipe_num].nentries = ce_cfg[pipe_num].nentries;
...@@ -2181,7 +2397,10 @@ static void ath11k_qmi_event_load_bdf(struct ath11k_qmi *qmi) ...@@ -2181,7 +2397,10 @@ static void ath11k_qmi_event_load_bdf(struct ath11k_qmi *qmi)
return; return;
} }
ret = ath11k_qmi_load_bdf(ab); if (ab->bus_params.fixed_bdf_addr)
ret = ath11k_qmi_load_bdf_fixed_addr(ab);
else
ret = ath11k_qmi_load_bdf_qmi(ab);
if (ret < 0) { if (ret < 0) {
ath11k_warn(ab, "qmi failed to load board data file:%d\n", ret); ath11k_warn(ab, "qmi failed to load board data file:%d\n", ret);
return; return;
...@@ -2220,10 +2439,20 @@ static void ath11k_qmi_msg_mem_request_cb(struct qmi_handle *qmi_hdl, ...@@ -2220,10 +2439,20 @@ static void ath11k_qmi_msg_mem_request_cb(struct qmi_handle *qmi_hdl,
msg->mem_seg[i].type, msg->mem_seg[i].size); msg->mem_seg[i].type, msg->mem_seg[i].size);
} }
ret = ath11k_qmi_alloc_target_mem_chunk(ab); if (ab->bus_params.fixed_mem_region) {
if (ret < 0) { ret = ath11k_qmi_assign_target_mem_chunk(ab);
ath11k_warn(ab, "qmi failed to alloc target memory:%d\n", ret); if (ret) {
return; ath11k_warn(ab, "qmi failed to assign target memory: %d\n",
ret);
return;
}
} else if (msg->mem_seg_len > 2) {
ret = ath11k_qmi_alloc_target_mem_chunk(ab);
if (ret) {
ath11k_warn(ab, "qmi failed to alloc target memory: %d\n",
ret);
return;
}
} }
ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_REQUEST_MEM, NULL); ath11k_qmi_driver_event_post(qmi, ATH11K_QMI_EVENT_REQUEST_MEM, NULL);
...@@ -2265,21 +2494,21 @@ static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = { ...@@ -2265,21 +2494,21 @@ static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = {
.type = QMI_INDICATION, .type = QMI_INDICATION,
.msg_id = QMI_WLFW_REQUEST_MEM_IND_V01, .msg_id = QMI_WLFW_REQUEST_MEM_IND_V01,
.ei = qmi_wlanfw_request_mem_ind_msg_v01_ei, .ei = qmi_wlanfw_request_mem_ind_msg_v01_ei,
.decoded_size = sizeof(qmi_wlanfw_request_mem_ind_msg_v01_ei), .decoded_size = sizeof(struct qmi_wlanfw_request_mem_ind_msg_v01),
.fn = ath11k_qmi_msg_mem_request_cb, .fn = ath11k_qmi_msg_mem_request_cb,
}, },
{ {
.type = QMI_INDICATION, .type = QMI_INDICATION,
.msg_id = QMI_WLFW_FW_MEM_READY_IND_V01, .msg_id = QMI_WLFW_FW_MEM_READY_IND_V01,
.ei = qmi_wlanfw_mem_ready_ind_msg_v01_ei, .ei = qmi_wlanfw_mem_ready_ind_msg_v01_ei,
.decoded_size = sizeof(qmi_wlanfw_mem_ready_ind_msg_v01_ei), .decoded_size = sizeof(struct qmi_wlanfw_fw_mem_ready_ind_msg_v01),
.fn = ath11k_qmi_msg_mem_ready_cb, .fn = ath11k_qmi_msg_mem_ready_cb,
}, },
{ {
.type = QMI_INDICATION, .type = QMI_INDICATION,
.msg_id = QMI_WLFW_FW_READY_IND_V01, .msg_id = QMI_WLFW_FW_READY_IND_V01,
.ei = qmi_wlanfw_fw_ready_ind_msg_v01_ei, .ei = qmi_wlanfw_fw_ready_ind_msg_v01_ei,
.decoded_size = sizeof(qmi_wlanfw_fw_ready_ind_msg_v01_ei), .decoded_size = sizeof(struct qmi_wlanfw_fw_ready_ind_msg_v01),
.fn = ath11k_qmi_msg_fw_ready_cb, .fn = ath11k_qmi_msg_fw_ready_cb,
}, },
{ {
...@@ -2287,7 +2516,7 @@ static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = { ...@@ -2287,7 +2516,7 @@ static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = {
.msg_id = QMI_WLFW_COLD_BOOT_CAL_DONE_IND_V01, .msg_id = QMI_WLFW_COLD_BOOT_CAL_DONE_IND_V01,
.ei = qmi_wlanfw_cold_boot_cal_done_ind_msg_v01_ei, .ei = qmi_wlanfw_cold_boot_cal_done_ind_msg_v01_ei,
.decoded_size = .decoded_size =
sizeof(qmi_wlanfw_cold_boot_cal_done_ind_msg_v01_ei), sizeof(struct qmi_wlanfw_fw_cold_cal_done_ind_msg_v01),
.fn = ath11k_qmi_msg_cold_boot_cal_done_cb, .fn = ath11k_qmi_msg_cold_boot_cal_done_cb,
}, },
}; };
...@@ -2416,9 +2645,10 @@ int ath11k_qmi_init_service(struct ath11k_base *ab) ...@@ -2416,9 +2645,10 @@ int ath11k_qmi_init_service(struct ath11k_base *ab)
ret = qmi_add_lookup(&ab->qmi.handle, ATH11K_QMI_WLFW_SERVICE_ID_V01, ret = qmi_add_lookup(&ab->qmi.handle, ATH11K_QMI_WLFW_SERVICE_ID_V01,
ATH11K_QMI_WLFW_SERVICE_VERS_V01, ATH11K_QMI_WLFW_SERVICE_VERS_V01,
ATH11K_QMI_WLFW_SERVICE_INS_ID_V01); ab->qmi.service_ins_id);
if (ret < 0) { if (ret < 0) {
ath11k_warn(ab, "failed to add qmi lookup\n"); ath11k_warn(ab, "failed to add qmi lookup\n");
destroy_workqueue(ab->qmi.event_wq);
return ret; return ret;
} }
...@@ -2430,5 +2660,7 @@ void ath11k_qmi_deinit_service(struct ath11k_base *ab) ...@@ -2430,5 +2660,7 @@ void ath11k_qmi_deinit_service(struct ath11k_base *ab)
qmi_handle_release(&ab->qmi.handle); qmi_handle_release(&ab->qmi.handle);
cancel_work_sync(&ab->qmi.event_work); cancel_work_sync(&ab->qmi.event_work);
destroy_workqueue(ab->qmi.event_wq); destroy_workqueue(ab->qmi.event_wq);
ath11k_qmi_m3_free(ab);
ath11k_qmi_free_target_mem_chunk(ab);
} }
...@@ -699,7 +699,7 @@ void ath11k_reg_free(struct ath11k_base *ab) ...@@ -699,7 +699,7 @@ void ath11k_reg_free(struct ath11k_base *ab)
{ {
int i; int i;
for (i = 0; i < MAX_RADIOS; i++) { for (i = 0; i < ab->hw_params.max_radios; i++) {
kfree(ab->default_regd[i]); kfree(ab->default_regd[i]);
kfree(ab->new_regd[i]); kfree(ab->new_regd[i]);
} }
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册