mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
wireless-drivers-next patches for v5.10
First set of patches for v5.10. Most noteworthy here is ath11k getting initial support for QCA6390 and IPQ6018 devices. But most of the patches are cleanup: W=1 warning fixes, fallthrough keywords, DMA API changes and tasklet API changes. Major changes: ath10k * support SDIO firmware codedumps * support station specific TID configurations ath11k * add support for IPQ6018 * add support for QCA6390 PCI devices ath9k * add support for NL80211_EXT_FEATURE_CAN_REPLACE_PTK0 to improve PTK0 rekeying wcn36xx * add support for TX ack -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQEcBAABAgAGBQJfW5XtAAoJEG4XJFUm622bnuoIAIx8xplr5UYZv/qaMyvBaoNQ gG7AU3IUs4QibSUabpE7kBpdLVX9O4mC5nLWCutGH1dTrJGIQsnuncW206yOAZPp +MPOauxBmfkBm61RmJ3beGXan6ZGlE7rwkO0Pf+mqrWk4XVovItKpJUuR+IWliu/ gdVbdC2Uu7bQlv44MI/3xOpx5Xvk5gq/4tPcTOE3b57wIyln0NSKJYOoOuL+i2f/ WDiTgPyA/9x+llrf6sA+oLmEN2F8TpVWSDv6F4mA5E9uYjJrJMEJLosSzohU7+ou j7gvCMv5F8+XnQYX4T/qJ05axBDQO2zRJ6YynWDoqQss4XW8xaiuQCEmaiHE8GM= =kS8U -----END PGP SIGNATURE----- Merge tag 'wireless-drivers-next-2020-09-11' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next Kalle Valo says: ==================== wireless-drivers-next patches for v5.10 First set of patches for v5.10. Most noteworthy here is ath11k getting initial support for QCA6390 and IPQ6018 devices. But most of the patches are cleanup: W=1 warning fixes, fallthrough keywords, DMA API changes and tasklet API changes. Major changes: ath10k * support SDIO firmware codedumps * support station specific TID configurations ath11k * add support for IPQ6018 * add support for QCA6390 PCI devices ath9k * add support for NL80211_EXT_FEATURE_CAN_REPLACE_PTK0 to improve PTK0 rekeying wcn36xx * add support for TX ack ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
e7a08121e0
@ -65,7 +65,8 @@ Optional properties:
|
||||
the length can vary between hw versions.
|
||||
- <supply-name>-supply: handle to the regulator device tree node
|
||||
optional "supply-name" are "vdd-0.8-cx-mx",
|
||||
"vdd-1.8-xo", "vdd-1.3-rfa" and "vdd-3.3-ch0".
|
||||
"vdd-1.8-xo", "vdd-1.3-rfa", "vdd-3.3-ch0",
|
||||
and "vdd-3.3-ch1".
|
||||
- memory-region:
|
||||
Usage: optional
|
||||
Value type: <phandle>
|
||||
@ -204,6 +205,7 @@ wifi@18000000 {
|
||||
vdd-1.8-xo-supply = <&vreg_l7a_1p8>;
|
||||
vdd-1.3-rfa-supply = <&vreg_l17a_1p3>;
|
||||
vdd-3.3-ch0-supply = <&vreg_l25a_3p3>;
|
||||
vdd-3.3-ch1-supply = <&vreg_l26a_3p3>;
|
||||
memory-region = <&wifi_msa_mem>;
|
||||
iommus = <&apps_smmu 0x0040 0x1>;
|
||||
qcom,msa-fixed-perm;
|
||||
|
@ -17,7 +17,9 @@ description: |
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: qcom,ipq8074-wifi
|
||||
enum:
|
||||
- qcom,ipq8074-wifi
|
||||
- qcom,ipq6018-wifi
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
@ -324,8 +324,8 @@ static void adm8211_interrupt_tci(struct ieee80211_hw *dev)
|
||||
|
||||
/* TODO: check TDES0_STATUS_TUF and TDES0_STATUS_TRO */
|
||||
|
||||
pci_unmap_single(priv->pdev, info->mapping,
|
||||
info->skb->len, PCI_DMA_TODEVICE);
|
||||
dma_unmap_single(&priv->pdev->dev, info->mapping,
|
||||
info->skb->len, DMA_TO_DEVICE);
|
||||
|
||||
ieee80211_tx_info_clear_status(txi);
|
||||
|
||||
@ -382,35 +382,34 @@ static void adm8211_interrupt_rci(struct ieee80211_hw *dev)
|
||||
} else if (pktlen < RX_COPY_BREAK) {
|
||||
skb = dev_alloc_skb(pktlen);
|
||||
if (skb) {
|
||||
pci_dma_sync_single_for_cpu(
|
||||
priv->pdev,
|
||||
priv->rx_buffers[entry].mapping,
|
||||
pktlen, PCI_DMA_FROMDEVICE);
|
||||
dma_sync_single_for_cpu(&priv->pdev->dev,
|
||||
priv->rx_buffers[entry].mapping,
|
||||
pktlen,
|
||||
DMA_FROM_DEVICE);
|
||||
skb_put_data(skb,
|
||||
skb_tail_pointer(priv->rx_buffers[entry].skb),
|
||||
pktlen);
|
||||
pci_dma_sync_single_for_device(
|
||||
priv->pdev,
|
||||
priv->rx_buffers[entry].mapping,
|
||||
RX_PKT_SIZE, PCI_DMA_FROMDEVICE);
|
||||
dma_sync_single_for_device(&priv->pdev->dev,
|
||||
priv->rx_buffers[entry].mapping,
|
||||
RX_PKT_SIZE,
|
||||
DMA_FROM_DEVICE);
|
||||
}
|
||||
} else {
|
||||
newskb = dev_alloc_skb(RX_PKT_SIZE);
|
||||
if (newskb) {
|
||||
skb = priv->rx_buffers[entry].skb;
|
||||
skb_put(skb, pktlen);
|
||||
pci_unmap_single(
|
||||
priv->pdev,
|
||||
priv->rx_buffers[entry].mapping,
|
||||
RX_PKT_SIZE, PCI_DMA_FROMDEVICE);
|
||||
dma_unmap_single(&priv->pdev->dev,
|
||||
priv->rx_buffers[entry].mapping,
|
||||
RX_PKT_SIZE, DMA_FROM_DEVICE);
|
||||
priv->rx_buffers[entry].skb = newskb;
|
||||
priv->rx_buffers[entry].mapping =
|
||||
pci_map_single(priv->pdev,
|
||||
dma_map_single(&priv->pdev->dev,
|
||||
skb_tail_pointer(newskb),
|
||||
RX_PKT_SIZE,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
if (pci_dma_mapping_error(priv->pdev,
|
||||
priv->rx_buffers[entry].mapping)) {
|
||||
DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(&priv->pdev->dev,
|
||||
priv->rx_buffers[entry].mapping)) {
|
||||
priv->rx_buffers[entry].skb = NULL;
|
||||
dev_kfree_skb(newskb);
|
||||
skb = NULL;
|
||||
@ -1449,11 +1448,11 @@ static int adm8211_init_rings(struct ieee80211_hw *dev)
|
||||
rx_info->skb = dev_alloc_skb(RX_PKT_SIZE);
|
||||
if (rx_info->skb == NULL)
|
||||
break;
|
||||
rx_info->mapping = pci_map_single(priv->pdev,
|
||||
rx_info->mapping = dma_map_single(&priv->pdev->dev,
|
||||
skb_tail_pointer(rx_info->skb),
|
||||
RX_PKT_SIZE,
|
||||
PCI_DMA_FROMDEVICE);
|
||||
if (pci_dma_mapping_error(priv->pdev, rx_info->mapping)) {
|
||||
DMA_FROM_DEVICE);
|
||||
if (dma_mapping_error(&priv->pdev->dev, rx_info->mapping)) {
|
||||
dev_kfree_skb(rx_info->skb);
|
||||
rx_info->skb = NULL;
|
||||
break;
|
||||
@ -1490,10 +1489,9 @@ static void adm8211_free_rings(struct ieee80211_hw *dev)
|
||||
if (!priv->rx_buffers[i].skb)
|
||||
continue;
|
||||
|
||||
pci_unmap_single(
|
||||
priv->pdev,
|
||||
priv->rx_buffers[i].mapping,
|
||||
RX_PKT_SIZE, PCI_DMA_FROMDEVICE);
|
||||
dma_unmap_single(&priv->pdev->dev,
|
||||
priv->rx_buffers[i].mapping, RX_PKT_SIZE,
|
||||
DMA_FROM_DEVICE);
|
||||
|
||||
dev_kfree_skb(priv->rx_buffers[i].skb);
|
||||
}
|
||||
@ -1502,10 +1500,9 @@ static void adm8211_free_rings(struct ieee80211_hw *dev)
|
||||
if (!priv->tx_buffers[i].skb)
|
||||
continue;
|
||||
|
||||
pci_unmap_single(priv->pdev,
|
||||
dma_unmap_single(&priv->pdev->dev,
|
||||
priv->tx_buffers[i].mapping,
|
||||
priv->tx_buffers[i].skb->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
priv->tx_buffers[i].skb->len, DMA_TO_DEVICE);
|
||||
|
||||
dev_kfree_skb(priv->tx_buffers[i].skb);
|
||||
}
|
||||
@ -1632,9 +1629,9 @@ static int adm8211_tx_raw(struct ieee80211_hw *dev, struct sk_buff *skb,
|
||||
unsigned int entry;
|
||||
u32 flag;
|
||||
|
||||
mapping = pci_map_single(priv->pdev, skb->data, skb->len,
|
||||
PCI_DMA_TODEVICE);
|
||||
if (pci_dma_mapping_error(priv->pdev, mapping))
|
||||
mapping = dma_map_single(&priv->pdev->dev, skb->data, skb->len,
|
||||
DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(&priv->pdev->dev, mapping))
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
@ -1745,8 +1742,8 @@ static int adm8211_alloc_rings(struct ieee80211_hw *dev)
|
||||
/* Allocate TX/RX descriptors */
|
||||
ring_size = sizeof(struct adm8211_desc) * priv->rx_ring_size +
|
||||
sizeof(struct adm8211_desc) * priv->tx_ring_size;
|
||||
priv->rx_ring = pci_alloc_consistent(priv->pdev, ring_size,
|
||||
&priv->rx_ring_dma);
|
||||
priv->rx_ring = dma_alloc_coherent(&priv->pdev->dev, ring_size,
|
||||
&priv->rx_ring_dma, GFP_KERNEL);
|
||||
|
||||
if (!priv->rx_ring) {
|
||||
kfree(priv->rx_buffers);
|
||||
@ -1818,8 +1815,8 @@ static int adm8211_probe(struct pci_dev *pdev,
|
||||
return err; /* someone else grabbed it? don't disable it */
|
||||
}
|
||||
|
||||
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) ||
|
||||
pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {
|
||||
if (dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)) ||
|
||||
dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32))) {
|
||||
printk(KERN_ERR "%s (adm8211): No suitable DMA available\n",
|
||||
pci_name(pdev));
|
||||
goto err_free_reg;
|
||||
@ -1929,10 +1926,10 @@ static int adm8211_probe(struct pci_dev *pdev,
|
||||
kfree(priv->eeprom);
|
||||
|
||||
err_free_desc:
|
||||
pci_free_consistent(pdev,
|
||||
sizeof(struct adm8211_desc) * priv->rx_ring_size +
|
||||
sizeof(struct adm8211_desc) * priv->tx_ring_size,
|
||||
priv->rx_ring, priv->rx_ring_dma);
|
||||
dma_free_coherent(&pdev->dev,
|
||||
sizeof(struct adm8211_desc) * priv->rx_ring_size +
|
||||
sizeof(struct adm8211_desc) * priv->tx_ring_size,
|
||||
priv->rx_ring, priv->rx_ring_dma);
|
||||
kfree(priv->rx_buffers);
|
||||
|
||||
err_iounmap:
|
||||
@ -1962,10 +1959,10 @@ static void adm8211_remove(struct pci_dev *pdev)
|
||||
|
||||
priv = dev->priv;
|
||||
|
||||
pci_free_consistent(pdev,
|
||||
sizeof(struct adm8211_desc) * priv->rx_ring_size +
|
||||
sizeof(struct adm8211_desc) * priv->tx_ring_size,
|
||||
priv->rx_ring, priv->rx_ring_dma);
|
||||
dma_free_coherent(&pdev->dev,
|
||||
sizeof(struct adm8211_desc) * priv->rx_ring_size +
|
||||
sizeof(struct adm8211_desc) * priv->tx_ring_size,
|
||||
priv->rx_ring, priv->rx_ring_dma);
|
||||
|
||||
kfree(priv->rx_buffers);
|
||||
kfree(priv->eeprom);
|
||||
|
@ -12,18 +12,11 @@
|
||||
|
||||
void ath10k_bmi_start(struct ath10k *ar)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi start\n");
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_bmi_start);
|
||||
|
||||
int ath10k_bmi_done(struct ath10k *ar)
|
||||
{
|
||||
@ -197,6 +190,7 @@ int ath10k_bmi_read_memory(struct ath10k *ar,
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_bmi_read_memory);
|
||||
|
||||
int ath10k_bmi_write_soc_reg(struct ath10k *ar, u32 address, u32 reg_val)
|
||||
{
|
||||
|
@ -1299,29 +1299,24 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
|
||||
struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs;
|
||||
u32 ctrl_addr = ce_state->ctrl_addr;
|
||||
|
||||
spin_lock_bh(&ce->ce_lock);
|
||||
|
||||
/* Clear the copy-complete interrupts that will be handled here. */
|
||||
/*
|
||||
* Clear before handling
|
||||
*
|
||||
* Misc CE interrupts are not being handled, but still need
|
||||
* to be cleared.
|
||||
*
|
||||
* NOTE: When the last copy engine interrupt is cleared the
|
||||
* hardware will go to sleep. Once this happens any access to
|
||||
* the CE registers can cause a hardware fault.
|
||||
*/
|
||||
ath10k_ce_engine_int_status_clear(ar, ctrl_addr,
|
||||
wm_regs->cc_mask);
|
||||
|
||||
spin_unlock_bh(&ce->ce_lock);
|
||||
wm_regs->cc_mask | wm_regs->wm_mask);
|
||||
|
||||
if (ce_state->recv_cb)
|
||||
ce_state->recv_cb(ce_state);
|
||||
|
||||
if (ce_state->send_cb)
|
||||
ce_state->send_cb(ce_state);
|
||||
|
||||
spin_lock_bh(&ce->ce_lock);
|
||||
|
||||
/*
|
||||
* Misc CE interrupts are not being handled, but still need
|
||||
* to be cleared.
|
||||
*/
|
||||
ath10k_ce_engine_int_status_clear(ar, ctrl_addr, wm_regs->wm_mask);
|
||||
|
||||
spin_unlock_bh(&ce->ce_lock);
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_ce_per_engine_service);
|
||||
|
||||
@ -1372,45 +1367,55 @@ static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state)
|
||||
ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
|
||||
}
|
||||
|
||||
int ath10k_ce_disable_interrupts(struct ath10k *ar)
|
||||
void ath10k_ce_disable_interrupt(struct ath10k *ar, int ce_id)
|
||||
{
|
||||
struct ath10k_ce *ce = ath10k_ce_priv(ar);
|
||||
struct ath10k_ce_pipe *ce_state;
|
||||
u32 ctrl_addr;
|
||||
|
||||
ce_state = &ce->ce_states[ce_id];
|
||||
if (ce_state->attr_flags & CE_ATTR_POLL)
|
||||
return;
|
||||
|
||||
ctrl_addr = ath10k_ce_base_address(ar, ce_id);
|
||||
|
||||
ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr);
|
||||
ath10k_ce_error_intr_disable(ar, ctrl_addr);
|
||||
ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_ce_disable_interrupt);
|
||||
|
||||
void ath10k_ce_disable_interrupts(struct ath10k *ar)
|
||||
{
|
||||
int ce_id;
|
||||
|
||||
for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
|
||||
ce_state = &ce->ce_states[ce_id];
|
||||
if (ce_state->attr_flags & CE_ATTR_POLL)
|
||||
continue;
|
||||
|
||||
ctrl_addr = ath10k_ce_base_address(ar, ce_id);
|
||||
|
||||
ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr);
|
||||
ath10k_ce_error_intr_disable(ar, ctrl_addr);
|
||||
ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
|
||||
ath10k_ce_disable_interrupt(ar, ce_id);
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_ce_disable_interrupts);
|
||||
|
||||
void ath10k_ce_enable_interrupts(struct ath10k *ar)
|
||||
void ath10k_ce_enable_interrupt(struct ath10k *ar, int ce_id)
|
||||
{
|
||||
struct ath10k_ce *ce = ath10k_ce_priv(ar);
|
||||
int ce_id;
|
||||
struct ath10k_ce_pipe *ce_state;
|
||||
|
||||
ce_state = &ce->ce_states[ce_id];
|
||||
if (ce_state->attr_flags & CE_ATTR_POLL)
|
||||
return;
|
||||
|
||||
ath10k_ce_per_engine_handler_adjust(ce_state);
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_ce_enable_interrupt);
|
||||
|
||||
void ath10k_ce_enable_interrupts(struct ath10k *ar)
|
||||
{
|
||||
int ce_id;
|
||||
|
||||
/* Enable interrupts for copy engine that
|
||||
* are not using polling mode.
|
||||
*/
|
||||
for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
|
||||
ce_state = &ce->ce_states[ce_id];
|
||||
if (ce_state->attr_flags & CE_ATTR_POLL)
|
||||
continue;
|
||||
|
||||
ath10k_ce_per_engine_handler_adjust(ce_state);
|
||||
}
|
||||
for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
|
||||
ath10k_ce_enable_interrupt(ar, ce_id);
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_ce_enable_interrupts);
|
||||
|
||||
@ -1555,7 +1560,7 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id,
|
||||
ret = ath10k_ce_alloc_shadow_base(ar, src_ring, nentries);
|
||||
if (ret) {
|
||||
dma_free_coherent(ar->dev,
|
||||
(nentries * sizeof(struct ce_desc_64) +
|
||||
(nentries * sizeof(struct ce_desc) +
|
||||
CE_DESC_RING_ALIGN),
|
||||
src_ring->base_addr_owner_space_unaligned,
|
||||
base_addr);
|
||||
|
@ -255,10 +255,13 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state,
|
||||
/*==================CE Interrupt Handlers====================*/
|
||||
void ath10k_ce_per_engine_service_any(struct ath10k *ar);
|
||||
void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id);
|
||||
int ath10k_ce_disable_interrupts(struct ath10k *ar);
|
||||
void ath10k_ce_disable_interrupt(struct ath10k *ar, int ce_id);
|
||||
void ath10k_ce_disable_interrupts(struct ath10k *ar);
|
||||
void ath10k_ce_enable_interrupt(struct ath10k *ar, int ce_id);
|
||||
void ath10k_ce_enable_interrupts(struct ath10k *ar);
|
||||
void ath10k_ce_dump_registers(struct ath10k *ar,
|
||||
struct ath10k_fw_crash_data *crash_data);
|
||||
|
||||
void ath10k_ce_alloc_rri(struct ath10k *ar);
|
||||
void ath10k_ce_free_rri(struct ath10k *ar);
|
||||
|
||||
@ -369,18 +372,14 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
|
||||
(((x) & CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK) >> \
|
||||
CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB)
|
||||
#define CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000
|
||||
#define CE_INTERRUPT_SUMMARY (GENMASK(CE_COUNT_MAX - 1, 0))
|
||||
|
||||
static inline u32 ath10k_ce_interrupt_summary(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_ce *ce = ath10k_ce_priv(ar);
|
||||
|
||||
if (!ar->hw_params.per_ce_irq)
|
||||
return CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET(
|
||||
ce->bus_ops->read32((ar), CE_WRAPPER_BASE_ADDRESS +
|
||||
CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS));
|
||||
else
|
||||
return CE_INTERRUPT_SUMMARY;
|
||||
return CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET(
|
||||
ce->bus_ops->read32((ar), CE_WRAPPER_BASE_ADDRESS +
|
||||
CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS));
|
||||
}
|
||||
|
||||
/* Host software's Copy Engine configuration. */
|
||||
|
@ -119,7 +119,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.num_wds_entries = 0x20,
|
||||
.target_64bit = false,
|
||||
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
|
||||
.per_ce_irq = false,
|
||||
.shadow_reg_support = false,
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
@ -155,7 +154,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.num_wds_entries = 0x20,
|
||||
.target_64bit = false,
|
||||
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
|
||||
.per_ce_irq = false,
|
||||
.shadow_reg_support = false,
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
@ -220,7 +218,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.num_wds_entries = 0x20,
|
||||
.target_64bit = false,
|
||||
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
|
||||
.per_ce_irq = false,
|
||||
.shadow_reg_support = false,
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
@ -255,7 +252,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.num_wds_entries = 0x20,
|
||||
.target_64bit = false,
|
||||
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
|
||||
.per_ce_irq = false,
|
||||
.shadow_reg_support = false,
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
@ -290,7 +286,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.num_wds_entries = 0x20,
|
||||
.target_64bit = false,
|
||||
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
|
||||
.per_ce_irq = false,
|
||||
.shadow_reg_support = false,
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
@ -328,12 +323,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.num_wds_entries = 0x20,
|
||||
.target_64bit = false,
|
||||
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
|
||||
.per_ce_irq = false,
|
||||
.shadow_reg_support = false,
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
.fw_diag_ce_download = true,
|
||||
.tx_stats_over_pktlog = false,
|
||||
.supports_peer_stats_info = true,
|
||||
},
|
||||
{
|
||||
.id = QCA99X0_HW_2_0_DEV_VERSION,
|
||||
@ -369,7 +364,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.num_wds_entries = 0x20,
|
||||
.target_64bit = false,
|
||||
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
|
||||
.per_ce_irq = false,
|
||||
.shadow_reg_support = false,
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
@ -417,7 +411,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.num_wds_entries = 0x20,
|
||||
.target_64bit = false,
|
||||
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
|
||||
.per_ce_irq = false,
|
||||
.shadow_reg_support = false,
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
@ -462,7 +455,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.num_wds_entries = 0x20,
|
||||
.target_64bit = false,
|
||||
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
|
||||
.per_ce_irq = false,
|
||||
.shadow_reg_support = false,
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
@ -497,7 +489,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.num_wds_entries = 0x20,
|
||||
.target_64bit = false,
|
||||
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
|
||||
.per_ce_irq = false,
|
||||
.shadow_reg_support = false,
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
@ -534,7 +525,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.num_wds_entries = 0x20,
|
||||
.target_64bit = false,
|
||||
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
|
||||
.per_ce_irq = false,
|
||||
.shadow_reg_support = false,
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
@ -603,7 +593,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.num_wds_entries = 0x20,
|
||||
.target_64bit = false,
|
||||
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL,
|
||||
.per_ce_irq = false,
|
||||
.shadow_reg_support = false,
|
||||
.rri_on_ddr = false,
|
||||
.hw_filter_reset_required = true,
|
||||
@ -631,7 +620,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
|
||||
.num_wds_entries = TARGET_HL_TLV_NUM_WDS_ENTRIES,
|
||||
.target_64bit = true,
|
||||
.rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL_DUAL_MAC,
|
||||
.per_ce_irq = true,
|
||||
.shadow_reg_support = true,
|
||||
.rri_on_ddr = true,
|
||||
.hw_filter_reset_required = false,
|
||||
@ -740,6 +728,16 @@ static int ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ath10k_bmi_read32(ar, hi_option_flag2, ¶m);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
param |= HI_OPTION_SDIO_CRASH_DUMP_ENHANCEMENT_HOST;
|
||||
|
||||
ret = ath10k_bmi_write32(ar, hi_option_flag2, param);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2320,7 +2318,7 @@ static void ath10k_core_restart(struct work_struct *work)
|
||||
break;
|
||||
case ATH10K_STATE_RESTARTED:
|
||||
ar->state = ATH10K_STATE_WEDGED;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case ATH10K_STATE_WEDGED:
|
||||
ath10k_warn(ar, "device is wedged, will not restart\n");
|
||||
break;
|
||||
@ -2614,6 +2612,13 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
||||
ar->running_fw->fw_file.fw_features)) {
|
||||
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)) {
|
||||
status = -EINVAL;
|
||||
goto err;
|
||||
@ -2797,6 +2802,10 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode,
|
||||
if (test_bit(WMI_SERVICE_REPORT_AIRTIME, ar->wmi.svc_map))
|
||||
val |= WMI_10_4_REPORT_AIRTIME;
|
||||
|
||||
if (test_bit(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
|
||||
ar->wmi.svc_map))
|
||||
val |= WMI_10_4_EXT_PEER_TID_CONFIGS_SUPPORT;
|
||||
|
||||
status = ath10k_mac_ext_resource_config(ar, val);
|
||||
if (status) {
|
||||
ath10k_err(ar,
|
||||
|
@ -82,6 +82,8 @@
|
||||
/* Default Airtime weight multipler (Tuned for multiclient performance) */
|
||||
#define ATH10K_AIRTIME_WEIGHT_MULTIPLIER 4
|
||||
|
||||
#define ATH10K_MAX_RETRY_COUNT 30
|
||||
|
||||
struct ath10k;
|
||||
|
||||
static inline const char *ath10k_bus_str(enum ath10k_bus bus)
|
||||
@ -109,6 +111,7 @@ enum ath10k_skb_flags {
|
||||
ATH10K_SKB_F_MGMT = BIT(3),
|
||||
ATH10K_SKB_F_QOS = BIT(4),
|
||||
ATH10K_SKB_F_RAW_TX = BIT(5),
|
||||
ATH10K_SKB_F_NOACK_TID = BIT(6),
|
||||
};
|
||||
|
||||
struct ath10k_skb_cb {
|
||||
@ -509,6 +512,8 @@ struct ath10k_htt_tx_stats {
|
||||
u64 ack_fails;
|
||||
};
|
||||
|
||||
#define ATH10K_TID_MAX 8
|
||||
|
||||
struct ath10k_sta {
|
||||
struct ath10k_vif *arvif;
|
||||
|
||||
@ -542,6 +547,13 @@ struct ath10k_sta {
|
||||
#endif
|
||||
/* Protected with ar->data_lock */
|
||||
u32 peer_ps_state;
|
||||
struct work_struct tid_config_wk;
|
||||
int noack[ATH10K_TID_MAX];
|
||||
int retry_long[ATH10K_TID_MAX];
|
||||
int ampdu[ATH10K_TID_MAX];
|
||||
u8 rate_ctrl[ATH10K_TID_MAX];
|
||||
u32 rate_code[ATH10K_TID_MAX];
|
||||
int rtscts[ATH10K_TID_MAX];
|
||||
};
|
||||
|
||||
#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ)
|
||||
@ -614,6 +626,14 @@ struct ath10k_vif {
|
||||
/* For setting VHT peer fixed rate, protected by conf_mutex */
|
||||
int vht_num_rates;
|
||||
u8 vht_pfr;
|
||||
u32 tid_conf_changed[ATH10K_TID_MAX];
|
||||
int noack[ATH10K_TID_MAX];
|
||||
int retry_long[ATH10K_TID_MAX];
|
||||
int ampdu[ATH10K_TID_MAX];
|
||||
u8 rate_ctrl[ATH10K_TID_MAX];
|
||||
u32 rate_code[ATH10K_TID_MAX];
|
||||
int rtscts[ATH10K_TID_MAX];
|
||||
u32 tids_rst;
|
||||
};
|
||||
|
||||
struct ath10k_vif_iter {
|
||||
|
@ -270,6 +270,277 @@ static const struct ath10k_mem_section qca6174_hw21_register_sections[] = {
|
||||
{0x80010, 0x80020},
|
||||
};
|
||||
|
||||
static const struct ath10k_mem_section qca6174_hw30_sdio_register_sections[] = {
|
||||
{0x800, 0x810},
|
||||
{0x820, 0x82C},
|
||||
{0x830, 0x8F4},
|
||||
{0x90C, 0x91C},
|
||||
{0xA14, 0xA18},
|
||||
{0xA84, 0xA94},
|
||||
{0xAA8, 0xAD4},
|
||||
{0xADC, 0xB40},
|
||||
{0x1000, 0x10A4},
|
||||
{0x10BC, 0x111C},
|
||||
{0x1134, 0x1138},
|
||||
{0x1144, 0x114C},
|
||||
{0x1150, 0x115C},
|
||||
{0x1160, 0x1178},
|
||||
{0x1240, 0x1260},
|
||||
{0x2000, 0x207C},
|
||||
{0x3000, 0x3014},
|
||||
{0x4000, 0x4014},
|
||||
{0x5000, 0x5124},
|
||||
{0x6000, 0x6040},
|
||||
{0x6080, 0x60CC},
|
||||
{0x6100, 0x611C},
|
||||
{0x6140, 0x61D8},
|
||||
{0x6200, 0x6238},
|
||||
{0x6240, 0x628C},
|
||||
{0x62C0, 0x62EC},
|
||||
{0x6380, 0x63E8},
|
||||
{0x6400, 0x6440},
|
||||
{0x6480, 0x64CC},
|
||||
{0x6500, 0x651C},
|
||||
{0x6540, 0x6580},
|
||||
{0x6600, 0x6638},
|
||||
{0x6640, 0x668C},
|
||||
{0x66C0, 0x66EC},
|
||||
{0x6780, 0x67E8},
|
||||
{0x7080, 0x708C},
|
||||
{0x70C0, 0x70C8},
|
||||
{0x7400, 0x741C},
|
||||
{0x7440, 0x7454},
|
||||
{0x7800, 0x7818},
|
||||
{0x8010, 0x8060},
|
||||
{0x8080, 0x8084},
|
||||
{0x80A0, 0x80A4},
|
||||
{0x80C0, 0x80C4},
|
||||
{0x80E0, 0x80ec},
|
||||
{0x8110, 0x8128},
|
||||
{0x9000, 0x9004},
|
||||
{0xF000, 0xF0E0},
|
||||
{0xF140, 0xF190},
|
||||
{0xF250, 0xF25C},
|
||||
{0xF260, 0xF268},
|
||||
{0xF26C, 0xF2A8},
|
||||
{0x10008, 0x1000C},
|
||||
{0x10014, 0x10018},
|
||||
{0x1001C, 0x10020},
|
||||
{0x10024, 0x10028},
|
||||
{0x10030, 0x10034},
|
||||
{0x10040, 0x10054},
|
||||
{0x10058, 0x1007C},
|
||||
{0x10080, 0x100C4},
|
||||
{0x100C8, 0x10114},
|
||||
{0x1012C, 0x10130},
|
||||
{0x10138, 0x10144},
|
||||
{0x10200, 0x10220},
|
||||
{0x10230, 0x10250},
|
||||
{0x10260, 0x10280},
|
||||
{0x10290, 0x102B0},
|
||||
{0x102C0, 0x102DC},
|
||||
{0x102E0, 0x102F4},
|
||||
{0x102FC, 0x1037C},
|
||||
{0x10380, 0x10390},
|
||||
{0x10800, 0x10828},
|
||||
{0x10840, 0x10844},
|
||||
{0x10880, 0x10884},
|
||||
{0x108C0, 0x108E8},
|
||||
{0x10900, 0x10928},
|
||||
{0x10940, 0x10944},
|
||||
{0x10980, 0x10984},
|
||||
{0x109C0, 0x109E8},
|
||||
{0x10A00, 0x10A28},
|
||||
{0x10A40, 0x10A50},
|
||||
{0x11000, 0x11028},
|
||||
{0x11030, 0x11034},
|
||||
{0x11038, 0x11068},
|
||||
{0x11070, 0x11074},
|
||||
{0x11078, 0x110A8},
|
||||
{0x110B0, 0x110B4},
|
||||
{0x110B8, 0x110E8},
|
||||
{0x110F0, 0x110F4},
|
||||
{0x110F8, 0x11128},
|
||||
{0x11138, 0x11144},
|
||||
{0x11178, 0x11180},
|
||||
{0x111B8, 0x111C0},
|
||||
{0x111F8, 0x11200},
|
||||
{0x11238, 0x1123C},
|
||||
{0x11270, 0x11274},
|
||||
{0x11278, 0x1127C},
|
||||
{0x112B0, 0x112B4},
|
||||
{0x112B8, 0x112BC},
|
||||
{0x112F0, 0x112F4},
|
||||
{0x112F8, 0x112FC},
|
||||
{0x11338, 0x1133C},
|
||||
{0x11378, 0x1137C},
|
||||
{0x113B8, 0x113BC},
|
||||
{0x113F8, 0x113FC},
|
||||
{0x11438, 0x11440},
|
||||
{0x11478, 0x11480},
|
||||
{0x114B8, 0x114BC},
|
||||
{0x114F8, 0x114FC},
|
||||
{0x11538, 0x1153C},
|
||||
{0x11578, 0x1157C},
|
||||
{0x115B8, 0x115BC},
|
||||
{0x115F8, 0x115FC},
|
||||
{0x11638, 0x1163C},
|
||||
{0x11678, 0x1167C},
|
||||
{0x116B8, 0x116BC},
|
||||
{0x116F8, 0x116FC},
|
||||
{0x11738, 0x1173C},
|
||||
{0x11778, 0x1177C},
|
||||
{0x117B8, 0x117BC},
|
||||
{0x117F8, 0x117FC},
|
||||
{0x17000, 0x1701C},
|
||||
{0x17020, 0x170AC},
|
||||
{0x18000, 0x18050},
|
||||
{0x18054, 0x18074},
|
||||
{0x18080, 0x180D4},
|
||||
{0x180DC, 0x18104},
|
||||
{0x18108, 0x1813C},
|
||||
{0x18144, 0x18148},
|
||||
{0x18168, 0x18174},
|
||||
{0x18178, 0x18180},
|
||||
{0x181C8, 0x181E0},
|
||||
{0x181E4, 0x181E8},
|
||||
{0x181EC, 0x1820C},
|
||||
{0x1825C, 0x18280},
|
||||
{0x18284, 0x18290},
|
||||
{0x18294, 0x182A0},
|
||||
{0x18300, 0x18304},
|
||||
{0x18314, 0x18320},
|
||||
{0x18328, 0x18350},
|
||||
{0x1835C, 0x1836C},
|
||||
{0x18370, 0x18390},
|
||||
{0x18398, 0x183AC},
|
||||
{0x183BC, 0x183D8},
|
||||
{0x183DC, 0x183F4},
|
||||
{0x18400, 0x186F4},
|
||||
{0x186F8, 0x1871C},
|
||||
{0x18720, 0x18790},
|
||||
{0x19800, 0x19830},
|
||||
{0x19834, 0x19840},
|
||||
{0x19880, 0x1989C},
|
||||
{0x198A4, 0x198B0},
|
||||
{0x198BC, 0x19900},
|
||||
{0x19C00, 0x19C88},
|
||||
{0x19D00, 0x19D20},
|
||||
{0x19E00, 0x19E7C},
|
||||
{0x19E80, 0x19E94},
|
||||
{0x19E98, 0x19EAC},
|
||||
{0x19EB0, 0x19EBC},
|
||||
{0x19F70, 0x19F74},
|
||||
{0x19F80, 0x19F8C},
|
||||
{0x19FA0, 0x19FB4},
|
||||
{0x19FC0, 0x19FD8},
|
||||
{0x1A000, 0x1A200},
|
||||
{0x1A204, 0x1A210},
|
||||
{0x1A228, 0x1A22C},
|
||||
{0x1A230, 0x1A248},
|
||||
{0x1A250, 0x1A270},
|
||||
{0x1A280, 0x1A290},
|
||||
{0x1A2A0, 0x1A2A4},
|
||||
{0x1A2C0, 0x1A2EC},
|
||||
{0x1A300, 0x1A3BC},
|
||||
{0x1A3F0, 0x1A3F4},
|
||||
{0x1A3F8, 0x1A434},
|
||||
{0x1A438, 0x1A444},
|
||||
{0x1A448, 0x1A468},
|
||||
{0x1A580, 0x1A58C},
|
||||
{0x1A644, 0x1A654},
|
||||
{0x1A670, 0x1A698},
|
||||
{0x1A6AC, 0x1A6B0},
|
||||
{0x1A6D0, 0x1A6D4},
|
||||
{0x1A6EC, 0x1A70C},
|
||||
{0x1A710, 0x1A738},
|
||||
{0x1A7C0, 0x1A7D0},
|
||||
{0x1A7D4, 0x1A7D8},
|
||||
{0x1A7DC, 0x1A7E4},
|
||||
{0x1A7F0, 0x1A7F8},
|
||||
{0x1A888, 0x1A89C},
|
||||
{0x1A8A8, 0x1A8AC},
|
||||
{0x1A8C0, 0x1A8DC},
|
||||
{0x1A8F0, 0x1A8FC},
|
||||
{0x1AE04, 0x1AE08},
|
||||
{0x1AE18, 0x1AE24},
|
||||
{0x1AF80, 0x1AF8C},
|
||||
{0x1AFA0, 0x1AFB4},
|
||||
{0x1B000, 0x1B200},
|
||||
{0x1B284, 0x1B288},
|
||||
{0x1B2D0, 0x1B2D8},
|
||||
{0x1B2DC, 0x1B2EC},
|
||||
{0x1B300, 0x1B340},
|
||||
{0x1B374, 0x1B378},
|
||||
{0x1B380, 0x1B384},
|
||||
{0x1B388, 0x1B38C},
|
||||
{0x1B404, 0x1B408},
|
||||
{0x1B420, 0x1B428},
|
||||
{0x1B440, 0x1B444},
|
||||
{0x1B448, 0x1B44C},
|
||||
{0x1B450, 0x1B458},
|
||||
{0x1B45C, 0x1B468},
|
||||
{0x1B584, 0x1B58C},
|
||||
{0x1B68C, 0x1B690},
|
||||
{0x1B6AC, 0x1B6B0},
|
||||
{0x1B7F0, 0x1B7F8},
|
||||
{0x1C800, 0x1CC00},
|
||||
{0x1CE00, 0x1CE04},
|
||||
{0x1CF80, 0x1CF84},
|
||||
{0x1D200, 0x1D800},
|
||||
{0x1E000, 0x20014},
|
||||
{0x20100, 0x20124},
|
||||
{0x21400, 0x217A8},
|
||||
{0x21800, 0x21BA8},
|
||||
{0x21C00, 0x21FA8},
|
||||
{0x22000, 0x223A8},
|
||||
{0x22400, 0x227A8},
|
||||
{0x22800, 0x22BA8},
|
||||
{0x22C00, 0x22FA8},
|
||||
{0x23000, 0x233A8},
|
||||
{0x24000, 0x24034},
|
||||
|
||||
/* EFUSE0,1,2 is disabled here
|
||||
* because its state may be reset
|
||||
*
|
||||
* {0x24800, 0x24804},
|
||||
* {0x25000, 0x25004},
|
||||
* {0x25800, 0x25804},
|
||||
*/
|
||||
|
||||
{0x26000, 0x26064},
|
||||
{0x27000, 0x27024},
|
||||
{0x34000, 0x3400C},
|
||||
{0x34400, 0x3445C},
|
||||
{0x34800, 0x3485C},
|
||||
{0x34C00, 0x34C5C},
|
||||
{0x35000, 0x3505C},
|
||||
{0x35400, 0x3545C},
|
||||
{0x35800, 0x3585C},
|
||||
{0x35C00, 0x35C5C},
|
||||
{0x36000, 0x3605C},
|
||||
{0x38000, 0x38064},
|
||||
{0x38070, 0x380E0},
|
||||
{0x3A000, 0x3A074},
|
||||
|
||||
/* DBI windows is skipped here, it can be only accessed when pcie
|
||||
* is active (not in reset) and CORE_CTRL_PCIE_LTSSM_EN = 0 &&
|
||||
* PCIE_CTRL_APP_LTSSM_ENALBE=0.
|
||||
* {0x3C000 , 0x3C004},
|
||||
*/
|
||||
|
||||
{0x40000, 0x400A4},
|
||||
|
||||
/* SI register is skiped here.
|
||||
* Because it will cause bus hang
|
||||
*
|
||||
* {0x50000, 0x50018},
|
||||
*/
|
||||
|
||||
{0x80000, 0x8000C},
|
||||
{0x80010, 0x80020},
|
||||
};
|
||||
|
||||
static const struct ath10k_mem_section qca6174_hw30_register_sections[] = {
|
||||
{0x800, 0x810},
|
||||
{0x820, 0x82C},
|
||||
@ -602,6 +873,59 @@ static const struct ath10k_mem_region qca6174_hw21_mem_regions[] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ath10k_mem_region qca6174_hw30_sdio_mem_regions[] = {
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_DRAM,
|
||||
.start = 0x400000,
|
||||
.len = 0xa8000,
|
||||
.name = "DRAM",
|
||||
.section_table = {
|
||||
.sections = NULL,
|
||||
.size = 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_AXI,
|
||||
.start = 0xa0000,
|
||||
.len = 0x18000,
|
||||
.name = "AXI",
|
||||
.section_table = {
|
||||
.sections = NULL,
|
||||
.size = 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_IRAM1,
|
||||
.start = 0x00980000,
|
||||
.len = 0x00080000,
|
||||
.name = "IRAM1",
|
||||
.section_table = {
|
||||
.sections = NULL,
|
||||
.size = 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_IRAM2,
|
||||
.start = 0x00a00000,
|
||||
.len = 0x00040000,
|
||||
.name = "IRAM2",
|
||||
.section_table = {
|
||||
.sections = NULL,
|
||||
.size = 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_REG,
|
||||
.start = 0x800,
|
||||
.len = 0x80020 - 0x800,
|
||||
.name = "REG_TOTAL",
|
||||
.section_table = {
|
||||
.sections = qca6174_hw30_sdio_register_sections,
|
||||
.size = ARRAY_SIZE(qca6174_hw30_sdio_register_sections),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static const struct ath10k_mem_region qca6174_hw30_mem_regions[] = {
|
||||
{
|
||||
.type = ATH10K_MEM_REGION_TYPE_DRAM,
|
||||
@ -968,6 +1292,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
|
||||
{
|
||||
.hw_id = QCA6174_HW_1_0_VERSION,
|
||||
.hw_rev = ATH10K_HW_QCA6174,
|
||||
.bus = ATH10K_BUS_PCI,
|
||||
.region_table = {
|
||||
.regions = qca6174_hw10_mem_regions,
|
||||
.size = ARRAY_SIZE(qca6174_hw10_mem_regions),
|
||||
@ -976,6 +1301,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
|
||||
{
|
||||
.hw_id = QCA6174_HW_1_1_VERSION,
|
||||
.hw_rev = ATH10K_HW_QCA6174,
|
||||
.bus = ATH10K_BUS_PCI,
|
||||
.region_table = {
|
||||
.regions = qca6174_hw10_mem_regions,
|
||||
.size = ARRAY_SIZE(qca6174_hw10_mem_regions),
|
||||
@ -984,6 +1310,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
|
||||
{
|
||||
.hw_id = QCA6174_HW_1_3_VERSION,
|
||||
.hw_rev = ATH10K_HW_QCA6174,
|
||||
.bus = ATH10K_BUS_PCI,
|
||||
.region_table = {
|
||||
.regions = qca6174_hw10_mem_regions,
|
||||
.size = ARRAY_SIZE(qca6174_hw10_mem_regions),
|
||||
@ -992,6 +1319,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
|
||||
{
|
||||
.hw_id = QCA6174_HW_2_1_VERSION,
|
||||
.hw_rev = ATH10K_HW_QCA6174,
|
||||
.bus = ATH10K_BUS_PCI,
|
||||
.region_table = {
|
||||
.regions = qca6174_hw21_mem_regions,
|
||||
.size = ARRAY_SIZE(qca6174_hw21_mem_regions),
|
||||
@ -1000,6 +1328,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
|
||||
{
|
||||
.hw_id = QCA6174_HW_3_0_VERSION,
|
||||
.hw_rev = ATH10K_HW_QCA6174,
|
||||
.bus = ATH10K_BUS_PCI,
|
||||
.region_table = {
|
||||
.regions = qca6174_hw30_mem_regions,
|
||||
.size = ARRAY_SIZE(qca6174_hw30_mem_regions),
|
||||
@ -1008,14 +1337,25 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
|
||||
{
|
||||
.hw_id = QCA6174_HW_3_2_VERSION,
|
||||
.hw_rev = ATH10K_HW_QCA6174,
|
||||
.bus = ATH10K_BUS_PCI,
|
||||
.region_table = {
|
||||
.regions = qca6174_hw30_mem_regions,
|
||||
.size = ARRAY_SIZE(qca6174_hw30_mem_regions),
|
||||
},
|
||||
},
|
||||
{
|
||||
.hw_id = QCA6174_HW_3_2_VERSION,
|
||||
.hw_rev = ATH10K_HW_QCA6174,
|
||||
.bus = ATH10K_BUS_SDIO,
|
||||
.region_table = {
|
||||
.regions = qca6174_hw30_sdio_mem_regions,
|
||||
.size = ARRAY_SIZE(qca6174_hw30_sdio_mem_regions),
|
||||
},
|
||||
},
|
||||
{
|
||||
.hw_id = QCA9377_HW_1_1_DEV_VERSION,
|
||||
.hw_rev = ATH10K_HW_QCA9377,
|
||||
.bus = ATH10K_BUS_PCI,
|
||||
.region_table = {
|
||||
.regions = qca6174_hw30_mem_regions,
|
||||
.size = ARRAY_SIZE(qca6174_hw30_mem_regions),
|
||||
@ -1024,6 +1364,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
|
||||
{
|
||||
.hw_id = QCA988X_HW_2_0_VERSION,
|
||||
.hw_rev = ATH10K_HW_QCA988X,
|
||||
.bus = ATH10K_BUS_PCI,
|
||||
.region_table = {
|
||||
.regions = qca988x_hw20_mem_regions,
|
||||
.size = ARRAY_SIZE(qca988x_hw20_mem_regions),
|
||||
@ -1032,6 +1373,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
|
||||
{
|
||||
.hw_id = QCA9984_HW_1_0_DEV_VERSION,
|
||||
.hw_rev = ATH10K_HW_QCA9984,
|
||||
.bus = ATH10K_BUS_PCI,
|
||||
.region_table = {
|
||||
.regions = qca9984_hw10_mem_regions,
|
||||
.size = ARRAY_SIZE(qca9984_hw10_mem_regions),
|
||||
@ -1040,6 +1382,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
|
||||
{
|
||||
.hw_id = QCA9888_HW_2_0_DEV_VERSION,
|
||||
.hw_rev = ATH10K_HW_QCA9888,
|
||||
.bus = ATH10K_BUS_PCI,
|
||||
.region_table = {
|
||||
.regions = qca9984_hw10_mem_regions,
|
||||
.size = ARRAY_SIZE(qca9984_hw10_mem_regions),
|
||||
@ -1048,6 +1391,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
|
||||
{
|
||||
.hw_id = QCA99X0_HW_2_0_DEV_VERSION,
|
||||
.hw_rev = ATH10K_HW_QCA99X0,
|
||||
.bus = ATH10K_BUS_PCI,
|
||||
.region_table = {
|
||||
.regions = qca99x0_hw20_mem_regions,
|
||||
.size = ARRAY_SIZE(qca99x0_hw20_mem_regions),
|
||||
@ -1056,6 +1400,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
|
||||
{
|
||||
.hw_id = QCA4019_HW_1_0_DEV_VERSION,
|
||||
.hw_rev = ATH10K_HW_QCA4019,
|
||||
.bus = ATH10K_BUS_AHB,
|
||||
.region_table = {
|
||||
.regions = qca4019_hw10_mem_regions,
|
||||
.size = ARRAY_SIZE(qca4019_hw10_mem_regions),
|
||||
@ -1064,6 +1409,7 @@ static const struct ath10k_hw_mem_layout hw_mem_layouts[] = {
|
||||
{
|
||||
.hw_id = WCN3990_HW_1_0_DEV_VERSION,
|
||||
.hw_rev = ATH10K_HW_WCN3990,
|
||||
.bus = ATH10K_BUS_SNOC,
|
||||
.region_table = {
|
||||
.regions = wcn399x_hw10_mem_regions,
|
||||
.size = ARRAY_SIZE(wcn399x_hw10_mem_regions),
|
||||
@ -1111,7 +1457,8 @@ const struct ath10k_hw_mem_layout *ath10k_coredump_get_mem_layout(struct ath10k
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(hw_mem_layouts); i++) {
|
||||
if (ar->target_version == hw_mem_layouts[i].hw_id &&
|
||||
ar->hw_rev == hw_mem_layouts[i].hw_rev)
|
||||
ar->hw_rev == hw_mem_layouts[i].hw_rev &&
|
||||
hw_mem_layouts[i].bus == ar->hif.bus)
|
||||
return &hw_mem_layouts[i];
|
||||
}
|
||||
|
||||
|
@ -156,6 +156,7 @@ struct ath10k_mem_region {
|
||||
struct ath10k_hw_mem_layout {
|
||||
u32 hw_id;
|
||||
u32 hw_rev;
|
||||
enum ath10k_bus bus;
|
||||
|
||||
struct {
|
||||
const struct ath10k_mem_region *regions;
|
||||
|
@ -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);
|
||||
|
||||
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) {
|
||||
skb = dev_alloc_skb(HTT_RX_BUF_SIZE + HTT_RX_DESC_ALIGN);
|
||||
if (!skb) {
|
||||
@ -941,6 +949,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
|
||||
u8 preamble = 0;
|
||||
u8 group_id;
|
||||
u32 info1, info2, info3;
|
||||
u32 stbc, nsts_su;
|
||||
|
||||
info1 = __le32_to_cpu(rxd->ppdu_start.info1);
|
||||
info2 = __le32_to_cpu(rxd->ppdu_start.info2);
|
||||
@ -985,11 +994,16 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
|
||||
*/
|
||||
bw = info2 & 3;
|
||||
sgi = info3 & 1;
|
||||
stbc = (info2 >> 3) & 1;
|
||||
group_id = (info2 >> 4) & 0x3F;
|
||||
|
||||
if (GROUP_ID_IS_SU_MIMO(group_id)) {
|
||||
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 {
|
||||
/* Hardware doesn't decode VHT-SIG-B into Rx descriptor
|
||||
* 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)
|
||||
ath10k_htt_rx_h_enqueue(ar, &amsdu, status);
|
||||
break;
|
||||
case -EAGAIN:
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
default:
|
||||
/* Should not happen. */
|
||||
ath10k_warn(ar, "failed to extract amsdu: %d\n", ret);
|
||||
@ -3575,12 +3589,14 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar,
|
||||
}
|
||||
|
||||
if (ar->htt.disable_tx_comp) {
|
||||
arsta->tx_retries += peer_stats->retry_pkts;
|
||||
arsta->tx_failed += peer_stats->failed_pkts;
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx retries %d tx failed %d\n",
|
||||
arsta->tx_retries, arsta->tx_failed);
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT, "tx failed %d\n",
|
||||
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))
|
||||
ath10k_accumulate_per_peer_tx_stats(ar, arsta, peer_stats,
|
||||
rate_idx);
|
||||
|
@ -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_NATIVE_WIFI:
|
||||
flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case ATH10K_HW_TXRX_ETHERNET:
|
||||
flags0 |= SM(txmode, HTT_DATA_TX_DESC_FLAGS0_PKT_TYPE);
|
||||
break;
|
||||
@ -1460,7 +1460,7 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt,
|
||||
case ATH10K_HW_TXRX_RAW:
|
||||
case ATH10K_HW_TXRX_NATIVE_WIFI:
|
||||
flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case ATH10K_HW_TXRX_ETHERNET:
|
||||
if (ar->hw_params.continuous_frag_desc) {
|
||||
ext_desc_t = htt->frag_desc.vaddr_desc_32;
|
||||
@ -1662,7 +1662,7 @@ static int ath10k_htt_tx_64(struct ath10k_htt *htt,
|
||||
case ATH10K_HW_TXRX_RAW:
|
||||
case ATH10K_HW_TXRX_NATIVE_WIFI:
|
||||
flags0 |= HTT_DATA_TX_DESC_FLAGS0_MAC_HDR_PRESENT;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case ATH10K_HW_TXRX_ETHERNET:
|
||||
if (ar->hw_params.continuous_frag_desc) {
|
||||
ext_desc_t = htt->frag_desc.vaddr_desc_64;
|
||||
|
@ -593,9 +593,6 @@ struct ath10k_hw_params {
|
||||
/* Target rx ring fill level */
|
||||
u32 rx_ring_fill_level;
|
||||
|
||||
/* target supporting per ce IRQ */
|
||||
bool per_ce_irq;
|
||||
|
||||
/* target supporting shadow register for ce write */
|
||||
bool shadow_reg_support;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2184,7 +2184,7 @@ err_req:
|
||||
|
||||
if (ret == 0 && resp_len) {
|
||||
*resp_len = min(*resp_len, xfer.resp_len);
|
||||
memcpy(resp, tresp, xfer.resp_len);
|
||||
memcpy(resp, tresp, *resp_len);
|
||||
}
|
||||
err_dma:
|
||||
kfree(treq);
|
||||
|
@ -23,6 +23,9 @@
|
||||
#include "targaddrs.h"
|
||||
#include "trace.h"
|
||||
#include "sdio.h"
|
||||
#include "coredump.h"
|
||||
|
||||
void ath10k_sdio_fw_crashed_dump(struct ath10k *ar);
|
||||
|
||||
#define ATH10K_SDIO_VSG_BUF_SIZE (64 * 1024)
|
||||
|
||||
@ -557,6 +560,10 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar,
|
||||
le16_to_cpu(htc_hdr->len),
|
||||
ATH10K_HTC_MBOX_MAX_PAYLOAD_LENGTH);
|
||||
ret = -ENOMEM;
|
||||
|
||||
queue_work(ar->workqueue, &ar->restart_work);
|
||||
ath10k_warn(ar, "exceeds length, start recovery\n");
|
||||
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -912,10 +919,9 @@ static int ath10k_sdio_mbox_proc_cpu_intr(struct ath10k *ar)
|
||||
|
||||
out:
|
||||
mutex_unlock(&irq_data->mtx);
|
||||
if (cpu_int_status & MBOX_CPU_STATUS_ENABLE_ASSERT_MASK) {
|
||||
ath10k_err(ar, "firmware crashed!\n");
|
||||
queue_work(ar->workqueue, &ar->restart_work);
|
||||
}
|
||||
if (cpu_int_status & MBOX_CPU_STATUS_ENABLE_ASSERT_MASK)
|
||||
ath10k_sdio_fw_crashed_dump(ar);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2181,6 +2187,323 @@ static int ath10k_sdio_napi_poll(struct napi_struct *ctx, int budget)
|
||||
return done;
|
||||
}
|
||||
|
||||
static int ath10k_sdio_read_host_interest_value(struct ath10k *ar,
|
||||
u32 item_offset,
|
||||
u32 *val)
|
||||
{
|
||||
u32 addr;
|
||||
int ret;
|
||||
|
||||
addr = host_interest_item_address(item_offset);
|
||||
|
||||
ret = ath10k_sdio_diag_read32(ar, addr, val);
|
||||
|
||||
if (ret)
|
||||
ath10k_warn(ar, "unable to read host interest offset %d value\n",
|
||||
item_offset);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_sdio_read_mem(struct ath10k *ar, u32 address, void *buf,
|
||||
u32 buf_len)
|
||||
{
|
||||
u32 val;
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < buf_len; i += 4) {
|
||||
ret = ath10k_sdio_diag_read32(ar, address + i, &val);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "unable to read mem %d value\n", address + i);
|
||||
break;
|
||||
}
|
||||
memcpy(buf + i, &val, 4);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool ath10k_sdio_is_fast_dump_supported(struct ath10k *ar)
|
||||
{
|
||||
u32 param;
|
||||
|
||||
ath10k_sdio_read_host_interest_value(ar, HI_ITEM(hi_option_flag2), ¶m);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_SDIO, "sdio hi_option_flag2 %x\n", param);
|
||||
|
||||
return param & HI_OPTION_SDIO_CRASH_DUMP_ENHANCEMENT_FW;
|
||||
}
|
||||
|
||||
static void ath10k_sdio_dump_registers(struct ath10k *ar,
|
||||
struct ath10k_fw_crash_data *crash_data,
|
||||
bool fast_dump)
|
||||
{
|
||||
u32 reg_dump_values[REG_DUMP_COUNT_QCA988X] = {};
|
||||
int i, ret;
|
||||
u32 reg_dump_area;
|
||||
|
||||
ret = ath10k_sdio_read_host_interest_value(ar, HI_ITEM(hi_failure_state),
|
||||
®_dump_area);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to read firmware dump area: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fast_dump)
|
||||
ret = ath10k_bmi_read_memory(ar, reg_dump_area, reg_dump_values,
|
||||
sizeof(reg_dump_values));
|
||||
else
|
||||
ret = ath10k_sdio_read_mem(ar, reg_dump_area, reg_dump_values,
|
||||
sizeof(reg_dump_values));
|
||||
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to read firmware dump value: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
ath10k_err(ar, "firmware register dump:\n");
|
||||
for (i = 0; i < ARRAY_SIZE(reg_dump_values); i += 4)
|
||||
ath10k_err(ar, "[%02d]: 0x%08X 0x%08X 0x%08X 0x%08X\n",
|
||||
i,
|
||||
reg_dump_values[i],
|
||||
reg_dump_values[i + 1],
|
||||
reg_dump_values[i + 2],
|
||||
reg_dump_values[i + 3]);
|
||||
|
||||
if (!crash_data)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(reg_dump_values); i++)
|
||||
crash_data->registers[i] = __cpu_to_le32(reg_dump_values[i]);
|
||||
}
|
||||
|
||||
static int ath10k_sdio_dump_memory_section(struct ath10k *ar,
|
||||
const struct ath10k_mem_region *mem_region,
|
||||
u8 *buf, size_t buf_len)
|
||||
{
|
||||
const struct ath10k_mem_section *cur_section, *next_section;
|
||||
unsigned int count, section_size, skip_size;
|
||||
int ret, i, j;
|
||||
|
||||
if (!mem_region || !buf)
|
||||
return 0;
|
||||
|
||||
cur_section = &mem_region->section_table.sections[0];
|
||||
|
||||
if (mem_region->start > cur_section->start) {
|
||||
ath10k_warn(ar, "incorrect memdump region 0x%x with section start address 0x%x.\n",
|
||||
mem_region->start, cur_section->start);
|
||||
return 0;
|
||||
}
|
||||
|
||||
skip_size = cur_section->start - mem_region->start;
|
||||
|
||||
/* fill the gap between the first register section and register
|
||||
* start address
|
||||
*/
|
||||
for (i = 0; i < skip_size; i++) {
|
||||
*buf = ATH10K_MAGIC_NOT_COPIED;
|
||||
buf++;
|
||||
}
|
||||
|
||||
count = 0;
|
||||
|
||||
for (i = 0; cur_section; i++) {
|
||||
section_size = cur_section->end - cur_section->start;
|
||||
|
||||
if (section_size <= 0) {
|
||||
ath10k_warn(ar, "incorrect ramdump format with start address 0x%x and stop address 0x%x\n",
|
||||
cur_section->start,
|
||||
cur_section->end);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((i + 1) == mem_region->section_table.size) {
|
||||
/* last section */
|
||||
next_section = NULL;
|
||||
skip_size = 0;
|
||||
} else {
|
||||
next_section = cur_section + 1;
|
||||
|
||||
if (cur_section->end > next_section->start) {
|
||||
ath10k_warn(ar, "next ramdump section 0x%x is smaller than current end address 0x%x\n",
|
||||
next_section->start,
|
||||
cur_section->end);
|
||||
break;
|
||||
}
|
||||
|
||||
skip_size = next_section->start - cur_section->end;
|
||||
}
|
||||
|
||||
if (buf_len < (skip_size + section_size)) {
|
||||
ath10k_warn(ar, "ramdump buffer is too small: %zu\n", buf_len);
|
||||
break;
|
||||
}
|
||||
|
||||
buf_len -= skip_size + section_size;
|
||||
|
||||
/* read section to dest memory */
|
||||
ret = ath10k_sdio_read_mem(ar, cur_section->start,
|
||||
buf, section_size);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to read ramdump from section 0x%x: %d\n",
|
||||
cur_section->start, ret);
|
||||
break;
|
||||
}
|
||||
|
||||
buf += section_size;
|
||||
count += section_size;
|
||||
|
||||
/* fill in the gap between this section and the next */
|
||||
for (j = 0; j < skip_size; j++) {
|
||||
*buf = ATH10K_MAGIC_NOT_COPIED;
|
||||
buf++;
|
||||
}
|
||||
|
||||
count += skip_size;
|
||||
|
||||
if (!next_section)
|
||||
/* this was the last section */
|
||||
break;
|
||||
|
||||
cur_section = next_section;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/* if an error happened returns < 0, otherwise the length */
|
||||
static int ath10k_sdio_dump_memory_generic(struct ath10k *ar,
|
||||
const struct ath10k_mem_region *current_region,
|
||||
u8 *buf,
|
||||
bool fast_dump)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (current_region->section_table.size > 0)
|
||||
/* Copy each section individually. */
|
||||
return ath10k_sdio_dump_memory_section(ar,
|
||||
current_region,
|
||||
buf,
|
||||
current_region->len);
|
||||
|
||||
/* No individiual memory sections defined so we can
|
||||
* copy the entire memory region.
|
||||
*/
|
||||
if (fast_dump)
|
||||
ret = ath10k_bmi_read_memory(ar,
|
||||
current_region->start,
|
||||
buf,
|
||||
current_region->len);
|
||||
else
|
||||
ret = ath10k_sdio_read_mem(ar,
|
||||
current_region->start,
|
||||
buf,
|
||||
current_region->len);
|
||||
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to copy ramdump region %s: %d\n",
|
||||
current_region->name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return current_region->len;
|
||||
}
|
||||
|
||||
static void ath10k_sdio_dump_memory(struct ath10k *ar,
|
||||
struct ath10k_fw_crash_data *crash_data,
|
||||
bool fast_dump)
|
||||
{
|
||||
const struct ath10k_hw_mem_layout *mem_layout;
|
||||
const struct ath10k_mem_region *current_region;
|
||||
struct ath10k_dump_ram_data_hdr *hdr;
|
||||
u32 count;
|
||||
size_t buf_len;
|
||||
int ret, i;
|
||||
u8 *buf;
|
||||
|
||||
if (!crash_data)
|
||||
return;
|
||||
|
||||
mem_layout = ath10k_coredump_get_mem_layout(ar);
|
||||
if (!mem_layout)
|
||||
return;
|
||||
|
||||
current_region = &mem_layout->region_table.regions[0];
|
||||
|
||||
buf = crash_data->ramdump_buf;
|
||||
buf_len = crash_data->ramdump_buf_len;
|
||||
|
||||
memset(buf, 0, buf_len);
|
||||
|
||||
for (i = 0; i < mem_layout->region_table.size; i++) {
|
||||
count = 0;
|
||||
|
||||
if (current_region->len > buf_len) {
|
||||
ath10k_warn(ar, "memory region %s size %d is larger that remaining ramdump buffer size %zu\n",
|
||||
current_region->name,
|
||||
current_region->len,
|
||||
buf_len);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Reserve space for the header. */
|
||||
hdr = (void *)buf;
|
||||
buf += sizeof(*hdr);
|
||||
buf_len -= sizeof(*hdr);
|
||||
|
||||
ret = ath10k_sdio_dump_memory_generic(ar, current_region, buf,
|
||||
fast_dump);
|
||||
if (ret >= 0)
|
||||
count = ret;
|
||||
|
||||
hdr->region_type = cpu_to_le32(current_region->type);
|
||||
hdr->start = cpu_to_le32(current_region->start);
|
||||
hdr->length = cpu_to_le32(count);
|
||||
|
||||
if (count == 0)
|
||||
/* Note: the header remains, just with zero length. */
|
||||
break;
|
||||
|
||||
buf += count;
|
||||
buf_len -= count;
|
||||
|
||||
current_region++;
|
||||
}
|
||||
}
|
||||
|
||||
void ath10k_sdio_fw_crashed_dump(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_fw_crash_data *crash_data;
|
||||
char guid[UUID_STRING_LEN + 1];
|
||||
bool fast_dump;
|
||||
|
||||
fast_dump = ath10k_sdio_is_fast_dump_supported(ar);
|
||||
|
||||
if (fast_dump)
|
||||
ath10k_bmi_start(ar);
|
||||
|
||||
ar->stats.fw_crash_counter++;
|
||||
|
||||
ath10k_sdio_disable_intrs(ar);
|
||||
|
||||
crash_data = ath10k_coredump_new(ar);
|
||||
|
||||
if (crash_data)
|
||||
scnprintf(guid, sizeof(guid), "%pUl", &crash_data->guid);
|
||||
else
|
||||
scnprintf(guid, sizeof(guid), "n/a");
|
||||
|
||||
ath10k_err(ar, "firmware crashed! (guid %s)\n", guid);
|
||||
ath10k_print_driver_info(ar);
|
||||
ath10k_sdio_dump_registers(ar, crash_data, fast_dump);
|
||||
ath10k_sdio_dump_memory(ar, crash_data, fast_dump);
|
||||
|
||||
ath10k_sdio_enable_intrs(ar);
|
||||
|
||||
queue_work(ar->workqueue, &ar->restart_work);
|
||||
}
|
||||
|
||||
static int ath10k_sdio_probe(struct sdio_func *func,
|
||||
const struct sdio_device_id *id)
|
||||
{
|
||||
|
@ -3,6 +3,7 @@
|
||||
* Copyright (c) 2018 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
@ -45,6 +46,7 @@ static const char * const ath10k_regulators[] = {
|
||||
"vdd-1.8-xo",
|
||||
"vdd-1.3-rfa",
|
||||
"vdd-3.3-ch0",
|
||||
"vdd-3.3-ch1",
|
||||
};
|
||||
|
||||
static const char * const ath10k_clocks[] = {
|
||||
@ -923,6 +925,7 @@ static int ath10k_snoc_hif_start(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
|
||||
bitmap_clear(ar_snoc->pending_ce_irqs, 0, CE_COUNT_MAX);
|
||||
napi_enable(&ar->napi);
|
||||
ath10k_snoc_irq_enable(ar);
|
||||
ath10k_snoc_rx_post(ar);
|
||||
@ -1158,7 +1161,9 @@ static irqreturn_t ath10k_snoc_per_engine_handler(int irq, void *arg)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
ath10k_snoc_irq_disable(ar);
|
||||
ath10k_ce_disable_interrupt(ar, ce_id);
|
||||
set_bit(ce_id, ar_snoc->pending_ce_irqs);
|
||||
|
||||
napi_schedule(&ar->napi);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@ -1167,20 +1172,25 @@ static irqreturn_t ath10k_snoc_per_engine_handler(int irq, void *arg)
|
||||
static int ath10k_snoc_napi_poll(struct napi_struct *ctx, int budget)
|
||||
{
|
||||
struct ath10k *ar = container_of(ctx, struct ath10k, napi);
|
||||
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
|
||||
int done = 0;
|
||||
int ce_id;
|
||||
|
||||
if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) {
|
||||
napi_complete(ctx);
|
||||
return done;
|
||||
}
|
||||
|
||||
ath10k_ce_per_engine_service_any(ar);
|
||||
for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
|
||||
if (test_and_clear_bit(ce_id, ar_snoc->pending_ce_irqs)) {
|
||||
ath10k_ce_per_engine_service(ar, ce_id);
|
||||
ath10k_ce_enable_interrupt(ar, ce_id);
|
||||
}
|
||||
|
||||
done = ath10k_htt_txrx_compl_task(ar, budget);
|
||||
|
||||
if (done < budget) {
|
||||
if (done < budget)
|
||||
napi_complete(ctx);
|
||||
ath10k_snoc_irq_enable(ar);
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
@ -1772,9 +1782,18 @@ static int ath10k_snoc_remove(struct platform_device *pdev)
|
||||
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 = {
|
||||
.probe = ath10k_snoc_probe,
|
||||
.remove = ath10k_snoc_remove,
|
||||
.shutdown = ath10k_snoc_shutdown,
|
||||
.driver = {
|
||||
.name = "ath10k_snoc",
|
||||
.of_match_table = ath10k_snoc_dt_match,
|
||||
|
@ -78,6 +78,7 @@ struct ath10k_snoc {
|
||||
unsigned long flags;
|
||||
bool xo_cal_supported;
|
||||
u32 xo_cal_data;
|
||||
DECLARE_BITMAP(pending_ce_irqs, CE_COUNT_MAX);
|
||||
};
|
||||
|
||||
static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar)
|
||||
|
@ -333,6 +333,17 @@ struct host_interest {
|
||||
#define HI_ACS_FLAGS_SDIO_SWAP_MAILBOX_FW_ACK (1 << 16)
|
||||
#define HI_ACS_FLAGS_SDIO_REDUCE_TX_COMPL_FW_ACK (1 << 17)
|
||||
|
||||
/*
|
||||
* If both SDIO_CRASH_DUMP_ENHANCEMENT_HOST and SDIO_CRASH_DUMP_ENHANCEMENT_FW
|
||||
* flags are set, then crashdump upload will be done using the BMI host/target
|
||||
* communication channel.
|
||||
*/
|
||||
/* HOST to support using BMI dump FW memory when hit assert */
|
||||
#define HI_OPTION_SDIO_CRASH_DUMP_ENHANCEMENT_HOST 0x400
|
||||
|
||||
/* FW to support using BMI dump FW memory when hit assert */
|
||||
#define HI_OPTION_SDIO_CRASH_DUMP_ENHANCEMENT_FW 0x800
|
||||
|
||||
/*
|
||||
* CONSOLE FLAGS
|
||||
*
|
||||
|
@ -50,6 +50,7 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
||||
struct ath10k_skb_cb *skb_cb;
|
||||
struct ath10k_txq *artxq;
|
||||
struct sk_buff *msdu;
|
||||
u8 flags;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT,
|
||||
"htt tx completion msdu_id %u status %d\n",
|
||||
@ -78,6 +79,7 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
||||
artxq->num_fw_queued--;
|
||||
}
|
||||
|
||||
flags = skb_cb->flags;
|
||||
ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
|
||||
ath10k_htt_tx_dec_pending(htt);
|
||||
if (htt->num_pending_tx == 0)
|
||||
@ -101,18 +103,21 @@ int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
||||
|
||||
trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id);
|
||||
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
|
||||
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
|
||||
!(flags & ATH10K_SKB_F_NOACK_TID))
|
||||
info->flags |= IEEE80211_TX_STAT_ACK;
|
||||
|
||||
if (tx_done->status == HTT_TX_COMPL_STATE_NOACK)
|
||||
info->flags &= ~IEEE80211_TX_STAT_ACK;
|
||||
|
||||
if ((tx_done->status == HTT_TX_COMPL_STATE_ACK) &&
|
||||
(info->flags & IEEE80211_TX_CTL_NO_ACK))
|
||||
((info->flags & IEEE80211_TX_CTL_NO_ACK) ||
|
||||
(flags & ATH10K_SKB_F_NOACK_TID)))
|
||||
info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
|
||||
|
||||
if (tx_done->status == HTT_TX_COMPL_STATE_DISCARD) {
|
||||
if (info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
if ((info->flags & IEEE80211_TX_CTL_NO_ACK) ||
|
||||
(flags & ATH10K_SKB_F_NOACK_TID))
|
||||
info->flags &= ~IEEE80211_TX_STAT_NOACK_TRANSMITTED;
|
||||
else
|
||||
info->flags &= ~IEEE80211_TX_STAT_ACK;
|
||||
|
@ -224,6 +224,8 @@ struct wmi_ops {
|
||||
struct sk_buff *(*gen_bb_timing)
|
||||
(struct ath10k *ar,
|
||||
const struct wmi_bb_timing_cfg_arg *arg);
|
||||
struct sk_buff *(*gen_per_peer_per_tid_cfg)(struct ath10k *ar,
|
||||
const struct wmi_per_peer_per_tid_cfg_arg *arg);
|
||||
|
||||
};
|
||||
|
||||
@ -1656,4 +1658,21 @@ ath10k_wmi_pdev_bb_timing(struct ath10k *ar,
|
||||
return ath10k_wmi_cmd_send(ar, skb,
|
||||
ar->wmi.cmd->set_bb_timing_cmdid);
|
||||
}
|
||||
|
||||
static inline int
|
||||
ath10k_wmi_set_per_peer_per_tid_cfg(struct ath10k *ar,
|
||||
const struct wmi_per_peer_per_tid_cfg_arg *arg)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (!ar->wmi.ops->gen_per_peer_per_tid_cfg)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
skb = ar->wmi.ops->gen_per_peer_per_tid_cfg(ar, arg);
|
||||
if (IS_ERR(skb))
|
||||
return PTR_ERR(skb);
|
||||
|
||||
return ath10k_wmi_cmd_send(ar, skb,
|
||||
ar->wmi.cmd->per_peer_per_tid_config_cmdid);
|
||||
}
|
||||
#endif
|
||||
|
@ -1614,6 +1614,8 @@ wmi_tlv_svc_map(const __le32 *in, unsigned long *out, size_t len)
|
||||
WMI_SERVICE_MESH_11S, len);
|
||||
SVCMAP(WMI_TLV_SERVICE_SYNC_DELETE_CMDS,
|
||||
WMI_SERVICE_SYNC_DELETE_CMDS, len);
|
||||
SVCMAP(WMI_TLV_SERVICE_PEER_STATS_INFO,
|
||||
WMI_SERVICE_PEER_STATS, len);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
@ -740,6 +740,7 @@ static struct wmi_cmd_map wmi_10_4_cmd_map = {
|
||||
.tdls_peer_update_cmdid = WMI_10_4_TDLS_PEER_UPDATE_CMDID,
|
||||
.tdls_set_offchan_mode_cmdid = WMI_10_4_TDLS_SET_OFFCHAN_MODE_CMDID,
|
||||
.radar_found_cmdid = WMI_10_4_RADAR_FOUND_CMDID,
|
||||
.per_peer_per_tid_config_cmdid = WMI_10_4_PER_PEER_PER_TID_CONFIG_CMDID,
|
||||
};
|
||||
|
||||
static struct wmi_peer_param_map wmi_peer_param_map = {
|
||||
@ -6551,7 +6552,7 @@ static struct sk_buff *ath10k_wmi_op_gen_init(struct ath10k *ar)
|
||||
struct wmi_init_cmd *cmd;
|
||||
struct sk_buff *buf;
|
||||
struct wmi_resource_config config = {};
|
||||
u32 len, val;
|
||||
u32 val;
|
||||
|
||||
config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS);
|
||||
config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS);
|
||||
@ -6603,10 +6604,8 @@ static struct sk_buff *ath10k_wmi_op_gen_init(struct ath10k *ar)
|
||||
config.num_msdu_desc = __cpu_to_le32(TARGET_NUM_MSDU_DESC);
|
||||
config.max_frag_entries = __cpu_to_le32(TARGET_MAX_FRAG_ENTRIES);
|
||||
|
||||
len = sizeof(*cmd) +
|
||||
(sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks);
|
||||
|
||||
buf = ath10k_wmi_alloc_skb(ar, len);
|
||||
buf = ath10k_wmi_alloc_skb(ar, struct_size(cmd, mem_chunks.items,
|
||||
ar->wmi.num_mem_chunks));
|
||||
if (!buf)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@ -6624,7 +6623,7 @@ static struct sk_buff *ath10k_wmi_10_1_op_gen_init(struct ath10k *ar)
|
||||
struct wmi_init_cmd_10x *cmd;
|
||||
struct sk_buff *buf;
|
||||
struct wmi_resource_config_10x config = {};
|
||||
u32 len, val;
|
||||
u32 val;
|
||||
|
||||
config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS);
|
||||
config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS);
|
||||
@ -6668,10 +6667,8 @@ static struct sk_buff *ath10k_wmi_10_1_op_gen_init(struct ath10k *ar)
|
||||
config.num_msdu_desc = __cpu_to_le32(TARGET_10X_NUM_MSDU_DESC);
|
||||
config.max_frag_entries = __cpu_to_le32(TARGET_10X_MAX_FRAG_ENTRIES);
|
||||
|
||||
len = sizeof(*cmd) +
|
||||
(sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks);
|
||||
|
||||
buf = ath10k_wmi_alloc_skb(ar, len);
|
||||
buf = ath10k_wmi_alloc_skb(ar, struct_size(cmd, mem_chunks.items,
|
||||
ar->wmi.num_mem_chunks));
|
||||
if (!buf)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@ -6689,7 +6686,7 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
|
||||
struct wmi_init_cmd_10_2 *cmd;
|
||||
struct sk_buff *buf;
|
||||
struct wmi_resource_config_10x config = {};
|
||||
u32 len, val, features;
|
||||
u32 val, features;
|
||||
|
||||
config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS);
|
||||
config.num_peer_keys = __cpu_to_le32(TARGET_10X_NUM_PEER_KEYS);
|
||||
@ -6741,10 +6738,8 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
|
||||
config.num_msdu_desc = __cpu_to_le32(TARGET_10X_NUM_MSDU_DESC);
|
||||
config.max_frag_entries = __cpu_to_le32(TARGET_10X_MAX_FRAG_ENTRIES);
|
||||
|
||||
len = sizeof(*cmd) +
|
||||
(sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks);
|
||||
|
||||
buf = ath10k_wmi_alloc_skb(ar, len);
|
||||
buf = ath10k_wmi_alloc_skb(ar, struct_size(cmd, mem_chunks.items,
|
||||
ar->wmi.num_mem_chunks));
|
||||
if (!buf)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@ -6776,7 +6771,6 @@ static struct sk_buff *ath10k_wmi_10_4_op_gen_init(struct ath10k *ar)
|
||||
struct wmi_init_cmd_10_4 *cmd;
|
||||
struct sk_buff *buf;
|
||||
struct wmi_resource_config_10_4 config = {};
|
||||
u32 len;
|
||||
|
||||
config.num_vdevs = __cpu_to_le32(ar->max_num_vdevs);
|
||||
config.num_peers = __cpu_to_le32(ar->max_num_peers);
|
||||
@ -6838,10 +6832,8 @@ static struct sk_buff *ath10k_wmi_10_4_op_gen_init(struct ath10k *ar)
|
||||
config.iphdr_pad_config = __cpu_to_le32(TARGET_10_4_IPHDR_PAD_CONFIG);
|
||||
config.qwrap_config = __cpu_to_le32(TARGET_10_4_QWRAP_CONFIG);
|
||||
|
||||
len = sizeof(*cmd) +
|
||||
(sizeof(struct host_memory_chunk) * ar->wmi.num_mem_chunks);
|
||||
|
||||
buf = ath10k_wmi_alloc_skb(ar, len);
|
||||
buf = ath10k_wmi_alloc_skb(ar, struct_size(cmd, mem_chunks.items,
|
||||
ar->wmi.num_mem_chunks));
|
||||
if (!buf)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@ -7549,12 +7541,9 @@ ath10k_wmi_op_gen_scan_chan_list(struct ath10k *ar,
|
||||
struct sk_buff *skb;
|
||||
struct wmi_channel_arg *ch;
|
||||
struct wmi_channel *ci;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
len = sizeof(*cmd) + arg->n_channels * sizeof(struct wmi_channel);
|
||||
|
||||
skb = ath10k_wmi_alloc_skb(ar, len);
|
||||
skb = ath10k_wmi_alloc_skb(ar, struct_size(cmd, chan_info, arg->n_channels));
|
||||
if (!skb)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
@ -9004,6 +8993,39 @@ ath10k_wmi_10_4_gen_radar_found(struct ath10k *ar,
|
||||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ath10k_wmi_10_4_gen_per_peer_per_tid_cfg(struct ath10k *ar,
|
||||
const struct wmi_per_peer_per_tid_cfg_arg *arg)
|
||||
{
|
||||
struct wmi_peer_per_tid_cfg_cmd *cmd;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
|
||||
if (!skb)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
memset(skb->data, 0, sizeof(*cmd));
|
||||
|
||||
cmd = (struct wmi_peer_per_tid_cfg_cmd *)skb->data;
|
||||
cmd->vdev_id = cpu_to_le32(arg->vdev_id);
|
||||
ether_addr_copy(cmd->peer_macaddr.addr, arg->peer_macaddr.addr);
|
||||
cmd->tid = cpu_to_le32(arg->tid);
|
||||
cmd->ack_policy = cpu_to_le32(arg->ack_policy);
|
||||
cmd->aggr_control = cpu_to_le32(arg->aggr_control);
|
||||
cmd->rate_control = cpu_to_le32(arg->rate_ctrl);
|
||||
cmd->retry_count = cpu_to_le32(arg->retry_count);
|
||||
cmd->rcode_flags = cpu_to_le32(arg->rcode_flags);
|
||||
cmd->ext_tid_cfg_bitmap = cpu_to_le32(arg->ext_tid_cfg_bitmap);
|
||||
cmd->rtscts_ctrl = cpu_to_le32(arg->rtscts_ctrl);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_WMI,
|
||||
"wmi noack tid %d vdev id %d ack_policy %d aggr %u rate_ctrl %u rcflag %u retry_count %d rtscts %d ext_tid_cfg_bitmap %d mac_addr %pM\n",
|
||||
arg->tid, arg->vdev_id, arg->ack_policy, arg->aggr_control,
|
||||
arg->rate_ctrl, arg->rcode_flags, arg->retry_count,
|
||||
arg->rtscts_ctrl, arg->ext_tid_cfg_bitmap, arg->peer_macaddr.addr);
|
||||
return skb;
|
||||
}
|
||||
|
||||
static struct sk_buff *
|
||||
ath10k_wmi_op_gen_echo(struct ath10k *ar, u32 value)
|
||||
{
|
||||
@ -9413,6 +9435,7 @@ static const struct wmi_ops wmi_10_4_ops = {
|
||||
.gen_pdev_get_tpc_table_cmdid =
|
||||
ath10k_wmi_10_4_op_gen_pdev_get_tpc_table_cmdid,
|
||||
.gen_radar_found = ath10k_wmi_10_4_gen_radar_found,
|
||||
.gen_per_peer_per_tid_cfg = ath10k_wmi_10_4_gen_per_peer_per_tid_cfg,
|
||||
|
||||
/* shared with 10.2 */
|
||||
.pull_echo_ev = ath10k_wmi_op_pull_echo_ev,
|
||||
|
@ -203,6 +203,8 @@ enum wmi_service {
|
||||
WMI_SERVICE_SYNC_DELETE_CMDS,
|
||||
WMI_SERVICE_TX_PWR_PER_PEER,
|
||||
WMI_SERVICE_SUPPORT_EXTEND_ADDRESS,
|
||||
WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT,
|
||||
WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
|
||||
|
||||
/* Remember to add the new value to wmi_service_name()! */
|
||||
|
||||
@ -503,6 +505,8 @@ static inline char *wmi_service_name(enum wmi_service service_id)
|
||||
SVCSTR(WMI_SERVICE_SYNC_DELETE_CMDS);
|
||||
SVCSTR(WMI_SERVICE_TX_PWR_PER_PEER);
|
||||
SVCSTR(WMI_SERVICE_SUPPORT_EXTEND_ADDRESS);
|
||||
SVCSTR(WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT);
|
||||
SVCSTR(WMI_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT);
|
||||
|
||||
case WMI_SERVICE_MAX:
|
||||
return NULL;
|
||||
@ -834,6 +838,10 @@ static inline void wmi_10_4_svc_map(const __le32 *in, unsigned long *out,
|
||||
WMI_SERVICE_TX_PWR_PER_PEER, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_RESET_CHIP,
|
||||
WMI_SERVICE_RESET_CHIP, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_PEER_TID_CONFIGS_SUPPORT,
|
||||
WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT, len);
|
||||
SVCMAP(WMI_10_4_SERVICE_EXT_PEER_TID_CONFIGS_SUPPORT,
|
||||
WMI_SERVICE_PEER_TID_CONFIGS_SUPPORT, len);
|
||||
}
|
||||
|
||||
#undef SVCMAP
|
||||
@ -1036,6 +1044,7 @@ struct wmi_cmd_map {
|
||||
u32 tdls_set_offchan_mode_cmdid;
|
||||
u32 radar_found_cmdid;
|
||||
u32 set_bb_timing_cmdid;
|
||||
u32 per_peer_per_tid_config_cmdid;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -1877,6 +1886,8 @@ enum wmi_10_4_cmd_id {
|
||||
WMI_10_4_PDEV_SET_BRIDGE_MACADDR_CMDID,
|
||||
WMI_10_4_ATF_GROUP_WMM_AC_CONFIG_REQUEST_CMDID,
|
||||
WMI_10_4_RADAR_FOUND_CMDID,
|
||||
WMI_10_4_PEER_CFR_CAPTURE_CMDID,
|
||||
WMI_10_4_PER_PEER_PER_TID_CONFIG_CMDID,
|
||||
WMI_10_4_PDEV_UTF_CMDID = WMI_10_4_END_CMDID - 1,
|
||||
};
|
||||
|
||||
@ -7220,6 +7231,71 @@ struct wmi_tdls_peer_event {
|
||||
__le32 vdev_id;
|
||||
} __packed;
|
||||
|
||||
enum wmi_tid_aggr_control_conf {
|
||||
WMI_TID_CONFIG_AGGR_CONTROL_IGNORE,
|
||||
WMI_TID_CONFIG_AGGR_CONTROL_ENABLE,
|
||||
WMI_TID_CONFIG_AGGR_CONTROL_DISABLE,
|
||||
};
|
||||
|
||||
enum wmi_noack_tid_conf {
|
||||
WMI_NOACK_TID_CONFIG_IGNORE_ACK_POLICY,
|
||||
WMI_PEER_TID_CONFIG_ACK,
|
||||
WMI_PEER_TID_CONFIG_NOACK,
|
||||
};
|
||||
|
||||
enum wmi_tid_rate_ctrl_conf {
|
||||
WMI_TID_CONFIG_RATE_CONTROL_IGNORE,
|
||||
WMI_TID_CONFIG_RATE_CONTROL_AUTO,
|
||||
WMI_TID_CONFIG_RATE_CONTROL_FIXED_RATE,
|
||||
WMI_TID_CONFIG_RATE_CONTROL_DEFAULT_LOWEST_RATE,
|
||||
WMI_PEER_TID_CONFIG_RATE_UPPER_CAP,
|
||||
};
|
||||
|
||||
enum wmi_tid_rtscts_control_conf {
|
||||
WMI_TID_CONFIG_RTSCTS_CONTROL_ENABLE,
|
||||
WMI_TID_CONFIG_RTSCTS_CONTROL_DISABLE,
|
||||
};
|
||||
|
||||
enum wmi_ext_tid_config_map {
|
||||
WMI_EXT_TID_RTS_CTS_CONFIG = BIT(0),
|
||||
};
|
||||
|
||||
struct wmi_per_peer_per_tid_cfg_arg {
|
||||
u32 vdev_id;
|
||||
struct wmi_mac_addr peer_macaddr;
|
||||
u32 tid;
|
||||
enum wmi_noack_tid_conf ack_policy;
|
||||
enum wmi_tid_aggr_control_conf aggr_control;
|
||||
u8 rate_ctrl;
|
||||
u32 retry_count;
|
||||
u32 rcode_flags;
|
||||
u32 ext_tid_cfg_bitmap;
|
||||
u32 rtscts_ctrl;
|
||||
};
|
||||
|
||||
struct wmi_peer_per_tid_cfg_cmd {
|
||||
__le32 vdev_id;
|
||||
struct wmi_mac_addr peer_macaddr;
|
||||
__le32 tid;
|
||||
|
||||
/* see enum wmi_noack_tid_conf */
|
||||
__le32 ack_policy;
|
||||
|
||||
/* see enum wmi_tid_aggr_control_conf */
|
||||
__le32 aggr_control;
|
||||
|
||||
/* see enum wmi_tid_rate_ctrl_conf */
|
||||
__le32 rate_control;
|
||||
__le32 rcode_flags;
|
||||
__le32 retry_count;
|
||||
|
||||
/* See enum wmi_ext_tid_config_map */
|
||||
__le32 ext_tid_cfg_bitmap;
|
||||
|
||||
/* see enum wmi_tid_rtscts_control_conf */
|
||||
__le32 rtscts_ctrl;
|
||||
} __packed;
|
||||
|
||||
enum wmi_txbf_conf {
|
||||
WMI_TXBF_CONF_UNSUPPORTED,
|
||||
WMI_TXBF_CONF_BEFORE_ASSOC,
|
||||
|
@ -275,7 +275,7 @@ static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif,
|
||||
switch (arvif->vdev_type) {
|
||||
case WMI_VDEV_TYPE_IBSS:
|
||||
__set_bit(WOW_BEACON_EVENT, &wow_mask);
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case WMI_VDEV_TYPE_AP:
|
||||
__set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask);
|
||||
__set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask);
|
||||
|
@ -2,9 +2,7 @@
|
||||
config ATH11K
|
||||
tristate "Qualcomm Technologies 802.11ax chipset support"
|
||||
depends on MAC80211 && HAS_DMA
|
||||
depends on REMOTEPROC
|
||||
depends on CRYPTO_MICHAEL_MIC
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
select ATH_COMMON
|
||||
select QCOM_QMI_HELPERS
|
||||
help
|
||||
@ -13,6 +11,22 @@ config 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
|
||||
bool "QCA ath11k debugging"
|
||||
depends on ATH11K
|
||||
|
@ -4,7 +4,6 @@ ath11k-y += core.o \
|
||||
hal.o \
|
||||
hal_tx.o \
|
||||
hal_rx.o \
|
||||
ahb.o \
|
||||
wmi.o \
|
||||
mac.o \
|
||||
reg.o \
|
||||
@ -16,7 +15,8 @@ ath11k-y += core.o \
|
||||
debug.o \
|
||||
ce.o \
|
||||
peer.o \
|
||||
dbring.o
|
||||
dbring.o \
|
||||
hw.o
|
||||
|
||||
ath11k-$(CONFIG_ATH11K_DEBUGFS) += debug_htt_stats.o debugfs_sta.o
|
||||
ath11k-$(CONFIG_NL80211_TESTMODE) += testmode.o
|
||||
@ -24,5 +24,11 @@ ath11k-$(CONFIG_ATH11K_TRACING) += trace.o
|
||||
ath11k-$(CONFIG_THERMAL) += thermal.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
|
||||
CFLAGS_trace.o := -I$(src)
|
||||
|
@ -20,248 +20,19 @@ static const struct of_device_id ath11k_ahb_of_match[] = {
|
||||
{ .compatible = "qcom,ipq8074-wifi",
|
||||
.data = (void *)ATH11K_HW_IPQ8074,
|
||||
},
|
||||
{ .compatible = "qcom,ipq6018-wifi",
|
||||
.data = (void *)ATH11K_HW_IPQ6018_HW10,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, ath11k_ahb_of_match);
|
||||
|
||||
/* Target firmware's Copy Engine configuration. */
|
||||
static const struct ce_pipe_config target_ce_config_wlan[] = {
|
||||
/* CE0: host->target HTC control and raw streams */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(0),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE1: target->host HTT + HTC control */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(1),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE2: target->host WMI */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE3: host->target WMI */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE4: host->target HTT */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(4),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
|
||||
.nentries = __cpu_to_le32(256),
|
||||
.nbytes_max = __cpu_to_le32(256),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE5: target->host Pktlog */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(5),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(0),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE6: Reserved for target autonomous hif_memcpy */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(6),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(65535),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE7 used only by Host */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(7),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE8 target->host used only by IPA */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(8),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(65535),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE9 host->target HTT */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(9),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE10 target->host HTT */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(10),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_INOUT_H2H),
|
||||
.nentries = __cpu_to_le32(0),
|
||||
.nbytes_max = __cpu_to_le32(0),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE11 Not used */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(0),
|
||||
.pipedir = __cpu_to_le32(0),
|
||||
.nentries = __cpu_to_le32(0),
|
||||
.nbytes_max = __cpu_to_le32(0),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
};
|
||||
|
||||
/* Map from service/endpoint to Copy Engine.
|
||||
* This table is derived from the CE_PCI TABLE, above.
|
||||
* It is passed to the Target at startup for use by firmware.
|
||||
*/
|
||||
static const struct service_to_pipe target_service_to_ce_map_wlan[] = {
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(7),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(9),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(0),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(1),
|
||||
},
|
||||
{ /* not used */
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(0),
|
||||
},
|
||||
{ /* not used */
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(1),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(4),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(1),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_PKT_LOG),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(5),
|
||||
},
|
||||
|
||||
/* (Additions here) */
|
||||
|
||||
{ /* terminator entry */ }
|
||||
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,
|
||||
};
|
||||
|
||||
#define ATH11K_IRQ_CE0_OFFSET 4
|
||||
@ -321,78 +92,6 @@ static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
|
||||
"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
|
||||
* like datapath
|
||||
*/
|
||||
@ -449,10 +148,10 @@ static void ath11k_ahb_kill_tasklets(struct ath11k_base *ab)
|
||||
{
|
||||
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];
|
||||
|
||||
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
|
||||
continue;
|
||||
|
||||
tasklet_kill(&ce_pipe->intr_tq);
|
||||
@ -509,7 +208,7 @@ static void ath11k_ahb_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
|
||||
{
|
||||
const struct ce_pipe_config *ce_config;
|
||||
|
||||
ce_config = &target_ce_config_wlan[ce_id];
|
||||
ce_config = &ab->hw_params.target_ce_config[ce_id];
|
||||
if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT)
|
||||
ath11k_ahb_setbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
|
||||
|
||||
@ -524,7 +223,7 @@ static void ath11k_ahb_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
|
||||
{
|
||||
const struct ce_pipe_config *ce_config;
|
||||
|
||||
ce_config = &target_ce_config_wlan[ce_id];
|
||||
ce_config = &ab->hw_params.target_ce_config[ce_id];
|
||||
if (__le32_to_cpu(ce_config->pipedir) & PIPEDIR_OUT)
|
||||
ath11k_ahb_clearbit32(ab, ce_id, CE_HOST_IE_ADDRESS);
|
||||
|
||||
@ -540,8 +239,8 @@ static void ath11k_ahb_sync_ce_irqs(struct ath11k_base *ab)
|
||||
int i;
|
||||
int irq_idx;
|
||||
|
||||
for (i = 0; i < CE_COUNT; i++) {
|
||||
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
|
||||
for (i = 0; i < ab->hw_params.ce_count; i++) {
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
|
||||
continue;
|
||||
|
||||
irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
|
||||
@ -568,8 +267,8 @@ static void ath11k_ahb_ce_irqs_enable(struct ath11k_base *ab)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CE_COUNT; i++) {
|
||||
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
|
||||
for (i = 0; i < ab->hw_params.ce_count; i++) {
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
|
||||
continue;
|
||||
ath11k_ahb_ce_irq_enable(ab, i);
|
||||
}
|
||||
@ -579,8 +278,8 @@ static void ath11k_ahb_ce_irqs_disable(struct ath11k_base *ab)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CE_COUNT; i++) {
|
||||
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
|
||||
for (i = 0; i < ab->hw_params.ce_count; i++) {
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
|
||||
continue;
|
||||
ath11k_ahb_ce_irq_disable(ab, i);
|
||||
}
|
||||
@ -642,10 +341,11 @@ static void ath11k_ahb_init_qmi_ce_config(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
|
||||
|
||||
cfg->tgt_ce_len = ARRAY_SIZE(target_ce_config_wlan) - 1;
|
||||
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 = target_service_to_ce_map_wlan;
|
||||
cfg->tgt_ce_len = ab->hw_params.target_ce_count;
|
||||
cfg->tgt_ce = ab->hw_params.target_ce_config;
|
||||
cfg->svc_to_ce_map_len = ab->hw_params.svc_to_ce_map_len;
|
||||
cfg->svc_to_ce_map = ab->hw_params.svc_to_ce_map;
|
||||
ab->qmi.service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074;
|
||||
}
|
||||
|
||||
static void ath11k_ahb_free_ext_irq(struct ath11k_base *ab)
|
||||
@ -665,8 +365,8 @@ static void ath11k_ahb_free_irq(struct ath11k_base *ab)
|
||||
int irq_idx;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CE_COUNT; i++) {
|
||||
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
|
||||
for (i = 0; i < ab->hw_params.ce_count; i++) {
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
|
||||
continue;
|
||||
irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
|
||||
free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]);
|
||||
@ -675,9 +375,9 @@ static void ath11k_ahb_free_irq(struct ath11k_base *ab)
|
||||
ath11k_ahb_free_ext_irq(ab);
|
||||
}
|
||||
|
||||
static void ath11k_ahb_ce_tasklet(unsigned long data)
|
||||
static void ath11k_ahb_ce_tasklet(struct tasklet_struct *t)
|
||||
{
|
||||
struct ath11k_ce_pipe *ce_pipe = (struct ath11k_ce_pipe *)data;
|
||||
struct ath11k_ce_pipe *ce_pipe = from_tasklet(ce_pipe, t, intr_tq);
|
||||
|
||||
ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
|
||||
|
||||
@ -734,6 +434,7 @@ static irqreturn_t ath11k_ahb_ext_interrupt_handler(int irq, void *arg)
|
||||
|
||||
static int ath11k_ahb_ext_irq_config(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_hw_params *hw = &ab->hw_params;
|
||||
int i, j;
|
||||
int irq;
|
||||
int ret;
|
||||
@ -749,45 +450,45 @@ static int ath11k_ahb_ext_irq_config(struct ath11k_base *ab)
|
||||
ath11k_ahb_ext_grp_napi_poll, NAPI_POLL_WEIGHT);
|
||||
|
||||
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++] =
|
||||
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++] =
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
if (j < MAX_RADIOS) {
|
||||
if (ath11k_rxdma2host_ring_mask[i] & BIT(j)) {
|
||||
if (j < ab->hw_params.max_radios) {
|
||||
if (ab->hw_params.ring_mask->rxdma2host[i] & BIT(j)) {
|
||||
irq_grp->irqs[num_irq++] =
|
||||
rxdma2host_destination_ring_mac1
|
||||
- ath11k_core_get_hw_mac_id(ab, j);
|
||||
rxdma2host_destination_ring_mac1 -
|
||||
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++] =
|
||||
host2rxdma_host_buf_ring_mac1
|
||||
- ath11k_core_get_hw_mac_id(ab, j);
|
||||
host2rxdma_host_buf_ring_mac1 -
|
||||
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++] =
|
||||
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++] =
|
||||
rxdma2host_monitor_status_ring_mac1 -
|
||||
ath11k_core_get_hw_mac_id(ab, j);
|
||||
ath11k_hw_get_mac_from_pdev_id(hw, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -819,16 +520,15 @@ static int ath11k_ahb_config_irq(struct ath11k_base *ab)
|
||||
int ret;
|
||||
|
||||
/* 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];
|
||||
|
||||
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
|
||||
continue;
|
||||
|
||||
irq_idx = ATH11K_IRQ_CE0_OFFSET + i;
|
||||
|
||||
tasklet_init(&ce_pipe->intr_tq, ath11k_ahb_ce_tasklet,
|
||||
(unsigned long)ce_pipe);
|
||||
tasklet_setup(&ce_pipe->intr_tq, ath11k_ahb_ce_tasklet);
|
||||
irq = platform_get_irq_byname(ab->pdev, irq_name[irq_idx]);
|
||||
ret = request_irq(irq, ath11k_ahb_ce_interrupt_handler,
|
||||
IRQF_TRIGGER_RISING, irq_name[irq_idx],
|
||||
@ -852,8 +552,8 @@ static int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id
|
||||
bool ul_set = false, dl_set = false;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(target_service_to_ce_map_wlan); i++) {
|
||||
entry = &target_service_to_ce_map_wlan[i];
|
||||
for (i = 0; i < ab->hw_params.svc_to_ce_map_len; i++) {
|
||||
entry = &ab->hw_params.svc_to_ce_map[i];
|
||||
|
||||
if (__le32_to_cpu(entry->service_id) != service_id)
|
||||
continue;
|
||||
@ -926,7 +626,7 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
|
||||
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) {
|
||||
dev_err(&pdev->dev, "failed to allocate ath11k base\n");
|
||||
return -ENOMEM;
|
||||
@ -939,6 +639,10 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
|
||||
ab->mem_len = resource_size(mem_res);
|
||||
platform_set_drvdata(pdev, ab);
|
||||
|
||||
ret = ath11k_core_pre_init(ab);
|
||||
if (ret)
|
||||
goto err_core_free;
|
||||
|
||||
ret = ath11k_hal_srng_init(ab);
|
||||
if (ret)
|
||||
goto err_core_free;
|
||||
@ -951,18 +655,18 @@ static int ath11k_ahb_probe(struct platform_device *pdev)
|
||||
|
||||
ath11k_ahb_init_qmi_ce_config(ab);
|
||||
|
||||
ret = ath11k_ahb_config_irq(ab);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to configure irq: %d\n", ret);
|
||||
goto err_ce_free;
|
||||
}
|
||||
|
||||
ret = ath11k_core_init(ab);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to init core: %d\n", ret);
|
||||
goto err_ce_free;
|
||||
}
|
||||
|
||||
ret = ath11k_ahb_config_irq(ab);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to configure irq: %d\n", ret);
|
||||
goto err_ce_free;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_ce_free:
|
||||
@ -1023,5 +727,5 @@ static void ath11k_ahb_exit(void)
|
||||
}
|
||||
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");
|
||||
|
@ -5,8 +5,9 @@
|
||||
|
||||
#include "dp_rx.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 */
|
||||
{
|
||||
.flags = CE_ATTR_FLAGS,
|
||||
@ -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,
|
||||
struct sk_buff *skb, dma_addr_t paddr)
|
||||
{
|
||||
@ -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,
|
||||
struct ath11k_ce_ring *ce_ring,
|
||||
int ce_id, enum hal_ring_type type)
|
||||
@ -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.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, ¶ms);
|
||||
|
||||
switch (type) {
|
||||
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;
|
||||
break;
|
||||
case HAL_CE_DST:
|
||||
params.max_buffer_len = host_ce_config_wlan[ce_id].src_sz_max;
|
||||
if (!(host_ce_config_wlan[ce_id].flags & CE_ATTR_DIS_INTR)) {
|
||||
params.max_buffer_len = ab->hw_params.host_ce_config[ce_id].src_sz_max;
|
||||
if (!(ab->hw_params.host_ce_config[ce_id].flags & CE_ATTR_DIS_INTR)) {
|
||||
params.intr_timer_thres_us = 1024;
|
||||
params.flags |= HAL_SRNG_FLAGS_LOW_THRESH_INTR_EN;
|
||||
params.low_threshold = ce_ring->nentries - 3;
|
||||
}
|
||||
break;
|
||||
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_timer_thres_us = 0x1000;
|
||||
}
|
||||
@ -395,6 +502,7 @@ static int ath11k_ce_init_ring(struct ath11k_base *ab,
|
||||
ret, ce_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ce_ring->hal_ring_id = ret;
|
||||
|
||||
return 0;
|
||||
@ -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)
|
||||
{
|
||||
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;
|
||||
int nentries;
|
||||
int desc_sz;
|
||||
@ -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)
|
||||
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,
|
||||
u16 transfer_id)
|
||||
@ -609,7 +718,7 @@ void ath11k_ce_cleanup_pipes(struct ath11k_base *ab)
|
||||
struct ath11k_ce_pipe *pipe;
|
||||
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];
|
||||
ath11k_ce_rx_pipe_cleanup(pipe);
|
||||
|
||||
@ -619,6 +728,7 @@ void ath11k_ce_cleanup_pipes(struct ath11k_base *ab)
|
||||
/* 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)
|
||||
{
|
||||
@ -626,7 +736,7 @@ void ath11k_ce_rx_post_buf(struct ath11k_base *ab)
|
||||
int i;
|
||||
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];
|
||||
ret = ath11k_ce_rx_post_pipe(pipe);
|
||||
if (ret) {
|
||||
@ -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)
|
||||
{
|
||||
@ -656,7 +767,7 @@ int ath11k_ce_init_pipes(struct ath11k_base *ab)
|
||||
int i;
|
||||
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];
|
||||
|
||||
if (pipe->src_ring) {
|
||||
@ -714,7 +825,7 @@ void ath11k_ce_free_pipes(struct ath11k_base *ab)
|
||||
int desc_sz;
|
||||
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];
|
||||
|
||||
if (pipe->src_ring) {
|
||||
@ -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)
|
||||
{
|
||||
@ -762,8 +874,8 @@ int ath11k_ce_alloc_pipes(struct ath11k_base *ab)
|
||||
|
||||
spin_lock_init(&ab->ce.ce_lock);
|
||||
|
||||
for (i = 0; i < CE_COUNT; i++) {
|
||||
attr = &host_ce_config_wlan[i];
|
||||
for (i = 0; i < ab->hw_params.ce_count; i++) {
|
||||
attr = &ab->hw_params.host_ce_config[i];
|
||||
pipe = &ab->ce.ce_pipe[i];
|
||||
pipe->pipe_num = i;
|
||||
pipe->ab = ab;
|
||||
@ -779,6 +891,7 @@ int ath11k_ce_alloc_pipes(struct ath11k_base *ab)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_ce_alloc_pipes);
|
||||
|
||||
/* For Big Endian Host, Copy Engine byte_swap is enabled
|
||||
* 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)
|
||||
}
|
||||
}
|
||||
|
||||
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 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 @@
|
||||
#ifndef ATH11K_CE_H
|
||||
#define ATH11K_CE_H
|
||||
|
||||
#define CE_COUNT 12
|
||||
#define CE_COUNT_MAX 12
|
||||
|
||||
/* Byte swap data words */
|
||||
#define CE_ATTR_BYTE_SWAP_DATA 2
|
||||
@ -165,11 +165,14 @@ struct ath11k_ce_pipe {
|
||||
};
|
||||
|
||||
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 */
|
||||
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_rx_replenish_retry(struct timer_list *t);
|
||||
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);
|
||||
int ath11k_ce_init_pipes(struct ath11k_base *ab);
|
||||
int ath11k_ce_alloc_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);
|
||||
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
|
||||
|
@ -14,43 +14,116 @@
|
||||
#include "hif.h"
|
||||
|
||||
unsigned int ath11k_debug_mask;
|
||||
EXPORT_SYMBOL(ath11k_debug_mask);
|
||||
module_param_named(debug_mask, ath11k_debug_mask, uint, 0644);
|
||||
MODULE_PARM_DESC(debug_mask, "Debugging mask");
|
||||
|
||||
static const struct ath11k_hw_params ath11k_hw_params = {
|
||||
.name = "ipq8074",
|
||||
.fw = {
|
||||
.dir = IPQ8074_FW_DIR,
|
||||
.board_size = IPQ8074_MAX_BOARD_DATA_SZ,
|
||||
.cal_size = IPQ8074_MAX_CAL_DATA_SZ,
|
||||
static unsigned int ath11k_crypto_mode;
|
||||
module_param_named(crypto_mode, ath11k_crypto_mode, uint, 0644);
|
||||
MODULE_PARM_DESC(crypto_mode, "crypto mode: 0-hardware, 1-software");
|
||||
|
||||
/* frame mode values are mapped as per enum ath11k_hw_txrx_mode */
|
||||
unsigned int ath11k_frame_mode = ATH11K_HW_TXRX_NATIVE_WIFI;
|
||||
module_param_named(frame_mode, ath11k_frame_mode, uint, 0644);
|
||||
MODULE_PARM_DESC(frame_mode,
|
||||
"Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");
|
||||
|
||||
static const struct ath11k_hw_params ath11k_hw_params[] = {
|
||||
{
|
||||
.hw_rev = ATH11K_HW_IPQ8074,
|
||||
.name = "ipq8074 hw2.0",
|
||||
.fw = {
|
||||
.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,
|
||||
.target_ce_config = ath11k_target_ce_config_wlan_ipq8074,
|
||||
.target_ce_count = 11,
|
||||
.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq8074,
|
||||
.svc_to_ce_map_len = 21,
|
||||
.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,
|
||||
},
|
||||
{
|
||||
.hw_rev = ATH11K_HW_IPQ6018_HW10,
|
||||
.name = "ipq6018 hw1.0",
|
||||
.fw = {
|
||||
.dir = "IPQ6018/hw1.0",
|
||||
.board_size = 256 * 1024,
|
||||
.cal_size = 256 * 1024,
|
||||
},
|
||||
.max_radios = 2,
|
||||
.bdf_addr = 0x4ABC0000,
|
||||
.hw_ops = &ipq6018_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,
|
||||
.target_ce_config = ath11k_target_ce_config_wlan_ipq8074,
|
||||
.target_ce_count = 11,
|
||||
.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_ipq6018,
|
||||
.svc_to_ce_map_len = 19,
|
||||
.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,
|
||||
.target_ce_config = ath11k_target_ce_config_wlan_qca6390,
|
||||
.target_ce_count = 9,
|
||||
.svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
|
||||
.svc_to_ce_map_len = 14,
|
||||
.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,
|
||||
size_t name_len)
|
||||
{
|
||||
/* Note: bus is fixed to ahb. When other bus type supported,
|
||||
* make it to dynamic.
|
||||
*/
|
||||
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.board_id);
|
||||
|
||||
@ -59,29 +132,24 @@ static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct firmware *ath11k_fetch_fw_file(struct ath11k_base *ab,
|
||||
const char *dir,
|
||||
const char *file)
|
||||
const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab,
|
||||
const char *file)
|
||||
{
|
||||
char filename[100];
|
||||
const struct firmware *fw;
|
||||
char path[100];
|
||||
int ret;
|
||||
|
||||
if (file == NULL)
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
if (dir == NULL)
|
||||
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);
|
||||
ath11k_core_create_firmware_path(ab, file, path, sizeof(path));
|
||||
|
||||
ret = firmware_request_nowarn(&fw, path, ab->dev);
|
||||
if (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;
|
||||
}
|
||||
@ -181,26 +249,30 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab,
|
||||
{
|
||||
size_t len, magic_len;
|
||||
const u8 *data;
|
||||
char *filename = ATH11K_BOARD_API2_FILE;
|
||||
char *filename, filepath[100];
|
||||
size_t ie_len;
|
||||
struct ath11k_fw_ie *hdr;
|
||||
int ret, ie_id;
|
||||
|
||||
filename = ATH11K_BOARD_API2_FILE;
|
||||
|
||||
if (!bd->fw)
|
||||
bd->fw = ath11k_fetch_fw_file(ab,
|
||||
ab->hw_params.fw.dir,
|
||||
filename);
|
||||
bd->fw = ath11k_core_firmware_request(ab, filename);
|
||||
|
||||
if (IS_ERR(bd->fw))
|
||||
return PTR_ERR(bd->fw);
|
||||
|
||||
data = bd->fw->data;
|
||||
len = bd->fw->size;
|
||||
|
||||
ath11k_core_create_firmware_path(ab, filename,
|
||||
filepath, sizeof(filepath));
|
||||
|
||||
/* magic has extra null byte padded */
|
||||
magic_len = strlen(ATH11K_BOARD_MAGIC) + 1;
|
||||
if (len < magic_len) {
|
||||
ath11k_err(ab, "failed to find magic value in %s/%s, file too short: %zu\n",
|
||||
ab->hw_params.fw.dir, filename, len);
|
||||
ath11k_err(ab, "failed to find magic value in %s, file too short: %zu\n",
|
||||
filepath, len);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
@ -214,8 +286,8 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab,
|
||||
/* magic is padded to 4 bytes */
|
||||
magic_len = ALIGN(magic_len, 4);
|
||||
if (len < magic_len) {
|
||||
ath11k_err(ab, "failed: %s/%s too small to contain board data, len: %zu\n",
|
||||
ab->hw_params.fw.dir, filename, len);
|
||||
ath11k_err(ab, "failed: %s too small to contain board data, len: %zu\n",
|
||||
filepath, len);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
@ -263,8 +335,8 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab,
|
||||
out:
|
||||
if (!bd->data || !bd->len) {
|
||||
ath11k_err(ab,
|
||||
"failed to fetch board data for %s from %s/%s\n",
|
||||
boardname, ab->hw_params.fw.dir, filename);
|
||||
"failed to fetch board data for %s from %s\n",
|
||||
boardname, filepath);
|
||||
ret = -ENODATA;
|
||||
goto err;
|
||||
}
|
||||
@ -279,9 +351,7 @@ err:
|
||||
static int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab,
|
||||
struct ath11k_board_data *bd)
|
||||
{
|
||||
bd->fw = ath11k_fetch_fw_file(ab,
|
||||
ab->hw_params.fw.dir,
|
||||
ATH11K_DEFAULT_BOARD_FILE);
|
||||
bd->fw = ath11k_core_firmware_request(ab, ATH11K_DEFAULT_BOARD_FILE);
|
||||
if (IS_ERR(bd->fw))
|
||||
return PTR_ERR(bd->fw);
|
||||
|
||||
@ -557,6 +627,23 @@ int ath11k_core_qmi_firmware_ready(struct ath11k_base *ab)
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (ath11k_crypto_mode) {
|
||||
case ATH11K_CRYPT_MODE_SW:
|
||||
set_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);
|
||||
set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
|
||||
break;
|
||||
case ATH11K_CRYPT_MODE_HW:
|
||||
clear_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags);
|
||||
clear_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
|
||||
break;
|
||||
default:
|
||||
ath11k_info(ab, "invalid crypto_mode: %d\n", ath11k_crypto_mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ath11k_frame_mode == ATH11K_HW_TXRX_RAW)
|
||||
set_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags);
|
||||
|
||||
mutex_lock(&ab->core_lock);
|
||||
ret = ath11k_core_start(ab, ATH11K_FIRMWARE_MODE_NORMAL);
|
||||
if (ret) {
|
||||
@ -706,7 +793,7 @@ static void ath11k_core_restart(struct work_struct *work)
|
||||
break;
|
||||
case ATH11K_STATE_RESTARTED:
|
||||
ar->state = ATH11K_STATE_WEDGED;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case ATH11K_STATE_WEDGED:
|
||||
ath11k_warn(ab,
|
||||
"device is wedged, will not restart radio %d\n", i);
|
||||
@ -717,12 +804,55 @@ static void ath11k_core_restart(struct work_struct *work)
|
||||
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 rproc *prproc;
|
||||
phandle rproc_phandle;
|
||||
int ret;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_REMOTEPROC))
|
||||
return 0;
|
||||
|
||||
if (ab->bus_params.mhi_support)
|
||||
return 0;
|
||||
|
||||
if (of_property_read_u32(dev->of_node, "qcom,rproc", &rproc_phandle)) {
|
||||
ath11k_err(ab, "failed to get q6_rproc handle\n");
|
||||
@ -735,7 +865,19 @@ int ath11k_core_init(struct ath11k_base *ab)
|
||||
return -EINVAL;
|
||||
}
|
||||
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_core_soc_create(ab);
|
||||
if (ret) {
|
||||
@ -745,6 +887,7 @@ int ath11k_core_init(struct ath11k_base *ab)
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_init);
|
||||
|
||||
void ath11k_core_deinit(struct ath11k_base *ab)
|
||||
{
|
||||
@ -759,14 +902,17 @@ void ath11k_core_deinit(struct ath11k_base *ab)
|
||||
ath11k_mac_destroy(ab);
|
||||
ath11k_core_soc_destroy(ab);
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_deinit);
|
||||
|
||||
void ath11k_core_free(struct ath11k_base *ab)
|
||||
{
|
||||
kfree(ab);
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_free);
|
||||
|
||||
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;
|
||||
|
||||
@ -789,6 +935,8 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size,
|
||||
INIT_WORK(&ab->restart_work, ath11k_core_restart);
|
||||
timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0);
|
||||
ab->dev = dev;
|
||||
ab->bus_params = *bus_params;
|
||||
ab->hif.bus = bus;
|
||||
|
||||
return ab;
|
||||
|
||||
@ -796,3 +944,7 @@ err_sc_free:
|
||||
kfree(ab);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_core_alloc);
|
||||
|
||||
MODULE_DESCRIPTION("Core module for Qualcomm Atheros 802.11ax wireless LAN cards.");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
@ -35,6 +35,8 @@
|
||||
|
||||
#define ATH11K_INVALID_HW_MAC_ID 0xFF
|
||||
|
||||
extern unsigned int ath11k_frame_mode;
|
||||
|
||||
enum ath11k_supported_bw {
|
||||
ATH11K_BW_20 = 0,
|
||||
ATH11K_BW_40 = 1,
|
||||
@ -54,6 +56,13 @@ enum wme_ac {
|
||||
#define ATH11K_VHT_MCS_MAX 9
|
||||
#define ATH11K_HE_MCS_MAX 11
|
||||
|
||||
enum ath11k_crypt_mode {
|
||||
/* Only use hardware crypto engine */
|
||||
ATH11K_CRYPT_MODE_HW,
|
||||
/* Only use software crypto */
|
||||
ATH11K_CRYPT_MODE_SW,
|
||||
};
|
||||
|
||||
static inline enum wme_ac ath11k_tid_to_ac(u32 tid)
|
||||
{
|
||||
return (((tid == 0) || (tid == 3)) ? WME_AC_BE :
|
||||
@ -90,6 +99,8 @@ struct ath11k_skb_rxcb {
|
||||
|
||||
enum ath11k_hw_rev {
|
||||
ATH11K_HW_IPQ8074,
|
||||
ATH11K_HW_QCA6390_HW20,
|
||||
ATH11K_HW_IPQ6018_HW10,
|
||||
};
|
||||
|
||||
enum ath11k_firmware_mode {
|
||||
@ -101,18 +112,8 @@ enum ath11k_firmware_mode {
|
||||
};
|
||||
|
||||
#define ATH11K_IRQ_NUM_MAX 52
|
||||
#define ATH11K_EXT_IRQ_GRP_NUM_MAX 11
|
||||
#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_base *ab;
|
||||
u32 irqs[ATH11K_EXT_IRQ_NUM_MAX];
|
||||
@ -226,6 +227,7 @@ struct ath11k_vif {
|
||||
int txpower;
|
||||
bool rsnie_present;
|
||||
bool wpaie_present;
|
||||
struct ieee80211_chanctx_conf chanctx;
|
||||
};
|
||||
|
||||
struct ath11k_vif_iter {
|
||||
@ -554,6 +556,7 @@ struct ath11k {
|
||||
};
|
||||
|
||||
struct ath11k_band_cap {
|
||||
u32 phy_id;
|
||||
u32 max_bw_supported;
|
||||
u32 ht_cap_info;
|
||||
u32 he_cap_info[2];
|
||||
@ -589,6 +592,13 @@ struct ath11k_board_data {
|
||||
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 */
|
||||
#define IPQ8074_CC_FREQ_HERTZ 320000
|
||||
|
||||
@ -651,6 +661,7 @@ struct ath11k_base {
|
||||
unsigned long mem_len;
|
||||
|
||||
struct {
|
||||
enum ath11k_bus bus;
|
||||
const struct ath11k_hif_ops *ops;
|
||||
} hif;
|
||||
|
||||
@ -677,7 +688,10 @@ struct ath11k_base {
|
||||
u32 ext_service_bitmap[WMI_SERVICE_EXT_BM_SIZE];
|
||||
bool pdevs_macaddr_valid;
|
||||
int bd_api;
|
||||
|
||||
struct ath11k_hw_params hw_params;
|
||||
struct ath11k_bus_params bus_params;
|
||||
|
||||
const struct firmware *cal_file;
|
||||
|
||||
/* Below regd's are protected by ab->data_lock */
|
||||
@ -841,6 +855,13 @@ struct ath11k_fw_stats_bcn {
|
||||
u32 tx_bcn_outage_cnt;
|
||||
};
|
||||
|
||||
extern const struct ce_pipe_config ath11k_target_ce_config_wlan_ipq8074[];
|
||||
extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq8074[];
|
||||
extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq6018[];
|
||||
|
||||
extern const struct ce_pipe_config ath11k_target_ce_config_wlan_qca6390[];
|
||||
extern const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_qca6390[];
|
||||
|
||||
void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id);
|
||||
void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id,
|
||||
u8 *mac_addr, u16 ast_hash);
|
||||
@ -850,17 +871,21 @@ struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab,
|
||||
const u8 *addr);
|
||||
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_pre_init(struct ath11k_base *ab);
|
||||
int ath11k_core_init(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,
|
||||
enum ath11k_bus bus);
|
||||
enum ath11k_bus bus,
|
||||
const struct ath11k_bus_params *bus_params);
|
||||
void ath11k_core_free(struct ath11k_base *ath11k);
|
||||
int ath11k_core_fetch_bdf(struct ath11k_base *ath11k,
|
||||
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);
|
||||
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)
|
||||
{
|
||||
@ -894,4 +919,30 @@ static inline struct ath11k_vif *ath11k_vif_to_arvif(struct ieee80211_vif *vif)
|
||||
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_ */
|
||||
|
@ -168,7 +168,7 @@ int ath11k_dbring_buf_setup(struct ath11k *ar,
|
||||
|
||||
srng = &ab->hal.srng_list[ring->refill_srng.ring_id];
|
||||
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_align = db_cap->min_buf_align;
|
||||
|
@ -62,6 +62,7 @@ void ath11k_info(struct ath11k_base *ab, const char *fmt, ...)
|
||||
/* TODO: Trace the log */
|
||||
va_end(args);
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_info);
|
||||
|
||||
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 */
|
||||
va_end(args);
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_err);
|
||||
|
||||
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 */
|
||||
va_end(args);
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_warn);
|
||||
|
||||
#ifdef CONFIG_ATH11K_DEBUG
|
||||
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);
|
||||
}
|
||||
EXPORT_SYMBOL(__ath11k_dbg);
|
||||
|
||||
void ath11k_dbg_dump(struct ath11k_base *ab,
|
||||
enum ath11k_debug_mask mask,
|
||||
@ -138,6 +142,7 @@ void ath11k_dbg_dump(struct ath11k_base *ab,
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_dbg_dump);
|
||||
|
||||
#endif
|
||||
|
||||
@ -693,8 +698,10 @@ static ssize_t ath11k_write_extd_rx_stats(struct file *file,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath11k *ar = file->private_data;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct htt_rx_ring_tlv_filter tlv_filter = {0};
|
||||
u32 enable, rx_filter = 0, ring_id;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
if (kstrtouint_from_user(ubuf, count, 0, &enable))
|
||||
@ -737,14 +744,16 @@ static ssize_t ath11k_write_extd_rx_stats(struct file *file,
|
||||
|
||||
ar->debug.rx_filter = tlv_filter.rx_filter;
|
||||
|
||||
ring_id = ar->dp.rx_mon_status_refill_ring.refill_buf_ring.ring_id;
|
||||
ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
|
||||
HAL_RXDMA_MONITOR_STATUS,
|
||||
DP_RX_BUFFER_SIZE, &tlv_filter);
|
||||
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,
|
||||
HAL_RXDMA_MONITOR_STATUS,
|
||||
DP_RX_BUFFER_SIZE, &tlv_filter);
|
||||
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
|
||||
goto exit;
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
ar->debug.extd_rx_stats = enable;
|
||||
@ -995,10 +1004,11 @@ static ssize_t ath11k_write_pktlog_filter(struct file *file,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath11k *ar = file->private_data;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct htt_rx_ring_tlv_filter tlv_filter = {0};
|
||||
u32 rx_filter = 0, ring_id, filter, mode;
|
||||
u8 buf[128] = {0};
|
||||
int ret;
|
||||
int i, ret;
|
||||
ssize_t rc;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
@ -1079,16 +1089,20 @@ static ssize_t ath11k_write_pktlog_filter(struct file *file,
|
||||
HTT_RX_FP_DATA_FILTER_FLASG3;
|
||||
}
|
||||
|
||||
ring_id = ar->dp.rx_mon_status_refill_ring.refill_buf_ring.ring_id;
|
||||
ret = ath11k_dp_tx_htt_rx_filter_setup(ar->ab, ring_id, ar->dp.mac_id,
|
||||
HAL_RXDMA_MONITOR_STATUS,
|
||||
DP_RX_BUFFER_SIZE, &tlv_filter);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to set rx filter for monitor status ring\n");
|
||||
goto out;
|
||||
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(ab, ring_id,
|
||||
ar->dp.mac_id + i,
|
||||
HAL_RXDMA_MONITOR_STATUS,
|
||||
DP_RX_BUFFER_SIZE, &tlv_filter);
|
||||
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to set rx filter for monitor 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"));
|
||||
|
||||
ar->debug.pktlog_filter = filter;
|
||||
|
@ -25,6 +25,9 @@ enum ath11k_debug_mask {
|
||||
ATH11K_DBG_REG = 0x00000200,
|
||||
ATH11K_DBG_TESTMODE = 0x00000400,
|
||||
ATH11k_DBG_HAL = 0x00000800,
|
||||
ATH11K_DBG_PCI = 0x00001000,
|
||||
ATH11K_DBG_DP_TX = 0x00001000,
|
||||
ATH11K_DBG_DP_RX = 0x00002000,
|
||||
ATH11K_DBG_ANY = 0xffffffff,
|
||||
};
|
||||
|
||||
|
@ -3895,50 +3895,6 @@ static inline void htt_print_backpressure_stats_tlv_v(const u32 *tag_buf,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void htt_htt_stats_debug_dump(const u32 *tag_buf,
|
||||
struct debug_htt_stats_req *stats_req)
|
||||
{
|
||||
u8 *buf = stats_req->buf;
|
||||
u32 len = stats_req->buf_len;
|
||||
u32 buf_len = ATH11K_HTT_STATS_BUF_SIZE;
|
||||
u32 tlv_len = 0, i = 0, word_len = 0;
|
||||
|
||||
tlv_len = FIELD_GET(HTT_TLV_LEN, *tag_buf) + HTT_TLV_HDR_LEN;
|
||||
word_len = (tlv_len % 4) == 0 ? (tlv_len / 4) : ((tlv_len / 4) + 1);
|
||||
len += HTT_DBG_OUT(buf + len, buf_len - len,
|
||||
"============================================");
|
||||
len += HTT_DBG_OUT(buf + len, buf_len - len,
|
||||
"HKDBG TLV DUMP: (tag_len=%u bytes, words=%u)",
|
||||
tlv_len, word_len);
|
||||
|
||||
for (i = 0; i + 3 < word_len; i += 4) {
|
||||
len += HTT_DBG_OUT(buf + len, buf_len - len,
|
||||
"0x%08x 0x%08x 0x%08x 0x%08x",
|
||||
tag_buf[i], tag_buf[i + 1],
|
||||
tag_buf[i + 2], tag_buf[i + 3]);
|
||||
}
|
||||
|
||||
if (i + 3 == word_len) {
|
||||
len += HTT_DBG_OUT(buf + len, buf_len - len, "0x%08x 0x%08x 0x%08x ",
|
||||
tag_buf[i], tag_buf[i + 1], tag_buf[i + 2]);
|
||||
} else if (i + 2 == word_len) {
|
||||
len += HTT_DBG_OUT(buf + len, buf_len - len, "0x%08x 0x%08x ",
|
||||
tag_buf[i], tag_buf[i + 1]);
|
||||
} else if (i + 1 == word_len) {
|
||||
len += HTT_DBG_OUT(buf + len, buf_len - len, "0x%08x ",
|
||||
tag_buf[i]);
|
||||
}
|
||||
len += HTT_DBG_OUT(buf + len, buf_len - len,
|
||||
"============================================");
|
||||
|
||||
if (len >= buf_len)
|
||||
buf[buf_len - 1] = 0;
|
||||
else
|
||||
buf[len] = 0;
|
||||
|
||||
stats_req->buf_len = len;
|
||||
}
|
||||
|
||||
static int ath11k_dbg_htt_ext_stats_parse(struct ath11k_base *ab,
|
||||
u16 tag, u16 len, const void *tag_buf,
|
||||
void *user_data)
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "core.h"
|
||||
#include "dp_tx.h"
|
||||
#include "hal_tx.h"
|
||||
#include "hif.h"
|
||||
#include "debug.h"
|
||||
#include "dp_rx.h"
|
||||
#include "peer.h"
|
||||
@ -106,13 +107,120 @@ void ath11k_dp_srng_cleanup(struct ath11k_base *ab, struct dp_srng *ring)
|
||||
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,
|
||||
enum hal_ring_type type, int ring_num,
|
||||
int mac_id, int num_entries)
|
||||
{
|
||||
struct hal_srng_params params = { 0 };
|
||||
int entry_sz = ath11k_hal_srng_get_entrysize(type);
|
||||
int max_entries = ath11k_hal_srng_get_max_entries(type);
|
||||
int entry_sz = ath11k_hal_srng_get_entrysize(ab, type);
|
||||
int max_entries = ath11k_hal_srng_get_max_entries(ab, type);
|
||||
int ret;
|
||||
|
||||
if (max_entries < 0 || entry_sz < 0)
|
||||
@ -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_paddr = ring->paddr;
|
||||
params.num_entries = num_entries;
|
||||
ath11k_dp_srng_msi_setup(ab, ¶ms, type, ring_num + mac_id);
|
||||
|
||||
switch (type) {
|
||||
case HAL_REO_DST:
|
||||
@ -159,7 +268,7 @@ int ath11k_dp_srng_setup(struct ath11k_base *ab, struct dp_srng *ring,
|
||||
break;
|
||||
}
|
||||
/* follow through when ring_num >= 3 */
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case HAL_REO_EXCEPTION:
|
||||
case HAL_REO_REINJECT:
|
||||
case HAL_REO_CMD:
|
||||
@ -367,7 +476,7 @@ static int ath11k_dp_scatter_idle_link_desc_setup(struct ath11k_base *ab,
|
||||
u32 end_offset;
|
||||
|
||||
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);
|
||||
|
||||
if (num_scatter_buf > DP_IDLE_SCATTER_BUFS_MAX)
|
||||
@ -565,7 +674,7 @@ int ath11k_dp_link_desc_setup(struct ath11k_base *ab,
|
||||
return ret;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Setup scatter desc list when the total memory requirement is more */
|
||||
@ -622,16 +731,16 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
|
||||
struct napi_struct *napi = &irq_grp->napi;
|
||||
int grp_id = irq_grp->grp_id;
|
||||
int work_done = 0;
|
||||
int i = 0;
|
||||
int i = 0, j;
|
||||
int tot_work_done = 0;
|
||||
|
||||
while (ath11k_tx_ring_mask[grp_id] >> i) {
|
||||
if (ath11k_tx_ring_mask[grp_id] & BIT(i))
|
||||
while (ab->hw_params.ring_mask->tx[grp_id] >> i) {
|
||||
if (ab->hw_params.ring_mask->tx[grp_id] & BIT(i))
|
||||
ath11k_dp_tx_completion_handler(ab, 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);
|
||||
budget -= work_done;
|
||||
tot_work_done += work_done;
|
||||
@ -639,7 +748,7 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
|
||||
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,
|
||||
napi,
|
||||
budget);
|
||||
@ -650,8 +759,8 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (ath11k_rx_ring_mask[grp_id]) {
|
||||
i = fls(ath11k_rx_ring_mask[grp_id]) - 1;
|
||||
if (ab->hw_params.ring_mask->rx[grp_id]) {
|
||||
i = fls(ab->hw_params.ring_mask->rx[grp_id]) - 1;
|
||||
work_done = ath11k_dp_process_rx(ab, i, napi,
|
||||
budget);
|
||||
budget -= work_done;
|
||||
@ -660,41 +769,52 @@ int ath11k_dp_service_srng(struct ath11k_base *ab,
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (rx_mon_status_ring_mask[grp_id]) {
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
if (rx_mon_status_ring_mask[grp_id] & BIT(i)) {
|
||||
work_done =
|
||||
ath11k_dp_rx_process_mon_rings(ab,
|
||||
i, napi,
|
||||
budget);
|
||||
budget -= work_done;
|
||||
tot_work_done += work_done;
|
||||
if (ab->hw_params.ring_mask->rx_mon_status[grp_id]) {
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
for (j = 0; j < ab->hw_params.num_rxmda_per_pdev; j++) {
|
||||
int id = i * ab->hw_params.num_rxmda_per_pdev + j;
|
||||
|
||||
if (ab->hw_params.ring_mask->rx_mon_status[grp_id] &
|
||||
BIT(id)) {
|
||||
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);
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
if (ath11k_rxdma2host_ring_mask[grp_id] & BIT(i)) {
|
||||
work_done = ath11k_dp_process_rxdma_err(ab, i, budget);
|
||||
budget -= work_done;
|
||||
tot_work_done += work_done;
|
||||
}
|
||||
for (j = 0; j < ab->hw_params.num_rxmda_per_pdev; j++) {
|
||||
int id = i * ab->hw_params.num_rxmda_per_pdev + j;
|
||||
|
||||
if (budget <= 0)
|
||||
goto done;
|
||||
if (ab->hw_params.ring_mask->rxdma2host[grp_id] & BIT(id)) {
|
||||
work_done = ath11k_dp_process_rxdma_err(ab, id, budget);
|
||||
budget -= work_done;
|
||||
tot_work_done += work_done;
|
||||
}
|
||||
|
||||
if (ath11k_host2rxdma_ring_mask[grp_id] & BIT(i)) {
|
||||
struct ath11k_pdev_dp *dp = &ab->pdevs[i].ar->dp;
|
||||
struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
|
||||
if (budget <= 0)
|
||||
goto done;
|
||||
|
||||
ath11k_dp_rxbufs_replenish(ab, i, rx_ring, 0,
|
||||
HAL_RX_BUF_RBM_SW3_BM,
|
||||
GFP_ATOMIC);
|
||||
if (ab->hw_params.ring_mask->host2rxdma[grp_id] & BIT(id)) {
|
||||
struct ath11k *ar = ath11k_ab_to_ar(ab, id);
|
||||
struct ath11k_pdev_dp *dp = &ar->dp;
|
||||
struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
|
||||
|
||||
ath11k_dp_rxbufs_replenish(ab, id, rx_ring, 0,
|
||||
HAL_RX_BUF_RBM_SW3_BM,
|
||||
GFP_ATOMIC);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* TODO: Implement handler for other interrupts */
|
||||
@ -722,6 +842,7 @@ void ath11k_dp_pdev_pre_alloc(struct ath11k_base *ab)
|
||||
struct ath11k *ar;
|
||||
struct ath11k_pdev_dp *dp;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
ar = ab->pdevs[i].ar;
|
||||
@ -731,8 +852,10 @@ void ath11k_dp_pdev_pre_alloc(struct ath11k_base *ab)
|
||||
spin_lock_init(&dp->rx_refill_buf_ring.idr_lock);
|
||||
atomic_set(&dp->num_tx_pending, 0);
|
||||
init_waitqueue_head(&dp->tx_empty_waitq);
|
||||
idr_init(&dp->rx_mon_status_refill_ring.bufs_idr);
|
||||
spin_lock_init(&dp->rx_mon_status_refill_ring.idr_lock);
|
||||
for (j = 0; j < ab->hw_params.num_rxmda_per_pdev; j++) {
|
||||
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);
|
||||
spin_lock_init(&dp->rxdma_mon_buf_ring.idr_lock);
|
||||
}
|
||||
@ -797,13 +920,20 @@ int ath11k_dp_htt_connect(struct ath11k_dp *dp)
|
||||
|
||||
static void ath11k_dp_update_vdev_search(struct ath11k_vif *arvif)
|
||||
{
|
||||
/* For STA mode, enable address search index,
|
||||
* tcl uses ast_hash value in the descriptor.
|
||||
/* When v2_map_support is true:for STA mode, enable address
|
||||
* 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) {
|
||||
case WMI_VDEV_TYPE_STA:
|
||||
arvif->hal_addr_search_flags = HAL_TX_ADDRX_EN;
|
||||
arvif->search_type = HAL_TX_ADDR_SEARCH_INDEX;
|
||||
if (arvif->ar->ab->hw_params.htt_peer_map_v2) {
|
||||
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;
|
||||
case WMI_VDEV_TYPE_AP:
|
||||
case WMI_VDEV_TYPE_IBSS:
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include "hal_rx.h"
|
||||
|
||||
#define MAX_RXDMA_PER_PDEV 2
|
||||
|
||||
struct ath11k_base;
|
||||
struct ath11k_peer;
|
||||
struct ath11k_dp;
|
||||
@ -142,12 +144,13 @@ struct ath11k_pdev_dp {
|
||||
atomic_t num_tx_pending;
|
||||
wait_queue_head_t tx_empty_waitq;
|
||||
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_desc_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 ath11k_mon_data mon_data;
|
||||
};
|
||||
@ -936,11 +939,13 @@ struct htt_rx_ring_tlv_filter {
|
||||
|
||||
enum htt_t2h_msg_type {
|
||||
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_PKTLOG = 0x8,
|
||||
HTT_T2H_MSG_TYPE_SEC_IND = 0xb,
|
||||
HTT_T2H_MSG_TYPE_PEER_MAP = 0x1e,
|
||||
HTT_T2H_MSG_TYPE_PEER_UNMAP = 0x1f,
|
||||
HTT_T2H_MSG_TYPE_PEER_MAP2 = 0x1e,
|
||||
HTT_T2H_MSG_TYPE_PEER_UNMAP2 = 0x1f,
|
||||
HTT_T2H_MSG_TYPE_PPDU_STATS_IND = 0x1d,
|
||||
HTT_T2H_MSG_TYPE_EXT_STATS_CONF = 0x1c,
|
||||
HTT_T2H_MSG_TYPE_BKPRESSURE_EVENT_IND = 0x24,
|
||||
|
@ -375,7 +375,13 @@ static int ath11k_dp_rxdma_buf_ring_free(struct ath11k *ar,
|
||||
idr_destroy(&rx_ring->bufs_idr);
|
||||
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);
|
||||
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,
|
||||
|
||||
idr_destroy(&rx_ring->bufs_idr);
|
||||
spin_unlock_bh(&rx_ring->idr_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_dp_rxdma_pdev_buf_free(struct ath11k *ar)
|
||||
{
|
||||
struct ath11k_pdev_dp *dp = &ar->dp;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct dp_rxdma_ring *rx_ring = &dp->rx_refill_buf_ring;
|
||||
int i;
|
||||
|
||||
ath11k_dp_rxdma_buf_ring_free(ar, rx_ring);
|
||||
|
||||
rx_ring = &dp->rxdma_mon_buf_ring;
|
||||
ath11k_dp_rxdma_buf_ring_free(ar, rx_ring);
|
||||
|
||||
rx_ring = &dp->rx_mon_status_refill_ring;
|
||||
ath11k_dp_rxdma_buf_ring_free(ar, rx_ring);
|
||||
for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
|
||||
rx_ring = &dp->rx_mon_status_refill_ring[i];
|
||||
ath11k_dp_rxdma_buf_ring_free(ar, rx_ring);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -416,7 +428,7 @@ static int ath11k_dp_rxdma_ring_buf_setup(struct ath11k *ar,
|
||||
int num_entries;
|
||||
|
||||
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;
|
||||
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,
|
||||
static int ath11k_dp_rxdma_pdev_buf_setup(struct ath11k *ar)
|
||||
{
|
||||
struct ath11k_pdev_dp *dp = &ar->dp;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
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);
|
||||
|
||||
rx_ring = &dp->rxdma_mon_buf_ring;
|
||||
ath11k_dp_rxdma_ring_buf_setup(ar, rx_ring, HAL_RXDMA_MONITOR_BUF);
|
||||
if (ar->ab->hw_params.rxdma1_enable) {
|
||||
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;
|
||||
ath11k_dp_rxdma_ring_buf_setup(ar, rx_ring, HAL_RXDMA_MONITOR_STATUS);
|
||||
for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
|
||||
rx_ring = &dp->rx_mon_status_refill_ring[i];
|
||||
ath11k_dp_rxdma_ring_buf_setup(ar, rx_ring, HAL_RXDMA_MONITOR_STATUS);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
struct ath11k_pdev_dp *dp = &ar->dp;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
int i;
|
||||
|
||||
ath11k_dp_srng_cleanup(ar->ab, &dp->rx_refill_buf_ring.refill_buf_ring);
|
||||
ath11k_dp_srng_cleanup(ar->ab, &dp->rxdma_err_dst_ring);
|
||||
ath11k_dp_srng_cleanup(ar->ab, &dp->rx_mon_status_refill_ring.refill_buf_ring);
|
||||
ath11k_dp_srng_cleanup(ar->ab, &dp->rxdma_mon_buf_ring.refill_buf_ring);
|
||||
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(ab, &dp->rxdma_err_dst_ring[i]);
|
||||
ath11k_dp_srng_cleanup(ab,
|
||||
&dp->rx_mon_status_refill_ring[i].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)
|
||||
@ -486,7 +514,9 @@ err_reo_cleanup:
|
||||
static int ath11k_dp_rx_pdev_srng_alloc(struct ath11k *ar)
|
||||
{
|
||||
struct ath11k_pdev_dp *dp = &ar->dp;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
struct dp_srng *srng = NULL;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
ret = ath11k_dp_srng_setup(ar->ab,
|
||||
@ -498,24 +528,50 @@ static int ath11k_dp_rx_pdev_srng_alloc(struct ath11k *ar)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath11k_dp_srng_setup(ar->ab, &dp->rxdma_err_dst_ring,
|
||||
HAL_RXDMA_DST, 0, dp->mac_id,
|
||||
DP_RXDMA_ERR_DST_RING_SIZE);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to setup rxdma_err_dst_ring\n");
|
||||
return ret;
|
||||
if (ar->ab->hw_params.rx_mac_buf_ring) {
|
||||
for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
|
||||
ret = ath11k_dp_srng_setup(ar->ab,
|
||||
&dp->rx_mac_buf_ring[i],
|
||||
HAL_RXDMA_BUF, 1,
|
||||
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;
|
||||
ret = ath11k_dp_srng_setup(ar->ab,
|
||||
srng,
|
||||
HAL_RXDMA_MONITOR_STATUS, 0, dp->mac_id,
|
||||
DP_RXDMA_MON_STATUS_RING_SIZE);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab,
|
||||
"failed to setup rx_mon_status_refill_ring\n");
|
||||
return ret;
|
||||
for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
|
||||
ret = ath11k_dp_srng_setup(ar->ab, &dp->rxdma_err_dst_ring[i],
|
||||
HAL_RXDMA_DST, 0, dp->mac_id + i,
|
||||
DP_RXDMA_ERR_DST_RING_SIZE);
|
||||
if (ret) {
|
||||
ath11k_warn(ar->ab, "failed to setup rxdma_err_dst_ring %d\n", i);
|
||||
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,
|
||||
&dp->rxdma_mon_buf_ring.refill_buf_ring,
|
||||
HAL_RXDMA_MONITOR_BUF, 0, dp->mac_id,
|
||||
@ -1569,6 +1625,17 @@ void ath11k_dp_htt_htc_t2h_msg_handler(struct ath11k_base *ab,
|
||||
complete(&dp->htt_tgt_version_received);
|
||||
break;
|
||||
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,
|
||||
resp->peer_map_ev.info);
|
||||
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,
|
||||
ath11k_peer_map_event(ab, vdev_id, peer_id, mac_addr, ast_hash);
|
||||
break;
|
||||
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,
|
||||
resp->peer_unmap_ev.info);
|
||||
ath11k_peer_unmap_event(ab, peer_id);
|
||||
@ -2065,8 +2133,6 @@ static void ath11k_dp_rx_h_mpdu(struct ath11k *ar,
|
||||
mcast = is_multicast_ether_addr(hdr->addr1);
|
||||
fill_crypto_hdr = mcast;
|
||||
|
||||
is_decrypted = ath11k_dp_rx_h_attn_is_decrypted(rx_desc);
|
||||
|
||||
spin_lock_bh(&ar->ab->base_lock);
|
||||
peer = ath11k_peer_find_by_addr(ar->ab, hdr->addr2);
|
||||
if (peer) {
|
||||
@ -2080,6 +2146,8 @@ static void ath11k_dp_rx_h_mpdu(struct ath11k *ar,
|
||||
spin_unlock_bh(&ar->ab->base_lock);
|
||||
|
||||
err_bitmap = ath11k_dp_rx_h_attn_mpdu_err(rx_desc);
|
||||
if (enctype != HAL_ENCRYPT_TYPE_OPEN && !err_bitmap)
|
||||
is_decrypted = ath11k_dp_rx_h_attn_is_decrypted(rx_desc);
|
||||
|
||||
/* Clear per-MPDU flags while leaving per-PPDU flags intact */
|
||||
rx_status->flag &= ~(RX_FLAG_FAILED_FCS_CRC |
|
||||
@ -2282,6 +2350,9 @@ static void ath11k_dp_rx_deliver_msdu(struct ath11k *ar, struct napi_struct *nap
|
||||
!!(status->flag & RX_FLAG_MMIC_ERROR),
|
||||
!!(status->flag & RX_FLAG_AMSDU_MORE));
|
||||
|
||||
ath11k_dbg_dump(ar->ab, ATH11K_DBG_DP_RX, NULL, "dp rx msdu: ",
|
||||
msdu->data, msdu->len);
|
||||
|
||||
/* TODO: trace rx packet */
|
||||
|
||||
ieee80211_rx_napi(ar->hw, NULL, msdu, napi);
|
||||
@ -2719,20 +2790,25 @@ fail_desc_get:
|
||||
static int ath11k_dp_rx_reap_mon_status_ring(struct ath11k_base *ab, int mac_id,
|
||||
int *budget, struct sk_buff_head *skb_list)
|
||||
{
|
||||
struct ath11k *ar = ab->pdevs[mac_id].ar;
|
||||
struct ath11k_pdev_dp *dp = &ar->dp;
|
||||
struct dp_rxdma_ring *rx_ring = &dp->rx_mon_status_refill_ring;
|
||||
struct ath11k *ar;
|
||||
struct ath11k_pdev_dp *dp;
|
||||
struct dp_rxdma_ring *rx_ring;
|
||||
struct hal_srng *srng;
|
||||
void *rx_mon_status_desc;
|
||||
struct sk_buff *skb;
|
||||
struct ath11k_skb_rxcb *rxcb;
|
||||
struct hal_tlv_hdr *tlv;
|
||||
u32 cookie;
|
||||
int buf_id;
|
||||
int buf_id, srng_id;
|
||||
dma_addr_t paddr;
|
||||
u8 rbm;
|
||||
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];
|
||||
|
||||
spin_lock_bh(&srng->lock);
|
||||
@ -2813,7 +2889,7 @@ move_next:
|
||||
int ath11k_dp_rx_process_mon_status(struct ath11k_base *ab, int mac_id,
|
||||
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;
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff_head skb_list;
|
||||
@ -3709,8 +3785,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
|
||||
* after incrementing the replay counters.
|
||||
*/
|
||||
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
default:
|
||||
/* TODO: Review other errors and process them to mac80211
|
||||
* as appropriate.
|
||||
@ -3820,7 +3895,7 @@ int ath11k_dp_rx_process_wbm_err(struct ath11k_base *ab,
|
||||
int total_num_buffs_reaped = 0;
|
||||
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]);
|
||||
|
||||
srng = &ab->hal.srng_list[dp->rx_rel_ring.ring_id];
|
||||
@ -3923,9 +3998,9 @@ done:
|
||||
|
||||
int ath11k_dp_process_rxdma_err(struct ath11k_base *ab, int mac_id, int budget)
|
||||
{
|
||||
struct ath11k *ar = ab->pdevs[mac_id].ar;
|
||||
struct dp_srng *err_ring = &ar->dp.rxdma_err_dst_ring;
|
||||
struct dp_rxdma_ring *rx_ring = &ar->dp.rx_refill_buf_ring;
|
||||
struct ath11k *ar;
|
||||
struct dp_srng *err_ring;
|
||||
struct dp_rxdma_ring *rx_ring;
|
||||
struct dp_link_desc_bank *link_desc_banks = ab->dp.link_desc_banks;
|
||||
struct hal_srng *srng;
|
||||
u32 msdu_cookies[HAL_NUM_RX_MSDUS_PER_LINK_DESC];
|
||||
@ -3944,6 +4019,11 @@ int ath11k_dp_process_rxdma_err(struct ath11k_base *ab, int mac_id, int budget)
|
||||
int i;
|
||||
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];
|
||||
|
||||
spin_lock_bh(&srng->lock);
|
||||
@ -4097,6 +4177,7 @@ int ath11k_dp_rx_pdev_alloc(struct ath11k_base *ab, int mac_id)
|
||||
struct ath11k *ar = ab->pdevs[mac_id].ar;
|
||||
struct ath11k_pdev_dp *dp = &ar->dp;
|
||||
u32 ring_id;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
ret = ath11k_dp_rx_pdev_srng_alloc(ar);
|
||||
@ -4119,14 +4200,33 @@ int ath11k_dp_rx_pdev_alloc(struct ath11k_base *ab, int mac_id)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ring_id = dp->rxdma_err_dst_ring.ring_id;
|
||||
ret = ath11k_dp_tx_htt_srng_setup(ab, ring_id, mac_id, HAL_RXDMA_DST);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "failed to configure rxdma_err_dest_ring %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
if (ab->hw_params.rx_mac_buf_ring) {
|
||||
for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
|
||||
ring_id = dp->rx_mac_buf_ring[i].ring_id;
|
||||
ret = ath11k_dp_tx_htt_srng_setup(ab, ring_id,
|
||||
mac_id + i, HAL_RXDMA_BUF);
|
||||
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;
|
||||
ret = ath11k_dp_tx_htt_srng_setup(ab, ring_id,
|
||||
mac_id, HAL_RXDMA_MONITOR_BUF);
|
||||
@ -4151,15 +4251,20 @@ int ath11k_dp_rx_pdev_alloc(struct ath11k_base *ab, int mac_id)
|
||||
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,
|
||||
HAL_RXDMA_MONITOR_STATUS);
|
||||
if (ret) {
|
||||
ath11k_warn(ab,
|
||||
"failed to configure mon_status_refill_ring %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
|
||||
config_refill_ring:
|
||||
for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
|
||||
ring_id = dp->rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
|
||||
ret = ath11k_dp_tx_htt_srng_setup(ab, ring_id, mac_id + i,
|
||||
HAL_RXDMA_MONITOR_STATUS);
|
||||
if (ret) {
|
||||
ath11k_warn(ab,
|
||||
"failed to configure mon_status_refill_ring%d %d\n",
|
||||
i, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -4777,7 +4882,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,
|
||||
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_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data;
|
||||
int num_buffs_reaped = 0;
|
||||
@ -4793,7 +4898,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,
|
||||
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;
|
||||
|
||||
if (test_bit(ATH11K_FLAG_MONITOR_ENABLED, &ar->monitor_flags))
|
||||
@ -4832,9 +4937,15 @@ int ath11k_dp_rx_pdev_mon_attach(struct ath11k *ar)
|
||||
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;
|
||||
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 =
|
||||
&ar->ab->hal.srng_list[dp->rxdma_mon_desc_ring.ring_id];
|
||||
|
||||
@ -4848,6 +4959,7 @@ int ath11k_dp_rx_pdev_mon_attach(struct ath11k *ar)
|
||||
pmon->mon_last_linkdesc_paddr = 0;
|
||||
pmon->mon_last_buf_cookie = DP_RX_DESC_COOKIE_MAX + 1;
|
||||
spin_lock_init(&pmon->mon_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,10 @@ static enum hal_tcl_encap_type
|
||||
ath11k_dp_tx_get_encap_type(struct ath11k_vif *arvif, struct sk_buff *skb)
|
||||
{
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
struct ath11k_base *ab = arvif->ar->ab;
|
||||
|
||||
if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags))
|
||||
return HAL_TCL_ENCAP_TYPE_RAW;
|
||||
|
||||
if (tx_info->control.flags & IEEE80211_TX_CTRL_HW_80211_ENCAP)
|
||||
return HAL_TCL_ENCAP_TYPE_ETHERNET;
|
||||
@ -79,6 +83,7 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
struct ath11k_dp *dp = &ab->dp;
|
||||
struct hal_tx_info ti = {0};
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
||||
struct ieee80211_key_conf *key = info->control.hw_key;
|
||||
struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB(skb);
|
||||
struct hal_srng *tcl_ring;
|
||||
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||
@ -110,7 +115,12 @@ int ath11k_dp_tx(struct ath11k *ar, struct ath11k_vif *arvif,
|
||||
|
||||
tcl_ring_sel:
|
||||
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);
|
||||
|
||||
tx_ring = &dp->tx_ring[ti.ring_id];
|
||||
@ -137,11 +147,17 @@ tcl_ring_sel:
|
||||
ti.encap_type = ath11k_dp_tx_get_encap_type(arvif, skb);
|
||||
ti.meta_data_flags = arvif->tcl_metadata;
|
||||
|
||||
if (info->control.hw_key)
|
||||
ti.encrypt_type =
|
||||
ath11k_dp_tx_get_encrypt_type(info->control.hw_key->cipher);
|
||||
else
|
||||
ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN;
|
||||
if (ti.encap_type == HAL_TCL_ENCAP_TYPE_RAW) {
|
||||
if (key) {
|
||||
ti.encrypt_type =
|
||||
ath11k_dp_tx_get_encrypt_type(key->cipher);
|
||||
|
||||
if (ieee80211_has_protected(hdr->frame_control))
|
||||
skb_put(skb, IEEE80211_CCMP_MIC_LEN);
|
||||
} else {
|
||||
ti.encrypt_type = HAL_ENCRYPT_TYPE_OPEN;
|
||||
}
|
||||
}
|
||||
|
||||
ti.addr_search_flags = arvif->hal_addr_search_flags;
|
||||
ti.search_type = arvif->search_type;
|
||||
@ -151,7 +167,8 @@ tcl_ring_sel:
|
||||
ti.bss_ast_hash = arvif->ast_hash;
|
||||
ti.dscp_tid_tbl_idx = 0;
|
||||
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL) {
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL &&
|
||||
ti.encap_type != HAL_TCL_ENCAP_TYPE_RAW) {
|
||||
ti.flags0 |= FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_IP4_CKSUM_EN, 1) |
|
||||
FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_UDP4_CKSUM_EN, 1) |
|
||||
FIELD_PREP(HAL_TCL_DATA_CMD_INFO1_UDP6_CKSUM_EN, 1) |
|
||||
@ -171,10 +188,11 @@ tcl_ring_sel:
|
||||
ath11k_dp_tx_encap_nwifi(skb);
|
||||
break;
|
||||
case HAL_TCL_ENCAP_TYPE_RAW:
|
||||
/* TODO: for CHECKSUM_PARTIAL case in raw mode, HW checksum offload
|
||||
* is not applicable, hence manual checksum calculation using
|
||||
* skb_checksum_help() is needed
|
||||
*/
|
||||
if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) {
|
||||
ret = -EINVAL;
|
||||
goto fail_remove_idr;
|
||||
}
|
||||
break;
|
||||
case HAL_TCL_ENCAP_TYPE_ETHERNET:
|
||||
/* no need to encap */
|
||||
break;
|
||||
@ -221,7 +239,8 @@ tcl_ring_sel:
|
||||
* checking this ring earlier for each pkt tx.
|
||||
* 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;
|
||||
ring_selector++;
|
||||
}
|
||||
@ -236,6 +255,9 @@ tcl_ring_sel:
|
||||
|
||||
spin_unlock_bh(&tcl_ring->lock);
|
||||
|
||||
ath11k_dbg_dump(ab, ATH11K_DBG_DP_TX, NULL, "dp tx msdu: ",
|
||||
skb->data, skb->len);
|
||||
|
||||
atomic_inc(&ar->dp.num_tx_pending);
|
||||
|
||||
return 0;
|
||||
@ -346,7 +368,6 @@ ath11k_dp_tx_process_htt_tx_complete(struct ath11k_base *ab,
|
||||
|
||||
wbm_status = FIELD_GET(HTT_TX_WBM_COMP_INFO0_STATUS,
|
||||
status_desc->info0);
|
||||
|
||||
switch (wbm_status) {
|
||||
case HAL_WBM_REL_HTT_TX_COMP_STATUS_OK:
|
||||
case HAL_WBM_REL_HTT_TX_COMP_STATUS_DROP:
|
||||
@ -633,14 +654,28 @@ ath11k_dp_tx_get_ring_id_type(struct ath11k_base *ab,
|
||||
switch (ring_type) {
|
||||
case HAL_RXDMA_BUF:
|
||||
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) ||
|
||||
ring_id == (HAL_SRNG_RING_ID_WMAC1_SW2RXDMA1_BUF +
|
||||
lmac_ring_id_offset))) {
|
||||
ret = -EINVAL;
|
||||
|
||||
/* for QCA6390, host fills rx buffer to fw and fw fills to
|
||||
* rxbuf ring for each rxdma
|
||||
*/
|
||||
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;
|
||||
case HAL_RXDMA_DST:
|
||||
*htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING;
|
||||
@ -720,7 +755,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 >>
|
||||
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)
|
||||
goto err_free;
|
||||
|
||||
@ -968,8 +1003,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)
|
||||
{
|
||||
struct ath11k_pdev_dp *dp = &ar->dp;
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
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;
|
||||
|
||||
@ -998,16 +1034,20 @@ int ath11k_dp_tx_htt_monitor_mode_ring_config(struct ath11k *ar, bool reset)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ring_id = dp->rx_mon_status_refill_ring.refill_buf_ring.ring_id;
|
||||
if (!reset)
|
||||
tlv_filter.rx_filter =
|
||||
HTT_RX_MON_FILTER_TLV_FLAGS_MON_STATUS_RING;
|
||||
else
|
||||
tlv_filter = ath11k_mac_mon_status_filter_default;
|
||||
for (i = 0; i < ab->hw_params.num_rxmda_per_pdev; i++) {
|
||||
ring_id = dp->rx_mon_status_refill_ring[i].refill_buf_ring.ring_id;
|
||||
if (!reset)
|
||||
tlv_filter.rx_filter =
|
||||
HTT_RX_MON_FILTER_TLV_FLAGS_MON_STATUS_RING;
|
||||
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;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include "hal_desc.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 */
|
||||
{ /* REO_DST */
|
||||
.start_ring_id = HAL_SRNG_RING_ID_REO2SW1,
|
||||
@ -16,14 +16,6 @@ static const struct hal_srng_config hw_srng_config[] = {
|
||||
.entry_size = sizeof(struct hal_reo_dest_ring) >> 2,
|
||||
.lmac_ring = false,
|
||||
.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,
|
||||
},
|
||||
{ /* REO_EXCEPTION */
|
||||
@ -36,10 +28,6 @@ static const struct hal_srng_config hw_srng_config[] = {
|
||||
.entry_size = sizeof(struct hal_reo_dest_ring) >> 2,
|
||||
.lmac_ring = false,
|
||||
.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,
|
||||
},
|
||||
{ /* REO_REINJECT */
|
||||
@ -48,10 +36,6 @@ static const struct hal_srng_config hw_srng_config[] = {
|
||||
.entry_size = sizeof(struct hal_reo_entrance_ring) >> 2,
|
||||
.lmac_ring = false,
|
||||
.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,
|
||||
},
|
||||
{ /* REO_CMD */
|
||||
@ -61,10 +45,6 @@ static const struct hal_srng_config hw_srng_config[] = {
|
||||
sizeof(struct hal_reo_get_queue_stats)) >> 2,
|
||||
.lmac_ring = false,
|
||||
.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,
|
||||
},
|
||||
{ /* REO_STATUS */
|
||||
@ -74,11 +54,6 @@ static const struct hal_srng_config hw_srng_config[] = {
|
||||
sizeof(struct hal_reo_get_queue_stats_status)) >> 2,
|
||||
.lmac_ring = false,
|
||||
.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,
|
||||
},
|
||||
{ /* TCL_DATA */
|
||||
@ -88,14 +63,6 @@ static const struct hal_srng_config hw_srng_config[] = {
|
||||
sizeof(struct hal_tcl_data_cmd)) >> 2,
|
||||
.lmac_ring = false,
|
||||
.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,
|
||||
},
|
||||
{ /* TCL_CMD */
|
||||
@ -105,10 +72,6 @@ static const struct hal_srng_config hw_srng_config[] = {
|
||||
sizeof(struct hal_tcl_gse_cmd)) >> 2,
|
||||
.lmac_ring = false,
|
||||
.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,
|
||||
},
|
||||
{ /* TCL_STATUS */
|
||||
@ -118,11 +81,6 @@ static const struct hal_srng_config hw_srng_config[] = {
|
||||
sizeof(struct hal_tcl_status_ring)) >> 2,
|
||||
.lmac_ring = false,
|
||||
.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,
|
||||
},
|
||||
{ /* CE_SRC */
|
||||
@ -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,
|
||||
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 val;
|
||||
|
||||
@ -371,7 +329,7 @@ static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab,
|
||||
|
||||
if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) {
|
||||
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);
|
||||
|
||||
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,
|
||||
HAL_ADDR_MSB_REG_SHIFT)) |
|
||||
HAL_REO1_RING_MSI1_BASE_MSB_MSI1_ENABLE;
|
||||
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,
|
||||
reg_base + HAL_REO1_RING_MSI1_DATA_OFFSET,
|
||||
reg_base + HAL_REO1_RING_MSI1_DATA_OFFSET(ab),
|
||||
srng->msi_data);
|
||||
}
|
||||
|
||||
@ -393,11 +351,11 @@ static void ath11k_hal_srng_dst_hw_init(struct ath11k_base *ab,
|
||||
HAL_ADDR_MSB_REG_SHIFT)) |
|
||||
FIELD_PREP(HAL_REO1_RING_BASE_MSB_RING_SIZE,
|
||||
(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) |
|
||||
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 */
|
||||
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,
|
||||
srng->entry_size));
|
||||
|
||||
ath11k_hif_write32(ab,
|
||||
reg_base + HAL_REO1_RING_PRODUCER_INT_SETUP_OFFSET,
|
||||
reg_base + HAL_REO1_RING_PRODUCER_INT_SETUP_OFFSET(ab),
|
||||
val);
|
||||
|
||||
hp_addr = hal->rdp.paddr +
|
||||
((unsigned long)srng->u.dst_ring.hp_addr -
|
||||
(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);
|
||||
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);
|
||||
|
||||
/* Initialize head and tail pointers to indicate ring is empty */
|
||||
reg_base = srng->hwreg_base[HAL_SRNG_REG_GRP_R2];
|
||||
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;
|
||||
|
||||
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,
|
||||
val |= HAL_REO1_RING_MISC_MSI_SWAP;
|
||||
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,
|
||||
@ -450,7 +408,7 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab,
|
||||
|
||||
if (srng->flags & HAL_SRNG_FLAGS_MSI_INTR) {
|
||||
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);
|
||||
|
||||
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,
|
||||
HAL_ADDR_MSB_REG_SHIFT)) |
|
||||
HAL_TCL1_RING_MSI1_BASE_MSB_MSI1_ENABLE;
|
||||
ath11k_hif_write32(ab, reg_base +
|
||||
HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET,
|
||||
HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET(ab),
|
||||
val);
|
||||
|
||||
ath11k_hif_write32(ab, reg_base +
|
||||
HAL_TCL1_RING_MSI1_DATA_OFFSET,
|
||||
HAL_TCL1_RING_MSI1_DATA_OFFSET(ab),
|
||||
srng->msi_data);
|
||||
}
|
||||
|
||||
@ -473,10 +431,10 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab,
|
||||
HAL_ADDR_MSB_REG_SHIFT)) |
|
||||
FIELD_PREP(HAL_TCL1_RING_BASE_MSB_RING_SIZE,
|
||||
(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);
|
||||
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 */
|
||||
/* 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,
|
||||
srng->entry_size));
|
||||
|
||||
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 = 0;
|
||||
@ -499,7 +457,7 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab,
|
||||
srng->u.src_ring.low_threshold);
|
||||
}
|
||||
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);
|
||||
|
||||
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,
|
||||
((unsigned long)srng->u.src_ring.tp_addr -
|
||||
(unsigned long)hal->rdp.vaddr);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -534,7 +492,7 @@ static void ath11k_hal_srng_src_hw_init(struct ath11k_base *ab,
|
||||
|
||||
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,
|
||||
@ -550,7 +508,7 @@ static int ath11k_hal_srng_get_ring_id(struct ath11k_base *ab,
|
||||
enum hal_ring_type type,
|
||||
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;
|
||||
|
||||
if (ring_num >= srng_config->max_rings) {
|
||||
@ -568,26 +526,26 @@ static int ath11k_hal_srng_get_ring_id(struct ath11k_base *ab,
|
||||
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))
|
||||
return -EINVAL;
|
||||
|
||||
srng_config = &hw_srng_config[ring_type];
|
||||
srng_config = &ab->hal.srng_config[ring_type];
|
||||
|
||||
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))
|
||||
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);
|
||||
}
|
||||
@ -1003,7 +961,7 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type,
|
||||
struct hal_srng_params *params)
|
||||
{
|
||||
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;
|
||||
int ring_id;
|
||||
u32 lmac_idx;
|
||||
@ -1027,6 +985,8 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type,
|
||||
params->intr_batch_cntr_thres_entries;
|
||||
srng->intr_timer_thres_us = params->intr_timer_thres_us;
|
||||
srng->flags = params->flags;
|
||||
srng->msi_addr = params->msi_addr;
|
||||
srng->msi_data = params->msi_data;
|
||||
srng->initialized = 1;
|
||||
spin_lock_init(&srng->lock);
|
||||
|
||||
@ -1085,7 +1045,7 @@ int ath11k_hal_srng_setup(struct ath11k_base *ab, enum hal_ring_type type,
|
||||
} else {
|
||||
srng->u.dst_ring.tp_addr =
|
||||
(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,
|
||||
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)
|
||||
{
|
||||
struct ath11k_hal *hal = &ab->hal;
|
||||
@ -1109,7 +1119,9 @@ int ath11k_hal_srng_init(struct ath11k_base *ab)
|
||||
|
||||
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);
|
||||
if (ret)
|
||||
@ -1127,12 +1139,17 @@ err_free_cont_rdp:
|
||||
err_hal:
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_hal_srng_init);
|
||||
|
||||
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_wrp(ab);
|
||||
kfree(hal->srng_config);
|
||||
}
|
||||
EXPORT_SYMBOL(ath11k_hal_srng_deinit);
|
||||
|
||||
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;
|
||||
|
||||
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];
|
||||
|
||||
if (ath11k_ce_get_attr_flags(i) & CE_ATTR_DIS_INTR)
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
|
||||
continue;
|
||||
|
||||
ath11k_err(ab, "CE_id %d pipe_num %d %ums before\n",
|
||||
|
@ -46,40 +46,47 @@ struct ath11k_base;
|
||||
/* SW2TCL(x) R0 ring configuration address */
|
||||
#define HAL_TCL1_RING_CMN_CTRL_REG 0x00000014
|
||||
#define HAL_TCL1_RING_DSCP_TID_MAP 0x0000002c
|
||||
#define HAL_TCL1_RING_BASE_LSB 0x00000510
|
||||
#define HAL_TCL1_RING_BASE_MSB 0x00000514
|
||||
#define HAL_TCL1_RING_ID 0x00000518
|
||||
#define HAL_TCL1_RING_MISC 0x00000520
|
||||
#define HAL_TCL1_RING_TP_ADDR_LSB 0x0000052c
|
||||
#define HAL_TCL1_RING_TP_ADDR_MSB 0x00000530
|
||||
#define HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0 0x00000540
|
||||
#define HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1 0x00000544
|
||||
#define HAL_TCL1_RING_MSI1_BASE_LSB 0x00000558
|
||||
#define HAL_TCL1_RING_MSI1_BASE_MSB 0x0000055c
|
||||
#define HAL_TCL1_RING_MSI1_DATA 0x00000560
|
||||
#define HAL_TCL2_RING_BASE_LSB 0x00000568
|
||||
#define HAL_TCL_RING_BASE_LSB 0x00000618
|
||||
#define HAL_TCL1_RING_BASE_LSB(ab) ab->hw_params.regs->hal_tcl1_ring_base_lsb
|
||||
#define HAL_TCL1_RING_BASE_MSB(ab) ab->hw_params.regs->hal_tcl1_ring_base_msb
|
||||
#define HAL_TCL1_RING_ID(ab) ab->hw_params.regs->hal_tcl1_ring_id
|
||||
#define HAL_TCL1_RING_MISC(ab) ab->hw_params.regs->hal_tcl1_ring_misc
|
||||
#define HAL_TCL1_RING_TP_ADDR_LSB(ab) \
|
||||
ab->hw_params.regs->hal_tcl1_ring_tp_addr_lsb
|
||||
#define HAL_TCL1_RING_TP_ADDR_MSB(ab) \
|
||||
ab->hw_params.regs->hal_tcl1_ring_tp_addr_msb
|
||||
#define HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0(ab) \
|
||||
ab->hw_params.regs->hal_tcl1_ring_consumer_int_setup_ix0
|
||||
#define HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1(ab) \
|
||||
ab->hw_params.regs->hal_tcl1_ring_consumer_int_setup_ix1
|
||||
#define HAL_TCL1_RING_MSI1_BASE_LSB(ab) \
|
||||
ab->hw_params.regs->hal_tcl1_ring_msi1_base_lsb
|
||||
#define HAL_TCL1_RING_MSI1_BASE_MSB(ab) \
|
||||
ab->hw_params.regs->hal_tcl1_ring_msi1_base_msb
|
||||
#define HAL_TCL1_RING_MSI1_DATA(ab) \
|
||||
ab->hw_params.regs->hal_tcl1_ring_msi1_data
|
||||
#define HAL_TCL2_RING_BASE_LSB(ab) ab->hw_params.regs->hal_tcl2_ring_base_lsb
|
||||
#define HAL_TCL_RING_BASE_LSB(ab) ab->hw_params.regs->hal_tcl_ring_base_lsb
|
||||
|
||||
#define HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET \
|
||||
(HAL_TCL1_RING_MSI1_BASE_LSB - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET \
|
||||
(HAL_TCL1_RING_MSI1_BASE_MSB - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_MSI1_DATA_OFFSET \
|
||||
(HAL_TCL1_RING_MSI1_DATA - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_BASE_MSB_OFFSET \
|
||||
(HAL_TCL1_RING_BASE_MSB - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_ID_OFFSET \
|
||||
(HAL_TCL1_RING_ID - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET \
|
||||
(HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0 - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_CONSR_INT_SETUP_IX1_OFFSET \
|
||||
(HAL_TCL1_RING_CONSUMER_INT_SETUP_IX1 - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_TP_ADDR_LSB_OFFSET \
|
||||
(HAL_TCL1_RING_TP_ADDR_LSB - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_TP_ADDR_MSB_OFFSET \
|
||||
(HAL_TCL1_RING_TP_ADDR_MSB - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_MISC_OFFSET \
|
||||
(HAL_TCL1_RING_MISC - HAL_TCL1_RING_BASE_LSB)
|
||||
#define HAL_TCL1_RING_MSI1_BASE_LSB_OFFSET(ab) \
|
||||
(HAL_TCL1_RING_MSI1_BASE_LSB(ab) - HAL_TCL1_RING_BASE_LSB(ab))
|
||||
#define HAL_TCL1_RING_MSI1_BASE_MSB_OFFSET(ab) \
|
||||
(HAL_TCL1_RING_MSI1_BASE_MSB(ab) - HAL_TCL1_RING_BASE_LSB(ab))
|
||||
#define HAL_TCL1_RING_MSI1_DATA_OFFSET(ab) \
|
||||
(HAL_TCL1_RING_MSI1_DATA(ab) - HAL_TCL1_RING_BASE_LSB(ab))
|
||||
#define HAL_TCL1_RING_BASE_MSB_OFFSET(ab) \
|
||||
(HAL_TCL1_RING_BASE_MSB(ab) - HAL_TCL1_RING_BASE_LSB(ab))
|
||||
#define HAL_TCL1_RING_ID_OFFSET(ab) \
|
||||
(HAL_TCL1_RING_ID(ab) - HAL_TCL1_RING_BASE_LSB(ab))
|
||||
#define HAL_TCL1_RING_CONSR_INT_SETUP_IX0_OFFSET(ab) \
|
||||
(HAL_TCL1_RING_CONSUMER_INT_SETUP_IX0(ab) - HAL_TCL1_RING_BASE_LSB(ab))
|
||||
#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 */
|
||||
#define HAL_TCL1_RING_HP 0x00002000
|
||||
@ -91,7 +98,8 @@ struct ath11k_base;
|
||||
(HAL_TCL1_RING_TP - HAL_TCL1_RING_HP)
|
||||
|
||||
/* 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
|
||||
|
||||
/* REO2SW(x) R0 ring configuration address */
|
||||
@ -100,51 +108,63 @@ struct ath11k_base;
|
||||
#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_3 0x00000010
|
||||
#define HAL_REO1_RING_BASE_LSB 0x0000029c
|
||||
#define HAL_REO1_RING_BASE_MSB 0x000002a0
|
||||
#define HAL_REO1_RING_ID 0x000002a4
|
||||
#define HAL_REO1_RING_MISC 0x000002ac
|
||||
#define HAL_REO1_RING_HP_ADDR_LSB 0x000002b0
|
||||
#define HAL_REO1_RING_HP_ADDR_MSB 0x000002b4
|
||||
#define HAL_REO1_RING_PRODUCER_INT_SETUP 0x000002c0
|
||||
#define HAL_REO1_RING_MSI1_BASE_LSB 0x000002e4
|
||||
#define HAL_REO1_RING_MSI1_BASE_MSB 0x000002e8
|
||||
#define HAL_REO1_RING_MSI1_DATA 0x000002ec
|
||||
#define HAL_REO2_RING_BASE_LSB 0x000002f4
|
||||
#define HAL_REO1_AGING_THRESH_IX_0 0x00000564
|
||||
#define HAL_REO1_AGING_THRESH_IX_1 0x00000568
|
||||
#define HAL_REO1_AGING_THRESH_IX_2 0x0000056c
|
||||
#define HAL_REO1_AGING_THRESH_IX_3 0x00000570
|
||||
#define HAL_REO1_RING_BASE_LSB(ab) ab->hw_params.regs->hal_reo1_ring_base_lsb
|
||||
#define HAL_REO1_RING_BASE_MSB(ab) ab->hw_params.regs->hal_reo1_ring_base_msb
|
||||
#define HAL_REO1_RING_ID(ab) ab->hw_params.regs->hal_reo1_ring_id
|
||||
#define HAL_REO1_RING_MISC(ab) ab->hw_params.regs->hal_reo1_ring_misc
|
||||
#define HAL_REO1_RING_HP_ADDR_LSB(ab) \
|
||||
ab->hw_params.regs->hal_reo1_ring_hp_addr_lsb
|
||||
#define HAL_REO1_RING_HP_ADDR_MSB(ab) \
|
||||
ab->hw_params.regs->hal_reo1_ring_hp_addr_msb
|
||||
#define HAL_REO1_RING_PRODUCER_INT_SETUP(ab) \
|
||||
ab->hw_params.regs->hal_reo1_ring_producer_int_setup
|
||||
#define HAL_REO1_RING_MSI1_BASE_LSB(ab) \
|
||||
ab->hw_params.regs->hal_reo1_ring_msi1_base_lsb
|
||||
#define HAL_REO1_RING_MSI1_BASE_MSB(ab) \
|
||||
ab->hw_params.regs->hal_reo1_ring_msi1_base_msb
|
||||
#define HAL_REO1_RING_MSI1_DATA(ab) \
|
||||
ab->hw_params.regs->hal_reo1_ring_msi1_data
|
||||
#define HAL_REO2_RING_BASE_LSB(ab) ab->hw_params.regs->hal_reo2_ring_base_lsb
|
||||
#define HAL_REO1_AGING_THRESH_IX_0(ab) \
|
||||
ab->hw_params.regs->hal_reo1_aging_thresh_ix_0
|
||||
#define HAL_REO1_AGING_THRESH_IX_1(ab) \
|
||||
ab->hw_params.regs->hal_reo1_aging_thresh_ix_1
|
||||
#define HAL_REO1_AGING_THRESH_IX_2(ab) \
|
||||
ab->hw_params.regs->hal_reo1_aging_thresh_ix_2
|
||||
#define HAL_REO1_AGING_THRESH_IX_3(ab) \
|
||||
ab->hw_params.regs->hal_reo1_aging_thresh_ix_3
|
||||
|
||||
#define HAL_REO1_RING_MSI1_BASE_LSB_OFFSET \
|
||||
(HAL_REO1_RING_MSI1_BASE_LSB - HAL_REO1_RING_BASE_LSB)
|
||||
#define HAL_REO1_RING_MSI1_BASE_MSB_OFFSET \
|
||||
(HAL_REO1_RING_MSI1_BASE_MSB - HAL_REO1_RING_BASE_LSB)
|
||||
#define HAL_REO1_RING_MSI1_DATA_OFFSET \
|
||||
(HAL_REO1_RING_MSI1_DATA - HAL_REO1_RING_BASE_LSB)
|
||||
#define HAL_REO1_RING_BASE_MSB_OFFSET \
|
||||
(HAL_REO1_RING_BASE_MSB - HAL_REO1_RING_BASE_LSB)
|
||||
#define HAL_REO1_RING_ID_OFFSET (HAL_REO1_RING_ID - HAL_REO1_RING_BASE_LSB)
|
||||
#define HAL_REO1_RING_PRODUCER_INT_SETUP_OFFSET \
|
||||
(HAL_REO1_RING_PRODUCER_INT_SETUP - HAL_REO1_RING_BASE_LSB)
|
||||
#define HAL_REO1_RING_HP_ADDR_LSB_OFFSET \
|
||||
(HAL_REO1_RING_HP_ADDR_LSB - HAL_REO1_RING_BASE_LSB)
|
||||
#define HAL_REO1_RING_HP_ADDR_MSB_OFFSET \
|
||||
(HAL_REO1_RING_HP_ADDR_MSB - HAL_REO1_RING_BASE_LSB)
|
||||
#define HAL_REO1_RING_MISC_OFFSET (HAL_REO1_RING_MISC - HAL_REO1_RING_BASE_LSB)
|
||||
#define HAL_REO1_RING_MSI1_BASE_LSB_OFFSET(ab) \
|
||||
(HAL_REO1_RING_MSI1_BASE_LSB(ab) - HAL_REO1_RING_BASE_LSB(ab))
|
||||
#define HAL_REO1_RING_MSI1_BASE_MSB_OFFSET(ab) \
|
||||
(HAL_REO1_RING_MSI1_BASE_MSB(ab) - HAL_REO1_RING_BASE_LSB(ab))
|
||||
#define HAL_REO1_RING_MSI1_DATA_OFFSET(ab) \
|
||||
(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 */
|
||||
#define HAL_REO1_RING_HP 0x00003038
|
||||
#define HAL_REO1_RING_TP 0x0000303c
|
||||
#define HAL_REO2_RING_HP 0x00003040
|
||||
#define HAL_REO1_RING_HP(ab) ab->hw_params.regs->hal_reo1_ring_hp
|
||||
#define HAL_REO1_RING_TP(ab) ab->hw_params.regs->hal_reo1_ring_tp
|
||||
#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 */
|
||||
#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 */
|
||||
#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 */
|
||||
#define HAL_REO_CMD_RING_BASE_LSB 0x00000194
|
||||
@ -168,8 +188,9 @@ struct ath11k_base;
|
||||
#define HAL_CE_DST_STATUS_RING_HP 0x00000408
|
||||
|
||||
/* REO status address */
|
||||
#define HAL_REO_STATUS_RING_BASE_LSB 0x00000504
|
||||
#define HAL_REO_STATUS_HP 0x00003070
|
||||
#define HAL_REO_STATUS_RING_BASE_LSB(ab) \
|
||||
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 */
|
||||
#define HAL_WBM_IDLE_LINK_RING_BASE_LSB 0x00000860
|
||||
@ -458,6 +479,8 @@ struct hal_srng_params {
|
||||
u32 flags;
|
||||
u32 max_buffer_len;
|
||||
u32 low_threshold;
|
||||
dma_addr_t msi_addr;
|
||||
u32 msi_data;
|
||||
|
||||
/* Add more params as needed */
|
||||
};
|
||||
@ -839,7 +862,7 @@ struct ath11k_hal {
|
||||
struct hal_srng srng_list[HAL_SRNG_RING_ID_MAX];
|
||||
|
||||
/* SRNG configuration table */
|
||||
const struct hal_srng_config *srng_config;
|
||||
struct hal_srng_config *srng_config;
|
||||
|
||||
/* Remote pointer memory for HW/FW updates */
|
||||
struct {
|
||||
@ -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);
|
||||
void ath11k_hal_ce_dst_set_desc(void *buf, dma_addr_t paddr);
|
||||
u32 ath11k_hal_ce_dst_status_get_length(void *buf);
|
||||
int ath11k_hal_srng_get_entrysize(u32 ring_type);
|
||||
int ath11k_hal_srng_get_max_entries(u32 ring_type);
|
||||
int ath11k_hal_srng_get_entrysize(struct ath11k_base *ab, 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,
|
||||
struct hal_srng_params *params);
|
||||
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,
|
||||
|
||||
memset(¶ms, 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, ¶ms);
|
||||
entry = (u8 *)params.ring_base_vaddr;
|
||||
|
||||
@ -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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
|
||||
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)
|
||||
|
||||
memset(¶ms, 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, ¶ms);
|
||||
desc = (u8 *)params.ring_base_vaddr;
|
||||
|
||||
|
@ -3,6 +3,9 @@
|
||||
* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _HIF_H_
|
||||
#define _HIF_H_
|
||||
|
||||
#include "core.h"
|
||||
|
||||
struct ath11k_hif_ops {
|
||||
@ -16,6 +19,11 @@ struct ath11k_hif_ops {
|
||||
void (*power_down)(struct ath11k_base *sc);
|
||||
int (*map_service_to_pipe)(struct ath11k_base *sc, u16 service_id,
|
||||
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)
|
||||
@ -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);
|
||||
}
|
||||
|
||||
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)
|
||||
if (!time_left) {
|
||||
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);
|
||||
|
||||
time_left =
|
||||
@ -748,7 +748,7 @@ int ath11k_htc_init(struct ath11k_base *ab)
|
||||
htc->wmi_ep_count = 3;
|
||||
break;
|
||||
default:
|
||||
htc->wmi_ep_count = 3;
|
||||
htc->wmi_ep_count = ab->hw_params.max_radios;
|
||||
break;
|
||||
}
|
||||
|
||||
|
890
drivers/net/wireless/ath/ath11k/hw.c
Normal file
890
drivers/net/wireless/ath/ath11k/hw.c
Normal file
@ -0,0 +1,890 @@
|
||||
// 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 = {
|
||||
},
|
||||
};
|
||||
|
||||
/* Target firmware's Copy Engine configuration. */
|
||||
const struct ce_pipe_config ath11k_target_ce_config_wlan_ipq8074[] = {
|
||||
/* CE0: host->target HTC control and raw streams */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(0),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE1: target->host HTT + HTC control */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(1),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE2: target->host WMI */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE3: host->target WMI */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE4: host->target HTT */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(4),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
|
||||
.nentries = __cpu_to_le32(256),
|
||||
.nbytes_max = __cpu_to_le32(256),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE5: target->host Pktlog */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(5),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(0),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE6: Reserved for target autonomous hif_memcpy */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(6),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(65535),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE7 used only by Host */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(7),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE8 target->host used only by IPA */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(8),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(65535),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE9 host->target HTT */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(9),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE10 target->host HTT */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(10),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_INOUT_H2H),
|
||||
.nentries = __cpu_to_le32(0),
|
||||
.nbytes_max = __cpu_to_le32(0),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE11 Not used */
|
||||
};
|
||||
|
||||
/* Map from service/endpoint to Copy Engine.
|
||||
* This table is derived from the CE_PCI TABLE, above.
|
||||
* It is passed to the Target at startup for use by firmware.
|
||||
*/
|
||||
const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq8074[] = {
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(7),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(9),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC2),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(0),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(1),
|
||||
},
|
||||
{ /* not used */
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(0),
|
||||
},
|
||||
{ /* not used */
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(1),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(4),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(1),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_PKT_LOG),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(5),
|
||||
},
|
||||
|
||||
/* (Additions here) */
|
||||
|
||||
{ /* terminator entry */ }
|
||||
};
|
||||
|
||||
const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_ipq6018[] = {
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(7),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL_MAC1),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(0),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(1),
|
||||
},
|
||||
{ /* not used */
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(0),
|
||||
},
|
||||
{ /* not used */
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_TEST_RAW_STREAMS),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(1),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
.pipenum = __cpu_to_le32(4),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(1),
|
||||
},
|
||||
{
|
||||
.service_id = __cpu_to_le32(ATH11K_HTC_SVC_ID_PKT_LOG),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
.pipenum = __cpu_to_le32(5),
|
||||
},
|
||||
|
||||
/* (Additions here) */
|
||||
|
||||
{ /* terminator entry */ }
|
||||
};
|
||||
|
||||
/* Target firmware's Copy Engine configuration. */
|
||||
const struct ce_pipe_config ath11k_target_ce_config_wlan_qca6390[] = {
|
||||
/* CE0: host->target HTC control and raw streams */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(0),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE1: target->host HTT + HTC control */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(1),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE2: target->host WMI */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(2),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE3: host->target WMI */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(3),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE4: host->target HTT */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(4),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_OUT),
|
||||
.nentries = __cpu_to_le32(256),
|
||||
.nbytes_max = __cpu_to_le32(256),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE5: target->host Pktlog */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(5),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_IN),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(2048),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE6: Reserved for target autonomous hif_memcpy */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(6),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(16384),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE7 used only by Host */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(7),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_INOUT_H2H),
|
||||
.nentries = __cpu_to_le32(0),
|
||||
.nbytes_max = __cpu_to_le32(0),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS | CE_ATTR_DIS_INTR),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
|
||||
/* CE8 target->host used only by IPA */
|
||||
{
|
||||
.pipenum = __cpu_to_le32(8),
|
||||
.pipedir = __cpu_to_le32(PIPEDIR_INOUT),
|
||||
.nentries = __cpu_to_le32(32),
|
||||
.nbytes_max = __cpu_to_le32(16384),
|
||||
.flags = __cpu_to_le32(CE_ATTR_FLAGS),
|
||||
.reserved = __cpu_to_le32(0),
|
||||
},
|
||||
/* CE 9, 10, 11 are used by MHI driver */
|
||||
};
|
||||
|
||||
/* Map from service/endpoint to Copy Engine.
|
||||
* This table is derived from the CE_PCI TABLE, above.
|
||||
* It is passed to the Target at startup for use by firmware.
|
||||
*/
|
||||
const struct service_to_pipe ath11k_target_service_to_ce_map_wlan_qca6390[] = {
|
||||
{
|
||||
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
|
||||
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
__cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VO),
|
||||
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
__cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
|
||||
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
__cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BK),
|
||||
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
__cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
|
||||
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
__cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_BE),
|
||||
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
__cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
|
||||
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
__cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_DATA_VI),
|
||||
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
__cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
|
||||
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
__cpu_to_le32(3),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH11K_HTC_SVC_ID_WMI_CONTROL),
|
||||
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
__cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
|
||||
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
__cpu_to_le32(0),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH11K_HTC_SVC_ID_RSVD_CTRL),
|
||||
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
__cpu_to_le32(2),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
|
||||
__cpu_to_le32(PIPEDIR_OUT), /* out = UL = host -> target */
|
||||
__cpu_to_le32(4),
|
||||
},
|
||||
{
|
||||
__cpu_to_le32(ATH11K_HTC_SVC_ID_HTT_DATA_MSG),
|
||||
__cpu_to_le32(PIPEDIR_IN), /* in = DL = target -> host */
|
||||
__cpu_to_le32(1),
|
||||
},
|
||||
|
||||
/* (Additions here) */
|
||||
|
||||
{ /* must be last */
|
||||
__cpu_to_le32(0),
|
||||
__cpu_to_le32(0),
|
||||
__cpu_to_le32(0),
|
||||
},
|
||||
};
|
||||
|
||||
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 @@
|
||||
#ifndef ATH11K_HW_H
|
||||
#define ATH11K_HW_H
|
||||
|
||||
#include "wmi.h"
|
||||
|
||||
/* Target configuration defines */
|
||||
|
||||
/* Num VDEVS per radio */
|
||||
@ -68,15 +70,12 @@
|
||||
|
||||
#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_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_AMSS_FILE "amss.bin"
|
||||
#define ATH11K_M3_FILE "m3.bin"
|
||||
|
||||
enum ath11k_hw_rate_cck {
|
||||
ATH11K_HW_RATE_CCK_LP_11M = 0,
|
||||
@ -104,15 +103,103 @@ enum ath11k_bus {
|
||||
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 {
|
||||
const char *name;
|
||||
u16 hw_rev;
|
||||
u8 max_radios;
|
||||
u32 bdf_addr;
|
||||
|
||||
struct {
|
||||
const char *dir;
|
||||
size_t board_size;
|
||||
size_t cal_size;
|
||||
} 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;
|
||||
const struct ce_pipe_config *target_ce_config;
|
||||
u32 target_ce_count;
|
||||
const struct service_to_pipe *svc_to_ce_map;
|
||||
u32 svc_to_ce_map_len;
|
||||
|
||||
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 {
|
||||
__le32 id;
|
||||
__le32 len;
|
||||
@ -130,4 +217,51 @@ enum ath11k_bd_ie_type {
|
||||
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
|
||||
|
@ -42,12 +42,6 @@
|
||||
.max_power = 30, \
|
||||
}
|
||||
|
||||
/* frame mode values are mapped as per enum ath11k_hw_txrx_mode */
|
||||
static unsigned int ath11k_frame_mode = ATH11K_HW_TXRX_NATIVE_WIFI;
|
||||
module_param_named(frame_mode, ath11k_frame_mode, uint, 0644);
|
||||
MODULE_PARM_DESC(frame_mode,
|
||||
"Datapath frame mode (0: raw, 1: native wifi (default), 2: ethernet)");
|
||||
|
||||
static const struct ieee80211_channel ath11k_2ghz_channels[] = {
|
||||
CHAN2G(1, 2412, 0),
|
||||
CHAN2G(2, 2417, 0),
|
||||
@ -244,6 +238,9 @@ static const u32 ath11k_smps_map[] = {
|
||||
[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 ret = 0;
|
||||
@ -521,6 +518,11 @@ struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id)
|
||||
int i;
|
||||
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))
|
||||
return NULL;
|
||||
|
||||
@ -1138,13 +1140,13 @@ ath11k_peer_assoc_h_vht_limit(u16 tx_mcs_set,
|
||||
idx_limit = -1;
|
||||
|
||||
switch (idx_limit) {
|
||||
case 0: /* fall through */
|
||||
case 1: /* fall through */
|
||||
case 2: /* fall through */
|
||||
case 3: /* fall through */
|
||||
case 4: /* fall through */
|
||||
case 5: /* fall through */
|
||||
case 6: /* fall through */
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
mcs = IEEE80211_VHT_MCS_SUPPORT_0_7;
|
||||
break;
|
||||
@ -1156,7 +1158,7 @@ ath11k_peer_assoc_h_vht_limit(u16 tx_mcs_set,
|
||||
break;
|
||||
default:
|
||||
WARN_ON(1);
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case -1:
|
||||
mcs = IEEE80211_VHT_MCS_NOT_SUPPORTED;
|
||||
break;
|
||||
@ -1268,6 +1270,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
|
||||
struct peer_assoc_params *arg)
|
||||
{
|
||||
const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
|
||||
u8 ampdu_factor;
|
||||
u16 v;
|
||||
|
||||
if (!he_cap->has_he)
|
||||
@ -1284,6 +1287,30 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
|
||||
/* the top most byte is used to indicate BSS color info */
|
||||
arg->peer_he_ops &= 0xffffff;
|
||||
|
||||
/* As per section 26.6.1 11ax Draft5.0, if the Max AMPDU Exponent Extension
|
||||
* in HE cap is zero, use the arg->peer_max_mpdu as calculated while parsing
|
||||
* VHT caps(if VHT caps is present) or HT caps (if VHT caps is not present).
|
||||
*
|
||||
* For non-zero value of Max AMPDU Extponent Extension in HE MAC caps,
|
||||
* if a HE STA sends VHT cap and HE cap IE in assoc request then, use
|
||||
* MAX_AMPDU_LEN_FACTOR as 20 to calculate max_ampdu length.
|
||||
* If a HE STA that does not send VHT cap, but HE and HT cap in assoc
|
||||
* request, then use MAX_AMPDU_LEN_FACTOR as 16 to calculate max_ampdu
|
||||
* length.
|
||||
*/
|
||||
ampdu_factor = (he_cap->he_cap_elem.mac_cap_info[3] &
|
||||
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK) >>
|
||||
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_SHIFT;
|
||||
|
||||
if (ampdu_factor) {
|
||||
if (sta->vht_cap.vht_supported)
|
||||
arg->peer_max_mpdu = (1 << (IEEE80211_HE_VHT_MAX_AMPDU_FACTOR +
|
||||
ampdu_factor)) - 1;
|
||||
else if (sta->ht_cap.ht_supported)
|
||||
arg->peer_max_mpdu = (1 << (IEEE80211_HE_HT_MAX_AMPDU_FACTOR +
|
||||
ampdu_factor)) - 1;
|
||||
}
|
||||
|
||||
if (he_cap->he_cap_elem.phy_cap_info[6] &
|
||||
IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) {
|
||||
int bit = 7;
|
||||
@ -1339,7 +1366,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_mcs_count++;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
|
||||
default:
|
||||
v = le16_to_cpu(he_cap->he_mcs_nss_supp.rx_mcs_80);
|
||||
@ -2114,7 +2141,7 @@ void __ath11k_mac_scan_finish(struct ath11k *ar)
|
||||
} else if (ar->scan.roc_notify) {
|
||||
ieee80211_remain_on_channel_expired(ar->hw);
|
||||
}
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case ATH11K_SCAN_STARTING:
|
||||
ar->scan.state = ATH11K_SCAN_IDLE;
|
||||
ar->scan_channel = NULL;
|
||||
@ -2372,6 +2399,9 @@ static int ath11k_install_key(struct ath11k_vif *arvif,
|
||||
|
||||
reinit_completion(&ar->install_key_done);
|
||||
|
||||
if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
|
||||
return 0;
|
||||
|
||||
if (cmd == DISABLE_KEY) {
|
||||
/* TODO: Check if FW expects value other than NONE for del */
|
||||
/* arg.key_cipher = WMI_CIPHER_NONE; */
|
||||
@ -2403,8 +2433,13 @@ static int ath11k_install_key(struct ath11k_vif *arvif,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (test_bit(ATH11K_FLAG_RAW_MODE, &ar->ab->dev_flags))
|
||||
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV |
|
||||
IEEE80211_KEY_FLAG_RESERVE_TAILROOM;
|
||||
|
||||
install:
|
||||
ret = ath11k_wmi_vdev_install_key(arvif->ar, &arg);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -2476,6 +2511,9 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
|
||||
key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256)
|
||||
return 1;
|
||||
|
||||
if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
|
||||
return 1;
|
||||
|
||||
if (key->keyidx > WMI_MAX_KEY_INDEX)
|
||||
return -ENOSPC;
|
||||
|
||||
@ -2955,6 +2993,14 @@ static int ath11k_mac_station_add(struct ath11k *ar,
|
||||
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;
|
||||
|
||||
free_tx_stats:
|
||||
@ -3039,10 +3085,6 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab, "Failed to associate station: %pM\n",
|
||||
sta->addr);
|
||||
else
|
||||
ath11k_info(ar->ab,
|
||||
"Station %pM moved to assoc state\n",
|
||||
sta->addr);
|
||||
} else if (old_state == IEEE80211_STA_ASSOC &&
|
||||
new_state == IEEE80211_STA_AUTH &&
|
||||
(vif->type == NL80211_IFTYPE_AP ||
|
||||
@ -3052,10 +3094,6 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
|
||||
if (ret)
|
||||
ath11k_warn(ar->ab, "Failed to disassociate station: %pM\n",
|
||||
sta->addr);
|
||||
else
|
||||
ath11k_info(ar->ab,
|
||||
"Station %pM moved to disassociated state\n",
|
||||
sta->addr);
|
||||
}
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
@ -4057,6 +4095,8 @@ void ath11k_mac_drain_tx(struct ath11k *ar)
|
||||
static int ath11k_mac_config_mon_status_default(struct ath11k *ar, bool enable)
|
||||
{
|
||||
struct htt_rx_ring_tlv_filter tlv_filter = {0};
|
||||
struct ath11k_base *ab = ar->ab;
|
||||
int i, ret = 0;
|
||||
u32 ring_id;
|
||||
|
||||
if (enable) {
|
||||
@ -4064,11 +4104,16 @@ static int ath11k_mac_config_mon_status_default(struct ath11k *ar, bool enable)
|
||||
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,
|
||||
HAL_RXDMA_MONITOR_STATUS,
|
||||
DP_RX_BUFFER_SIZE, &tlv_filter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath11k_mac_op_start(struct ieee80211_hw *hw)
|
||||
@ -4368,7 +4413,7 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
||||
break;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_MESH_11S;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case NL80211_IFTYPE_AP:
|
||||
arvif->vdev_type = WMI_VDEV_TYPE_AP;
|
||||
break;
|
||||
@ -4421,6 +4466,8 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
|
||||
|
||||
if (ieee80211_set_hw_80211_encap(vif, hw_encap))
|
||||
param_value = ATH11K_HW_TXRX_ETHERNET;
|
||||
else if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags))
|
||||
param_value = ATH11K_HW_TXRX_RAW;
|
||||
else
|
||||
param_value = ATH11K_HW_TXRX_NATIVE_WIFI;
|
||||
|
||||
@ -5112,6 +5159,39 @@ unlock:
|
||||
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
|
||||
ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
@ -5128,6 +5208,13 @@ ath11k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
|
||||
"mac chanctx assign ptr %pK vdev_id %i\n",
|
||||
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)) {
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return -EBUSY;
|
||||
@ -5829,12 +5916,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,
|
||||
u32 supported_bands)
|
||||
{
|
||||
struct ieee80211_supported_band *band;
|
||||
struct ath11k_hal_reg_capabilities_ext *reg_cap;
|
||||
void *channels;
|
||||
u32 phy_id;
|
||||
|
||||
BUILD_BUG_ON((ARRAY_SIZE(ath11k_2ghz_channels) +
|
||||
ARRAY_SIZE(ath11k_5ghz_channels) +
|
||||
@ -5857,6 +5961,11 @@ static int ath11k_mac_setup_channels_rates(struct ath11k *ar,
|
||||
band->n_bitrates = ath11k_g_rates_size;
|
||||
band->bitrates = ath11k_g_rates;
|
||||
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,
|
||||
reg_cap->low_2ghz_chan,
|
||||
reg_cap->high_2ghz_chan);
|
||||
@ -5901,6 +6010,12 @@ static int ath11k_mac_setup_channels_rates(struct ath11k *ar,
|
||||
band->n_bitrates = ath11k_a_rates_size;
|
||||
band->bitrates = ath11k_a_rates;
|
||||
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,
|
||||
reg_cap->low_5ghz_chan,
|
||||
reg_cap->high_5ghz_chan);
|
||||
@ -6006,7 +6121,7 @@ static int __ath11k_mac_register(struct ath11k *ar)
|
||||
ret = ath11k_mac_setup_channels_rates(ar,
|
||||
cap->supported_bands);
|
||||
if (ret)
|
||||
goto err_free;
|
||||
goto err;
|
||||
|
||||
ath11k_mac_setup_ht_vht_cap(ar, cap, &ht_cap);
|
||||
ath11k_mac_setup_he_cap(ar, cap);
|
||||
@ -6026,7 +6141,6 @@ static int __ath11k_mac_register(struct ath11k *ar)
|
||||
ieee80211_hw_set(ar->hw, HAS_RATE_CONTROL);
|
||||
ieee80211_hw_set(ar->hw, AP_LINK_PS);
|
||||
ieee80211_hw_set(ar->hw, SPECTRUM_MGMT);
|
||||
ieee80211_hw_set(ar->hw, SUPPORT_FAST_XMIT);
|
||||
ieee80211_hw_set(ar->hw, CONNECTION_MONITOR);
|
||||
ieee80211_hw_set(ar->hw, SUPPORTS_PER_STA_GTK);
|
||||
ieee80211_hw_set(ar->hw, WANT_MONITOR_VIF);
|
||||
@ -6093,8 +6207,11 @@ static int __ath11k_mac_register(struct ath11k *ar)
|
||||
|
||||
ath11k_reg_init(ar);
|
||||
|
||||
/* advertise HW checksum offload capabilities */
|
||||
ar->hw->netdev_features = NETIF_F_HW_CSUM;
|
||||
if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) {
|
||||
ar->hw->netdev_features = NETIF_F_HW_CSUM;
|
||||
ieee80211_hw_set(ar->hw, SW_CRYPTO_CONTROL);
|
||||
ieee80211_hw_set(ar->hw, SUPPORT_FAST_XMIT);
|
||||
}
|
||||
|
||||
ret = ieee80211_register_hw(ar->hw);
|
||||
if (ret) {
|
||||
@ -6120,7 +6237,9 @@ static int __ath11k_mac_register(struct ath11k *ar)
|
||||
err_free:
|
||||
kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);
|
||||
kfree(ar->mac.sbands[NL80211_BAND_5GHZ].channels);
|
||||
kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels);
|
||||
|
||||
err:
|
||||
SET_IEEE80211_DEV(ar->hw, NULL);
|
||||
return ret;
|
||||
}
|
||||
@ -6194,7 +6313,7 @@ int ath11k_mac_allocate(struct ath11k_base *ab)
|
||||
ar->ab = ab;
|
||||
ar->pdev = pdev;
|
||||
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];
|
||||
/* FIXME wmi[0] is already initialized during attach,
|
||||
|
467
drivers/net/wireless/ath/ath11k/mhi.c
Normal file
467
drivers/net/wireless/ath/ath11k/mhi.c
Normal file
@ -0,0 +1,467 @@
|
||||
// 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 -ENOMEM;
|
||||
|
||||
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);
|
||||
}
|
||||
|
39
drivers/net/wireless/ath/ath11k/mhi.h
Normal file
39
drivers/net/wireless/ath/ath11k/mhi.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* 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
|
995
drivers/net/wireless/ath/ath11k/pci.c
Normal file
995
drivers/net/wireless/ath/ath11k/pci.c
Normal file
@ -0,0 +1,995 @@
|
||||
// SPDX-License-Identifier: BSD-3-Clause-Clear
|
||||
/*
|
||||
* Copyright (c) 2019-2020 The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/msi.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "pci.h"
|
||||
#include "core.h"
|
||||
#include "hif.h"
|
||||
#include "mhi.h"
|
||||
#include "debug.h"
|
||||
|
||||
#define ATH11K_PCI_BAR_NUM 0
|
||||
#define ATH11K_PCI_DMA_MASK 32
|
||||
|
||||
#define ATH11K_PCI_IRQ_CE0_OFFSET 3
|
||||
|
||||
#define WINDOW_ENABLE_BIT 0x40000000
|
||||
#define WINDOW_REG_ADDRESS 0x310c
|
||||
#define WINDOW_VALUE_MASK GENMASK(24, 19)
|
||||
#define WINDOW_START 0x80000
|
||||
#define WINDOW_RANGE_MASK GENMASK(18, 0)
|
||||
|
||||
#define QCA6390_DEVICE_ID 0x1101
|
||||
|
||||
static const struct pci_device_id ath11k_pci_id_table[] = {
|
||||
{ PCI_VDEVICE(QCOM, QCA6390_DEVICE_ID) },
|
||||
{0}
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(pci, ath11k_pci_id_table);
|
||||
|
||||
static const struct ath11k_bus_params ath11k_pci_bus_params = {
|
||||
.mhi_support = true,
|
||||
.m3_fw_support = true,
|
||||
.fixed_bdf_addr = false,
|
||||
.fixed_mem_region = false,
|
||||
};
|
||||
|
||||
static const struct ath11k_msi_config msi_config = {
|
||||
.total_vectors = 32,
|
||||
.total_users = 4,
|
||||
.users = (struct ath11k_msi_user[]) {
|
||||
{ .name = "MHI", .num_vectors = 3, .base_vector = 0 },
|
||||
{ .name = "CE", .num_vectors = 10, .base_vector = 3 },
|
||||
{ .name = "WAKE", .num_vectors = 1, .base_vector = 13 },
|
||||
{ .name = "DP", .num_vectors = 18, .base_vector = 14 },
|
||||
},
|
||||
};
|
||||
|
||||
static const char *irq_name[ATH11K_IRQ_NUM_MAX] = {
|
||||
"bhi",
|
||||
"mhi-er0",
|
||||
"mhi-er1",
|
||||
"ce0",
|
||||
"ce1",
|
||||
"ce2",
|
||||
"ce3",
|
||||
"ce4",
|
||||
"ce5",
|
||||
"ce6",
|
||||
"ce7",
|
||||
"ce8",
|
||||
"ce9",
|
||||
"ce10",
|
||||
"ce11",
|
||||
"host2wbm-desc-feed",
|
||||
"host2reo-re-injection",
|
||||
"host2reo-command",
|
||||
"host2rxdma-monitor-ring3",
|
||||
"host2rxdma-monitor-ring2",
|
||||
"host2rxdma-monitor-ring1",
|
||||
"reo2ost-exception",
|
||||
"wbm2host-rx-release",
|
||||
"reo2host-status",
|
||||
"reo2host-destination-ring4",
|
||||
"reo2host-destination-ring3",
|
||||
"reo2host-destination-ring2",
|
||||
"reo2host-destination-ring1",
|
||||
"rxdma2host-monitor-destination-mac3",
|
||||
"rxdma2host-monitor-destination-mac2",
|
||||
"rxdma2host-monitor-destination-mac1",
|
||||
"ppdu-end-interrupts-mac3",
|
||||
"ppdu-end-interrupts-mac2",
|
||||
"ppdu-end-interrupts-mac1",
|
||||
"rxdma2host-monitor-status-ring-mac3",
|
||||
"rxdma2host-monitor-status-ring-mac2",
|
||||
"rxdma2host-monitor-status-ring-mac1",
|
||||
"host2rxdma-host-buf-ring-mac3",
|
||||
"host2rxdma-host-buf-ring-mac2",
|
||||
"host2rxdma-host-buf-ring-mac1",
|
||||
"rxdma2host-destination-ring-mac3",
|
||||
"rxdma2host-destination-ring-mac2",
|
||||
"rxdma2host-destination-ring-mac1",
|
||||
"host2tcl-input-ring4",
|
||||
"host2tcl-input-ring3",
|
||||
"host2tcl-input-ring2",
|
||||
"host2tcl-input-ring1",
|
||||
"wbm2host-tx-completions-ring3",
|
||||
"wbm2host-tx-completions-ring2",
|
||||
"wbm2host-tx-completions-ring1",
|
||||
"tcl2host-status-ring",
|
||||
};
|
||||
|
||||
static inline void ath11k_pci_select_window(struct ath11k_pci *ab_pci, u32 offset)
|
||||
{
|
||||
struct ath11k_base *ab = ab_pci->ab;
|
||||
|
||||
u32 window = FIELD_GET(WINDOW_VALUE_MASK, offset);
|
||||
|
||||
lockdep_assert_held(&ab_pci->window_lock);
|
||||
|
||||
if (window != ab_pci->register_window) {
|
||||
iowrite32(WINDOW_ENABLE_BIT | window,
|
||||
ab->mem + WINDOW_REG_ADDRESS);
|
||||
ab_pci->register_window = window;
|
||||
}
|
||||
}
|
||||
|
||||
void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value)
|
||||
{
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
|
||||
if (offset < WINDOW_START) {
|
||||
iowrite32(value, ab->mem + offset);
|
||||
} else {
|
||||
spin_lock_bh(&ab_pci->window_lock);
|
||||
ath11k_pci_select_window(ab_pci, offset);
|
||||
iowrite32(value, ab->mem + WINDOW_START + (offset & WINDOW_RANGE_MASK));
|
||||
spin_unlock_bh(&ab_pci->window_lock);
|
||||
}
|
||||
}
|
||||
|
||||
u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset)
|
||||
{
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
u32 val;
|
||||
|
||||
if (offset < WINDOW_START) {
|
||||
val = ioread32(ab->mem + offset);
|
||||
} else {
|
||||
spin_lock_bh(&ab_pci->window_lock);
|
||||
ath11k_pci_select_window(ab_pci, offset);
|
||||
val = ioread32(ab->mem + WINDOW_START + (offset & WINDOW_RANGE_MASK));
|
||||
spin_unlock_bh(&ab_pci->window_lock);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void ath11k_pci_soc_global_reset(struct ath11k_base *ab)
|
||||
{
|
||||
u32 val, delay;
|
||||
|
||||
val = ath11k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET);
|
||||
|
||||
val |= PCIE_SOC_GLOBAL_RESET_V;
|
||||
|
||||
ath11k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
|
||||
|
||||
/* TODO: exact time to sleep is uncertain */
|
||||
delay = 10;
|
||||
mdelay(delay);
|
||||
|
||||
/* Need to toggle V bit back otherwise stuck in reset status */
|
||||
val &= ~PCIE_SOC_GLOBAL_RESET_V;
|
||||
|
||||
ath11k_pci_write32(ab, PCIE_SOC_GLOBAL_RESET, val);
|
||||
|
||||
mdelay(delay);
|
||||
|
||||
val = ath11k_pci_read32(ab, PCIE_SOC_GLOBAL_RESET);
|
||||
if (val == 0xffffffff)
|
||||
ath11k_warn(ab, "link down error during global reset\n");
|
||||
}
|
||||
|
||||
static void ath11k_pci_clear_dbg_registers(struct ath11k_base *ab)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* read cookie */
|
||||
val = ath11k_pci_read32(ab, PCIE_Q6_COOKIE_ADDR);
|
||||
ath11k_dbg(ab, ATH11K_DBG_PCI, "cookie:0x%x\n", val);
|
||||
|
||||
val = ath11k_pci_read32(ab, WLAON_WARM_SW_ENTRY);
|
||||
ath11k_dbg(ab, ATH11K_DBG_PCI, "WLAON_WARM_SW_ENTRY 0x%x\n", val);
|
||||
|
||||
/* TODO: exact time to sleep is uncertain */
|
||||
mdelay(10);
|
||||
|
||||
/* write 0 to WLAON_WARM_SW_ENTRY to prevent Q6 from
|
||||
* continuing warm path and entering dead loop.
|
||||
*/
|
||||
ath11k_pci_write32(ab, WLAON_WARM_SW_ENTRY, 0);
|
||||
mdelay(10);
|
||||
|
||||
val = ath11k_pci_read32(ab, WLAON_WARM_SW_ENTRY);
|
||||
ath11k_dbg(ab, ATH11K_DBG_PCI, "WLAON_WARM_SW_ENTRY 0x%x\n", val);
|
||||
|
||||
/* A read clear register. clear the register to prevent
|
||||
* Q6 from entering wrong code path.
|
||||
*/
|
||||
val = ath11k_pci_read32(ab, WLAON_SOC_RESET_CAUSE_REG);
|
||||
ath11k_dbg(ab, ATH11K_DBG_PCI, "soc reset cause:%d\n", val);
|
||||
}
|
||||
|
||||
static void ath11k_pci_force_wake(struct ath11k_base *ab)
|
||||
{
|
||||
ath11k_pci_write32(ab, PCIE_SOC_WAKE_PCIE_LOCAL_REG, 1);
|
||||
mdelay(5);
|
||||
}
|
||||
|
||||
static void ath11k_pci_sw_reset(struct ath11k_base *ab)
|
||||
{
|
||||
ath11k_pci_soc_global_reset(ab);
|
||||
ath11k_mhi_clear_vector(ab);
|
||||
ath11k_pci_soc_global_reset(ab);
|
||||
ath11k_mhi_set_mhictrl_reset(ab);
|
||||
ath11k_pci_clear_dbg_registers(ab);
|
||||
}
|
||||
|
||||
int ath11k_pci_get_msi_irq(struct device *dev, unsigned int vector)
|
||||
{
|
||||
struct pci_dev *pci_dev = to_pci_dev(dev);
|
||||
|
||||
return pci_irq_vector(pci_dev, vector);
|
||||
}
|
||||
|
||||
static void ath11k_pci_get_msi_address(struct ath11k_base *ab, u32 *msi_addr_lo,
|
||||
u32 *msi_addr_hi)
|
||||
{
|
||||
struct pci_dev *pci_dev = to_pci_dev(ab->dev);
|
||||
|
||||
pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_LO,
|
||||
msi_addr_lo);
|
||||
|
||||
pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI,
|
||||
msi_addr_hi);
|
||||
}
|
||||
|
||||
int ath11k_pci_get_user_msi_assignment(struct ath11k_pci *ab_pci, char *user_name,
|
||||
int *num_vectors, u32 *user_base_data,
|
||||
u32 *base_vector)
|
||||
{
|
||||
struct ath11k_base *ab = ab_pci->ab;
|
||||
int idx;
|
||||
|
||||
for (idx = 0; idx < msi_config.total_users; idx++) {
|
||||
if (strcmp(user_name, msi_config.users[idx].name) == 0) {
|
||||
*num_vectors = msi_config.users[idx].num_vectors;
|
||||
*user_base_data = msi_config.users[idx].base_vector
|
||||
+ ab_pci->msi_ep_base_data;
|
||||
*base_vector = msi_config.users[idx].base_vector;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_PCI, "Assign MSI to user: %s, num_vectors: %d, user_base_data: %u, base_vector: %u\n",
|
||||
user_name, *num_vectors, *user_base_data,
|
||||
*base_vector);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
ath11k_err(ab, "Failed to find MSI assignment for %s!\n", user_name);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ath11k_get_user_msi_assignment(struct ath11k_base *ab, char *user_name,
|
||||
int *num_vectors, u32 *user_base_data,
|
||||
u32 *base_vector)
|
||||
{
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
|
||||
return ath11k_pci_get_user_msi_assignment(ab_pci, user_name,
|
||||
num_vectors, user_base_data,
|
||||
base_vector);
|
||||
}
|
||||
|
||||
static void ath11k_pci_free_ext_irq(struct ath11k_base *ab)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
|
||||
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
|
||||
|
||||
for (j = 0; j < irq_grp->num_irq; j++)
|
||||
free_irq(ab->irq_num[irq_grp->irqs[j]], irq_grp);
|
||||
|
||||
netif_napi_del(&irq_grp->napi);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_pci_free_irq(struct ath11k_base *ab)
|
||||
{
|
||||
int i, irq_idx;
|
||||
|
||||
for (i = 0; i < ab->hw_params.ce_count; i++) {
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
|
||||
continue;
|
||||
irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
|
||||
free_irq(ab->irq_num[irq_idx], &ab->ce.ce_pipe[i]);
|
||||
}
|
||||
|
||||
ath11k_pci_free_ext_irq(ab);
|
||||
}
|
||||
|
||||
static void ath11k_pci_ce_irq_enable(struct ath11k_base *ab, u16 ce_id)
|
||||
{
|
||||
u32 irq_idx;
|
||||
|
||||
irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
|
||||
enable_irq(ab->irq_num[irq_idx]);
|
||||
}
|
||||
|
||||
static void ath11k_pci_ce_irq_disable(struct ath11k_base *ab, u16 ce_id)
|
||||
{
|
||||
u32 irq_idx;
|
||||
|
||||
irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + ce_id;
|
||||
disable_irq_nosync(ab->irq_num[irq_idx]);
|
||||
}
|
||||
|
||||
static void ath11k_pci_ce_irqs_disable(struct ath11k_base *ab)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ab->hw_params.ce_count; i++) {
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
|
||||
continue;
|
||||
ath11k_pci_ce_irq_disable(ab, i);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_pci_sync_ce_irqs(struct ath11k_base *ab)
|
||||
{
|
||||
int i;
|
||||
int irq_idx;
|
||||
|
||||
for (i = 0; i < ab->hw_params.ce_count; i++) {
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
|
||||
continue;
|
||||
|
||||
irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
|
||||
synchronize_irq(ab->irq_num[irq_idx]);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_pci_ce_tasklet(unsigned long data)
|
||||
{
|
||||
struct ath11k_ce_pipe *ce_pipe = (struct ath11k_ce_pipe *)data;
|
||||
|
||||
ath11k_ce_per_engine_service(ce_pipe->ab, ce_pipe->pipe_num);
|
||||
|
||||
ath11k_pci_ce_irq_enable(ce_pipe->ab, ce_pipe->pipe_num);
|
||||
}
|
||||
|
||||
static irqreturn_t ath11k_pci_ce_interrupt_handler(int irq, void *arg)
|
||||
{
|
||||
struct ath11k_ce_pipe *ce_pipe = arg;
|
||||
|
||||
ath11k_pci_ce_irq_disable(ce_pipe->ab, ce_pipe->pipe_num);
|
||||
tasklet_schedule(&ce_pipe->intr_tq);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void ath11k_pci_ext_grp_disable(struct ath11k_ext_irq_grp *irq_grp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < irq_grp->num_irq; i++)
|
||||
disable_irq_nosync(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
|
||||
}
|
||||
|
||||
static void __ath11k_pci_ext_irq_disable(struct ath11k_base *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
|
||||
struct ath11k_ext_irq_grp *irq_grp = &sc->ext_irq_grp[i];
|
||||
|
||||
ath11k_pci_ext_grp_disable(irq_grp);
|
||||
|
||||
napi_synchronize(&irq_grp->napi);
|
||||
napi_disable(&irq_grp->napi);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_pci_ext_grp_enable(struct ath11k_ext_irq_grp *irq_grp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < irq_grp->num_irq; i++)
|
||||
enable_irq(irq_grp->ab->irq_num[irq_grp->irqs[i]]);
|
||||
}
|
||||
|
||||
static void ath11k_pci_ext_irq_enable(struct ath11k_base *ab)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
|
||||
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
|
||||
|
||||
napi_enable(&irq_grp->napi);
|
||||
ath11k_pci_ext_grp_enable(irq_grp);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_pci_sync_ext_irqs(struct ath11k_base *ab)
|
||||
{
|
||||
int i, j, irq_idx;
|
||||
|
||||
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
|
||||
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
|
||||
|
||||
for (j = 0; j < irq_grp->num_irq; j++) {
|
||||
irq_idx = irq_grp->irqs[j];
|
||||
synchronize_irq(ab->irq_num[irq_idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_pci_ext_irq_disable(struct ath11k_base *ab)
|
||||
{
|
||||
__ath11k_pci_ext_irq_disable(ab);
|
||||
ath11k_pci_sync_ext_irqs(ab);
|
||||
}
|
||||
|
||||
static int ath11k_pci_ext_grp_napi_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct ath11k_ext_irq_grp *irq_grp = container_of(napi,
|
||||
struct ath11k_ext_irq_grp,
|
||||
napi);
|
||||
struct ath11k_base *ab = irq_grp->ab;
|
||||
int work_done;
|
||||
|
||||
work_done = ath11k_dp_service_srng(ab, irq_grp, budget);
|
||||
if (work_done < budget) {
|
||||
napi_complete_done(napi, work_done);
|
||||
ath11k_pci_ext_grp_enable(irq_grp);
|
||||
}
|
||||
|
||||
if (work_done > budget)
|
||||
work_done = budget;
|
||||
|
||||
return work_done;
|
||||
}
|
||||
|
||||
static irqreturn_t ath11k_pci_ext_interrupt_handler(int irq, void *arg)
|
||||
{
|
||||
struct ath11k_ext_irq_grp *irq_grp = arg;
|
||||
|
||||
ath11k_dbg(irq_grp->ab, ATH11K_DBG_PCI, "ext irq:%d\n", irq);
|
||||
|
||||
ath11k_pci_ext_grp_disable(irq_grp);
|
||||
|
||||
napi_schedule(&irq_grp->napi);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int ath11k_pci_ext_irq_config(struct ath11k_base *ab)
|
||||
{
|
||||
int i, j, ret, num_vectors = 0;
|
||||
u32 user_base_data = 0, base_vector = 0;
|
||||
|
||||
ret = ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab), "DP",
|
||||
&num_vectors,
|
||||
&user_base_data,
|
||||
&base_vector);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
for (i = 0; i < ATH11K_EXT_IRQ_GRP_NUM_MAX; i++) {
|
||||
struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
|
||||
u32 num_irq = 0;
|
||||
|
||||
irq_grp->ab = ab;
|
||||
irq_grp->grp_id = i;
|
||||
init_dummy_netdev(&irq_grp->napi_ndev);
|
||||
netif_napi_add(&irq_grp->napi_ndev, &irq_grp->napi,
|
||||
ath11k_pci_ext_grp_napi_poll, NAPI_POLL_WEIGHT);
|
||||
|
||||
if (ab->hw_params.ring_mask->tx[i] ||
|
||||
ab->hw_params.ring_mask->rx[i] ||
|
||||
ab->hw_params.ring_mask->rx_err[i] ||
|
||||
ab->hw_params.ring_mask->rx_wbm_rel[i] ||
|
||||
ab->hw_params.ring_mask->reo_status[i] ||
|
||||
ab->hw_params.ring_mask->rxdma2host[i] ||
|
||||
ab->hw_params.ring_mask->host2rxdma[i] ||
|
||||
ab->hw_params.ring_mask->rx_mon_status[i]) {
|
||||
num_irq = 1;
|
||||
}
|
||||
|
||||
irq_grp->num_irq = num_irq;
|
||||
irq_grp->irqs[0] = base_vector + i;
|
||||
|
||||
for (j = 0; j < irq_grp->num_irq; j++) {
|
||||
int irq_idx = irq_grp->irqs[j];
|
||||
int vector = (i % num_vectors) + base_vector;
|
||||
int irq = ath11k_pci_get_msi_irq(ab->dev, vector);
|
||||
|
||||
ab->irq_num[irq_idx] = irq;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_PCI,
|
||||
"irq:%d group:%d\n", irq, i);
|
||||
ret = request_irq(irq, ath11k_pci_ext_interrupt_handler,
|
||||
IRQF_SHARED,
|
||||
"DP_EXT_IRQ", irq_grp);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed request irq %d: %d\n",
|
||||
vector, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
disable_irq_nosync(ab->irq_num[irq_idx]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_pci_config_irq(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_ce_pipe *ce_pipe;
|
||||
u32 msi_data_start;
|
||||
u32 msi_data_count;
|
||||
u32 msi_irq_start;
|
||||
unsigned int msi_data;
|
||||
int irq, i, ret, irq_idx;
|
||||
|
||||
ret = ath11k_pci_get_user_msi_assignment(ath11k_pci_priv(ab),
|
||||
"CE", &msi_data_count,
|
||||
&msi_data_start, &msi_irq_start);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Configure CE irqs */
|
||||
for (i = 0; i < ab->hw_params.ce_count; i++) {
|
||||
msi_data = (i % msi_data_count) + msi_irq_start;
|
||||
irq = ath11k_pci_get_msi_irq(ab->dev, msi_data);
|
||||
ce_pipe = &ab->ce.ce_pipe[i];
|
||||
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
|
||||
continue;
|
||||
|
||||
irq_idx = ATH11K_PCI_IRQ_CE0_OFFSET + i;
|
||||
|
||||
tasklet_init(&ce_pipe->intr_tq, ath11k_pci_ce_tasklet,
|
||||
(unsigned long)ce_pipe);
|
||||
|
||||
ret = request_irq(irq, ath11k_pci_ce_interrupt_handler,
|
||||
IRQF_SHARED, irq_name[irq_idx],
|
||||
ce_pipe);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to request irq %d: %d\n",
|
||||
irq_idx, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ab->irq_num[irq_idx] = irq;
|
||||
ath11k_pci_ce_irq_disable(ab, i);
|
||||
}
|
||||
|
||||
ret = ath11k_pci_ext_irq_config(ab);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_pci_init_qmi_ce_config(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_qmi_ce_cfg *cfg = &ab->qmi.ce_cfg;
|
||||
|
||||
cfg->tgt_ce = ab->hw_params.target_ce_config;
|
||||
cfg->tgt_ce_len = ab->hw_params.target_ce_count;
|
||||
|
||||
cfg->svc_to_ce_map = ab->hw_params.svc_to_ce_map;
|
||||
cfg->svc_to_ce_map_len = ab->hw_params.svc_to_ce_map_len;
|
||||
ab->qmi.service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390;
|
||||
}
|
||||
|
||||
static void ath11k_pci_ce_irqs_enable(struct ath11k_base *ab)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ab->hw_params.ce_count; i++) {
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
|
||||
continue;
|
||||
ath11k_pci_ce_irq_enable(ab, i);
|
||||
}
|
||||
}
|
||||
|
||||
static int ath11k_pci_enable_msi(struct ath11k_pci *ab_pci)
|
||||
{
|
||||
struct ath11k_base *ab = ab_pci->ab;
|
||||
struct msi_desc *msi_desc;
|
||||
int num_vectors;
|
||||
int ret;
|
||||
|
||||
num_vectors = pci_alloc_irq_vectors(ab_pci->pdev,
|
||||
msi_config.total_vectors,
|
||||
msi_config.total_vectors,
|
||||
PCI_IRQ_MSI);
|
||||
if (num_vectors != msi_config.total_vectors) {
|
||||
ath11k_err(ab, "failed to get %d MSI vectors, only %d available",
|
||||
msi_config.total_vectors, num_vectors);
|
||||
|
||||
if (num_vectors >= 0)
|
||||
return -EINVAL;
|
||||
else
|
||||
return num_vectors;
|
||||
}
|
||||
|
||||
msi_desc = irq_get_msi_desc(ab_pci->pdev->irq);
|
||||
if (!msi_desc) {
|
||||
ath11k_err(ab, "msi_desc is NULL!\n");
|
||||
ret = -EINVAL;
|
||||
goto free_msi_vector;
|
||||
}
|
||||
|
||||
ab_pci->msi_ep_base_data = msi_desc->msg.data;
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_PCI, "msi base data is %d\n", ab_pci->msi_ep_base_data);
|
||||
|
||||
return 0;
|
||||
|
||||
free_msi_vector:
|
||||
pci_free_irq_vectors(ab_pci->pdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_pci_disable_msi(struct ath11k_pci *ab_pci)
|
||||
{
|
||||
pci_free_irq_vectors(ab_pci->pdev);
|
||||
}
|
||||
|
||||
static int ath11k_pci_claim(struct ath11k_pci *ab_pci, struct pci_dev *pdev)
|
||||
{
|
||||
struct ath11k_base *ab = ab_pci->ab;
|
||||
u16 device_id;
|
||||
int ret = 0;
|
||||
|
||||
pci_read_config_word(pdev, PCI_DEVICE_ID, &device_id);
|
||||
if (device_id != ab_pci->dev_id) {
|
||||
ath11k_err(ab, "pci device id mismatch: 0x%x 0x%x\n",
|
||||
device_id, ab_pci->dev_id);
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = pci_assign_resource(pdev, ATH11K_PCI_BAR_NUM);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to assign pci resource: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = pci_enable_device(pdev);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to enable pci device: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = pci_request_region(pdev, ATH11K_PCI_BAR_NUM, "ath11k_pci");
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to request pci region: %d\n", ret);
|
||||
goto disable_device;
|
||||
}
|
||||
|
||||
ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(ATH11K_PCI_DMA_MASK));
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to set pci dma mask to %d: %d\n",
|
||||
ATH11K_PCI_DMA_MASK, ret);
|
||||
goto release_region;
|
||||
}
|
||||
|
||||
ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(ATH11K_PCI_DMA_MASK));
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to set pci consistent dma mask to %d: %d\n",
|
||||
ATH11K_PCI_DMA_MASK, ret);
|
||||
goto release_region;
|
||||
}
|
||||
|
||||
pci_set_master(pdev);
|
||||
|
||||
ab->mem_len = pci_resource_len(pdev, ATH11K_PCI_BAR_NUM);
|
||||
ab->mem = pci_iomap(pdev, ATH11K_PCI_BAR_NUM, 0);
|
||||
if (!ab->mem) {
|
||||
ath11k_err(ab, "failed to map pci bar %d\n", ATH11K_PCI_BAR_NUM);
|
||||
ret = -EIO;
|
||||
goto clear_master;
|
||||
}
|
||||
|
||||
ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot pci_mem 0x%pK\n", ab->mem);
|
||||
return 0;
|
||||
|
||||
clear_master:
|
||||
pci_clear_master(pdev);
|
||||
release_region:
|
||||
pci_release_region(pdev, ATH11K_PCI_BAR_NUM);
|
||||
disable_device:
|
||||
pci_disable_device(pdev);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_pci_free_region(struct ath11k_pci *ab_pci)
|
||||
{
|
||||
struct ath11k_base *ab = ab_pci->ab;
|
||||
struct pci_dev *pci_dev = ab_pci->pdev;
|
||||
|
||||
pci_iounmap(pci_dev, ab->mem);
|
||||
ab->mem = NULL;
|
||||
pci_clear_master(pci_dev);
|
||||
pci_release_region(pci_dev, ATH11K_PCI_BAR_NUM);
|
||||
if (pci_is_enabled(pci_dev))
|
||||
pci_disable_device(pci_dev);
|
||||
}
|
||||
|
||||
static int ath11k_pci_power_up(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
int ret;
|
||||
|
||||
ath11k_pci_sw_reset(ab_pci->ab);
|
||||
|
||||
ret = ath11k_mhi_start(ab_pci);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to start mhi: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath11k_pci_power_down(struct ath11k_base *ab)
|
||||
{
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
|
||||
ath11k_mhi_stop(ab_pci);
|
||||
ath11k_pci_force_wake(ab_pci->ab);
|
||||
ath11k_pci_sw_reset(ab_pci->ab);
|
||||
}
|
||||
|
||||
static void ath11k_pci_kill_tasklets(struct ath11k_base *ab)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ab->hw_params.ce_count; i++) {
|
||||
struct ath11k_ce_pipe *ce_pipe = &ab->ce.ce_pipe[i];
|
||||
|
||||
if (ath11k_ce_get_attr_flags(ab, i) & CE_ATTR_DIS_INTR)
|
||||
continue;
|
||||
|
||||
tasklet_kill(&ce_pipe->intr_tq);
|
||||
}
|
||||
}
|
||||
|
||||
static void ath11k_pci_stop(struct ath11k_base *ab)
|
||||
{
|
||||
ath11k_pci_ce_irqs_disable(ab);
|
||||
ath11k_pci_sync_ce_irqs(ab);
|
||||
ath11k_pci_kill_tasklets(ab);
|
||||
ath11k_ce_cleanup_pipes(ab);
|
||||
}
|
||||
|
||||
static int ath11k_pci_start(struct ath11k_base *ab)
|
||||
{
|
||||
ath11k_pci_ce_irqs_enable(ab);
|
||||
ath11k_ce_rx_post_buf(ab);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath11k_pci_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
|
||||
u8 *ul_pipe, u8 *dl_pipe)
|
||||
{
|
||||
const struct service_to_pipe *entry;
|
||||
bool ul_set = false, dl_set = false;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ab->hw_params.svc_to_ce_map_len; i++) {
|
||||
entry = &ab->hw_params.svc_to_ce_map[i];
|
||||
|
||||
if (__le32_to_cpu(entry->service_id) != service_id)
|
||||
continue;
|
||||
|
||||
switch (__le32_to_cpu(entry->pipedir)) {
|
||||
case PIPEDIR_NONE:
|
||||
break;
|
||||
case PIPEDIR_IN:
|
||||
WARN_ON(dl_set);
|
||||
*dl_pipe = __le32_to_cpu(entry->pipenum);
|
||||
dl_set = true;
|
||||
break;
|
||||
case PIPEDIR_OUT:
|
||||
WARN_ON(ul_set);
|
||||
*ul_pipe = __le32_to_cpu(entry->pipenum);
|
||||
ul_set = true;
|
||||
break;
|
||||
case PIPEDIR_INOUT:
|
||||
WARN_ON(dl_set);
|
||||
WARN_ON(ul_set);
|
||||
*dl_pipe = __le32_to_cpu(entry->pipenum);
|
||||
*ul_pipe = __le32_to_cpu(entry->pipenum);
|
||||
dl_set = true;
|
||||
ul_set = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (WARN_ON(!ul_set || !dl_set))
|
||||
return -ENOENT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct ath11k_hif_ops ath11k_pci_hif_ops = {
|
||||
.start = ath11k_pci_start,
|
||||
.stop = ath11k_pci_stop,
|
||||
.read32 = ath11k_pci_read32,
|
||||
.write32 = ath11k_pci_write32,
|
||||
.power_down = ath11k_pci_power_down,
|
||||
.power_up = ath11k_pci_power_up,
|
||||
.irq_enable = ath11k_pci_ext_irq_enable,
|
||||
.irq_disable = ath11k_pci_ext_irq_disable,
|
||||
.get_msi_address = ath11k_pci_get_msi_address,
|
||||
.get_user_msi_vector = ath11k_get_user_msi_assignment,
|
||||
.map_service_to_pipe = ath11k_pci_map_service_to_pipe,
|
||||
};
|
||||
|
||||
static int ath11k_pci_probe(struct pci_dev *pdev,
|
||||
const struct pci_device_id *pci_dev)
|
||||
{
|
||||
struct ath11k_base *ab;
|
||||
struct ath11k_pci *ab_pci;
|
||||
enum ath11k_hw_rev hw_rev;
|
||||
int ret;
|
||||
|
||||
dev_warn(&pdev->dev, "WARNING: ath11k PCI support is experimental!\n");
|
||||
|
||||
switch (pci_dev->device) {
|
||||
case QCA6390_DEVICE_ID:
|
||||
hw_rev = ATH11K_HW_QCA6390_HW20;
|
||||
break;
|
||||
default:
|
||||
dev_err(&pdev->dev, "Unknown PCI device found: 0x%x\n",
|
||||
pci_dev->device);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
ab = ath11k_core_alloc(&pdev->dev, sizeof(*ab_pci), ATH11K_BUS_PCI,
|
||||
&ath11k_pci_bus_params);
|
||||
if (!ab) {
|
||||
dev_err(&pdev->dev, "failed to allocate ath11k base\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ab->dev = &pdev->dev;
|
||||
ab->hw_rev = hw_rev;
|
||||
pci_set_drvdata(pdev, ab);
|
||||
ab_pci = ath11k_pci_priv(ab);
|
||||
ab_pci->dev_id = pci_dev->device;
|
||||
ab_pci->ab = ab;
|
||||
ab_pci->pdev = pdev;
|
||||
ab->hif.ops = &ath11k_pci_hif_ops;
|
||||
pci_set_drvdata(pdev, ab);
|
||||
spin_lock_init(&ab_pci->window_lock);
|
||||
|
||||
ret = ath11k_pci_claim(ab_pci, pdev);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to claim device: %d\n", ret);
|
||||
goto err_free_core;
|
||||
}
|
||||
|
||||
ret = ath11k_pci_enable_msi(ab_pci);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to enable msi: %d\n", ret);
|
||||
goto err_pci_free_region;
|
||||
}
|
||||
|
||||
ret = ath11k_core_pre_init(ab);
|
||||
if (ret)
|
||||
goto err_pci_disable_msi;
|
||||
|
||||
ret = ath11k_mhi_register(ab_pci);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to register mhi: %d\n", ret);
|
||||
goto err_pci_disable_msi;
|
||||
}
|
||||
|
||||
ret = ath11k_hal_srng_init(ab);
|
||||
if (ret)
|
||||
goto err_mhi_unregister;
|
||||
|
||||
ret = ath11k_ce_alloc_pipes(ab);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to allocate ce pipes: %d\n", ret);
|
||||
goto err_hal_srng_deinit;
|
||||
}
|
||||
|
||||
ath11k_pci_init_qmi_ce_config(ab);
|
||||
|
||||
ret = ath11k_pci_config_irq(ab);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to config irq: %d\n", ret);
|
||||
goto err_ce_free;
|
||||
}
|
||||
|
||||
ret = ath11k_core_init(ab);
|
||||
if (ret) {
|
||||
ath11k_err(ab, "failed to init core: %d\n", ret);
|
||||
goto err_free_irq;
|
||||
}
|
||||
return 0;
|
||||
|
||||
err_free_irq:
|
||||
ath11k_pci_free_irq(ab);
|
||||
|
||||
err_ce_free:
|
||||
ath11k_ce_free_pipes(ab);
|
||||
|
||||
err_hal_srng_deinit:
|
||||
ath11k_hal_srng_deinit(ab);
|
||||
|
||||
err_mhi_unregister:
|
||||
ath11k_mhi_unregister(ab_pci);
|
||||
|
||||
err_pci_disable_msi:
|
||||
ath11k_pci_disable_msi(ab_pci);
|
||||
|
||||
err_pci_free_region:
|
||||
ath11k_pci_free_region(ab_pci);
|
||||
|
||||
err_free_core:
|
||||
ath11k_core_free(ab);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath11k_pci_remove(struct pci_dev *pdev)
|
||||
{
|
||||
struct ath11k_base *ab = pci_get_drvdata(pdev);
|
||||
struct ath11k_pci *ab_pci = ath11k_pci_priv(ab);
|
||||
|
||||
set_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags);
|
||||
ath11k_mhi_unregister(ab_pci);
|
||||
ath11k_pci_disable_msi(ab_pci);
|
||||
ath11k_pci_free_region(ab_pci);
|
||||
ath11k_pci_free_irq(ab);
|
||||
ath11k_core_free(ab);
|
||||
}
|
||||
|
||||
static void ath11k_pci_shutdown(struct pci_dev *pdev)
|
||||
{
|
||||
struct ath11k_base *ab = pci_get_drvdata(pdev);
|
||||
|
||||
ath11k_pci_power_down(ab);
|
||||
}
|
||||
|
||||
static struct pci_driver ath11k_pci_driver = {
|
||||
.name = "ath11k_pci",
|
||||
.id_table = ath11k_pci_id_table,
|
||||
.probe = ath11k_pci_probe,
|
||||
.remove = ath11k_pci_remove,
|
||||
.shutdown = ath11k_pci_shutdown,
|
||||
};
|
||||
|
||||
static int ath11k_pci_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pci_register_driver(&ath11k_pci_driver);
|
||||
if (ret)
|
||||
pr_err("failed to register ath11k pci driver: %d\n",
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
module_init(ath11k_pci_init);
|
||||
|
||||
static void ath11k_pci_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&ath11k_pci_driver);
|
||||
}
|
||||
|
||||
module_exit(ath11k_pci_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Driver support for Qualcomm Technologies 802.11ax WLAN PCIe devices");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
65
drivers/net/wireless/ath/ath11k/pci.h
Normal file
65
drivers/net/wireless/ath/ath11k/pci.h
Normal file
@ -0,0 +1,65 @@
|
||||
/* 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,
|
||||
peer = ath11k_peer_find_by_pdev_idx(ar->ab, ar->pdev_idx, param->peer_addr);
|
||||
if (peer) {
|
||||
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;
|
||||
}
|
||||
spin_unlock_bh(&ar->ab->base_lock);
|
||||
|
@ -9,6 +9,9 @@
|
||||
#include <linux/of.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[] = {
|
||||
{
|
||||
.data_type = QMI_OPT_FLAG,
|
||||
@ -1516,15 +1519,35 @@ static int ath11k_qmi_host_cap_send(struct ath11k_base *ab)
|
||||
req.bdf_support_valid = 1;
|
||||
req.bdf_support = 1;
|
||||
|
||||
req.m3_support_valid = 0;
|
||||
req.m3_support = 0;
|
||||
|
||||
req.m3_cache_support_valid = 0;
|
||||
req.m3_cache_support = 0;
|
||||
if (ab->bus_params.m3_fw_support) {
|
||||
req.m3_support_valid = 1;
|
||||
req.m3_support = 1;
|
||||
req.m3_cache_support_valid = 1;
|
||||
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 = 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,
|
||||
qmi_wlanfw_host_cap_resp_msg_v01_ei, &resp);
|
||||
if (ret < 0)
|
||||
@ -1634,19 +1657,30 @@ static int ath11k_qmi_respond_fw_mem_request(struct ath11k_base *ab)
|
||||
|
||||
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,
|
||||
qmi_wlanfw_respond_mem_resp_msg_v01_ei, &resp);
|
||||
if (ret < 0)
|
||||
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,
|
||||
QMI_WLANFW_RESPOND_MEM_REQ_V01,
|
||||
QMI_WLANFW_RESPOND_MEM_REQ_MSG_V01_MAX_LEN,
|
||||
@ -1674,15 +1708,56 @@ out:
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
||||
for (i = 0, idx = 0; i < ab->qmi.mem_seg_count; i++) {
|
||||
switch (ab->qmi.target_mem[i].type) {
|
||||
case BDF_MEM_REGION_TYPE:
|
||||
ab->qmi.target_mem[idx].paddr = ATH11K_QMI_BDF_ADDRESS;
|
||||
ab->qmi.target_mem[idx].vaddr = ATH11K_QMI_BDF_ADDRESS;
|
||||
ab->qmi.target_mem[idx].paddr = ab->hw_params.bdf_addr;
|
||||
ab->qmi.target_mem[idx].vaddr = NULL;
|
||||
ab->qmi.target_mem[idx].size = ab->qmi.target_mem[i].size;
|
||||
ab->qmi.target_mem[idx].type = ab->qmi.target_mem[i].type;
|
||||
idx++;
|
||||
@ -1694,7 +1769,7 @@ static int ath11k_qmi_alloc_target_mem_chunk(struct ath11k_base *ab)
|
||||
}
|
||||
/* TODO ath11k does not support cold boot calibration */
|
||||
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].type = ab->qmi.target_mem[i].type;
|
||||
idx++;
|
||||
@ -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,
|
||||
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.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_build_timestamp,
|
||||
ab->qmi.target.fw_build_id);
|
||||
@ -1790,21 +1865,19 @@ ath11k_qmi_prepare_bdf_download(struct ath11k_base *ab, int type,
|
||||
struct qmi_wlanfw_bdf_download_req_msg_v01 *req,
|
||||
void __iomem *bdf_addr)
|
||||
{
|
||||
struct device *dev = ab->dev;
|
||||
char filename[ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE];
|
||||
const struct firmware *fw_entry;
|
||||
struct ath11k_board_data bd;
|
||||
u32 fw_size;
|
||||
int ret = 0;
|
||||
|
||||
memset(&bd, 0, sizeof(bd));
|
||||
int ret;
|
||||
|
||||
switch (type) {
|
||||
case ATH11K_QMI_FILE_TYPE_BDF_GOLDEN:
|
||||
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;
|
||||
return ret;
|
||||
}
|
||||
|
||||
fw_size = min_t(u32, ab->hw_params.fw.board_size, bd.len);
|
||||
@ -1812,12 +1885,12 @@ ath11k_qmi_prepare_bdf_download(struct ath11k_base *ab, int type,
|
||||
ath11k_core_free_bdf(ab, &bd);
|
||||
break;
|
||||
case ATH11K_QMI_FILE_TYPE_CALDATA:
|
||||
snprintf(filename, sizeof(filename),
|
||||
"%s/%s", ab->hw_params.fw.dir, ATH11K_QMI_DEFAULT_CAL_FILE_NAME);
|
||||
ret = request_firmware(&fw_entry, filename, dev);
|
||||
if (ret) {
|
||||
ath11k_warn(ab, "qmi failed to load CAL: %s\n", filename);
|
||||
goto out;
|
||||
fw_entry = ath11k_core_firmware_request(ab, ATH11K_DEFAULT_CAL_FILE);
|
||||
if (IS_ERR(fw_entry)) {
|
||||
ret = PTR_ERR(fw_entry);
|
||||
ath11k_warn(ab, "failed to load %s: %d\n",
|
||||
ATH11K_DEFAULT_CAL_FILE, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
fw_size = min_t(u32, ab->hw_params.fw.board_size,
|
||||
@ -1825,23 +1898,18 @@ ath11k_qmi_prepare_bdf_download(struct ath11k_base *ab, int type,
|
||||
|
||||
memcpy_toio(bdf_addr + ATH11K_QMI_CALDATA_OFFSET,
|
||||
fw_entry->data, fw_size);
|
||||
ath11k_info(ab, "qmi downloading BDF: %s, size: %zu\n",
|
||||
filename, fw_entry->size);
|
||||
|
||||
release_firmware(fw_entry);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
req->total_size = fw_size;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
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_resp_msg_v01 resp;
|
||||
@ -1854,7 +1922,7 @@ static int ath11k_qmi_load_bdf(struct ath11k_base *ab)
|
||||
return -ENOMEM;
|
||||
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) {
|
||||
ath11k_warn(ab, "qmi ioremap error for BDF\n");
|
||||
ret = -EIO;
|
||||
@ -1905,7 +1973,6 @@ static int ath11k_qmi_load_bdf(struct ath11k_base *ab)
|
||||
goto out_qmi_bdf;
|
||||
}
|
||||
}
|
||||
ath11k_info(ab, "qmi BDF downloaded\n");
|
||||
|
||||
out_qmi_bdf:
|
||||
iounmap(bdf_addr);
|
||||
@ -1914,8 +1981,143 @@ out:
|
||||
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)
|
||||
{
|
||||
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
|
||||
struct qmi_wlanfw_m3_info_req_msg_v01 req;
|
||||
struct qmi_wlanfw_m3_info_resp_msg_v01 resp;
|
||||
struct qmi_txn txn = {};
|
||||
@ -1923,8 +2125,20 @@ static int ath11k_qmi_wlanfw_m3_info_send(struct ath11k_base *ab)
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
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,
|
||||
qmi_wlanfw_m3_info_resp_msg_v01_ei, &resp);
|
||||
@ -2034,7 +2248,7 @@ static int ath11k_qmi_wlanfw_wlan_cfg_send(struct ath11k_base *ab)
|
||||
req->tgt_cfg_valid = 1;
|
||||
/* This is number of CE configs */
|
||||
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_dir = ce_cfg[pipe_num].pipedir;
|
||||
req->tgt_cfg[pipe_num].nentries = ce_cfg[pipe_num].nentries;
|
||||
@ -2181,7 +2395,10 @@ static void ath11k_qmi_event_load_bdf(struct ath11k_qmi *qmi)
|
||||
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) {
|
||||
ath11k_warn(ab, "qmi failed to load board data file:%d\n", ret);
|
||||
return;
|
||||
@ -2220,10 +2437,20 @@ static void ath11k_qmi_msg_mem_request_cb(struct qmi_handle *qmi_hdl,
|
||||
msg->mem_seg[i].type, msg->mem_seg[i].size);
|
||||
}
|
||||
|
||||
ret = ath11k_qmi_alloc_target_mem_chunk(ab);
|
||||
if (ret < 0) {
|
||||
ath11k_warn(ab, "qmi failed to alloc target memory:%d\n", ret);
|
||||
return;
|
||||
if (ab->bus_params.fixed_mem_region) {
|
||||
ret = ath11k_qmi_assign_target_mem_chunk(ab);
|
||||
if (ret) {
|
||||
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);
|
||||
@ -2265,21 +2492,21 @@ static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = {
|
||||
.type = QMI_INDICATION,
|
||||
.msg_id = QMI_WLFW_REQUEST_MEM_IND_V01,
|
||||
.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,
|
||||
},
|
||||
{
|
||||
.type = QMI_INDICATION,
|
||||
.msg_id = QMI_WLFW_FW_MEM_READY_IND_V01,
|
||||
.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,
|
||||
},
|
||||
{
|
||||
.type = QMI_INDICATION,
|
||||
.msg_id = QMI_WLFW_FW_READY_IND_V01,
|
||||
.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,
|
||||
},
|
||||
{
|
||||
@ -2287,7 +2514,7 @@ static const struct qmi_msg_handler ath11k_qmi_msg_handlers[] = {
|
||||
.msg_id = QMI_WLFW_COLD_BOOT_CAL_DONE_IND_V01,
|
||||
.ei = qmi_wlanfw_cold_boot_cal_done_ind_msg_v01_ei,
|
||||
.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,
|
||||
},
|
||||
};
|
||||
@ -2416,9 +2643,10 @@ int ath11k_qmi_init_service(struct ath11k_base *ab)
|
||||
|
||||
ret = qmi_add_lookup(&ab->qmi.handle, ATH11K_QMI_WLFW_SERVICE_ID_V01,
|
||||
ATH11K_QMI_WLFW_SERVICE_VERS_V01,
|
||||
ATH11K_QMI_WLFW_SERVICE_INS_ID_V01);
|
||||
ab->qmi.service_ins_id);
|
||||
if (ret < 0) {
|
||||
ath11k_warn(ab, "failed to add qmi lookup\n");
|
||||
destroy_workqueue(ab->qmi.event_wq);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -2430,5 +2658,7 @@ void ath11k_qmi_deinit_service(struct ath11k_base *ab)
|
||||
qmi_handle_release(&ab->qmi.handle);
|
||||
cancel_work_sync(&ab->qmi.event_work);
|
||||
destroy_workqueue(ab->qmi.event_wq);
|
||||
ath11k_qmi_m3_free(ab);
|
||||
ath11k_qmi_free_target_mem_chunk(ab);
|
||||
}
|
||||
|
||||
|
@ -12,18 +12,18 @@
|
||||
#define ATH11K_HOST_VERSION_STRING "WIN"
|
||||
#define ATH11K_QMI_WLANFW_TIMEOUT_MS 5000
|
||||
#define ATH11K_QMI_MAX_BDF_FILE_NAME_SIZE 64
|
||||
#define ATH11K_QMI_BDF_ADDRESS 0x4B0C0000
|
||||
#define ATH11K_QMI_BDF_MAX_SIZE (256 * 1024)
|
||||
#define ATH11K_QMI_CALDATA_OFFSET (128 * 1024)
|
||||
#define ATH11K_QMI_WLANFW_MAX_BUILD_ID_LEN_V01 128
|
||||
#define ATH11K_QMI_WLFW_SERVICE_ID_V01 0x45
|
||||
#define ATH11K_QMI_WLFW_SERVICE_VERS_V01 0x01
|
||||
#define ATH11K_QMI_WLFW_SERVICE_INS_ID_V01 0x02
|
||||
#define ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390 0x01
|
||||
#define ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ8074 0x02
|
||||
#define ATH11K_QMI_WLANFW_MAX_TIMESTAMP_LEN_V01 32
|
||||
#define ATH11K_QMI_RESP_LEN_MAX 8192
|
||||
#define ATH11K_QMI_WLANFW_MAX_NUM_MEM_SEG_V01 32
|
||||
#define ATH11K_QMI_CALDB_SIZE 0x480000
|
||||
#define ATH11K_QMI_DEFAULT_CAL_FILE_NAME "caldata.bin"
|
||||
|
||||
#define QMI_WLFW_REQUEST_MEM_IND_V01 0x0035
|
||||
#define QMI_WLFW_FW_MEM_READY_IND_V01 0x0037
|
||||
@ -42,6 +42,11 @@ enum ath11k_qmi_file_type {
|
||||
ATH11K_QMI_MAX_FILE_TYPE,
|
||||
};
|
||||
|
||||
enum ath11k_qmi_bdf_type {
|
||||
ATH11K_QMI_BDF_TYPE_BIN = 0,
|
||||
ATH11K_QMI_BDF_TYPE_ELF = 1,
|
||||
};
|
||||
|
||||
enum ath11k_qmi_event_type {
|
||||
ATH11K_QMI_EVENT_SERVER_ARRIVE,
|
||||
ATH11K_QMI_EVENT_SERVER_EXIT,
|
||||
@ -85,7 +90,7 @@ struct target_mem_chunk {
|
||||
u32 size;
|
||||
u32 type;
|
||||
dma_addr_t paddr;
|
||||
u32 vaddr;
|
||||
u32 *vaddr;
|
||||
};
|
||||
|
||||
struct target_info {
|
||||
@ -98,6 +103,12 @@ struct target_info {
|
||||
char fw_build_id[ATH11K_QMI_WLANFW_MAX_BUILD_ID_LEN_V01 + 1];
|
||||
};
|
||||
|
||||
struct m3_mem_region {
|
||||
u32 size;
|
||||
dma_addr_t paddr;
|
||||
void *vaddr;
|
||||
};
|
||||
|
||||
struct ath11k_qmi {
|
||||
struct ath11k_base *ab;
|
||||
struct qmi_handle handle;
|
||||
@ -112,6 +123,8 @@ struct ath11k_qmi {
|
||||
u32 target_mem_mode;
|
||||
u8 cal_done;
|
||||
struct target_info target;
|
||||
struct m3_mem_region m3_mem;
|
||||
unsigned int service_ins_id;
|
||||
};
|
||||
|
||||
#define QMI_WLANFW_HOST_CAP_REQ_MSG_V01_MAX_LEN 189
|
||||
@ -254,6 +267,14 @@ struct qmi_wlanfw_fw_mem_ready_ind_msg_v01 {
|
||||
char placeholder;
|
||||
};
|
||||
|
||||
struct qmi_wlanfw_fw_ready_ind_msg_v01 {
|
||||
char placeholder;
|
||||
};
|
||||
|
||||
struct qmi_wlanfw_fw_cold_cal_done_ind_msg_v01 {
|
||||
char placeholder;
|
||||
};
|
||||
|
||||
#define QMI_WLANFW_CAP_REQ_MSG_V01_MAX_LEN 0
|
||||
#define QMI_WLANFW_CAP_RESP_MSG_V01_MAX_LEN 207
|
||||
#define QMI_WLANFW_CAP_REQ_V01 0x0024
|
||||
|
@ -699,7 +699,7 @@ void ath11k_reg_free(struct ath11k_base *ab)
|
||||
{
|
||||
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->new_regd[i]);
|
||||
}
|
||||
|
@ -773,6 +773,8 @@ static int ath11k_spectral_process_data(struct ath11k *ar,
|
||||
i += sizeof(*tlv) + tlv_len;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
err:
|
||||
kfree(fft_sample);
|
||||
unlock:
|
||||
@ -954,10 +956,8 @@ int ath11k_spectral_init(struct ath11k_base *ab)
|
||||
int i;
|
||||
|
||||
if (!test_bit(WMI_TLV_SERVICE_FREQINFO_IN_METADATA,
|
||||
ab->wmi_ab.svc_map)) {
|
||||
ath11k_info(ab, "spectral not supported\n");
|
||||
ab->wmi_ab.svc_map))
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < ab->num_radios; i++) {
|
||||
ar = ab->pdevs[i].ar;
|
||||
@ -966,10 +966,8 @@ int ath11k_spectral_init(struct ath11k_base *ab)
|
||||
ret = ath11k_dbring_get_cap(ar->ab, ar->pdev_idx,
|
||||
WMI_DIRECT_BUF_SPECTRAL,
|
||||
&db_cap);
|
||||
if (ret) {
|
||||
ath11k_info(ab, "spectral not enabled for pdev %d\n", i);
|
||||
if (ret)
|
||||
continue;
|
||||
}
|
||||
|
||||
idr_init(&sp->rx_ring.bufs_idr);
|
||||
spin_lock_init(&sp->rx_ring.idr_lock);
|
||||
|
@ -338,7 +338,7 @@ ath11k_pull_mac_phy_cap_svc_ready_ext(struct ath11k_pdev_wmi *wmi_handle,
|
||||
mac_phy_caps = wmi_mac_phy_caps + phy_idx;
|
||||
|
||||
pdev->pdev_id = mac_phy_caps->pdev_id;
|
||||
pdev_cap->supported_bands = mac_phy_caps->supported_bands;
|
||||
pdev_cap->supported_bands |= mac_phy_caps->supported_bands;
|
||||
pdev_cap->ampdu_density = mac_phy_caps->ampdu_density;
|
||||
|
||||
/* Take non-zero tx/rx chainmask. If tx/rx chainmask differs from
|
||||
@ -371,27 +371,33 @@ ath11k_pull_mac_phy_cap_svc_ready_ext(struct ath11k_pdev_wmi *wmi_handle,
|
||||
pdev_cap->rx_chain_mask_shift =
|
||||
find_first_bit((unsigned long *)&pdev_cap->rx_chain_mask, 32);
|
||||
|
||||
cap_band = &pdev_cap->band[NL80211_BAND_2GHZ];
|
||||
cap_band->max_bw_supported = mac_phy_caps->max_bw_supported_2g;
|
||||
cap_band->ht_cap_info = mac_phy_caps->ht_cap_info_2g;
|
||||
cap_band->he_cap_info[0] = mac_phy_caps->he_cap_info_2g;
|
||||
cap_band->he_cap_info[1] = mac_phy_caps->he_cap_info_2g_ext;
|
||||
cap_band->he_mcs = mac_phy_caps->he_supp_mcs_2g;
|
||||
memcpy(cap_band->he_cap_phy_info, &mac_phy_caps->he_cap_phy_info_2g,
|
||||
sizeof(u32) * PSOC_HOST_MAX_PHY_SIZE);
|
||||
memcpy(&cap_band->he_ppet, &mac_phy_caps->he_ppet2g,
|
||||
sizeof(struct ath11k_ppe_threshold));
|
||||
if (mac_phy_caps->supported_bands & WMI_HOST_WLAN_2G_CAP) {
|
||||
cap_band = &pdev_cap->band[NL80211_BAND_2GHZ];
|
||||
cap_band->phy_id = mac_phy_caps->phy_id;
|
||||
cap_band->max_bw_supported = mac_phy_caps->max_bw_supported_2g;
|
||||
cap_band->ht_cap_info = mac_phy_caps->ht_cap_info_2g;
|
||||
cap_band->he_cap_info[0] = mac_phy_caps->he_cap_info_2g;
|
||||
cap_band->he_cap_info[1] = mac_phy_caps->he_cap_info_2g_ext;
|
||||
cap_band->he_mcs = mac_phy_caps->he_supp_mcs_2g;
|
||||
memcpy(cap_band->he_cap_phy_info, &mac_phy_caps->he_cap_phy_info_2g,
|
||||
sizeof(u32) * PSOC_HOST_MAX_PHY_SIZE);
|
||||
memcpy(&cap_band->he_ppet, &mac_phy_caps->he_ppet2g,
|
||||
sizeof(struct ath11k_ppe_threshold));
|
||||
}
|
||||
|
||||
cap_band = &pdev_cap->band[NL80211_BAND_5GHZ];
|
||||
cap_band->max_bw_supported = mac_phy_caps->max_bw_supported_5g;
|
||||
cap_band->ht_cap_info = mac_phy_caps->ht_cap_info_5g;
|
||||
cap_band->he_cap_info[0] = mac_phy_caps->he_cap_info_5g;
|
||||
cap_band->he_cap_info[1] = mac_phy_caps->he_cap_info_5g_ext;
|
||||
cap_band->he_mcs = mac_phy_caps->he_supp_mcs_5g;
|
||||
memcpy(cap_band->he_cap_phy_info, &mac_phy_caps->he_cap_phy_info_5g,
|
||||
sizeof(u32) * PSOC_HOST_MAX_PHY_SIZE);
|
||||
memcpy(&cap_band->he_ppet, &mac_phy_caps->he_ppet5g,
|
||||
sizeof(struct ath11k_ppe_threshold));
|
||||
if (mac_phy_caps->supported_bands & WMI_HOST_WLAN_5G_CAP) {
|
||||
cap_band = &pdev_cap->band[NL80211_BAND_5GHZ];
|
||||
cap_band->phy_id = mac_phy_caps->phy_id;
|
||||
cap_band->max_bw_supported = mac_phy_caps->max_bw_supported_5g;
|
||||
cap_band->ht_cap_info = mac_phy_caps->ht_cap_info_5g;
|
||||
cap_band->he_cap_info[0] = mac_phy_caps->he_cap_info_5g;
|
||||
cap_band->he_cap_info[1] = mac_phy_caps->he_cap_info_5g_ext;
|
||||
cap_band->he_mcs = mac_phy_caps->he_supp_mcs_5g;
|
||||
memcpy(cap_band->he_cap_phy_info, &mac_phy_caps->he_cap_phy_info_5g,
|
||||
sizeof(u32) * PSOC_HOST_MAX_PHY_SIZE);
|
||||
memcpy(&cap_band->he_ppet, &mac_phy_caps->he_ppet5g,
|
||||
sizeof(struct ath11k_ppe_threshold));
|
||||
}
|
||||
|
||||
cap_band = &pdev_cap->band[NL80211_BAND_6GHZ];
|
||||
cap_band->max_bw_supported = mac_phy_caps->max_bw_supported_5g;
|
||||
@ -3175,7 +3181,7 @@ static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi,
|
||||
(param->num_band_to_mac * sizeof(*band_to_mac));
|
||||
|
||||
len = sizeof(*cmd) + TLV_HDR_SIZE + sizeof(*cfg) + hw_mode_len +
|
||||
(sizeof(*host_mem_chunks) * WMI_MAX_MEM_REQS);
|
||||
(param->num_mem_chunks ? (sizeof(*host_mem_chunks) * WMI_MAX_MEM_REQS) : 0);
|
||||
|
||||
skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
|
||||
if (!skb)
|
||||
@ -3360,6 +3366,10 @@ int ath11k_wmi_cmd_init(struct ath11k_base *ab)
|
||||
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;
|
||||
|
||||
if (test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags))
|
||||
config.rx_decap_mode = TARGET_DECAP_MODE_RAW;
|
||||
|
||||
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;
|
||||
@ -3381,6 +3391,8 @@ int ath11k_wmi_cmd_init(struct ath11k_base *ab)
|
||||
config.twt_ap_pdev_count = ab->num_radios;
|
||||
config.twt_ap_sta_count = 1000;
|
||||
|
||||
ab->hw_params.hw_ops->wmi_init_config(ab, &config);
|
||||
|
||||
memcpy(&wmi_sc->wlan_resource_config, &config, sizeof(config));
|
||||
|
||||
init_param.res_cfg = &wmi_sc->wlan_resource_config;
|
||||
@ -3391,9 +3403,10 @@ int ath11k_wmi_cmd_init(struct ath11k_base *ab)
|
||||
if (wmi_sc->preferred_hw_mode == WMI_HOST_HW_MODE_SINGLE)
|
||||
init_param.hw_mode_id = WMI_HOST_HW_MODE_MAX;
|
||||
|
||||
init_param.num_band_to_mac = ab->num_radios;
|
||||
|
||||
ath11k_fill_band_to_mac_param(ab, init_param.band_to_mac);
|
||||
if (ab->hw_params.needs_band_to_mac) {
|
||||
init_param.num_band_to_mac = ab->num_radios;
|
||||
ath11k_fill_band_to_mac_param(ab, init_param.band_to_mac);
|
||||
}
|
||||
|
||||
return ath11k_init_cmd_send(&wmi_sc->wmi[0], &init_param);
|
||||
}
|
||||
@ -3688,6 +3701,8 @@ static int ath11k_wmi_tlv_hw_mode_caps(struct ath11k_base *soc,
|
||||
i++;
|
||||
}
|
||||
|
||||
ath11k_dbg(soc, ATH11K_DBG_WMI, "preferred_hw_mode:%d\n",
|
||||
soc->wmi_ab.preferred_hw_mode);
|
||||
if (soc->wmi_ab.preferred_hw_mode == WMI_HOST_HW_MODE_MAX)
|
||||
return -EINVAL;
|
||||
|
||||
@ -3778,6 +3793,7 @@ static int ath11k_wmi_tlv_ext_soc_hal_reg_caps_parse(struct ath11k_base *soc,
|
||||
struct wmi_tlv_svc_rdy_ext_parse *svc_rdy_ext = data;
|
||||
u8 hw_mode_id = svc_rdy_ext->pref_hw_mode_caps.hw_mode_id;
|
||||
u32 phy_id_map;
|
||||
int pdev_index = 0;
|
||||
int ret;
|
||||
|
||||
svc_rdy_ext->soc_hal_reg_caps = (struct wmi_soc_hal_reg_capabilities *)ptr;
|
||||
@ -3793,7 +3809,7 @@ static int ath11k_wmi_tlv_ext_soc_hal_reg_caps_parse(struct ath11k_base *soc,
|
||||
svc_rdy_ext->soc_hal_reg_caps,
|
||||
svc_rdy_ext->mac_phy_caps,
|
||||
hw_mode_id, soc->num_radios,
|
||||
&soc->pdevs[soc->num_radios]);
|
||||
&soc->pdevs[pdev_index]);
|
||||
if (ret) {
|
||||
ath11k_warn(soc, "failed to extract mac caps, idx :%d\n",
|
||||
soc->num_radios);
|
||||
@ -3802,9 +3818,25 @@ static int ath11k_wmi_tlv_ext_soc_hal_reg_caps_parse(struct ath11k_base *soc,
|
||||
|
||||
soc->num_radios++;
|
||||
|
||||
/* For QCA6390, save mac_phy capability in the same pdev */
|
||||
if (soc->hw_params.single_pdev_only)
|
||||
pdev_index = 0;
|
||||
else
|
||||
pdev_index = soc->num_radios;
|
||||
|
||||
/* TODO: mac_phy_cap prints */
|
||||
phy_id_map >>= 1;
|
||||
}
|
||||
|
||||
/* For QCA6390, set num_radios to 1 because host manages
|
||||
* both 2G and 5G radio in one pdev.
|
||||
* Set pdev_id = 0 and 0 means soc level.
|
||||
*/
|
||||
if (soc->hw_params.single_pdev_only) {
|
||||
soc->num_radios = 1;
|
||||
soc->pdevs[0].pdev_id = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -5434,8 +5466,17 @@ static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *sk
|
||||
|
||||
pdev_idx = reg_info->phy_id;
|
||||
|
||||
if (pdev_idx >= ab->num_radios)
|
||||
goto fallback;
|
||||
if (pdev_idx >= ab->num_radios) {
|
||||
/* Process the event for phy0 only if single_pdev_only
|
||||
* is true. If pdev_idx is valid but not 0, discard the
|
||||
* event. Otherwise, it goes to fallback.
|
||||
*/
|
||||
if (ab->hw_params.single_pdev_only &&
|
||||
pdev_idx < ab->hw_params.num_rxmda_per_pdev)
|
||||
goto mem_free;
|
||||
else
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
/* Avoid multiple overwrites to default regd, during core
|
||||
* stop-start after mac registration.
|
||||
@ -6682,7 +6723,7 @@ int ath11k_wmi_connect(struct ath11k_base *ab)
|
||||
u8 wmi_ep_count;
|
||||
|
||||
wmi_ep_count = ab->htc.wmi_ep_count;
|
||||
if (wmi_ep_count > MAX_RADIOS)
|
||||
if (wmi_ep_count > ab->hw_params.max_radios)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < wmi_ep_count; i++)
|
||||
@ -6704,7 +6745,7 @@ int ath11k_wmi_pdev_attach(struct ath11k_base *ab,
|
||||
{
|
||||
struct ath11k_pdev_wmi *wmi_handle;
|
||||
|
||||
if (pdev_id >= MAX_RADIOS)
|
||||
if (pdev_id >= ab->hw_params.max_radios)
|
||||
return -EINVAL;
|
||||
|
||||
wmi_handle = &ab->wmi_ab.wmi[pdev_id];
|
||||
@ -6728,6 +6769,10 @@ int ath11k_wmi_attach(struct ath11k_base *ab)
|
||||
ab->wmi_ab.ab = ab;
|
||||
ab->wmi_ab.preferred_hw_mode = WMI_HOST_HW_MODE_MAX;
|
||||
|
||||
/* It's overwritten when service_ext_ready is handled */
|
||||
if (ab->hw_params.single_pdev_only)
|
||||
ab->wmi_ab.preferred_hw_mode = WMI_HOST_HW_MODE_SINGLE;
|
||||
|
||||
/* TODO: Init remaining wmi soc resources required */
|
||||
init_completion(&ab->wmi_ab.service_ready);
|
||||
init_completion(&ab->wmi_ab.unified_ready);
|
||||
|
@ -410,7 +410,7 @@ enum ath5k_radio {
|
||||
* This article claims Super G sticks to bonding of channels 5 and 6 for
|
||||
* USA:
|
||||
*
|
||||
* http://www.pcworld.com/article/id,113428-page,1/article.html
|
||||
* https://www.pcworld.com/article/id,113428-page,1/article.html
|
||||
*
|
||||
* The channel bonding seems to be driver specific though.
|
||||
*
|
||||
|
@ -1098,7 +1098,7 @@ err:
|
||||
/**
|
||||
* ath5k_drain_tx_buffs - Empty tx buffers
|
||||
*
|
||||
* @ah The &struct ath5k_hw
|
||||
* @ah: The &struct ath5k_hw
|
||||
*
|
||||
* Empty tx buffers from all queues in preparation
|
||||
* of a reset or during shutdown.
|
||||
@ -1536,12 +1536,12 @@ ath5k_set_current_imask(struct ath5k_hw *ah)
|
||||
}
|
||||
|
||||
static void
|
||||
ath5k_tasklet_rx(unsigned long data)
|
||||
ath5k_tasklet_rx(struct tasklet_struct *t)
|
||||
{
|
||||
struct ath5k_rx_status rs = {};
|
||||
struct sk_buff *skb, *next_skb;
|
||||
dma_addr_t next_skb_addr;
|
||||
struct ath5k_hw *ah = (void *)data;
|
||||
struct ath5k_hw *ah = from_tasklet(ah, t, rxtq);
|
||||
struct ath_common *common = ath5k_hw_common(ah);
|
||||
struct ath5k_buf *bf;
|
||||
struct ath5k_desc *ds;
|
||||
@ -1784,10 +1784,10 @@ ath5k_tx_processq(struct ath5k_hw *ah, struct ath5k_txq *txq)
|
||||
}
|
||||
|
||||
static void
|
||||
ath5k_tasklet_tx(unsigned long data)
|
||||
ath5k_tasklet_tx(struct tasklet_struct *t)
|
||||
{
|
||||
int i;
|
||||
struct ath5k_hw *ah = (void *)data;
|
||||
struct ath5k_hw *ah = from_tasklet(ah, t, txtq);
|
||||
|
||||
for (i = 0; i < AR5K_NUM_TX_QUEUES; i++)
|
||||
if (ah->txqs[i].setup && (ah->ah_txq_isr_txok_all & BIT(i)))
|
||||
@ -2176,9 +2176,9 @@ ath5k_beacon_config(struct ath5k_hw *ah)
|
||||
spin_unlock_bh(&ah->block);
|
||||
}
|
||||
|
||||
static void ath5k_tasklet_beacon(unsigned long data)
|
||||
static void ath5k_tasklet_beacon(struct tasklet_struct *t)
|
||||
{
|
||||
struct ath5k_hw *ah = (struct ath5k_hw *) data;
|
||||
struct ath5k_hw *ah = from_tasklet(ah, t, beacontq);
|
||||
|
||||
/*
|
||||
* Software beacon alert--time to send a beacon.
|
||||
@ -2447,9 +2447,9 @@ ath5k_calibrate_work(struct work_struct *work)
|
||||
|
||||
|
||||
static void
|
||||
ath5k_tasklet_ani(unsigned long data)
|
||||
ath5k_tasklet_ani(struct tasklet_struct *t)
|
||||
{
|
||||
struct ath5k_hw *ah = (void *)data;
|
||||
struct ath5k_hw *ah = from_tasklet(ah, t, ani_tasklet);
|
||||
|
||||
ah->ah_cal_mask |= AR5K_CALIBRATION_ANI;
|
||||
ath5k_ani_calibration(ah);
|
||||
@ -3069,10 +3069,10 @@ ath5k_init(struct ieee80211_hw *hw)
|
||||
hw->queues = 1;
|
||||
}
|
||||
|
||||
tasklet_init(&ah->rxtq, ath5k_tasklet_rx, (unsigned long)ah);
|
||||
tasklet_init(&ah->txtq, ath5k_tasklet_tx, (unsigned long)ah);
|
||||
tasklet_init(&ah->beacontq, ath5k_tasklet_beacon, (unsigned long)ah);
|
||||
tasklet_init(&ah->ani_tasklet, ath5k_tasklet_ani, (unsigned long)ah);
|
||||
tasklet_setup(&ah->rxtq, ath5k_tasklet_rx);
|
||||
tasklet_setup(&ah->txtq, ath5k_tasklet_tx);
|
||||
tasklet_setup(&ah->beacontq, ath5k_tasklet_beacon);
|
||||
tasklet_setup(&ah->ani_tasklet, ath5k_tasklet_ani);
|
||||
|
||||
INIT_WORK(&ah->reset_work, ath5k_reset_work);
|
||||
INIT_WORK(&ah->calib_work, ath5k_calibrate_work);
|
||||
|
@ -1172,13 +1172,13 @@ ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
|
||||
offset += ath5k_pdgains_size_2413(ee,
|
||||
AR5K_EEPROM_MODE_11B) +
|
||||
AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case AR5K_EEPROM_MODE_11B:
|
||||
if (AR5K_EEPROM_HDR_11A(ee->ee_header))
|
||||
offset += ath5k_pdgains_size_2413(ee,
|
||||
AR5K_EEPROM_MODE_11A) +
|
||||
AR5K_EEPROM_N_5GHZ_CHAN / 2;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case AR5K_EEPROM_MODE_11A:
|
||||
break;
|
||||
default:
|
||||
|
@ -101,6 +101,7 @@ static const unsigned int ack_rates_high[] =
|
||||
/**
|
||||
* ath5k_hw_get_frame_duration() - Get tx time of a frame
|
||||
* @ah: The &struct ath5k_hw
|
||||
* @band: One of enum nl80211_band
|
||||
* @len: Frame's length in bytes
|
||||
* @rate: The @struct ieee80211_rate
|
||||
* @shortpre: Indicate short preample
|
||||
@ -670,7 +671,7 @@ ath5k_hw_init_beacon_timers(struct ath5k_hw *ah, u32 next_beacon, u32 interval)
|
||||
break;
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_ADHOC_BCN_ATIM);
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
default:
|
||||
/* On non-STA modes timer1 is used as next DMA
|
||||
* beacon alert (DBA) timer and timer2 as next
|
||||
@ -913,7 +914,7 @@ ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
|
||||
pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
|
||||
| (ah->ah_version == AR5K_AR5210 ?
|
||||
AR5K_STA_ID1_PWR_SV : 0);
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
|
||||
| (ah->ah_version == AR5K_AR5210 ?
|
||||
@ -945,7 +946,6 @@ ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
|
||||
* ath5k_hw_pcu_init() - Initialize PCU
|
||||
* @ah: The &struct ath5k_hw
|
||||
* @op_mode: One of enum nl80211_iftype
|
||||
* @mode: One of enum ath5k_driver_mode
|
||||
*
|
||||
* This function is used to initialize PCU by setting current
|
||||
* operation mode and various other settings.
|
||||
|
@ -3229,10 +3229,10 @@ ath5k_write_pwr_to_pdadc_table(struct ath5k_hw *ah, u8 ee_mode)
|
||||
switch (pdcurves) {
|
||||
case 3:
|
||||
reg |= AR5K_REG_SM(pdg_to_idx[2], AR5K_PHY_TPC_RG1_PDGAIN_3);
|
||||
/* Fall through */
|
||||
fallthrough;
|
||||
case 2:
|
||||
reg |= AR5K_REG_SM(pdg_to_idx[1], AR5K_PHY_TPC_RG1_PDGAIN_2);
|
||||
/* Fall through */
|
||||
fallthrough;
|
||||
case 1:
|
||||
reg |= AR5K_REG_SM(pdg_to_idx[0], AR5K_PHY_TPC_RG1_PDGAIN_1);
|
||||
break;
|
||||
@ -3353,7 +3353,7 @@ ath5k_setup_channel_powertable(struct ath5k_hw *ah,
|
||||
table_min[pdg] = table_max[pdg] - 126;
|
||||
}
|
||||
|
||||
/* Fall through */
|
||||
fallthrough;
|
||||
case AR5K_PWRTABLE_PWR_TO_PCDAC:
|
||||
case AR5K_PWRTABLE_PWR_TO_PDADC:
|
||||
|
||||
|
@ -522,7 +522,7 @@ ath5k_hw_set_power_mode(struct ath5k_hw *ah, enum ath5k_power_mode mode,
|
||||
switch (mode) {
|
||||
case AR5K_PM_AUTO:
|
||||
staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA;
|
||||
/* fallthrough */
|
||||
fallthrough;
|
||||
case AR5K_PM_NETWORK_SLEEP:
|
||||
if (set_chip)
|
||||
ath5k_hw_reg_write(ah,
|
||||
|
@ -42,7 +42,7 @@
|
||||
* Also check out reg.h and U.S. Patent 6677779 B1 (about buffer
|
||||
* registers and control registers):
|
||||
*
|
||||
* http://www.google.com/patents?id=qNURAAAAEBAJ
|
||||
* https://www.google.com/patents?id=qNURAAAAEBAJ
|
||||
*/
|
||||
|
||||
|
||||
|
@ -73,9 +73,9 @@ ath5k_is_rfkill_set(struct ath5k_hw *ah)
|
||||
}
|
||||
|
||||
static void
|
||||
ath5k_tasklet_rfkill_toggle(unsigned long data)
|
||||
ath5k_tasklet_rfkill_toggle(struct tasklet_struct *t)
|
||||
{
|
||||
struct ath5k_hw *ah = (void *)data;
|
||||
struct ath5k_hw *ah = from_tasklet(ah, t, rf_kill.toggleq);
|
||||
bool blocked;
|
||||
|
||||
blocked = ath5k_is_rfkill_set(ah);
|
||||
@ -90,8 +90,7 @@ ath5k_rfkill_hw_start(struct ath5k_hw *ah)
|
||||
ah->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin;
|
||||
ah->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol;
|
||||
|
||||
tasklet_init(&ah->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle,
|
||||
(unsigned long)ah);
|
||||
tasklet_setup(&ah->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle);
|
||||
|
||||
ath5k_rfkill_disable(ah);
|
||||
|
||||
|
@ -3897,19 +3897,19 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
|
||||
switch (ar->hw.cap) {
|
||||
case WMI_11AN_CAP:
|
||||
ht = true;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case WMI_11A_CAP:
|
||||
band_5gig = true;
|
||||
break;
|
||||
case WMI_11GN_CAP:
|
||||
ht = true;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case WMI_11G_CAP:
|
||||
band_2gig = true;
|
||||
break;
|
||||
case WMI_11AGN_CAP:
|
||||
ht = true;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case WMI_11AG_CAP:
|
||||
band_2gig = true;
|
||||
band_5gig = true;
|
||||
|
@ -1752,7 +1752,7 @@ static int __ath6kl_init_hw_start(struct ath6kl *ar)
|
||||
|
||||
ret = ath6kl_init_service_ep(ar);
|
||||
if (ret) {
|
||||
ath6kl_err("Endpoint service initilisation failed: %d\n", ret);
|
||||
ath6kl_err("Endpoint service initialization failed: %d\n", ret);
|
||||
goto err_cleanup_scatter;
|
||||
}
|
||||
|
||||
|
@ -389,7 +389,7 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel)
|
||||
if (!ik->valid || ik->key_type != WAPI_CRYPT)
|
||||
break;
|
||||
/* for WAPI, we need to set the delayed group key, continue: */
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case WPA_PSK_AUTH:
|
||||
case WPA2_PSK_AUTH:
|
||||
case (WPA_PSK_AUTH | WPA2_PSK_AUTH):
|
||||
@ -430,6 +430,9 @@ void ath6kl_connect_ap_mode_sta(struct ath6kl_vif *vif, u16 aid, u8 *mac_addr,
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n", mac_addr, aid);
|
||||
|
||||
if (aid < 1 || aid > AP_MAX_NUM_STA)
|
||||
return;
|
||||
|
||||
if (assoc_req_len > sizeof(struct ieee80211_hdr_3addr)) {
|
||||
struct ieee80211_mgmt *mgmt =
|
||||
(struct ieee80211_mgmt *) assoc_info;
|
||||
|
@ -1201,8 +1201,7 @@ static int ath6kl_wmi_pstream_timeout_event_rx(struct wmi *wmi, u8 *datap,
|
||||
static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len)
|
||||
{
|
||||
struct wmi_bit_rate_reply *reply;
|
||||
s32 rate;
|
||||
u32 sgi, index;
|
||||
u32 index;
|
||||
|
||||
if (len < sizeof(struct wmi_bit_rate_reply))
|
||||
return -EINVAL;
|
||||
@ -1211,15 +1210,10 @@ static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len)
|
||||
|
||||
ath6kl_dbg(ATH6KL_DBG_WMI, "rateindex %d\n", reply->rate_index);
|
||||
|
||||
if (reply->rate_index == (s8) RATE_AUTO) {
|
||||
rate = RATE_AUTO;
|
||||
} else {
|
||||
if (reply->rate_index != (s8) RATE_AUTO) {
|
||||
index = reply->rate_index & 0x7f;
|
||||
if (WARN_ON_ONCE(index > (RATE_MCS_7_40 + 1)))
|
||||
return -EINVAL;
|
||||
|
||||
sgi = (reply->rate_index & 0x80) ? 1 : 0;
|
||||
rate = wmi_rate_tbl[index][sgi];
|
||||
}
|
||||
|
||||
ath6kl_wakeup_event(wmi->parent_dev);
|
||||
|
@ -22,10 +22,10 @@ config ATH9K
|
||||
tristate "Atheros 802.11n wireless cards support"
|
||||
depends on MAC80211 && HAS_DMA
|
||||
select ATH9K_HW
|
||||
select MAC80211_LEDS
|
||||
select LEDS_CLASS
|
||||
select NEW_LEDS
|
||||
select ATH9K_COMMON
|
||||
imply NEW_LEDS
|
||||
imply LEDS_CLASS
|
||||
imply MAC80211_LEDS
|
||||
help
|
||||
This module adds support for wireless adapters based on
|
||||
Atheros IEEE 802.11n AR5008, AR9001 and AR9002 family
|
||||
@ -177,10 +177,10 @@ config ATH9K_HTC
|
||||
tristate "Atheros HTC based wireless cards support"
|
||||
depends on USB && MAC80211
|
||||
select ATH9K_HW
|
||||
select MAC80211_LEDS
|
||||
select LEDS_CLASS
|
||||
select NEW_LEDS
|
||||
select ATH9K_COMMON
|
||||
imply NEW_LEDS
|
||||
imply LEDS_CLASS
|
||||
imply MAC80211_LEDS
|
||||
help
|
||||
Support for Atheros HTC based cards.
|
||||
Chipsets supported: AR9271
|
||||
|
@ -74,7 +74,7 @@ static const struct ani_ofdm_level_entry ofdm_level_table[] = {
|
||||
* Regardless of alignment in time, the antenna signals add constructively after
|
||||
* FFT and improve your reception. For more information:
|
||||
*
|
||||
* http://en.wikipedia.org/wiki/Maximal-ratio_combining
|
||||
* https://en.wikipedia.org/wiki/Maximal-ratio_combining
|
||||
*/
|
||||
|
||||
struct ani_cck_level_entry {
|
||||
|
@ -459,12 +459,6 @@ static const u32 ar5416Common[][2] = {
|
||||
{0x0000a3e0, 0x000001ce},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank0[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x000098b0, 0x1e5795e5},
|
||||
{0x000098e0, 0x02008020},
|
||||
};
|
||||
|
||||
static const u32 ar5416BB_RfGain[][3] = {
|
||||
/* Addr 5G 2G */
|
||||
{0x00009a00, 0x00000000, 0x00000000},
|
||||
@ -533,60 +527,6 @@ static const u32 ar5416BB_RfGain[][3] = {
|
||||
{0x00009afc, 0x000000f9, 0x000000f9},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank1[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x000098b0, 0x02108421},
|
||||
{0x000098ec, 0x00000008},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank2[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x000098b0, 0x0e73ff17},
|
||||
{0x000098e0, 0x00000420},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank3[][3] = {
|
||||
/* Addr 5G 2G */
|
||||
{0x000098f0, 0x01400018, 0x01c00018},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank6[][3] = {
|
||||
/* Addr 5G 2G */
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00e00000, 0x00e00000},
|
||||
{0x0000989c, 0x005e0000, 0x005e0000},
|
||||
{0x0000989c, 0x00120000, 0x00120000},
|
||||
{0x0000989c, 0x00620000, 0x00620000},
|
||||
{0x0000989c, 0x00020000, 0x00020000},
|
||||
{0x0000989c, 0x00ff0000, 0x00ff0000},
|
||||
{0x0000989c, 0x00ff0000, 0x00ff0000},
|
||||
{0x0000989c, 0x00ff0000, 0x00ff0000},
|
||||
{0x0000989c, 0x40ff0000, 0x40ff0000},
|
||||
{0x0000989c, 0x005f0000, 0x005f0000},
|
||||
{0x0000989c, 0x00870000, 0x00870000},
|
||||
{0x0000989c, 0x00f90000, 0x00f90000},
|
||||
{0x0000989c, 0x007b0000, 0x007b0000},
|
||||
{0x0000989c, 0x00ff0000, 0x00ff0000},
|
||||
{0x0000989c, 0x00f50000, 0x00f50000},
|
||||
{0x0000989c, 0x00dc0000, 0x00dc0000},
|
||||
{0x0000989c, 0x00110000, 0x00110000},
|
||||
{0x0000989c, 0x006100a8, 0x006100a8},
|
||||
{0x0000989c, 0x004210a2, 0x004210a2},
|
||||
{0x0000989c, 0x0014008f, 0x0014008f},
|
||||
{0x0000989c, 0x00c40003, 0x00c40003},
|
||||
{0x0000989c, 0x003000f2, 0x003000f2},
|
||||
{0x0000989c, 0x00440016, 0x00440016},
|
||||
{0x0000989c, 0x00410040, 0x00410040},
|
||||
{0x0000989c, 0x0001805e, 0x0001805e},
|
||||
{0x0000989c, 0x0000c0ab, 0x0000c0ab},
|
||||
{0x0000989c, 0x000000f1, 0x000000f1},
|
||||
{0x0000989c, 0x00002081, 0x00002081},
|
||||
{0x0000989c, 0x000000d4, 0x000000d4},
|
||||
{0x000098d0, 0x0000000f, 0x0010000f},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank6TPC[][3] = {
|
||||
/* Addr 5G 2G */
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
@ -624,13 +564,6 @@ static const u32 ar5416Bank6TPC[][3] = {
|
||||
{0x000098d0, 0x0000000f, 0x0010000f},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank7[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x0000989c, 0x00000500},
|
||||
{0x0000989c, 0x00000800},
|
||||
{0x000098cc, 0x0000000e},
|
||||
};
|
||||
|
||||
static const u32 ar5416Addac[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x0000989c, 0x00000000},
|
||||
@ -671,4 +604,3 @@ static const u32 ar5416Addac[][2] = {
|
||||
{0x0000989c, 0x00000000},
|
||||
{0x000098c4, 0x00000000},
|
||||
};
|
||||
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "hw-ops.h"
|
||||
#include "../regd.h"
|
||||
#include "ar9002_phy.h"
|
||||
#include "ar5008_initvals.h"
|
||||
|
||||
/* All code below is for AR5008, AR9001, AR9002 */
|
||||
|
||||
@ -51,6 +50,36 @@ static const int m2ThreshLowExt_off = 127;
|
||||
static const int m1ThreshExt_off = 127;
|
||||
static const int m2ThreshExt_off = 127;
|
||||
|
||||
static const u32 ar5416Bank0[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x000098b0, 0x1e5795e5},
|
||||
{0x000098e0, 0x02008020},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank1[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x000098b0, 0x02108421},
|
||||
{0x000098ec, 0x00000008},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank2[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x000098b0, 0x0e73ff17},
|
||||
{0x000098e0, 0x00000420},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank3[][3] = {
|
||||
/* Addr 5G 2G */
|
||||
{0x000098f0, 0x01400018, 0x01c00018},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank7[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x0000989c, 0x00000500},
|
||||
{0x0000989c, 0x00000800},
|
||||
{0x000098cc, 0x0000000e},
|
||||
};
|
||||
|
||||
static const struct ar5416IniArray bank0 = STATIC_INI_ARRAY(ar5416Bank0);
|
||||
static const struct ar5416IniArray bank1 = STATIC_INI_ARRAY(ar5416Bank1);
|
||||
static const struct ar5416IniArray bank2 = STATIC_INI_ARRAY(ar5416Bank2);
|
||||
@ -579,14 +608,14 @@ static void ar5008_hw_init_chain_masks(struct ath_hw *ah)
|
||||
case 0x5:
|
||||
REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
|
||||
AR_PHY_SWAP_ALT_CHAIN);
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case 0x3:
|
||||
if (ah->hw_version.macVersion == AR_SREV_REVISION_5416_10) {
|
||||
REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7);
|
||||
REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7);
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case 0x1:
|
||||
case 0x2:
|
||||
case 0x7:
|
||||
|
@ -459,43 +459,6 @@ static const u32 ar5416Common_9100[][2] = {
|
||||
{0x0000a3e0, 0x000001ce},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank6_9100[][3] = {
|
||||
/* Addr 5G 2G */
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
{0x0000989c, 0x00e00000, 0x00e00000},
|
||||
{0x0000989c, 0x005e0000, 0x005e0000},
|
||||
{0x0000989c, 0x00120000, 0x00120000},
|
||||
{0x0000989c, 0x00620000, 0x00620000},
|
||||
{0x0000989c, 0x00020000, 0x00020000},
|
||||
{0x0000989c, 0x00ff0000, 0x00ff0000},
|
||||
{0x0000989c, 0x00ff0000, 0x00ff0000},
|
||||
{0x0000989c, 0x00ff0000, 0x00ff0000},
|
||||
{0x0000989c, 0x00ff0000, 0x00ff0000},
|
||||
{0x0000989c, 0x005f0000, 0x005f0000},
|
||||
{0x0000989c, 0x00870000, 0x00870000},
|
||||
{0x0000989c, 0x00f90000, 0x00f90000},
|
||||
{0x0000989c, 0x007b0000, 0x007b0000},
|
||||
{0x0000989c, 0x00ff0000, 0x00ff0000},
|
||||
{0x0000989c, 0x00f50000, 0x00f50000},
|
||||
{0x0000989c, 0x00dc0000, 0x00dc0000},
|
||||
{0x0000989c, 0x00110000, 0x00110000},
|
||||
{0x0000989c, 0x006100a8, 0x006100a8},
|
||||
{0x0000989c, 0x004210a2, 0x004210a2},
|
||||
{0x0000989c, 0x0014000f, 0x0014000f},
|
||||
{0x0000989c, 0x00c40002, 0x00c40002},
|
||||
{0x0000989c, 0x003000f2, 0x003000f2},
|
||||
{0x0000989c, 0x00440016, 0x00440016},
|
||||
{0x0000989c, 0x00410040, 0x00410040},
|
||||
{0x0000989c, 0x000180d6, 0x000180d6},
|
||||
{0x0000989c, 0x0000c0aa, 0x0000c0aa},
|
||||
{0x0000989c, 0x000000b1, 0x000000b1},
|
||||
{0x0000989c, 0x00002000, 0x00002000},
|
||||
{0x0000989c, 0x000000d4, 0x000000d4},
|
||||
{0x000098d0, 0x0000000f, 0x0010000f},
|
||||
};
|
||||
|
||||
static const u32 ar5416Bank6TPC_9100[][3] = {
|
||||
/* Addr 5G 2G */
|
||||
{0x0000989c, 0x00000000, 0x00000000},
|
||||
|
@ -897,20 +897,6 @@ static const u32 ar9280Modes_original_tx_gain_9280_2[][5] = {
|
||||
{0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480},
|
||||
};
|
||||
|
||||
static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x00004040, 0x9248fd00},
|
||||
{0x00004040, 0x24924924},
|
||||
{0x00004040, 0xa8000019},
|
||||
{0x00004040, 0x13160820},
|
||||
{0x00004040, 0xe5980560},
|
||||
{0x00004040, 0xc01dcffc},
|
||||
{0x00004040, 0x1aaabe41},
|
||||
{0x00004040, 0xbe105554},
|
||||
{0x00004040, 0x00043007},
|
||||
{0x00004044, 0x00000000},
|
||||
};
|
||||
|
||||
static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x00004040, 0x9248fd00},
|
||||
|
@ -267,7 +267,7 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
|
||||
switch (i->aggr) {
|
||||
case AGGR_BUF_FIRST:
|
||||
ctl6 |= SM(i->aggr_len, AR_AggrLen);
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case AGGR_BUF_MIDDLE:
|
||||
ctl1 |= AR_IsAggr | AR_MoreAggr;
|
||||
ctl6 |= SM(i->ndelim, AR_PadDelim);
|
||||
|
@ -119,7 +119,7 @@ static int ar9002_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
|
||||
aModeRefSel = 2;
|
||||
if (aModeRefSel)
|
||||
break;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case 1:
|
||||
default:
|
||||
aModeRefSel = 0;
|
||||
|
@ -120,7 +120,7 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
|
||||
switch (i->aggr) {
|
||||
case AGGR_BUF_FIRST:
|
||||
ctl17 |= SM(i->aggr_len, AR_AggrLen);
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case AGGR_BUF_MIDDLE:
|
||||
ctl12 |= AR_IsAggr | AR_MoreAggr;
|
||||
ctl17 |= SM(i->ndelim, AR_PadDelim);
|
||||
|
@ -713,7 +713,7 @@ struct ath_beacon {
|
||||
bool tx_last;
|
||||
};
|
||||
|
||||
void ath9k_beacon_tasklet(unsigned long data);
|
||||
void ath9k_beacon_tasklet(struct tasklet_struct *t);
|
||||
void ath9k_beacon_config(struct ath_softc *sc, struct ieee80211_vif *main_vif,
|
||||
bool beacons);
|
||||
void ath9k_beacon_assign_slot(struct ath_softc *sc, struct ieee80211_vif *vif);
|
||||
@ -1117,7 +1117,7 @@ static inline void ath_read_cachesize(struct ath_common *common, int *csz)
|
||||
common->bus_ops->read_cachesize(common, csz);
|
||||
}
|
||||
|
||||
void ath9k_tasklet(unsigned long data);
|
||||
void ath9k_tasklet(struct tasklet_struct *t);
|
||||
int ath_cabq_update(struct ath_softc *);
|
||||
u8 ath9k_parse_mpdudensity(u8 mpdudensity);
|
||||
irqreturn_t ath_isr(int irq, void *dev);
|
||||
|
@ -385,9 +385,9 @@ void ath9k_csa_update(struct ath_softc *sc)
|
||||
ath9k_csa_update_vif, sc);
|
||||
}
|
||||
|
||||
void ath9k_beacon_tasklet(unsigned long data)
|
||||
void ath9k_beacon_tasklet(struct tasklet_struct *t)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *)data;
|
||||
struct ath_softc *sc = from_tasklet(sc, t, bcon_tasklet);
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
struct ath_buf *bf = NULL;
|
||||
|
@ -706,7 +706,7 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
|
||||
"Move chanctx state from FORCE_ACTIVE to IDLE\n");
|
||||
|
||||
sc->sched.state = ATH_CHANCTX_STATE_IDLE;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case ATH_CHANCTX_EVENT_SWITCH:
|
||||
if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags) ||
|
||||
sc->sched.state == ATH_CHANCTX_STATE_FORCE_ACTIVE ||
|
||||
@ -1080,7 +1080,7 @@ static void ath_offchannel_timer(struct timer_list *t)
|
||||
mod_timer(&sc->offchannel.timer, jiffies + HZ / 10);
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case ATH_OFFCHANNEL_SUSPEND:
|
||||
if (!sc->offchannel.scan_req)
|
||||
return;
|
||||
|
@ -402,7 +402,7 @@ static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah,
|
||||
return AR5416_PWR_TABLE_OFFSET_DB;
|
||||
case EEP_ANTENNA_GAIN_2G:
|
||||
band = 1;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case EEP_ANTENNA_GAIN_5G:
|
||||
return max_t(u8, max_t(u8,
|
||||
pModal[band].antennaGainCh[0],
|
||||
|
@ -1375,7 +1375,7 @@ static void ath9k_hif_usb_disconnect(struct usb_interface *interface)
|
||||
if (hif_dev->flags & HIF_USB_READY) {
|
||||
ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
|
||||
ath9k_hif_usb_dev_deinit(hif_dev);
|
||||
ath9k_destoy_wmi(hif_dev->htc_handle->drv_priv);
|
||||
ath9k_destroy_wmi(hif_dev->htc_handle->drv_priv);
|
||||
ath9k_htc_hw_free(hif_dev->htc_handle);
|
||||
}
|
||||
|
||||
|
@ -583,14 +583,14 @@ int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv);
|
||||
void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot);
|
||||
void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv);
|
||||
void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event);
|
||||
void ath9k_tx_failed_tasklet(unsigned long data);
|
||||
void ath9k_tx_failed_tasklet(struct tasklet_struct *t);
|
||||
void ath9k_htc_tx_cleanup_timer(struct timer_list *t);
|
||||
bool ath9k_htc_csa_is_finished(struct ath9k_htc_priv *priv);
|
||||
|
||||
int ath9k_rx_init(struct ath9k_htc_priv *priv);
|
||||
void ath9k_rx_cleanup(struct ath9k_htc_priv *priv);
|
||||
void ath9k_host_rx_init(struct ath9k_htc_priv *priv);
|
||||
void ath9k_rx_tasklet(unsigned long data);
|
||||
void ath9k_rx_tasklet(struct tasklet_struct *t);
|
||||
u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv);
|
||||
|
||||
void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv);
|
||||
|
@ -645,10 +645,8 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
|
||||
spin_lock_init(&priv->tx.tx_lock);
|
||||
mutex_init(&priv->mutex);
|
||||
mutex_init(&priv->htc_pm_lock);
|
||||
tasklet_init(&priv->rx_tasklet, ath9k_rx_tasklet,
|
||||
(unsigned long)priv);
|
||||
tasklet_init(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet,
|
||||
(unsigned long)priv);
|
||||
tasklet_setup(&priv->rx_tasklet, ath9k_rx_tasklet);
|
||||
tasklet_setup(&priv->tx_failed_tasklet, ath9k_tx_failed_tasklet);
|
||||
INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work);
|
||||
INIT_WORK(&priv->ps_work, ath9k_ps_work);
|
||||
INIT_WORK(&priv->fatal_work, ath9k_fatal_work);
|
||||
@ -973,7 +971,7 @@ err_init:
|
||||
ath9k_stop_wmi(priv);
|
||||
hif_dev = (struct hif_device_usb *)htc_handle->hif_dev;
|
||||
ath9k_hif_usb_dealloc_urbs(hif_dev);
|
||||
ath9k_destoy_wmi(priv);
|
||||
ath9k_destroy_wmi(priv);
|
||||
err_free:
|
||||
ieee80211_free_hw(hw);
|
||||
return ret;
|
||||
|
@ -570,9 +570,9 @@ void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv)
|
||||
spin_unlock_bh(&priv->tx.tx_lock);
|
||||
}
|
||||
|
||||
void ath9k_tx_failed_tasklet(unsigned long data)
|
||||
void ath9k_tx_failed_tasklet(struct tasklet_struct *t)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
|
||||
struct ath9k_htc_priv *priv = from_tasklet(priv, t, tx_failed_tasklet);
|
||||
|
||||
spin_lock(&priv->tx.tx_lock);
|
||||
if (priv->tx.flags & ATH9K_HTC_OP_TX_DRAIN) {
|
||||
@ -974,7 +974,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
|
||||
struct ath_htc_rx_status *rxstatus;
|
||||
struct ath_rx_status rx_stats;
|
||||
bool decrypt_error = false;
|
||||
__be16 rs_datalen;
|
||||
u16 rs_datalen;
|
||||
bool is_phyerr;
|
||||
|
||||
if (skb->len < HTC_RX_FRAME_HEADER_SIZE) {
|
||||
@ -1062,9 +1062,9 @@ rx_next:
|
||||
/*
|
||||
* FIXME: Handle FLUSH later on.
|
||||
*/
|
||||
void ath9k_rx_tasklet(unsigned long data)
|
||||
void ath9k_rx_tasklet(struct tasklet_struct *t)
|
||||
{
|
||||
struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
|
||||
struct ath9k_htc_priv *priv = from_tasklet(priv, t, rx_tasklet);
|
||||
struct ath9k_htc_rxbuf *rxbuf = NULL, *tmp_buf = NULL;
|
||||
struct ieee80211_rx_status rx_status;
|
||||
struct sk_buff *skb;
|
||||
|
@ -339,6 +339,8 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
|
||||
|
||||
if (skb) {
|
||||
htc_hdr = (struct htc_frame_hdr *) skb->data;
|
||||
if (htc_hdr->endpoint_id >= ARRAY_SIZE(htc_handle->endpoint))
|
||||
goto ret;
|
||||
endpoint = &htc_handle->endpoint[htc_hdr->endpoint_id];
|
||||
skb_pull(skb, sizeof(struct htc_frame_hdr));
|
||||
|
||||
|
@ -1277,12 +1277,12 @@ static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode)
|
||||
REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case NL80211_IFTYPE_OCB:
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_AP:
|
||||
set |= AR_STA_ID1_STA_AP;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION);
|
||||
break;
|
||||
@ -2293,7 +2293,7 @@ void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period)
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
REG_SET_BIT(ah, AR_TXCFG,
|
||||
AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY);
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case NL80211_IFTYPE_MESH_POINT:
|
||||
case NL80211_IFTYPE_AP:
|
||||
REG_WRITE(ah, AR_NEXT_TBTT_TIMER, next_beacon);
|
||||
|
@ -728,9 +728,8 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
|
||||
spin_lock_init(&sc->sc_pm_lock);
|
||||
spin_lock_init(&sc->chan_lock);
|
||||
mutex_init(&sc->mutex);
|
||||
tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
|
||||
tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
|
||||
(unsigned long)sc);
|
||||
tasklet_setup(&sc->intr_tq, ath9k_tasklet);
|
||||
tasklet_setup(&sc->bcon_tasklet, ath9k_beacon_tasklet);
|
||||
|
||||
timer_setup(&sc->sleep_timer, ath_ps_full_sleep, 0);
|
||||
INIT_WORK(&sc->hw_reset_work, ath_reset_work);
|
||||
@ -1014,6 +1013,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
|
||||
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_AIRTIME_FAIRNESS);
|
||||
wiphy_ext_feature_set(hw->wiphy,
|
||||
NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS);
|
||||
wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
|
||||
}
|
||||
|
||||
int ath9k_init_device(u16 devid, struct ath_softc *sc,
|
||||
|
@ -19,6 +19,9 @@
|
||||
#include "ath9k.h"
|
||||
#include "btcoex.h"
|
||||
|
||||
static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
||||
u32 queues, bool drop);
|
||||
|
||||
u8 ath9k_parse_mpdudensity(u8 mpdudensity)
|
||||
{
|
||||
/*
|
||||
@ -368,9 +371,9 @@ static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta)
|
||||
ath_dynack_node_deinit(sc->sc_ah, an);
|
||||
}
|
||||
|
||||
void ath9k_tasklet(unsigned long data)
|
||||
void ath9k_tasklet(struct tasklet_struct *t)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *)data;
|
||||
struct ath_softc *sc = from_tasklet(sc, t, intr_tq);
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
enum ath_reset_type type;
|
||||
@ -1701,6 +1704,15 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/* There may be MPDUs queued for the outgoing PTK key. Flush queues to
|
||||
* make sure these are not send unencrypted or with a wrong (new) key
|
||||
*/
|
||||
if (cmd == DISABLE_KEY && key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
|
||||
ieee80211_stop_queues(hw);
|
||||
ath9k_flush(hw, vif, 0, true);
|
||||
ieee80211_wake_queues(hw);
|
||||
}
|
||||
|
||||
mutex_lock(&sc->mutex);
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath_dbg(common, CONFIG, "Set HW Key %d\n", cmd);
|
||||
@ -1934,7 +1946,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH:
|
||||
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
|
||||
flush = true;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
case IEEE80211_AMPDU_TX_STOP_CONT:
|
||||
ath9k_ps_wakeup(sc);
|
||||
ath_tx_aggr_stop(sc, sta, tid);
|
||||
|
@ -825,6 +825,7 @@ static void ath_pci_aspm_init(struct ath_common *common)
|
||||
struct pci_dev *pdev = to_pci_dev(sc->dev);
|
||||
struct pci_dev *parent;
|
||||
u16 aspm;
|
||||
int ret;
|
||||
|
||||
if (!ah->is_pciexpress)
|
||||
return;
|
||||
@ -866,8 +867,8 @@ static void ath_pci_aspm_init(struct ath_common *common)
|
||||
if (AR_SREV_9462(ah))
|
||||
pci_read_config_dword(pdev, 0x70c, &ah->config.aspm_l1_fix);
|
||||
|
||||
pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &aspm);
|
||||
if (aspm & (PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1)) {
|
||||
ret = pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &aspm);
|
||||
if (!ret && (aspm & (PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1))) {
|
||||
ah->aspm_enabled = true;
|
||||
/* Initialize PCIe PM and SERDES registers. */
|
||||
ath9k_hw_configpcipowersave(ah, false);
|
||||
|
@ -106,8 +106,7 @@ struct wmi *ath9k_init_wmi(struct ath9k_htc_priv *priv)
|
||||
mutex_init(&wmi->multi_rmw_mutex);
|
||||
init_completion(&wmi->cmd_wait);
|
||||
INIT_LIST_HEAD(&wmi->pending_tx_events);
|
||||
tasklet_init(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet,
|
||||
(unsigned long)wmi);
|
||||
tasklet_setup(&wmi->wmi_event_tasklet, ath9k_wmi_event_tasklet);
|
||||
|
||||
return wmi;
|
||||
}
|
||||
@ -121,7 +120,7 @@ void ath9k_stop_wmi(struct ath9k_htc_priv *priv)
|
||||
mutex_unlock(&wmi->op_mutex);
|
||||
}
|
||||
|
||||
void ath9k_destoy_wmi(struct ath9k_htc_priv *priv)
|
||||
void ath9k_destroy_wmi(struct ath9k_htc_priv *priv)
|
||||
{
|
||||
kfree(priv->wmi);
|
||||
}
|
||||
@ -136,9 +135,9 @@ void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv)
|
||||
spin_unlock_irqrestore(&priv->wmi->wmi_lock, flags);
|
||||
}
|
||||
|
||||
void ath9k_wmi_event_tasklet(unsigned long data)
|
||||
void ath9k_wmi_event_tasklet(struct tasklet_struct *t)
|
||||
{
|
||||
struct wmi *wmi = (struct wmi *)data;
|
||||
struct wmi *wmi = from_tasklet(wmi, t, wmi_event_tasklet);
|
||||
struct ath9k_htc_priv *priv = wmi->drv_priv;
|
||||
struct wmi_cmd_hdr *hdr;
|
||||
void *wmi_event;
|
||||
|
@ -185,11 +185,11 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
|
||||
u8 *cmd_buf, u32 cmd_len,
|
||||
u8 *rsp_buf, u32 rsp_len,
|
||||
u32 timeout);
|
||||
void ath9k_wmi_event_tasklet(unsigned long data);
|
||||
void ath9k_wmi_event_tasklet(struct tasklet_struct *t);
|
||||
void ath9k_fatal_work(struct work_struct *work);
|
||||
void ath9k_wmi_event_drain(struct ath9k_htc_priv *priv);
|
||||
void ath9k_stop_wmi(struct ath9k_htc_priv *priv);
|
||||
void ath9k_destoy_wmi(struct ath9k_htc_priv *priv);
|
||||
void ath9k_destroy_wmi(struct ath9k_htc_priv *priv);
|
||||
|
||||
#define WMI_CMD(_wmi_cmd) \
|
||||
do { \
|
||||
|
@ -68,7 +68,10 @@
|
||||
|
||||
#define PAYLOAD_MAX (CARL9170_MAX_CMD_LEN / 4 - 1)
|
||||
|
||||
static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 3, 2, 1, 0 };
|
||||
static inline u8 ar9170_qmap(u8 idx)
|
||||
{
|
||||
return 3 - idx; /* { 3, 2, 1, 0 } */
|
||||
}
|
||||
|
||||
#define CARL9170_MAX_RX_BUFFER_SIZE 8192
|
||||
|
||||
|
@ -1374,7 +1374,7 @@ static int carl9170_op_conf_tx(struct ieee80211_hw *hw,
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ar->mutex);
|
||||
memcpy(&ar->edcf[ar9170_qmap[queue]], param, sizeof(*param));
|
||||
memcpy(&ar->edcf[ar9170_qmap(queue)], param, sizeof(*param));
|
||||
ret = carl9170_set_qos(ar);
|
||||
mutex_unlock(&ar->mutex);
|
||||
return ret;
|
||||
|
@ -766,7 +766,7 @@ static void carl9170_rx_untie_data(struct ar9170 *ar, u8 *buf, int len)
|
||||
|
||||
goto drop;
|
||||
}
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
|
||||
case AR9170_RX_STATUS_MPDU_MIDDLE:
|
||||
/* These are just data + mac status */
|
||||
|
@ -663,7 +663,7 @@ static void __carl9170_tx_process_status(struct ar9170 *ar,
|
||||
unsigned int r, t, q;
|
||||
bool success = true;
|
||||
|
||||
q = ar9170_qmap[info & CARL9170_TX_STATUS_QUEUE];
|
||||
q = ar9170_qmap(info & CARL9170_TX_STATUS_QUEUE);
|
||||
|
||||
skb = carl9170_get_queued_skb(ar, cookie, &ar->tx_status[q]);
|
||||
if (!skb) {
|
||||
@ -830,12 +830,12 @@ static bool carl9170_tx_rts_check(struct ar9170 *ar,
|
||||
case CARL9170_ERP_AUTO:
|
||||
if (ampdu)
|
||||
break;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
|
||||
case CARL9170_ERP_MAC80211:
|
||||
if (!(rate->flags & IEEE80211_TX_RC_USE_RTS_CTS))
|
||||
break;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
|
||||
case CARL9170_ERP_RTS:
|
||||
if (likely(!multi))
|
||||
@ -856,7 +856,7 @@ static bool carl9170_tx_cts_check(struct ar9170 *ar,
|
||||
case CARL9170_ERP_MAC80211:
|
||||
if (!(rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT))
|
||||
break;
|
||||
/* fall through */
|
||||
fallthrough;
|
||||
|
||||
case CARL9170_ERP_CTS:
|
||||
return true;
|
||||
@ -979,7 +979,7 @@ static int carl9170_tx_prepare(struct ar9170 *ar,
|
||||
((CARL9170_TX_SUPER_MISC_VIF_ID >>
|
||||
CARL9170_TX_SUPER_MISC_VIF_ID_S) + 1));
|
||||
|
||||
hw_queue = ar9170_qmap[carl9170_get_queue(ar, skb)];
|
||||
hw_queue = ar9170_qmap(carl9170_get_queue(ar, skb));
|
||||
|
||||
hdr = (void *)skb->data;
|
||||
info = IEEE80211_SKB_CB(skb);
|
||||
@ -1279,7 +1279,7 @@ void carl9170_tx_drop(struct ar9170 *ar, struct sk_buff *skb)
|
||||
|
||||
super = (void *)skb->data;
|
||||
SET_VAL(CARL9170_TX_SUPER_MISC_QUEUE, q,
|
||||
ar9170_qmap[carl9170_get_queue(ar, skb)]);
|
||||
ar9170_qmap(carl9170_get_queue(ar, skb)));
|
||||
__carl9170_tx_process_status(ar, super->s.cookie, q);
|
||||
}
|
||||
|
||||
|
@ -377,9 +377,9 @@ void carl9170_usb_handle_tx_err(struct ar9170 *ar)
|
||||
}
|
||||
}
|
||||
|
||||
static void carl9170_usb_tasklet(unsigned long data)
|
||||
static void carl9170_usb_tasklet(struct tasklet_struct *t)
|
||||
{
|
||||
struct ar9170 *ar = (struct ar9170 *) data;
|
||||
struct ar9170 *ar = from_tasklet(ar, t, usb_tasklet);
|
||||
|
||||
if (!IS_INITIALIZED(ar))
|
||||
return;
|
||||
@ -1082,8 +1082,7 @@ static int carl9170_usb_probe(struct usb_interface *intf,
|
||||
init_completion(&ar->cmd_wait);
|
||||
init_completion(&ar->fw_boot_wait);
|
||||
init_completion(&ar->fw_load_wait);
|
||||
tasklet_init(&ar->usb_tasklet, carl9170_usb_tasklet,
|
||||
(unsigned long)ar);
|
||||
tasklet_setup(&ar->usb_tasklet, carl9170_usb_tasklet);
|
||||
|
||||
atomic_set(&ar->tx_cmd_urbs, 0);
|
||||
atomic_set(&ar->tx_anch_urbs, 0);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user