提交 59e25676 编写于 作者: J John W. Linville

Merge branch 'for-linville' of git://github.com/kvalo/ath

...@@ -25,6 +25,7 @@ config ATH10K_DEBUG ...@@ -25,6 +25,7 @@ config ATH10K_DEBUG
config ATH10K_DEBUGFS config ATH10K_DEBUGFS
bool "Atheros ath10k debugfs support" bool "Atheros ath10k debugfs support"
depends on ATH10K depends on ATH10K
select RELAY
---help--- ---help---
Enabled debugfs support Enabled debugfs support
......
...@@ -10,6 +10,7 @@ ath10k_core-y += mac.o \ ...@@ -10,6 +10,7 @@ ath10k_core-y += mac.o \
wmi.o \ wmi.o \
bmi.o bmi.o
ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o
ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o
obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
void ath10k_bmi_start(struct ath10k *ar) void ath10k_bmi_start(struct ath10k *ar)
{ {
ath10k_dbg(ATH10K_DBG_BMI, "bmi start\n"); ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi start\n");
ar->bmi.done_sent = false; ar->bmi.done_sent = false;
} }
...@@ -33,10 +33,10 @@ int ath10k_bmi_done(struct ath10k *ar) ...@@ -33,10 +33,10 @@ int ath10k_bmi_done(struct ath10k *ar)
u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.done); u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.done);
int ret; int ret;
ath10k_dbg(ATH10K_DBG_BMI, "bmi done\n"); ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi done\n");
if (ar->bmi.done_sent) { if (ar->bmi.done_sent) {
ath10k_dbg(ATH10K_DBG_BMI, "bmi skipped\n"); ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi skipped\n");
return 0; return 0;
} }
...@@ -45,7 +45,7 @@ int ath10k_bmi_done(struct ath10k *ar) ...@@ -45,7 +45,7 @@ int ath10k_bmi_done(struct ath10k *ar)
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, NULL, NULL); ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, NULL, NULL);
if (ret) { if (ret) {
ath10k_warn("unable to write to the device: %d\n", ret); ath10k_warn(ar, "unable to write to the device: %d\n", ret);
return ret; return ret;
} }
...@@ -61,10 +61,10 @@ int ath10k_bmi_get_target_info(struct ath10k *ar, ...@@ -61,10 +61,10 @@ int ath10k_bmi_get_target_info(struct ath10k *ar,
u32 resplen = sizeof(resp.get_target_info); u32 resplen = sizeof(resp.get_target_info);
int ret; int ret;
ath10k_dbg(ATH10K_DBG_BMI, "bmi get target info\n"); ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi get target info\n");
if (ar->bmi.done_sent) { if (ar->bmi.done_sent) {
ath10k_warn("BMI Get Target Info Command disallowed\n"); ath10k_warn(ar, "BMI Get Target Info Command disallowed\n");
return -EBUSY; return -EBUSY;
} }
...@@ -72,12 +72,12 @@ int ath10k_bmi_get_target_info(struct ath10k *ar, ...@@ -72,12 +72,12 @@ int ath10k_bmi_get_target_info(struct ath10k *ar,
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &resp, &resplen); ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &resp, &resplen);
if (ret) { if (ret) {
ath10k_warn("unable to get target info from device\n"); ath10k_warn(ar, "unable to get target info from device\n");
return ret; return ret;
} }
if (resplen < sizeof(resp.get_target_info)) { if (resplen < sizeof(resp.get_target_info)) {
ath10k_warn("invalid get_target_info response length (%d)\n", ath10k_warn(ar, "invalid get_target_info response length (%d)\n",
resplen); resplen);
return -EIO; return -EIO;
} }
...@@ -97,11 +97,11 @@ int ath10k_bmi_read_memory(struct ath10k *ar, ...@@ -97,11 +97,11 @@ int ath10k_bmi_read_memory(struct ath10k *ar,
u32 rxlen; u32 rxlen;
int ret; int ret;
ath10k_dbg(ATH10K_DBG_BMI, "bmi read address 0x%x length %d\n", ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi read address 0x%x length %d\n",
address, length); address, length);
if (ar->bmi.done_sent) { if (ar->bmi.done_sent) {
ath10k_warn("command disallowed\n"); ath10k_warn(ar, "command disallowed\n");
return -EBUSY; return -EBUSY;
} }
...@@ -115,7 +115,7 @@ int ath10k_bmi_read_memory(struct ath10k *ar, ...@@ -115,7 +115,7 @@ int ath10k_bmi_read_memory(struct ath10k *ar,
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen,
&resp, &rxlen); &resp, &rxlen);
if (ret) { if (ret) {
ath10k_warn("unable to read from the device (%d)\n", ath10k_warn(ar, "unable to read from the device (%d)\n",
ret); ret);
return ret; return ret;
} }
...@@ -137,11 +137,11 @@ int ath10k_bmi_write_memory(struct ath10k *ar, ...@@ -137,11 +137,11 @@ int ath10k_bmi_write_memory(struct ath10k *ar,
u32 txlen; u32 txlen;
int ret; int ret;
ath10k_dbg(ATH10K_DBG_BMI, "bmi write address 0x%x length %d\n", ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi write address 0x%x length %d\n",
address, length); address, length);
if (ar->bmi.done_sent) { if (ar->bmi.done_sent) {
ath10k_warn("command disallowed\n"); ath10k_warn(ar, "command disallowed\n");
return -EBUSY; return -EBUSY;
} }
...@@ -159,7 +159,7 @@ int ath10k_bmi_write_memory(struct ath10k *ar, ...@@ -159,7 +159,7 @@ int ath10k_bmi_write_memory(struct ath10k *ar,
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, hdrlen + txlen, ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, hdrlen + txlen,
NULL, NULL); NULL, NULL);
if (ret) { if (ret) {
ath10k_warn("unable to write to the device (%d)\n", ath10k_warn(ar, "unable to write to the device (%d)\n",
ret); ret);
return ret; return ret;
} }
...@@ -183,11 +183,11 @@ int ath10k_bmi_execute(struct ath10k *ar, u32 address, u32 param, u32 *result) ...@@ -183,11 +183,11 @@ int ath10k_bmi_execute(struct ath10k *ar, u32 address, u32 param, u32 *result)
u32 resplen = sizeof(resp.execute); u32 resplen = sizeof(resp.execute);
int ret; int ret;
ath10k_dbg(ATH10K_DBG_BMI, "bmi execute address 0x%x param 0x%x\n", ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi execute address 0x%x param 0x%x\n",
address, param); address, param);
if (ar->bmi.done_sent) { if (ar->bmi.done_sent) {
ath10k_warn("command disallowed\n"); ath10k_warn(ar, "command disallowed\n");
return -EBUSY; return -EBUSY;
} }
...@@ -197,19 +197,19 @@ int ath10k_bmi_execute(struct ath10k *ar, u32 address, u32 param, u32 *result) ...@@ -197,19 +197,19 @@ int ath10k_bmi_execute(struct ath10k *ar, u32 address, u32 param, u32 *result)
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &resp, &resplen); ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &resp, &resplen);
if (ret) { if (ret) {
ath10k_warn("unable to read from the device\n"); ath10k_warn(ar, "unable to read from the device\n");
return ret; return ret;
} }
if (resplen < sizeof(resp.execute)) { if (resplen < sizeof(resp.execute)) {
ath10k_warn("invalid execute response length (%d)\n", ath10k_warn(ar, "invalid execute response length (%d)\n",
resplen); resplen);
return -EIO; return -EIO;
} }
*result = __le32_to_cpu(resp.execute.result); *result = __le32_to_cpu(resp.execute.result);
ath10k_dbg(ATH10K_DBG_BMI, "bmi execute result 0x%x\n", *result); ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi execute result 0x%x\n", *result);
return 0; return 0;
} }
...@@ -221,11 +221,11 @@ int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length) ...@@ -221,11 +221,11 @@ int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length)
u32 txlen; u32 txlen;
int ret; int ret;
ath10k_dbg(ATH10K_DBG_BMI, "bmi lz data buffer 0x%p length %d\n", ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi lz data buffer 0x%p length %d\n",
buffer, length); buffer, length);
if (ar->bmi.done_sent) { if (ar->bmi.done_sent) {
ath10k_warn("command disallowed\n"); ath10k_warn(ar, "command disallowed\n");
return -EBUSY; return -EBUSY;
} }
...@@ -241,7 +241,7 @@ int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length) ...@@ -241,7 +241,7 @@ int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length)
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, hdrlen + txlen, ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, hdrlen + txlen,
NULL, NULL); NULL, NULL);
if (ret) { if (ret) {
ath10k_warn("unable to write to the device\n"); ath10k_warn(ar, "unable to write to the device\n");
return ret; return ret;
} }
...@@ -258,11 +258,11 @@ int ath10k_bmi_lz_stream_start(struct ath10k *ar, u32 address) ...@@ -258,11 +258,11 @@ int ath10k_bmi_lz_stream_start(struct ath10k *ar, u32 address)
u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.lz_start); u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.lz_start);
int ret; int ret;
ath10k_dbg(ATH10K_DBG_BMI, "bmi lz stream start address 0x%x\n", ath10k_dbg(ar, ATH10K_DBG_BMI, "bmi lz stream start address 0x%x\n",
address); address);
if (ar->bmi.done_sent) { if (ar->bmi.done_sent) {
ath10k_warn("command disallowed\n"); ath10k_warn(ar, "command disallowed\n");
return -EBUSY; return -EBUSY;
} }
...@@ -271,7 +271,7 @@ int ath10k_bmi_lz_stream_start(struct ath10k *ar, u32 address) ...@@ -271,7 +271,7 @@ int ath10k_bmi_lz_stream_start(struct ath10k *ar, u32 address)
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, NULL, NULL); ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, NULL, NULL);
if (ret) { if (ret) {
ath10k_warn("unable to Start LZ Stream to the device\n"); ath10k_warn(ar, "unable to Start LZ Stream to the device\n");
return ret; return ret;
} }
...@@ -286,7 +286,7 @@ int ath10k_bmi_fast_download(struct ath10k *ar, ...@@ -286,7 +286,7 @@ int ath10k_bmi_fast_download(struct ath10k *ar,
u32 trailer_len = length - head_len; u32 trailer_len = length - head_len;
int ret; int ret;
ath10k_dbg(ATH10K_DBG_BMI, ath10k_dbg(ar, ATH10K_DBG_BMI,
"bmi fast download address 0x%x buffer 0x%p length %d\n", "bmi fast download address 0x%x buffer 0x%p length %d\n",
address, buffer, length); address, buffer, length);
......
...@@ -284,13 +284,9 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, ...@@ -284,13 +284,9 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
int ret = 0; int ret = 0;
if (nbytes > ce_state->src_sz_max) if (nbytes > ce_state->src_sz_max)
ath10k_warn("%s: send more we can (nbytes: %d, max: %d)\n", ath10k_warn(ar, "%s: send more we can (nbytes: %d, max: %d)\n",
__func__, nbytes, ce_state->src_sz_max); __func__, nbytes, ce_state->src_sz_max);
ret = ath10k_pci_wake(ar);
if (ret)
return ret;
if (unlikely(CE_RING_DELTA(nentries_mask, if (unlikely(CE_RING_DELTA(nentries_mask,
write_index, sw_index - 1) <= 0)) { write_index, sw_index - 1) <= 0)) {
ret = -ENOSR; ret = -ENOSR;
...@@ -325,7 +321,6 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, ...@@ -325,7 +321,6 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
src_ring->write_index = write_index; src_ring->write_index = write_index;
exit: exit:
ath10k_pci_sleep(ar);
return ret; return ret;
} }
...@@ -390,49 +385,57 @@ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe) ...@@ -390,49 +385,57 @@ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe)
return delta; return delta;
} }
int ath10k_ce_recv_buf_enqueue(struct ath10k_ce_pipe *ce_state,
void *per_recv_context, int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe)
u32 buffer)
{ {
struct ath10k_ce_ring *dest_ring = ce_state->dest_ring; struct ath10k *ar = pipe->ar;
u32 ctrl_addr = ce_state->ctrl_addr;
struct ath10k *ar = ce_state->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_ce_ring *dest_ring = pipe->dest_ring;
unsigned int nentries_mask = dest_ring->nentries_mask; unsigned int nentries_mask = dest_ring->nentries_mask;
unsigned int write_index; unsigned int write_index = dest_ring->write_index;
unsigned int sw_index; unsigned int sw_index = dest_ring->sw_index;
int ret;
spin_lock_bh(&ar_pci->ce_lock); lockdep_assert_held(&ar_pci->ce_lock);
write_index = dest_ring->write_index;
sw_index = dest_ring->sw_index;
ret = ath10k_pci_wake(ar); return CE_RING_DELTA(nentries_mask, write_index, sw_index - 1);
if (ret) }
goto out;
if (CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) > 0) { int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
struct ce_desc *base = dest_ring->base_addr_owner_space; {
struct ce_desc *desc = CE_DEST_RING_TO_DESC(base, write_index); struct ath10k *ar = pipe->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_ce_ring *dest_ring = pipe->dest_ring;
unsigned int nentries_mask = dest_ring->nentries_mask;
unsigned int write_index = dest_ring->write_index;
unsigned int sw_index = dest_ring->sw_index;
struct ce_desc *base = dest_ring->base_addr_owner_space;
struct ce_desc *desc = CE_DEST_RING_TO_DESC(base, write_index);
u32 ctrl_addr = pipe->ctrl_addr;
/* Update destination descriptor */ lockdep_assert_held(&ar_pci->ce_lock);
desc->addr = __cpu_to_le32(buffer);
desc->nbytes = 0;
dest_ring->per_transfer_context[write_index] = if (CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0)
per_recv_context; return -EIO;
/* Update Destination Ring Write Index */ desc->addr = __cpu_to_le32(paddr);
write_index = CE_RING_IDX_INCR(nentries_mask, write_index); desc->nbytes = 0;
ath10k_ce_dest_ring_write_index_set(ar, ctrl_addr, write_index);
dest_ring->write_index = write_index; dest_ring->per_transfer_context[write_index] = ctx;
ret = 0; write_index = CE_RING_IDX_INCR(nentries_mask, write_index);
} else { ath10k_ce_dest_ring_write_index_set(ar, ctrl_addr, write_index);
ret = -EIO; dest_ring->write_index = write_index;
}
ath10k_pci_sleep(ar); return 0;
}
int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
{
struct ath10k *ar = pipe->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ret;
out: spin_lock_bh(&ar_pci->ce_lock);
ret = __ath10k_ce_rx_post_buf(pipe, ctx, paddr);
spin_unlock_bh(&ar_pci->ce_lock); spin_unlock_bh(&ar_pci->ce_lock);
return ret; return ret;
...@@ -588,7 +591,6 @@ static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, ...@@ -588,7 +591,6 @@ static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
unsigned int sw_index = src_ring->sw_index; unsigned int sw_index = src_ring->sw_index;
struct ce_desc *sdesc, *sbase; struct ce_desc *sdesc, *sbase;
unsigned int read_index; unsigned int read_index;
int ret;
if (src_ring->hw_index == sw_index) { if (src_ring->hw_index == sw_index) {
/* /*
...@@ -599,18 +601,12 @@ static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, ...@@ -599,18 +601,12 @@ static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
* value of the HW index has become stale. * value of the HW index has become stale.
*/ */
ret = ath10k_pci_wake(ar);
if (ret)
return ret;
read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
if (read_index == 0xffffffff) if (read_index == 0xffffffff)
return -ENODEV; return -ENODEV;
read_index &= nentries_mask; read_index &= nentries_mask;
src_ring->hw_index = read_index; src_ring->hw_index = read_index;
ath10k_pci_sleep(ar);
} }
read_index = src_ring->hw_index; read_index = src_ring->hw_index;
...@@ -731,11 +727,6 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) ...@@ -731,11 +727,6 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
u32 ctrl_addr = ce_state->ctrl_addr; u32 ctrl_addr = ce_state->ctrl_addr;
int ret;
ret = ath10k_pci_wake(ar);
if (ret)
return;
spin_lock_bh(&ar_pci->ce_lock); spin_lock_bh(&ar_pci->ce_lock);
...@@ -760,7 +751,6 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) ...@@ -760,7 +751,6 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
ath10k_ce_engine_int_status_clear(ar, ctrl_addr, CE_WATERMARK_MASK); ath10k_ce_engine_int_status_clear(ar, ctrl_addr, CE_WATERMARK_MASK);
spin_unlock_bh(&ar_pci->ce_lock); spin_unlock_bh(&ar_pci->ce_lock);
ath10k_pci_sleep(ar);
} }
/* /*
...@@ -771,13 +761,9 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) ...@@ -771,13 +761,9 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id)
void ath10k_ce_per_engine_service_any(struct ath10k *ar) void ath10k_ce_per_engine_service_any(struct ath10k *ar)
{ {
int ce_id, ret; int ce_id;
u32 intr_summary; u32 intr_summary;
ret = ath10k_pci_wake(ar);
if (ret)
return;
intr_summary = CE_INTERRUPT_SUMMARY(ar); intr_summary = CE_INTERRUPT_SUMMARY(ar);
for (ce_id = 0; intr_summary && (ce_id < CE_COUNT); ce_id++) { for (ce_id = 0; intr_summary && (ce_id < CE_COUNT); ce_id++) {
...@@ -789,8 +775,6 @@ void ath10k_ce_per_engine_service_any(struct ath10k *ar) ...@@ -789,8 +775,6 @@ void ath10k_ce_per_engine_service_any(struct ath10k *ar)
ath10k_ce_per_engine_service(ar, ce_id); ath10k_ce_per_engine_service(ar, ce_id);
} }
ath10k_pci_sleep(ar);
} }
/* /*
...@@ -800,16 +784,11 @@ void ath10k_ce_per_engine_service_any(struct ath10k *ar) ...@@ -800,16 +784,11 @@ void ath10k_ce_per_engine_service_any(struct ath10k *ar)
* *
* Called with ce_lock held. * Called with ce_lock held.
*/ */
static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state, static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state)
int disable_copy_compl_intr)
{ {
u32 ctrl_addr = ce_state->ctrl_addr; u32 ctrl_addr = ce_state->ctrl_addr;
struct ath10k *ar = ce_state->ar; struct ath10k *ar = ce_state->ar;
int ret; bool disable_copy_compl_intr = ce_state->attr_flags & CE_ATTR_DIS_INTR;
ret = ath10k_pci_wake(ar);
if (ret)
return;
if ((!disable_copy_compl_intr) && if ((!disable_copy_compl_intr) &&
(ce_state->send_cb || ce_state->recv_cb)) (ce_state->send_cb || ce_state->recv_cb))
...@@ -818,17 +797,11 @@ static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state, ...@@ -818,17 +797,11 @@ static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state,
ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr); ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr);
ath10k_ce_watermark_intr_disable(ar, ctrl_addr); ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
ath10k_pci_sleep(ar);
} }
int ath10k_ce_disable_interrupts(struct ath10k *ar) int ath10k_ce_disable_interrupts(struct ath10k *ar)
{ {
int ce_id, ret; int ce_id;
ret = ath10k_pci_wake(ar);
if (ret)
return ret;
for (ce_id = 0; ce_id < CE_COUNT; ce_id++) { for (ce_id = 0; ce_id < CE_COUNT; ce_id++) {
u32 ctrl_addr = ath10k_ce_base_address(ce_id); u32 ctrl_addr = ath10k_ce_base_address(ce_id);
...@@ -838,34 +811,16 @@ int ath10k_ce_disable_interrupts(struct ath10k *ar) ...@@ -838,34 +811,16 @@ int ath10k_ce_disable_interrupts(struct ath10k *ar)
ath10k_ce_watermark_intr_disable(ar, ctrl_addr); ath10k_ce_watermark_intr_disable(ar, ctrl_addr);
} }
ath10k_pci_sleep(ar);
return 0; return 0;
} }
void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state, void ath10k_ce_enable_interrupts(struct ath10k *ar)
void (*send_cb)(struct ath10k_ce_pipe *),
int disable_interrupts)
{ {
struct ath10k *ar = ce_state->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ce_id;
spin_lock_bh(&ar_pci->ce_lock); for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
ce_state->send_cb = send_cb; ath10k_ce_per_engine_handler_adjust(&ar_pci->ce_states[ce_id]);
ath10k_ce_per_engine_handler_adjust(ce_state, disable_interrupts);
spin_unlock_bh(&ar_pci->ce_lock);
}
void ath10k_ce_recv_cb_register(struct ath10k_ce_pipe *ce_state,
void (*recv_cb)(struct ath10k_ce_pipe *))
{
struct ath10k *ar = ce_state->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
spin_lock_bh(&ar_pci->ce_lock);
ce_state->recv_cb = recv_cb;
ath10k_ce_per_engine_handler_adjust(ce_state, 0);
spin_unlock_bh(&ar_pci->ce_lock);
} }
static int ath10k_ce_init_src_ring(struct ath10k *ar, static int ath10k_ce_init_src_ring(struct ath10k *ar,
...@@ -898,7 +853,7 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar, ...@@ -898,7 +853,7 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar,
ath10k_ce_src_ring_lowmark_set(ar, ctrl_addr, 0); ath10k_ce_src_ring_lowmark_set(ar, ctrl_addr, 0);
ath10k_ce_src_ring_highmark_set(ar, ctrl_addr, nentries); ath10k_ce_src_ring_highmark_set(ar, ctrl_addr, nentries);
ath10k_dbg(ATH10K_DBG_BOOT, ath10k_dbg(ar, ATH10K_DBG_BOOT,
"boot init ce src ring id %d entries %d base_addr %p\n", "boot init ce src ring id %d entries %d base_addr %p\n",
ce_id, nentries, src_ring->base_addr_owner_space); ce_id, nentries, src_ring->base_addr_owner_space);
...@@ -932,7 +887,7 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar, ...@@ -932,7 +887,7 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar,
ath10k_ce_dest_ring_lowmark_set(ar, ctrl_addr, 0); ath10k_ce_dest_ring_lowmark_set(ar, ctrl_addr, 0);
ath10k_ce_dest_ring_highmark_set(ar, ctrl_addr, nentries); ath10k_ce_dest_ring_highmark_set(ar, ctrl_addr, nentries);
ath10k_dbg(ATH10K_DBG_BOOT, ath10k_dbg(ar, ATH10K_DBG_BOOT,
"boot ce dest ring id %d entries %d base_addr %p\n", "boot ce dest ring id %d entries %d base_addr %p\n",
ce_id, nentries, dest_ring->base_addr_owner_space); ce_id, nentries, dest_ring->base_addr_owner_space);
...@@ -1067,7 +1022,9 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id, ...@@ -1067,7 +1022,9 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id,
* initialized by software/firmware. * initialized by software/firmware.
*/ */
int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id, int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
const struct ce_attr *attr) const struct ce_attr *attr,
void (*send_cb)(struct ath10k_ce_pipe *),
void (*recv_cb)(struct ath10k_ce_pipe *))
{ {
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
...@@ -1084,39 +1041,37 @@ int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id, ...@@ -1084,39 +1041,37 @@ int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC > BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC >
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
ret = ath10k_pci_wake(ar);
if (ret)
return ret;
spin_lock_bh(&ar_pci->ce_lock); spin_lock_bh(&ar_pci->ce_lock);
ce_state->ar = ar; ce_state->ar = ar;
ce_state->id = ce_id; ce_state->id = ce_id;
ce_state->ctrl_addr = ath10k_ce_base_address(ce_id); ce_state->ctrl_addr = ath10k_ce_base_address(ce_id);
ce_state->attr_flags = attr->flags; ce_state->attr_flags = attr->flags;
ce_state->src_sz_max = attr->src_sz_max; ce_state->src_sz_max = attr->src_sz_max;
if (attr->src_nentries)
ce_state->send_cb = send_cb;
if (attr->dest_nentries)
ce_state->recv_cb = recv_cb;
spin_unlock_bh(&ar_pci->ce_lock); spin_unlock_bh(&ar_pci->ce_lock);
if (attr->src_nentries) { if (attr->src_nentries) {
ret = ath10k_ce_init_src_ring(ar, ce_id, attr); ret = ath10k_ce_init_src_ring(ar, ce_id, attr);
if (ret) { if (ret) {
ath10k_err("Failed to initialize CE src ring for ID: %d (%d)\n", ath10k_err(ar, "Failed to initialize CE src ring for ID: %d (%d)\n",
ce_id, ret); ce_id, ret);
goto out; return ret;
} }
} }
if (attr->dest_nentries) { if (attr->dest_nentries) {
ret = ath10k_ce_init_dest_ring(ar, ce_id, attr); ret = ath10k_ce_init_dest_ring(ar, ce_id, attr);
if (ret) { if (ret) {
ath10k_err("Failed to initialize CE dest ring for ID: %d (%d)\n", ath10k_err(ar, "Failed to initialize CE dest ring for ID: %d (%d)\n",
ce_id, ret); ce_id, ret);
goto out; return ret;
} }
} }
out: return 0;
ath10k_pci_sleep(ar);
return ret;
} }
static void ath10k_ce_deinit_src_ring(struct ath10k *ar, unsigned int ce_id) static void ath10k_ce_deinit_src_ring(struct ath10k *ar, unsigned int ce_id)
...@@ -1140,16 +1095,8 @@ static void ath10k_ce_deinit_dest_ring(struct ath10k *ar, unsigned int ce_id) ...@@ -1140,16 +1095,8 @@ static void ath10k_ce_deinit_dest_ring(struct ath10k *ar, unsigned int ce_id)
void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id) void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id)
{ {
int ret;
ret = ath10k_pci_wake(ar);
if (ret)
return;
ath10k_ce_deinit_src_ring(ar, ce_id); ath10k_ce_deinit_src_ring(ar, ce_id);
ath10k_ce_deinit_dest_ring(ar, ce_id); ath10k_ce_deinit_dest_ring(ar, ce_id);
ath10k_pci_sleep(ar);
} }
int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
...@@ -1163,7 +1110,7 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, ...@@ -1163,7 +1110,7 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
ce_state->src_ring = ath10k_ce_alloc_src_ring(ar, ce_id, attr); ce_state->src_ring = ath10k_ce_alloc_src_ring(ar, ce_id, attr);
if (IS_ERR(ce_state->src_ring)) { if (IS_ERR(ce_state->src_ring)) {
ret = PTR_ERR(ce_state->src_ring); ret = PTR_ERR(ce_state->src_ring);
ath10k_err("failed to allocate copy engine source ring %d: %d\n", ath10k_err(ar, "failed to allocate copy engine source ring %d: %d\n",
ce_id, ret); ce_id, ret);
ce_state->src_ring = NULL; ce_state->src_ring = NULL;
return ret; return ret;
...@@ -1175,7 +1122,7 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, ...@@ -1175,7 +1122,7 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
attr); attr);
if (IS_ERR(ce_state->dest_ring)) { if (IS_ERR(ce_state->dest_ring)) {
ret = PTR_ERR(ce_state->dest_ring); ret = PTR_ERR(ce_state->dest_ring);
ath10k_err("failed to allocate copy engine destination ring %d: %d\n", ath10k_err(ar, "failed to allocate copy engine destination ring %d: %d\n",
ce_id, ret); ce_id, ret);
ce_state->dest_ring = NULL; ce_state->dest_ring = NULL;
return ret; return ret;
......
...@@ -162,30 +162,13 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state, ...@@ -162,30 +162,13 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
void __ath10k_ce_send_revert(struct ath10k_ce_pipe *pipe); void __ath10k_ce_send_revert(struct ath10k_ce_pipe *pipe);
void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state,
void (*send_cb)(struct ath10k_ce_pipe *),
int disable_interrupts);
int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe); int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe);
/*==================Recv=======================*/ /*==================Recv=======================*/
/* int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe);
* Make a buffer available to receive. The buffer must be at least of a int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr);
* minimal size appropriate for this copy engine (src_sz_max attribute). int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr);
* ce - which copy engine to use
* per_transfer_recv_context - context passed back to caller's recv_cb
* buffer - address of buffer in CE space
* Returns 0 on success; otherwise an error status.
*
* Implemenation note: Pushes a buffer to Dest ring.
*/
int ath10k_ce_recv_buf_enqueue(struct ath10k_ce_pipe *ce_state,
void *per_transfer_recv_context,
u32 buffer);
void ath10k_ce_recv_cb_register(struct ath10k_ce_pipe *ce_state,
void (*recv_cb)(struct ath10k_ce_pipe *));
/* recv flags */ /* recv flags */
/* Data is byte-swapped */ /* Data is byte-swapped */
...@@ -214,7 +197,9 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, ...@@ -214,7 +197,9 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
/*==================CE Engine Initialization=======================*/ /*==================CE Engine Initialization=======================*/
int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id, int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
const struct ce_attr *attr); const struct ce_attr *attr,
void (*send_cb)(struct ath10k_ce_pipe *),
void (*recv_cb)(struct ath10k_ce_pipe *));
void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id); void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id);
int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
const struct ce_attr *attr); const struct ce_attr *attr);
...@@ -245,6 +230,7 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state, ...@@ -245,6 +230,7 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state,
void ath10k_ce_per_engine_service_any(struct ath10k *ar); void ath10k_ce_per_engine_service_any(struct ath10k *ar);
void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id); void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id);
int ath10k_ce_disable_interrupts(struct ath10k *ar); int ath10k_ce_disable_interrupts(struct ath10k *ar);
void ath10k_ce_enable_interrupts(struct ath10k *ar);
/* ce_attr.flags values */ /* ce_attr.flags values */
/* Use NonSnooping PCIe accesses? */ /* Use NonSnooping PCIe accesses? */
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#include <linux/if_ether.h> #include <linux/if_ether.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/uuid.h>
#include <linux/time.h>
#include "htt.h" #include "htt.h"
#include "htc.h" #include "htc.h"
...@@ -31,6 +33,7 @@ ...@@ -31,6 +33,7 @@
#include "../ath.h" #include "../ath.h"
#include "../regd.h" #include "../regd.h"
#include "../dfs_pattern_detector.h" #include "../dfs_pattern_detector.h"
#include "spectral.h"
#define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB) #define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
...@@ -237,6 +240,7 @@ struct ath10k_vif { ...@@ -237,6 +240,7 @@ struct ath10k_vif {
bool is_started; bool is_started;
bool is_up; bool is_up;
bool spectral_enabled;
u32 aid; u32 aid;
u8 bssid[ETH_ALEN]; u8 bssid[ETH_ALEN];
...@@ -276,11 +280,20 @@ struct ath10k_vif_iter { ...@@ -276,11 +280,20 @@ struct ath10k_vif_iter {
struct ath10k_vif *arvif; struct ath10k_vif *arvif;
}; };
/* used for crash-dump storage, protected by data-lock */
struct ath10k_fw_crash_data {
bool crashed_since_read;
uuid_le uuid;
struct timespec timestamp;
__le32 registers[REG_DUMP_COUNT_QCA988X];
};
struct ath10k_debug { struct ath10k_debug {
struct dentry *debugfs_phy; struct dentry *debugfs_phy;
struct ath10k_target_stats target_stats; struct ath10k_target_stats target_stats;
u32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE]; DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_BM_SIZE);
struct completion event_stats_compl; struct completion event_stats_compl;
...@@ -293,6 +306,8 @@ struct ath10k_debug { ...@@ -293,6 +306,8 @@ struct ath10k_debug {
u8 htt_max_amsdu; u8 htt_max_amsdu;
u8 htt_max_ampdu; u8 htt_max_ampdu;
struct ath10k_fw_crash_data *fw_crash_data;
}; };
enum ath10k_state { enum ath10k_state {
...@@ -330,6 +345,11 @@ enum ath10k_fw_features { ...@@ -330,6 +345,11 @@ enum ath10k_fw_features {
/* Firmware does not support P2P */ /* Firmware does not support P2P */
ATH10K_FW_FEATURE_NO_P2P = 3, ATH10K_FW_FEATURE_NO_P2P = 3,
/* Firmware 10.2 feature bit. The ATH10K_FW_FEATURE_WMI_10X feature bit
* is required to be set as well.
*/
ATH10K_FW_FEATURE_WMI_10_2 = 4,
/* keep last */ /* keep last */
ATH10K_FW_FEATURE_COUNT, ATH10K_FW_FEATURE_COUNT,
}; };
...@@ -337,10 +357,32 @@ enum ath10k_fw_features { ...@@ -337,10 +357,32 @@ enum ath10k_fw_features {
enum ath10k_dev_flags { enum ath10k_dev_flags {
/* Indicates that ath10k device is during CAC phase of DFS */ /* Indicates that ath10k device is during CAC phase of DFS */
ATH10K_CAC_RUNNING, ATH10K_CAC_RUNNING,
ATH10K_FLAG_FIRST_BOOT_DONE,
ATH10K_FLAG_CORE_REGISTERED, ATH10K_FLAG_CORE_REGISTERED,
}; };
enum ath10k_scan_state {
ATH10K_SCAN_IDLE,
ATH10K_SCAN_STARTING,
ATH10K_SCAN_RUNNING,
ATH10K_SCAN_ABORTING,
};
static inline const char *ath10k_scan_state_str(enum ath10k_scan_state state)
{
switch (state) {
case ATH10K_SCAN_IDLE:
return "idle";
case ATH10K_SCAN_STARTING:
return "starting";
case ATH10K_SCAN_RUNNING:
return "running";
case ATH10K_SCAN_ABORTING:
return "aborting";
}
return "unknown";
}
struct ath10k { struct ath10k {
struct ath_common ath_common; struct ath_common ath_common;
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
...@@ -368,7 +410,6 @@ struct ath10k { ...@@ -368,7 +410,6 @@ struct ath10k {
bool p2p; bool p2p;
struct { struct {
void *priv;
const struct ath10k_hif_ops *ops; const struct ath10k_hif_ops *ops;
} hif; } hif;
...@@ -410,10 +451,9 @@ struct ath10k { ...@@ -410,10 +451,9 @@ struct ath10k {
struct completion started; struct completion started;
struct completion completed; struct completion completed;
struct completion on_channel; struct completion on_channel;
struct timer_list timeout; struct delayed_work timeout;
enum ath10k_scan_state state;
bool is_roc; bool is_roc;
bool in_progress;
bool aborting;
int vdev_id; int vdev_id;
int roc_freq; int roc_freq;
} scan; } scan;
...@@ -494,9 +534,21 @@ struct ath10k { ...@@ -494,9 +534,21 @@ struct ath10k {
#ifdef CONFIG_ATH10K_DEBUGFS #ifdef CONFIG_ATH10K_DEBUGFS
struct ath10k_debug debug; struct ath10k_debug debug;
#endif #endif
struct {
/* relay(fs) channel for spectral scan */
struct rchan *rfs_chan_spec_scan;
/* spectral_mode and spec_config are protected by conf_mutex */
enum ath10k_spectral_mode mode;
struct ath10k_spec_scan config;
} spectral;
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
}; };
struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev, struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
const struct ath10k_hif_ops *hif_ops); const struct ath10k_hif_ops *hif_ops);
void ath10k_core_destroy(struct ath10k *ar); void ath10k_core_destroy(struct ath10k *ar);
......
...@@ -17,6 +17,9 @@ ...@@ -17,6 +17,9 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/version.h>
#include <linux/vermagic.h>
#include <linux/vmalloc.h>
#include "core.h" #include "core.h"
#include "debug.h" #include "debug.h"
...@@ -24,25 +27,86 @@ ...@@ -24,25 +27,86 @@
/* ms */ /* ms */
#define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000 #define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
static int ath10k_printk(const char *level, const char *fmt, ...) #define ATH10K_FW_CRASH_DUMP_VERSION 1
{
struct va_format vaf;
va_list args;
int rtn;
va_start(args, fmt); /**
* enum ath10k_fw_crash_dump_type - types of data in the dump file
* @ATH10K_FW_CRASH_DUMP_REGDUMP: Register crash dump in binary format
*/
enum ath10k_fw_crash_dump_type {
ATH10K_FW_CRASH_DUMP_REGISTERS = 0,
vaf.fmt = fmt; ATH10K_FW_CRASH_DUMP_MAX,
vaf.va = &args; };
rtn = printk("%sath10k: %pV", level, &vaf); struct ath10k_tlv_dump_data {
/* see ath10k_fw_crash_dump_type above */
__le32 type;
va_end(args); /* in bytes */
__le32 tlv_len;
return rtn; /* pad to 32-bit boundaries as needed */
} u8 tlv_data[];
} __packed;
struct ath10k_dump_file_data {
/* dump file information */
/* "ATH10K-FW-DUMP" */
char df_magic[16];
__le32 len;
/* file dump version */
__le32 version;
/* some info we can get from ath10k struct that might help */
u8 uuid[16];
__le32 chip_id;
/* 0 for now, in place for later hardware */
__le32 bus_type;
__le32 target_version;
__le32 fw_version_major;
__le32 fw_version_minor;
__le32 fw_version_release;
__le32 fw_version_build;
__le32 phy_capability;
__le32 hw_min_tx_power;
__le32 hw_max_tx_power;
__le32 ht_cap_info;
__le32 vht_cap_info;
__le32 num_rf_chains;
/* firmware version string */
char fw_ver[ETHTOOL_FWVERS_LEN];
/* Kernel related information */
/* time-of-day stamp */
__le64 tv_sec;
int ath10k_info(const char *fmt, ...) /* time-of-day stamp, nano-seconds */
__le64 tv_nsec;
/* LINUX_VERSION_CODE */
__le32 kernel_ver_code;
/* VERMAGIC_STRING */
char kernel_ver[64];
/* room for growth w/out changing binary format */
u8 unused[128];
/* struct ath10k_tlv_dump_data + more */
u8 data[0];
} __packed;
int ath10k_info(struct ath10k *ar, const char *fmt, ...)
{ {
struct va_format vaf = { struct va_format vaf = {
.fmt = fmt, .fmt = fmt,
...@@ -52,7 +116,7 @@ int ath10k_info(const char *fmt, ...) ...@@ -52,7 +116,7 @@ int ath10k_info(const char *fmt, ...)
va_start(args, fmt); va_start(args, fmt);
vaf.va = &args; vaf.va = &args;
ret = ath10k_printk(KERN_INFO, "%pV", &vaf); ret = dev_info(ar->dev, "%pV", &vaf);
trace_ath10k_log_info(&vaf); trace_ath10k_log_info(&vaf);
va_end(args); va_end(args);
...@@ -60,7 +124,25 @@ int ath10k_info(const char *fmt, ...) ...@@ -60,7 +124,25 @@ int ath10k_info(const char *fmt, ...)
} }
EXPORT_SYMBOL(ath10k_info); EXPORT_SYMBOL(ath10k_info);
int ath10k_err(const char *fmt, ...) void ath10k_print_driver_info(struct ath10k *ar)
{
ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
ar->hw_params.name,
ar->target_version,
ar->chip_id,
ar->hw->wiphy->fw_version,
ar->fw_api,
ar->htt.target_version_major,
ar->htt.target_version_minor);
ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d\n",
config_enabled(CONFIG_ATH10K_DEBUG),
config_enabled(CONFIG_ATH10K_DEBUGFS),
config_enabled(CONFIG_ATH10K_TRACING),
config_enabled(CONFIG_ATH10K_DFS_CERTIFIED));
}
EXPORT_SYMBOL(ath10k_print_driver_info);
int ath10k_err(struct ath10k *ar, const char *fmt, ...)
{ {
struct va_format vaf = { struct va_format vaf = {
.fmt = fmt, .fmt = fmt,
...@@ -70,7 +152,7 @@ int ath10k_err(const char *fmt, ...) ...@@ -70,7 +152,7 @@ int ath10k_err(const char *fmt, ...)
va_start(args, fmt); va_start(args, fmt);
vaf.va = &args; vaf.va = &args;
ret = ath10k_printk(KERN_ERR, "%pV", &vaf); ret = dev_err(ar->dev, "%pV", &vaf);
trace_ath10k_log_err(&vaf); trace_ath10k_log_err(&vaf);
va_end(args); va_end(args);
...@@ -78,25 +160,21 @@ int ath10k_err(const char *fmt, ...) ...@@ -78,25 +160,21 @@ int ath10k_err(const char *fmt, ...)
} }
EXPORT_SYMBOL(ath10k_err); EXPORT_SYMBOL(ath10k_err);
int ath10k_warn(const char *fmt, ...) int ath10k_warn(struct ath10k *ar, const char *fmt, ...)
{ {
struct va_format vaf = { struct va_format vaf = {
.fmt = fmt, .fmt = fmt,
}; };
va_list args; va_list args;
int ret = 0;
va_start(args, fmt); va_start(args, fmt);
vaf.va = &args; vaf.va = &args;
dev_warn_ratelimited(ar->dev, "%pV", &vaf);
if (net_ratelimit())
ret = ath10k_printk(KERN_WARNING, "%pV", &vaf);
trace_ath10k_log_warn(&vaf); trace_ath10k_log_warn(&vaf);
va_end(args); va_end(args);
return ret; return 0;
} }
EXPORT_SYMBOL(ath10k_warn); EXPORT_SYMBOL(ath10k_warn);
...@@ -115,9 +193,10 @@ static ssize_t ath10k_read_wmi_services(struct file *file, ...@@ -115,9 +193,10 @@ static ssize_t ath10k_read_wmi_services(struct file *file,
{ {
struct ath10k *ar = file->private_data; struct ath10k *ar = file->private_data;
char *buf; char *buf;
unsigned int len = 0, buf_len = 1500; unsigned int len = 0, buf_len = 4096;
const char *status; const char *name;
ssize_t ret_cnt; ssize_t ret_cnt;
bool enabled;
int i; int i;
buf = kzalloc(buf_len, GFP_KERNEL); buf = kzalloc(buf_len, GFP_KERNEL);
...@@ -129,15 +208,22 @@ static ssize_t ath10k_read_wmi_services(struct file *file, ...@@ -129,15 +208,22 @@ static ssize_t ath10k_read_wmi_services(struct file *file,
if (len > buf_len) if (len > buf_len)
len = buf_len; len = buf_len;
for (i = 0; i < WMI_SERVICE_LAST; i++) { for (i = 0; i < WMI_MAX_SERVICE; i++) {
if (WMI_SERVICE_IS_ENABLED(ar->debug.wmi_service_bitmap, i)) enabled = test_bit(i, ar->debug.wmi_service_bitmap);
status = "enabled"; name = wmi_service_name(i);
else
status = "disabled"; if (!name) {
if (enabled)
len += scnprintf(buf + len, buf_len - len,
"%-40s %s (bit %d)\n",
"unknown", "enabled", i);
continue;
}
len += scnprintf(buf + len, buf_len - len, len += scnprintf(buf + len, buf_len - len,
"0x%02x - %20s - %s\n", "%-40s %s\n",
i, wmi_service_name(i), status); name, enabled ? "enabled" : "-");
} }
ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
...@@ -309,7 +395,7 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf, ...@@ -309,7 +395,7 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT); ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
if (ret) { if (ret) {
ath10k_warn("could not request stats (%d)\n", ret); ath10k_warn(ar, "could not request stats (%d)\n", ret);
goto exit; goto exit;
} }
...@@ -527,11 +613,14 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file, ...@@ -527,11 +613,14 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
} }
if (!strcmp(buf, "soft")) { if (!strcmp(buf, "soft")) {
ath10k_info("simulating soft firmware crash\n"); ath10k_info(ar, "simulating soft firmware crash\n");
ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0); ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
} else if (!strcmp(buf, "hard")) { } else if (!strcmp(buf, "hard")) {
ath10k_info("simulating hard firmware crash\n"); ath10k_info(ar, "simulating hard firmware crash\n");
ret = ath10k_wmi_vdev_set_param(ar, TARGET_NUM_VDEVS + 1, /* 0x7fff is vdev id, and it is always out of range for all
* firmware variants in order to force a firmware crash.
*/
ret = ath10k_wmi_vdev_set_param(ar, 0x7fff,
ar->wmi.vdev_param->rts_threshold, 0); ar->wmi.vdev_param->rts_threshold, 0);
} else { } else {
ret = -EINVAL; ret = -EINVAL;
...@@ -539,7 +628,7 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file, ...@@ -539,7 +628,7 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
} }
if (ret) { if (ret) {
ath10k_warn("failed to simulate firmware crash: %d\n", ret); ath10k_warn(ar, "failed to simulate firmware crash: %d\n", ret);
goto exit; goto exit;
} }
...@@ -577,6 +666,138 @@ static const struct file_operations fops_chip_id = { ...@@ -577,6 +666,138 @@ static const struct file_operations fops_chip_id = {
.llseek = default_llseek, .llseek = default_llseek,
}; };
struct ath10k_fw_crash_data *
ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
{
struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
lockdep_assert_held(&ar->data_lock);
crash_data->crashed_since_read = true;
uuid_le_gen(&crash_data->uuid);
getnstimeofday(&crash_data->timestamp);
return crash_data;
}
EXPORT_SYMBOL(ath10k_debug_get_new_fw_crash_data);
static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
{
struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data;
struct ath10k_dump_file_data *dump_data;
struct ath10k_tlv_dump_data *dump_tlv;
int hdr_len = sizeof(*dump_data);
unsigned int len, sofar = 0;
unsigned char *buf;
len = hdr_len;
len += sizeof(*dump_tlv) + sizeof(crash_data->registers);
sofar += hdr_len;
/* This is going to get big when we start dumping FW RAM and such,
* so go ahead and use vmalloc.
*/
buf = vzalloc(len);
if (!buf)
return NULL;
spin_lock_bh(&ar->data_lock);
if (!crash_data->crashed_since_read) {
spin_unlock_bh(&ar->data_lock);
vfree(buf);
return NULL;
}
dump_data = (struct ath10k_dump_file_data *)(buf);
strlcpy(dump_data->df_magic, "ATH10K-FW-DUMP",
sizeof(dump_data->df_magic));
dump_data->len = cpu_to_le32(len);
dump_data->version = cpu_to_le32(ATH10K_FW_CRASH_DUMP_VERSION);
memcpy(dump_data->uuid, &crash_data->uuid, sizeof(dump_data->uuid));
dump_data->chip_id = cpu_to_le32(ar->chip_id);
dump_data->bus_type = cpu_to_le32(0);
dump_data->target_version = cpu_to_le32(ar->target_version);
dump_data->fw_version_major = cpu_to_le32(ar->fw_version_major);
dump_data->fw_version_minor = cpu_to_le32(ar->fw_version_minor);
dump_data->fw_version_release = cpu_to_le32(ar->fw_version_release);
dump_data->fw_version_build = cpu_to_le32(ar->fw_version_build);
dump_data->phy_capability = cpu_to_le32(ar->phy_capability);
dump_data->hw_min_tx_power = cpu_to_le32(ar->hw_min_tx_power);
dump_data->hw_max_tx_power = cpu_to_le32(ar->hw_max_tx_power);
dump_data->ht_cap_info = cpu_to_le32(ar->ht_cap_info);
dump_data->vht_cap_info = cpu_to_le32(ar->vht_cap_info);
dump_data->num_rf_chains = cpu_to_le32(ar->num_rf_chains);
strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
sizeof(dump_data->fw_ver));
dump_data->kernel_ver_code = cpu_to_le32(LINUX_VERSION_CODE);
strlcpy(dump_data->kernel_ver, VERMAGIC_STRING,
sizeof(dump_data->kernel_ver));
dump_data->tv_sec = cpu_to_le64(crash_data->timestamp.tv_sec);
dump_data->tv_nsec = cpu_to_le64(crash_data->timestamp.tv_nsec);
/* Gather crash-dump */
dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar);
dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_REGISTERS);
dump_tlv->tlv_len = cpu_to_le32(sizeof(crash_data->registers));
memcpy(dump_tlv->tlv_data, &crash_data->registers,
sizeof(crash_data->registers));
sofar += sizeof(*dump_tlv) + sizeof(crash_data->registers);
ar->debug.fw_crash_data->crashed_since_read = false;
spin_unlock_bh(&ar->data_lock);
return dump_data;
}
static int ath10k_fw_crash_dump_open(struct inode *inode, struct file *file)
{
struct ath10k *ar = inode->i_private;
struct ath10k_dump_file_data *dump;
dump = ath10k_build_dump_file(ar);
if (!dump)
return -ENODATA;
file->private_data = dump;
return 0;
}
static ssize_t ath10k_fw_crash_dump_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k_dump_file_data *dump_file = file->private_data;
return simple_read_from_buffer(user_buf, count, ppos,
dump_file,
le32_to_cpu(dump_file->len));
}
static int ath10k_fw_crash_dump_release(struct inode *inode,
struct file *file)
{
vfree(file->private_data);
return 0;
}
static const struct file_operations fops_fw_crash_dump = {
.open = ath10k_fw_crash_dump_open,
.read = ath10k_fw_crash_dump_read,
.release = ath10k_fw_crash_dump_release,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static int ath10k_debug_htt_stats_req(struct ath10k *ar) static int ath10k_debug_htt_stats_req(struct ath10k *ar)
{ {
u64 cookie; u64 cookie;
...@@ -596,7 +817,7 @@ static int ath10k_debug_htt_stats_req(struct ath10k *ar) ...@@ -596,7 +817,7 @@ static int ath10k_debug_htt_stats_req(struct ath10k *ar)
ret = ath10k_htt_h2t_stats_req(&ar->htt, ar->debug.htt_stats_mask, ret = ath10k_htt_h2t_stats_req(&ar->htt, ar->debug.htt_stats_mask,
cookie); cookie);
if (ret) { if (ret) {
ath10k_warn("failed to send htt stats request: %d\n", ret); ath10k_warn(ar, "failed to send htt stats request: %d\n", ret);
return ret; return ret;
} }
...@@ -770,7 +991,7 @@ static ssize_t ath10k_write_fw_dbglog(struct file *file, ...@@ -770,7 +991,7 @@ static ssize_t ath10k_write_fw_dbglog(struct file *file,
if (ar->state == ATH10K_STATE_ON) { if (ar->state == ATH10K_STATE_ON) {
ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask); ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask);
if (ret) { if (ret) {
ath10k_warn("dbglog cfg failed from debugfs: %d\n", ath10k_warn(ar, "dbglog cfg failed from debugfs: %d\n",
ret); ret);
goto exit; goto exit;
} }
...@@ -801,13 +1022,14 @@ int ath10k_debug_start(struct ath10k *ar) ...@@ -801,13 +1022,14 @@ int ath10k_debug_start(struct ath10k *ar)
ret = ath10k_debug_htt_stats_req(ar); ret = ath10k_debug_htt_stats_req(ar);
if (ret) if (ret)
/* continue normally anyway, this isn't serious */ /* continue normally anyway, this isn't serious */
ath10k_warn("failed to start htt stats workqueue: %d\n", ret); ath10k_warn(ar, "failed to start htt stats workqueue: %d\n",
ret);
if (ar->debug.fw_dbglog_mask) { if (ar->debug.fw_dbglog_mask) {
ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask); ret = ath10k_wmi_dbglog_cfg(ar, ar->debug.fw_dbglog_mask);
if (ret) if (ret)
/* not serious */ /* not serious */
ath10k_warn("failed to enable dbglog during start: %d", ath10k_warn(ar, "failed to enable dbglog during start: %d",
ret); ret);
} }
...@@ -910,11 +1132,20 @@ static const struct file_operations fops_dfs_stats = { ...@@ -910,11 +1132,20 @@ static const struct file_operations fops_dfs_stats = {
int ath10k_debug_create(struct ath10k *ar) int ath10k_debug_create(struct ath10k *ar)
{ {
int ret;
ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
if (!ar->debug.fw_crash_data) {
ret = -ENOMEM;
goto err;
}
ar->debug.debugfs_phy = debugfs_create_dir("ath10k", ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
ar->hw->wiphy->debugfsdir); ar->hw->wiphy->debugfsdir);
if (!ar->debug.debugfs_phy) {
if (!ar->debug.debugfs_phy) ret = -ENOMEM;
return -ENOMEM; goto err_free_fw_crash_data;
}
INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork, INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
ath10k_debug_htt_stats_dwork); ath10k_debug_htt_stats_dwork);
...@@ -930,6 +1161,9 @@ int ath10k_debug_create(struct ath10k *ar) ...@@ -930,6 +1161,9 @@ int ath10k_debug_create(struct ath10k *ar)
debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy, debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_simulate_fw_crash); ar, &fops_simulate_fw_crash);
debugfs_create_file("fw_crash_dump", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_fw_crash_dump);
debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy, debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_chip_id); ar, &fops_chip_id);
...@@ -958,17 +1192,25 @@ int ath10k_debug_create(struct ath10k *ar) ...@@ -958,17 +1192,25 @@ int ath10k_debug_create(struct ath10k *ar)
} }
return 0; return 0;
err_free_fw_crash_data:
vfree(ar->debug.fw_crash_data);
err:
return ret;
} }
void ath10k_debug_destroy(struct ath10k *ar) void ath10k_debug_destroy(struct ath10k *ar)
{ {
vfree(ar->debug.fw_crash_data);
cancel_delayed_work_sync(&ar->debug.htt_stats_dwork); cancel_delayed_work_sync(&ar->debug.htt_stats_dwork);
} }
#endif /* CONFIG_ATH10K_DEBUGFS */ #endif /* CONFIG_ATH10K_DEBUGFS */
#ifdef CONFIG_ATH10K_DEBUG #ifdef CONFIG_ATH10K_DEBUG
void ath10k_dbg(enum ath10k_debug_mask mask, const char *fmt, ...) void ath10k_dbg(struct ath10k *ar, enum ath10k_debug_mask mask,
const char *fmt, ...)
{ {
struct va_format vaf; struct va_format vaf;
va_list args; va_list args;
...@@ -979,7 +1221,7 @@ void ath10k_dbg(enum ath10k_debug_mask mask, const char *fmt, ...) ...@@ -979,7 +1221,7 @@ void ath10k_dbg(enum ath10k_debug_mask mask, const char *fmt, ...)
vaf.va = &args; vaf.va = &args;
if (ath10k_debug_mask & mask) if (ath10k_debug_mask & mask)
ath10k_printk(KERN_DEBUG, "%pV", &vaf); dev_printk(KERN_DEBUG, ar->dev, "%pV", &vaf);
trace_ath10k_log_dbg(mask, &vaf); trace_ath10k_log_dbg(mask, &vaf);
...@@ -987,13 +1229,14 @@ void ath10k_dbg(enum ath10k_debug_mask mask, const char *fmt, ...) ...@@ -987,13 +1229,14 @@ void ath10k_dbg(enum ath10k_debug_mask mask, const char *fmt, ...)
} }
EXPORT_SYMBOL(ath10k_dbg); EXPORT_SYMBOL(ath10k_dbg);
void ath10k_dbg_dump(enum ath10k_debug_mask mask, void ath10k_dbg_dump(struct ath10k *ar,
enum ath10k_debug_mask mask,
const char *msg, const char *prefix, const char *msg, const char *prefix,
const void *buf, size_t len) const void *buf, size_t len)
{ {
if (ath10k_debug_mask & mask) { if (ath10k_debug_mask & mask) {
if (msg) if (msg)
ath10k_dbg(mask, "%s\n", msg); ath10k_dbg(ar, mask, "%s\n", msg);
print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len);
} }
......
...@@ -39,9 +39,10 @@ enum ath10k_debug_mask { ...@@ -39,9 +39,10 @@ enum ath10k_debug_mask {
extern unsigned int ath10k_debug_mask; extern unsigned int ath10k_debug_mask;
__printf(1, 2) int ath10k_info(const char *fmt, ...); __printf(2, 3) int ath10k_info(struct ath10k *ar, const char *fmt, ...);
__printf(1, 2) int ath10k_err(const char *fmt, ...); __printf(2, 3) int ath10k_err(struct ath10k *ar, const char *fmt, ...);
__printf(1, 2) int ath10k_warn(const char *fmt, ...); __printf(2, 3) int ath10k_warn(struct ath10k *ar, const char *fmt, ...);
void ath10k_print_driver_info(struct ath10k *ar);
#ifdef CONFIG_ATH10K_DEBUGFS #ifdef CONFIG_ATH10K_DEBUGFS
int ath10k_debug_start(struct ath10k *ar); int ath10k_debug_start(struct ath10k *ar);
...@@ -53,6 +54,10 @@ void ath10k_debug_read_service_map(struct ath10k *ar, ...@@ -53,6 +54,10 @@ void ath10k_debug_read_service_map(struct ath10k *ar,
size_t map_size); size_t map_size);
void ath10k_debug_read_target_stats(struct ath10k *ar, void ath10k_debug_read_target_stats(struct ath10k *ar,
struct wmi_stats_event *ev); struct wmi_stats_event *ev);
struct ath10k_fw_crash_data *
ath10k_debug_get_new_fw_crash_data(struct ath10k *ar);
void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len);
#define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++) #define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++)
...@@ -86,25 +91,40 @@ static inline void ath10k_debug_read_target_stats(struct ath10k *ar, ...@@ -86,25 +91,40 @@ static inline void ath10k_debug_read_target_stats(struct ath10k *ar,
{ {
} }
static inline void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer,
int len)
{
}
static inline struct ath10k_fw_crash_data *
ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
{
return NULL;
}
#define ATH10K_DFS_STAT_INC(ar, c) do { } while (0) #define ATH10K_DFS_STAT_INC(ar, c) do { } while (0)
#endif /* CONFIG_ATH10K_DEBUGFS */ #endif /* CONFIG_ATH10K_DEBUGFS */
#ifdef CONFIG_ATH10K_DEBUG #ifdef CONFIG_ATH10K_DEBUG
__printf(2, 3) void ath10k_dbg(enum ath10k_debug_mask mask, __printf(3, 4) void ath10k_dbg(struct ath10k *ar,
enum ath10k_debug_mask mask,
const char *fmt, ...); const char *fmt, ...);
void ath10k_dbg_dump(enum ath10k_debug_mask mask, void ath10k_dbg_dump(struct ath10k *ar,
enum ath10k_debug_mask mask,
const char *msg, const char *prefix, const char *msg, const char *prefix,
const void *buf, size_t len); const void *buf, size_t len);
#else /* CONFIG_ATH10K_DEBUG */ #else /* CONFIG_ATH10K_DEBUG */
static inline int ath10k_dbg(enum ath10k_debug_mask dbg_mask, static inline int ath10k_dbg(struct ath10k *ar,
enum ath10k_debug_mask dbg_mask,
const char *fmt, ...) const char *fmt, ...)
{ {
return 0; return 0;
} }
static inline void ath10k_dbg_dump(enum ath10k_debug_mask mask, static inline void ath10k_dbg_dump(struct ath10k *ar,
enum ath10k_debug_mask mask,
const char *msg, const char *prefix, const char *msg, const char *prefix,
const void *buf, size_t len) const void *buf, size_t len)
{ {
......
...@@ -46,7 +46,7 @@ static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar) ...@@ -46,7 +46,7 @@ static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar)
skb = dev_alloc_skb(ATH10K_HTC_CONTROL_BUFFER_SIZE); skb = dev_alloc_skb(ATH10K_HTC_CONTROL_BUFFER_SIZE);
if (!skb) { if (!skb) {
ath10k_warn("Unable to allocate ctrl skb\n"); ath10k_warn(ar, "Unable to allocate ctrl skb\n");
return NULL; return NULL;
} }
...@@ -56,7 +56,7 @@ static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar) ...@@ -56,7 +56,7 @@ static struct sk_buff *ath10k_htc_build_tx_ctrl_skb(void *ar)
skb_cb = ATH10K_SKB_CB(skb); skb_cb = ATH10K_SKB_CB(skb);
memset(skb_cb, 0, sizeof(*skb_cb)); memset(skb_cb, 0, sizeof(*skb_cb));
ath10k_dbg(ATH10K_DBG_HTC, "%s: skb %p\n", __func__, skb); ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: skb %p\n", __func__, skb);
return skb; return skb;
} }
...@@ -72,13 +72,15 @@ static inline void ath10k_htc_restore_tx_skb(struct ath10k_htc *htc, ...@@ -72,13 +72,15 @@ static inline void ath10k_htc_restore_tx_skb(struct ath10k_htc *htc,
static void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep, static void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
struct sk_buff *skb) struct sk_buff *skb)
{ {
ath10k_dbg(ATH10K_DBG_HTC, "%s: ep %d skb %p\n", __func__, struct ath10k *ar = ep->htc->ar;
ath10k_dbg(ar, ATH10K_DBG_HTC, "%s: ep %d skb %p\n", __func__,
ep->eid, skb); ep->eid, skb);
ath10k_htc_restore_tx_skb(ep->htc, skb); ath10k_htc_restore_tx_skb(ep->htc, skb);
if (!ep->ep_ops.ep_tx_complete) { if (!ep->ep_ops.ep_tx_complete) {
ath10k_warn("no tx handler for eid %d\n", ep->eid); ath10k_warn(ar, "no tx handler for eid %d\n", ep->eid);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return; return;
} }
...@@ -89,12 +91,14 @@ static void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep, ...@@ -89,12 +91,14 @@ static void ath10k_htc_notify_tx_completion(struct ath10k_htc_ep *ep,
/* assumes tx_lock is held */ /* assumes tx_lock is held */
static bool ath10k_htc_ep_need_credit_update(struct ath10k_htc_ep *ep) static bool ath10k_htc_ep_need_credit_update(struct ath10k_htc_ep *ep)
{ {
struct ath10k *ar = ep->htc->ar;
if (!ep->tx_credit_flow_enabled) if (!ep->tx_credit_flow_enabled)
return false; return false;
if (ep->tx_credits >= ep->tx_credits_per_max_message) if (ep->tx_credits >= ep->tx_credits_per_max_message)
return false; return false;
ath10k_dbg(ATH10K_DBG_HTC, "HTC: endpoint %d needs credit update\n", ath10k_dbg(ar, ATH10K_DBG_HTC, "HTC: endpoint %d needs credit update\n",
ep->eid); ep->eid);
return true; return true;
} }
...@@ -123,6 +127,7 @@ int ath10k_htc_send(struct ath10k_htc *htc, ...@@ -123,6 +127,7 @@ int ath10k_htc_send(struct ath10k_htc *htc,
enum ath10k_htc_ep_id eid, enum ath10k_htc_ep_id eid,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct ath10k *ar = htc->ar;
struct ath10k_htc_ep *ep = &htc->endpoint[eid]; struct ath10k_htc_ep *ep = &htc->endpoint[eid];
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb); struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
struct ath10k_hif_sg_item sg_item; struct ath10k_hif_sg_item sg_item;
...@@ -134,18 +139,10 @@ int ath10k_htc_send(struct ath10k_htc *htc, ...@@ -134,18 +139,10 @@ int ath10k_htc_send(struct ath10k_htc *htc,
return -ECOMM; return -ECOMM;
if (eid >= ATH10K_HTC_EP_COUNT) { if (eid >= ATH10K_HTC_EP_COUNT) {
ath10k_warn("Invalid endpoint id: %d\n", eid); ath10k_warn(ar, "Invalid endpoint id: %d\n", eid);
return -ENOENT; return -ENOENT;
} }
/* FIXME: This looks ugly, can we fix it? */
spin_lock_bh(&htc->tx_lock);
if (htc->stopped) {
spin_unlock_bh(&htc->tx_lock);
return -ESHUTDOWN;
}
spin_unlock_bh(&htc->tx_lock);
skb_push(skb, sizeof(struct ath10k_htc_hdr)); skb_push(skb, sizeof(struct ath10k_htc_hdr));
if (ep->tx_credit_flow_enabled) { if (ep->tx_credit_flow_enabled) {
...@@ -157,7 +154,7 @@ int ath10k_htc_send(struct ath10k_htc *htc, ...@@ -157,7 +154,7 @@ int ath10k_htc_send(struct ath10k_htc *htc,
goto err_pull; goto err_pull;
} }
ep->tx_credits -= credits; ep->tx_credits -= credits;
ath10k_dbg(ATH10K_DBG_HTC, ath10k_dbg(ar, ATH10K_DBG_HTC,
"htc ep %d consumed %d credits (total %d)\n", "htc ep %d consumed %d credits (total %d)\n",
eid, credits, ep->tx_credits); eid, credits, ep->tx_credits);
spin_unlock_bh(&htc->tx_lock); spin_unlock_bh(&htc->tx_lock);
...@@ -188,7 +185,7 @@ int ath10k_htc_send(struct ath10k_htc *htc, ...@@ -188,7 +185,7 @@ int ath10k_htc_send(struct ath10k_htc *htc,
if (ep->tx_credit_flow_enabled) { if (ep->tx_credit_flow_enabled) {
spin_lock_bh(&htc->tx_lock); spin_lock_bh(&htc->tx_lock);
ep->tx_credits += credits; ep->tx_credits += credits;
ath10k_dbg(ATH10K_DBG_HTC, ath10k_dbg(ar, ATH10K_DBG_HTC,
"htc ep %d reverted %d credits back (total %d)\n", "htc ep %d reverted %d credits back (total %d)\n",
eid, credits, ep->tx_credits); eid, credits, ep->tx_credits);
spin_unlock_bh(&htc->tx_lock); spin_unlock_bh(&htc->tx_lock);
...@@ -227,11 +224,12 @@ ath10k_htc_process_credit_report(struct ath10k_htc *htc, ...@@ -227,11 +224,12 @@ ath10k_htc_process_credit_report(struct ath10k_htc *htc,
int len, int len,
enum ath10k_htc_ep_id eid) enum ath10k_htc_ep_id eid)
{ {
struct ath10k *ar = htc->ar;
struct ath10k_htc_ep *ep; struct ath10k_htc_ep *ep;
int i, n_reports; int i, n_reports;
if (len % sizeof(*report)) if (len % sizeof(*report))
ath10k_warn("Uneven credit report len %d", len); ath10k_warn(ar, "Uneven credit report len %d", len);
n_reports = len / sizeof(*report); n_reports = len / sizeof(*report);
...@@ -243,7 +241,7 @@ ath10k_htc_process_credit_report(struct ath10k_htc *htc, ...@@ -243,7 +241,7 @@ ath10k_htc_process_credit_report(struct ath10k_htc *htc,
ep = &htc->endpoint[report->eid]; ep = &htc->endpoint[report->eid];
ep->tx_credits += report->credits; ep->tx_credits += report->credits;
ath10k_dbg(ATH10K_DBG_HTC, "htc ep %d got %d credits (total %d)\n", ath10k_dbg(ar, ATH10K_DBG_HTC, "htc ep %d got %d credits (total %d)\n",
report->eid, report->credits, ep->tx_credits); report->eid, report->credits, ep->tx_credits);
if (ep->ep_ops.ep_tx_credits) { if (ep->ep_ops.ep_tx_credits) {
...@@ -260,6 +258,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc, ...@@ -260,6 +258,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc,
int length, int length,
enum ath10k_htc_ep_id src_eid) enum ath10k_htc_ep_id src_eid)
{ {
struct ath10k *ar = htc->ar;
int status = 0; int status = 0;
struct ath10k_htc_record *record; struct ath10k_htc_record *record;
u8 *orig_buffer; u8 *orig_buffer;
...@@ -279,7 +278,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc, ...@@ -279,7 +278,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc,
if (record->hdr.len > length) { if (record->hdr.len > length) {
/* no room left in buffer for record */ /* no room left in buffer for record */
ath10k_warn("Invalid record length: %d\n", ath10k_warn(ar, "Invalid record length: %d\n",
record->hdr.len); record->hdr.len);
status = -EINVAL; status = -EINVAL;
break; break;
...@@ -289,7 +288,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc, ...@@ -289,7 +288,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc,
case ATH10K_HTC_RECORD_CREDITS: case ATH10K_HTC_RECORD_CREDITS:
len = sizeof(struct ath10k_htc_credit_report); len = sizeof(struct ath10k_htc_credit_report);
if (record->hdr.len < len) { if (record->hdr.len < len) {
ath10k_warn("Credit report too long\n"); ath10k_warn(ar, "Credit report too long\n");
status = -EINVAL; status = -EINVAL;
break; break;
} }
...@@ -299,7 +298,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc, ...@@ -299,7 +298,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc,
src_eid); src_eid);
break; break;
default: default:
ath10k_warn("Unhandled record: id:%d length:%d\n", ath10k_warn(ar, "Unhandled record: id:%d length:%d\n",
record->hdr.id, record->hdr.len); record->hdr.id, record->hdr.len);
break; break;
} }
...@@ -313,7 +312,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc, ...@@ -313,7 +312,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc,
} }
if (status) if (status)
ath10k_dbg_dump(ATH10K_DBG_HTC, "htc rx bad trailer", "", ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc rx bad trailer", "",
orig_buffer, orig_length); orig_buffer, orig_length);
return status; return status;
...@@ -339,8 +338,8 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar, ...@@ -339,8 +338,8 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
eid = hdr->eid; eid = hdr->eid;
if (eid >= ATH10K_HTC_EP_COUNT) { if (eid >= ATH10K_HTC_EP_COUNT) {
ath10k_warn("HTC Rx: invalid eid %d\n", eid); ath10k_warn(ar, "HTC Rx: invalid eid %d\n", eid);
ath10k_dbg_dump(ATH10K_DBG_HTC, "htc bad header", "", ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad header", "",
hdr, sizeof(*hdr)); hdr, sizeof(*hdr));
status = -EINVAL; status = -EINVAL;
goto out; goto out;
...@@ -360,19 +359,19 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar, ...@@ -360,19 +359,19 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
payload_len = __le16_to_cpu(hdr->len); payload_len = __le16_to_cpu(hdr->len);
if (payload_len + sizeof(*hdr) > ATH10K_HTC_MAX_LEN) { if (payload_len + sizeof(*hdr) > ATH10K_HTC_MAX_LEN) {
ath10k_warn("HTC rx frame too long, len: %zu\n", ath10k_warn(ar, "HTC rx frame too long, len: %zu\n",
payload_len + sizeof(*hdr)); payload_len + sizeof(*hdr));
ath10k_dbg_dump(ATH10K_DBG_HTC, "htc bad rx pkt len", "", ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len", "",
hdr, sizeof(*hdr)); hdr, sizeof(*hdr));
status = -EINVAL; status = -EINVAL;
goto out; goto out;
} }
if (skb->len < payload_len) { if (skb->len < payload_len) {
ath10k_dbg(ATH10K_DBG_HTC, ath10k_dbg(ar, ATH10K_DBG_HTC,
"HTC Rx: insufficient length, got %d, expected %d\n", "HTC Rx: insufficient length, got %d, expected %d\n",
skb->len, payload_len); skb->len, payload_len);
ath10k_dbg_dump(ATH10K_DBG_HTC, "htc bad rx pkt len", ath10k_dbg_dump(ar, ATH10K_DBG_HTC, "htc bad rx pkt len",
"", hdr, sizeof(*hdr)); "", hdr, sizeof(*hdr));
status = -EINVAL; status = -EINVAL;
goto out; goto out;
...@@ -388,7 +387,7 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar, ...@@ -388,7 +387,7 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
if ((trailer_len < min_len) || if ((trailer_len < min_len) ||
(trailer_len > payload_len)) { (trailer_len > payload_len)) {
ath10k_warn("Invalid trailer length: %d\n", ath10k_warn(ar, "Invalid trailer length: %d\n",
trailer_len); trailer_len);
status = -EPROTO; status = -EPROTO;
goto out; goto out;
...@@ -421,7 +420,7 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar, ...@@ -421,7 +420,7 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
* this is a fatal error, target should not be * this is a fatal error, target should not be
* sending unsolicited messages on the ep 0 * sending unsolicited messages on the ep 0
*/ */
ath10k_warn("HTC rx ctrl still processing\n"); ath10k_warn(ar, "HTC rx ctrl still processing\n");
status = -EINVAL; status = -EINVAL;
complete(&htc->ctl_resp); complete(&htc->ctl_resp);
goto out; goto out;
...@@ -442,7 +441,7 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar, ...@@ -442,7 +441,7 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
goto out; goto out;
} }
ath10k_dbg(ATH10K_DBG_HTC, "htc rx completion ep %d skb %p\n", ath10k_dbg(ar, ATH10K_DBG_HTC, "htc rx completion ep %d skb %p\n",
eid, skb); eid, skb);
ep->ep_ops.ep_rx_complete(ar, skb); ep->ep_ops.ep_rx_complete(ar, skb);
...@@ -459,7 +458,7 @@ static void ath10k_htc_control_rx_complete(struct ath10k *ar, ...@@ -459,7 +458,7 @@ static void ath10k_htc_control_rx_complete(struct ath10k *ar,
{ {
/* This is unexpected. FW is not supposed to send regular rx on this /* This is unexpected. FW is not supposed to send regular rx on this
* endpoint. */ * endpoint. */
ath10k_warn("unexpected htc rx\n"); ath10k_warn(ar, "unexpected htc rx\n");
kfree_skb(skb); kfree_skb(skb);
} }
...@@ -546,6 +545,7 @@ static u8 ath10k_htc_get_credit_allocation(struct ath10k_htc *htc, ...@@ -546,6 +545,7 @@ static u8 ath10k_htc_get_credit_allocation(struct ath10k_htc *htc,
int ath10k_htc_wait_target(struct ath10k_htc *htc) int ath10k_htc_wait_target(struct ath10k_htc *htc)
{ {
struct ath10k *ar = htc->ar;
int i, status = 0; int i, status = 0;
struct ath10k_htc_svc_conn_req conn_req; struct ath10k_htc_svc_conn_req conn_req;
struct ath10k_htc_svc_conn_resp conn_resp; struct ath10k_htc_svc_conn_resp conn_resp;
...@@ -563,7 +563,7 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) ...@@ -563,7 +563,7 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
* iomap writes unmasking PCI CE irqs aren't propagated * iomap writes unmasking PCI CE irqs aren't propagated
* properly in KVM PCI-passthrough sometimes. * properly in KVM PCI-passthrough sometimes.
*/ */
ath10k_warn("failed to receive control response completion, polling..\n"); ath10k_warn(ar, "failed to receive control response completion, polling..\n");
for (i = 0; i < CE_COUNT; i++) for (i = 0; i < CE_COUNT; i++)
ath10k_hif_send_complete_check(htc->ar, i, 1); ath10k_hif_send_complete_check(htc->ar, i, 1);
...@@ -576,12 +576,12 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) ...@@ -576,12 +576,12 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
} }
if (status < 0) { if (status < 0) {
ath10k_err("ctl_resp never came in (%d)\n", status); ath10k_err(ar, "ctl_resp never came in (%d)\n", status);
return status; return status;
} }
if (htc->control_resp_len < sizeof(msg->hdr) + sizeof(msg->ready)) { if (htc->control_resp_len < sizeof(msg->hdr) + sizeof(msg->ready)) {
ath10k_err("Invalid HTC ready msg len:%d\n", ath10k_err(ar, "Invalid HTC ready msg len:%d\n",
htc->control_resp_len); htc->control_resp_len);
return -ECOMM; return -ECOMM;
} }
...@@ -592,21 +592,21 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) ...@@ -592,21 +592,21 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
credit_size = __le16_to_cpu(msg->ready.credit_size); credit_size = __le16_to_cpu(msg->ready.credit_size);
if (message_id != ATH10K_HTC_MSG_READY_ID) { if (message_id != ATH10K_HTC_MSG_READY_ID) {
ath10k_err("Invalid HTC ready msg: 0x%x\n", message_id); ath10k_err(ar, "Invalid HTC ready msg: 0x%x\n", message_id);
return -ECOMM; return -ECOMM;
} }
htc->total_transmit_credits = credit_count; htc->total_transmit_credits = credit_count;
htc->target_credit_size = credit_size; htc->target_credit_size = credit_size;
ath10k_dbg(ATH10K_DBG_HTC, ath10k_dbg(ar, ATH10K_DBG_HTC,
"Target ready! transmit resources: %d size:%d\n", "Target ready! transmit resources: %d size:%d\n",
htc->total_transmit_credits, htc->total_transmit_credits,
htc->target_credit_size); htc->target_credit_size);
if ((htc->total_transmit_credits == 0) || if ((htc->total_transmit_credits == 0) ||
(htc->target_credit_size == 0)) { (htc->target_credit_size == 0)) {
ath10k_err("Invalid credit size received\n"); ath10k_err(ar, "Invalid credit size received\n");
return -ECOMM; return -ECOMM;
} }
...@@ -623,7 +623,8 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) ...@@ -623,7 +623,8 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
/* connect fake service */ /* connect fake service */
status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp); status = ath10k_htc_connect_service(htc, &conn_req, &conn_resp);
if (status) { if (status) {
ath10k_err("could not connect to htc service (%d)\n", status); ath10k_err(ar, "could not connect to htc service (%d)\n",
status);
return status; return status;
} }
...@@ -634,6 +635,7 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc, ...@@ -634,6 +635,7 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
struct ath10k_htc_svc_conn_req *conn_req, struct ath10k_htc_svc_conn_req *conn_req,
struct ath10k_htc_svc_conn_resp *conn_resp) struct ath10k_htc_svc_conn_resp *conn_resp)
{ {
struct ath10k *ar = htc->ar;
struct ath10k_htc_msg *msg; struct ath10k_htc_msg *msg;
struct ath10k_htc_conn_svc *req_msg; struct ath10k_htc_conn_svc *req_msg;
struct ath10k_htc_conn_svc_response resp_msg_dummy; struct ath10k_htc_conn_svc_response resp_msg_dummy;
...@@ -659,13 +661,13 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc, ...@@ -659,13 +661,13 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
tx_alloc = ath10k_htc_get_credit_allocation(htc, tx_alloc = ath10k_htc_get_credit_allocation(htc,
conn_req->service_id); conn_req->service_id);
if (!tx_alloc) if (!tx_alloc)
ath10k_dbg(ATH10K_DBG_BOOT, ath10k_dbg(ar, ATH10K_DBG_BOOT,
"boot htc service %s does not allocate target credits\n", "boot htc service %s does not allocate target credits\n",
htc_service_name(conn_req->service_id)); htc_service_name(conn_req->service_id));
skb = ath10k_htc_build_tx_ctrl_skb(htc->ar); skb = ath10k_htc_build_tx_ctrl_skb(htc->ar);
if (!skb) { if (!skb) {
ath10k_err("Failed to allocate HTC packet\n"); ath10k_err(ar, "Failed to allocate HTC packet\n");
return -ENOMEM; return -ENOMEM;
} }
...@@ -703,7 +705,7 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc, ...@@ -703,7 +705,7 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
if (status <= 0) { if (status <= 0) {
if (status == 0) if (status == 0)
status = -ETIMEDOUT; status = -ETIMEDOUT;
ath10k_err("Service connect timeout: %d\n", status); ath10k_err(ar, "Service connect timeout: %d\n", status);
return status; return status;
} }
...@@ -716,11 +718,11 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc, ...@@ -716,11 +718,11 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
if ((message_id != ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID) || if ((message_id != ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID) ||
(htc->control_resp_len < sizeof(msg->hdr) + (htc->control_resp_len < sizeof(msg->hdr) +
sizeof(msg->connect_service_response))) { sizeof(msg->connect_service_response))) {
ath10k_err("Invalid resp message ID 0x%x", message_id); ath10k_err(ar, "Invalid resp message ID 0x%x", message_id);
return -EPROTO; return -EPROTO;
} }
ath10k_dbg(ATH10K_DBG_HTC, ath10k_dbg(ar, ATH10K_DBG_HTC,
"HTC Service %s connect response: status: 0x%x, assigned ep: 0x%x\n", "HTC Service %s connect response: status: 0x%x, assigned ep: 0x%x\n",
htc_service_name(service_id), htc_service_name(service_id),
resp_msg->status, resp_msg->eid); resp_msg->status, resp_msg->eid);
...@@ -729,7 +731,7 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc, ...@@ -729,7 +731,7 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
/* check response status */ /* check response status */
if (resp_msg->status != ATH10K_HTC_CONN_SVC_STATUS_SUCCESS) { if (resp_msg->status != ATH10K_HTC_CONN_SVC_STATUS_SUCCESS) {
ath10k_err("HTC Service %s connect request failed: 0x%x)\n", ath10k_err(ar, "HTC Service %s connect request failed: 0x%x)\n",
htc_service_name(service_id), htc_service_name(service_id),
resp_msg->status); resp_msg->status);
return -EPROTO; return -EPROTO;
...@@ -780,18 +782,18 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc, ...@@ -780,18 +782,18 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
if (status) if (status)
return status; return status;
ath10k_dbg(ATH10K_DBG_BOOT, ath10k_dbg(ar, ATH10K_DBG_BOOT,
"boot htc service '%s' ul pipe %d dl pipe %d eid %d ready\n", "boot htc service '%s' ul pipe %d dl pipe %d eid %d ready\n",
htc_service_name(ep->service_id), ep->ul_pipe_id, htc_service_name(ep->service_id), ep->ul_pipe_id,
ep->dl_pipe_id, ep->eid); ep->dl_pipe_id, ep->eid);
ath10k_dbg(ATH10K_DBG_BOOT, ath10k_dbg(ar, ATH10K_DBG_BOOT,
"boot htc ep %d ul polled %d dl polled %d\n", "boot htc ep %d ul polled %d dl polled %d\n",
ep->eid, ep->ul_is_polled, ep->dl_is_polled); ep->eid, ep->ul_is_polled, ep->dl_is_polled);
if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) { if (disable_credit_flow_ctrl && ep->tx_credit_flow_enabled) {
ep->tx_credit_flow_enabled = false; ep->tx_credit_flow_enabled = false;
ath10k_dbg(ATH10K_DBG_BOOT, ath10k_dbg(ar, ATH10K_DBG_BOOT,
"boot htc service '%s' eid %d TX flow control disabled\n", "boot htc service '%s' eid %d TX flow control disabled\n",
htc_service_name(ep->service_id), assigned_eid); htc_service_name(ep->service_id), assigned_eid);
} }
...@@ -799,13 +801,13 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc, ...@@ -799,13 +801,13 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
return status; return status;
} }
struct sk_buff *ath10k_htc_alloc_skb(int size) struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size)
{ {
struct sk_buff *skb; struct sk_buff *skb;
skb = dev_alloc_skb(size + sizeof(struct ath10k_htc_hdr)); skb = dev_alloc_skb(size + sizeof(struct ath10k_htc_hdr));
if (!skb) { if (!skb) {
ath10k_warn("could not allocate HTC tx skb\n"); ath10k_warn(ar, "could not allocate HTC tx skb\n");
return NULL; return NULL;
} }
...@@ -813,13 +815,14 @@ struct sk_buff *ath10k_htc_alloc_skb(int size) ...@@ -813,13 +815,14 @@ struct sk_buff *ath10k_htc_alloc_skb(int size)
/* FW/HTC requires 4-byte aligned streams */ /* FW/HTC requires 4-byte aligned streams */
if (!IS_ALIGNED((unsigned long)skb->data, 4)) if (!IS_ALIGNED((unsigned long)skb->data, 4))
ath10k_warn("Unaligned HTC tx skb\n"); ath10k_warn(ar, "Unaligned HTC tx skb\n");
return skb; return skb;
} }
int ath10k_htc_start(struct ath10k_htc *htc) int ath10k_htc_start(struct ath10k_htc *htc)
{ {
struct ath10k *ar = htc->ar;
struct sk_buff *skb; struct sk_buff *skb;
int status = 0; int status = 0;
struct ath10k_htc_msg *msg; struct ath10k_htc_msg *msg;
...@@ -835,7 +838,7 @@ int ath10k_htc_start(struct ath10k_htc *htc) ...@@ -835,7 +838,7 @@ int ath10k_htc_start(struct ath10k_htc *htc)
msg->hdr.message_id = msg->hdr.message_id =
__cpu_to_le16(ATH10K_HTC_MSG_SETUP_COMPLETE_EX_ID); __cpu_to_le16(ATH10K_HTC_MSG_SETUP_COMPLETE_EX_ID);
ath10k_dbg(ATH10K_DBG_HTC, "HTC is using TX credit flow control\n"); ath10k_dbg(ar, ATH10K_DBG_HTC, "HTC is using TX credit flow control\n");
status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb); status = ath10k_htc_send(htc, ATH10K_HTC_EP_0, skb);
if (status) { if (status) {
...@@ -846,13 +849,6 @@ int ath10k_htc_start(struct ath10k_htc *htc) ...@@ -846,13 +849,6 @@ int ath10k_htc_start(struct ath10k_htc *htc)
return 0; return 0;
} }
void ath10k_htc_stop(struct ath10k_htc *htc)
{
spin_lock_bh(&htc->tx_lock);
htc->stopped = true;
spin_unlock_bh(&htc->tx_lock);
}
/* registered target arrival callback from the HIF layer */ /* registered target arrival callback from the HIF layer */
int ath10k_htc_init(struct ath10k *ar) int ath10k_htc_init(struct ath10k *ar)
{ {
...@@ -862,7 +858,6 @@ int ath10k_htc_init(struct ath10k *ar) ...@@ -862,7 +858,6 @@ int ath10k_htc_init(struct ath10k *ar)
spin_lock_init(&htc->tx_lock); spin_lock_init(&htc->tx_lock);
htc->stopped = false;
ath10k_htc_reset_endpoint_states(htc); ath10k_htc_reset_endpoint_states(htc);
/* setup HIF layer callbacks */ /* setup HIF layer callbacks */
......
...@@ -332,7 +332,7 @@ struct ath10k_htc { ...@@ -332,7 +332,7 @@ struct ath10k_htc {
struct ath10k *ar; struct ath10k *ar;
struct ath10k_htc_ep endpoint[ATH10K_HTC_EP_COUNT]; struct ath10k_htc_ep endpoint[ATH10K_HTC_EP_COUNT];
/* protects endpoint and stopped fields */ /* protects endpoints */
spinlock_t tx_lock; spinlock_t tx_lock;
struct ath10k_htc_ops htc_ops; struct ath10k_htc_ops htc_ops;
...@@ -345,8 +345,6 @@ struct ath10k_htc { ...@@ -345,8 +345,6 @@ struct ath10k_htc {
int total_transmit_credits; int total_transmit_credits;
struct ath10k_htc_svc_tx_credits service_tx_alloc[ATH10K_HTC_EP_COUNT]; struct ath10k_htc_svc_tx_credits service_tx_alloc[ATH10K_HTC_EP_COUNT];
int target_credit_size; int target_credit_size;
bool stopped;
}; };
int ath10k_htc_init(struct ath10k *ar); int ath10k_htc_init(struct ath10k *ar);
...@@ -357,7 +355,6 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc, ...@@ -357,7 +355,6 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
struct ath10k_htc_svc_conn_resp *conn_resp); struct ath10k_htc_svc_conn_resp *conn_resp);
int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid, int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid,
struct sk_buff *packet); struct sk_buff *packet);
void ath10k_htc_stop(struct ath10k_htc *htc); struct sk_buff *ath10k_htc_alloc_skb(struct ath10k *ar, int size);
struct sk_buff *ath10k_htc_alloc_skb(int size);
#endif #endif
...@@ -74,12 +74,14 @@ int ath10k_htt_init(struct ath10k *ar) ...@@ -74,12 +74,14 @@ int ath10k_htt_init(struct ath10k *ar)
static int ath10k_htt_verify_version(struct ath10k_htt *htt) static int ath10k_htt_verify_version(struct ath10k_htt *htt)
{ {
ath10k_dbg(ATH10K_DBG_BOOT, "htt target version %d.%d\n", struct ath10k *ar = htt->ar;
ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt target version %d.%d\n",
htt->target_version_major, htt->target_version_minor); htt->target_version_major, htt->target_version_minor);
if (htt->target_version_major != 2 && if (htt->target_version_major != 2 &&
htt->target_version_major != 3) { htt->target_version_major != 3) {
ath10k_err("unsupported htt major version %d. supported versions are 2 and 3\n", ath10k_err(ar, "unsupported htt major version %d. supported versions are 2 and 3\n",
htt->target_version_major); htt->target_version_major);
return -ENOTSUPP; return -ENOTSUPP;
} }
...@@ -89,6 +91,7 @@ static int ath10k_htt_verify_version(struct ath10k_htt *htt) ...@@ -89,6 +91,7 @@ static int ath10k_htt_verify_version(struct ath10k_htt *htt)
int ath10k_htt_setup(struct ath10k_htt *htt) int ath10k_htt_setup(struct ath10k_htt *htt)
{ {
struct ath10k *ar = htt->ar;
int status; int status;
init_completion(&htt->target_version_received); init_completion(&htt->target_version_received);
...@@ -100,7 +103,7 @@ int ath10k_htt_setup(struct ath10k_htt *htt) ...@@ -100,7 +103,7 @@ int ath10k_htt_setup(struct ath10k_htt *htt)
status = wait_for_completion_timeout(&htt->target_version_received, status = wait_for_completion_timeout(&htt->target_version_received,
HTT_TARGET_VERSION_TIMEOUT_HZ); HTT_TARGET_VERSION_TIMEOUT_HZ);
if (status <= 0) { if (status <= 0) {
ath10k_warn("htt version request timed out\n"); ath10k_warn(ar, "htt version request timed out\n");
return -ETIMEDOUT; return -ETIMEDOUT;
} }
......
...@@ -271,13 +271,14 @@ void ath10k_htt_rx_free(struct ath10k_htt *htt) ...@@ -271,13 +271,14 @@ void ath10k_htt_rx_free(struct ath10k_htt *htt)
static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt) static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt)
{ {
struct ath10k *ar = htt->ar;
int idx; int idx;
struct sk_buff *msdu; struct sk_buff *msdu;
lockdep_assert_held(&htt->rx_ring.lock); lockdep_assert_held(&htt->rx_ring.lock);
if (htt->rx_ring.fill_cnt == 0) { if (htt->rx_ring.fill_cnt == 0) {
ath10k_warn("tried to pop sk_buff from an empty rx ring\n"); ath10k_warn(ar, "tried to pop sk_buff from an empty rx ring\n");
return NULL; return NULL;
} }
...@@ -311,6 +312,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -311,6 +312,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
struct sk_buff **tail_msdu, struct sk_buff **tail_msdu,
u32 *attention) u32 *attention)
{ {
struct ath10k *ar = htt->ar;
int msdu_len, msdu_chaining = 0; int msdu_len, msdu_chaining = 0;
struct sk_buff *msdu; struct sk_buff *msdu;
struct htt_rx_desc *rx_desc; struct htt_rx_desc *rx_desc;
...@@ -318,7 +320,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -318,7 +320,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
lockdep_assert_held(&htt->rx_ring.lock); lockdep_assert_held(&htt->rx_ring.lock);
if (htt->rx_confused) { if (htt->rx_confused) {
ath10k_warn("htt is confused. refusing rx\n"); ath10k_warn(ar, "htt is confused. refusing rx\n");
return -1; return -1;
} }
...@@ -331,7 +333,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -331,7 +333,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
msdu->len + skb_tailroom(msdu), msdu->len + skb_tailroom(msdu),
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt rx pop: ", ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx pop: ",
msdu->data, msdu->len + skb_tailroom(msdu)); msdu->data, msdu->len + skb_tailroom(msdu));
rx_desc = (struct htt_rx_desc *)msdu->data; rx_desc = (struct htt_rx_desc *)msdu->data;
...@@ -354,7 +356,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -354,7 +356,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
ath10k_htt_rx_free_msdu_chain(*head_msdu); ath10k_htt_rx_free_msdu_chain(*head_msdu);
*head_msdu = NULL; *head_msdu = NULL;
msdu = NULL; msdu = NULL;
ath10k_err("htt rx stopped. cannot recover\n"); ath10k_err(ar, "htt rx stopped. cannot recover\n");
htt->rx_confused = true; htt->rx_confused = true;
break; break;
} }
...@@ -429,7 +431,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -429,7 +431,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
next->len + skb_tailroom(next), next->len + skb_tailroom(next),
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL,
"htt rx chained: ", next->data, "htt rx chained: ", next->data,
next->len + skb_tailroom(next)); next->len + skb_tailroom(next));
...@@ -483,13 +485,14 @@ static void ath10k_htt_rx_replenish_task(unsigned long ptr) ...@@ -483,13 +485,14 @@ static void ath10k_htt_rx_replenish_task(unsigned long ptr)
int ath10k_htt_rx_alloc(struct ath10k_htt *htt) int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
{ {
struct ath10k *ar = htt->ar;
dma_addr_t paddr; dma_addr_t paddr;
void *vaddr; void *vaddr;
struct timer_list *timer = &htt->rx_ring.refill_retry_timer; struct timer_list *timer = &htt->rx_ring.refill_retry_timer;
htt->rx_ring.size = ath10k_htt_rx_ring_size(htt); htt->rx_ring.size = ath10k_htt_rx_ring_size(htt);
if (!is_power_of_2(htt->rx_ring.size)) { if (!is_power_of_2(htt->rx_ring.size)) {
ath10k_warn("htt rx ring size is not power of 2\n"); ath10k_warn(ar, "htt rx ring size is not power of 2\n");
return -EINVAL; return -EINVAL;
} }
...@@ -550,7 +553,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) ...@@ -550,7 +553,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
tasklet_init(&htt->txrx_compl_task, ath10k_htt_txrx_compl_task, tasklet_init(&htt->txrx_compl_task, ath10k_htt_txrx_compl_task,
(unsigned long)htt); (unsigned long)htt);
ath10k_dbg(ATH10K_DBG_BOOT, "htt rx ring size %d fill_level %d\n", ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt rx ring size %d fill_level %d\n",
htt->rx_ring.size, htt->rx_ring.fill_level); htt->rx_ring.size, htt->rx_ring.fill_level);
return 0; return 0;
...@@ -572,7 +575,8 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) ...@@ -572,7 +575,8 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
return -ENOMEM; return -ENOMEM;
} }
static int ath10k_htt_rx_crypto_param_len(enum htt_rx_mpdu_encrypt_type type) static int ath10k_htt_rx_crypto_param_len(struct ath10k *ar,
enum htt_rx_mpdu_encrypt_type type)
{ {
switch (type) { switch (type) {
case HTT_RX_MPDU_ENCRYPT_WEP40: case HTT_RX_MPDU_ENCRYPT_WEP40:
...@@ -588,11 +592,12 @@ static int ath10k_htt_rx_crypto_param_len(enum htt_rx_mpdu_encrypt_type type) ...@@ -588,11 +592,12 @@ static int ath10k_htt_rx_crypto_param_len(enum htt_rx_mpdu_encrypt_type type)
return 0; return 0;
} }
ath10k_warn("unknown encryption type %d\n", type); ath10k_warn(ar, "unknown encryption type %d\n", type);
return 0; return 0;
} }
static int ath10k_htt_rx_crypto_tail_len(enum htt_rx_mpdu_encrypt_type type) static int ath10k_htt_rx_crypto_tail_len(struct ath10k *ar,
enum htt_rx_mpdu_encrypt_type type)
{ {
switch (type) { switch (type) {
case HTT_RX_MPDU_ENCRYPT_NONE: case HTT_RX_MPDU_ENCRYPT_NONE:
...@@ -608,7 +613,7 @@ static int ath10k_htt_rx_crypto_tail_len(enum htt_rx_mpdu_encrypt_type type) ...@@ -608,7 +613,7 @@ static int ath10k_htt_rx_crypto_tail_len(enum htt_rx_mpdu_encrypt_type type)
return 8; return 8;
} }
ath10k_warn("unknown encryption type %d\n", type); ath10k_warn(ar, "unknown encryption type %d\n", type);
return 0; return 0;
} }
...@@ -819,19 +824,55 @@ static bool ath10k_htt_rx_h_channel(struct ath10k *ar, ...@@ -819,19 +824,55 @@ static bool ath10k_htt_rx_h_channel(struct ath10k *ar,
return true; return true;
} }
static const char * const tid_to_ac[] = {
"BE",
"BK",
"BK",
"BE",
"VI",
"VI",
"VO",
"VO",
};
static char *ath10k_get_tid(struct ieee80211_hdr *hdr, char *out, size_t size)
{
u8 *qc;
int tid;
if (!ieee80211_is_data_qos(hdr->frame_control))
return "";
qc = ieee80211_get_qos_ctl(hdr);
tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
if (tid < 8)
snprintf(out, size, "tid %d (%s)", tid, tid_to_ac[tid]);
else
snprintf(out, size, "tid %d", tid);
return out;
}
static void ath10k_process_rx(struct ath10k *ar, static void ath10k_process_rx(struct ath10k *ar,
struct ieee80211_rx_status *rx_status, struct ieee80211_rx_status *rx_status,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct ieee80211_rx_status *status; struct ieee80211_rx_status *status;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
char tid[32];
status = IEEE80211_SKB_RXCB(skb); status = IEEE80211_SKB_RXCB(skb);
*status = *rx_status; *status = *rx_status;
ath10k_dbg(ATH10K_DBG_DATA, ath10k_dbg(ar, ATH10K_DBG_DATA,
"rx skb %p len %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %imic-err %i\n", "rx skb %p len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%x fcs-err %i mic-err %i amsdu-more %i\n",
skb, skb,
skb->len, skb->len,
ieee80211_get_SA(hdr),
ath10k_get_tid(hdr, tid, sizeof(tid)),
is_multicast_ether_addr(ieee80211_get_DA(hdr)) ?
"mcast" : "ucast",
(__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4,
status->flag == 0 ? "legacy" : "", status->flag == 0 ? "legacy" : "",
status->flag & RX_FLAG_HT ? "ht" : "", status->flag & RX_FLAG_HT ? "ht" : "",
status->flag & RX_FLAG_VHT ? "vht" : "", status->flag & RX_FLAG_VHT ? "vht" : "",
...@@ -843,8 +884,9 @@ static void ath10k_process_rx(struct ath10k *ar, ...@@ -843,8 +884,9 @@ static void ath10k_process_rx(struct ath10k *ar,
status->freq, status->freq,
status->band, status->flag, status->band, status->flag,
!!(status->flag & RX_FLAG_FAILED_FCS_CRC), !!(status->flag & RX_FLAG_FAILED_FCS_CRC),
!!(status->flag & RX_FLAG_MMIC_ERROR)); !!(status->flag & RX_FLAG_MMIC_ERROR),
ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ", !!(status->flag & RX_FLAG_AMSDU_MORE));
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ",
skb->data, skb->len); skb->data, skb->len);
ieee80211_rx(ar->hw, skb); ieee80211_rx(ar->hw, skb);
...@@ -860,13 +902,14 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, ...@@ -860,13 +902,14 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
struct ieee80211_rx_status *rx_status, struct ieee80211_rx_status *rx_status,
struct sk_buff *skb_in) struct sk_buff *skb_in)
{ {
struct ath10k *ar = htt->ar;
struct htt_rx_desc *rxd; struct htt_rx_desc *rxd;
struct sk_buff *skb = skb_in; struct sk_buff *skb = skb_in;
struct sk_buff *first; struct sk_buff *first;
enum rx_msdu_decap_format fmt; enum rx_msdu_decap_format fmt;
enum htt_rx_mpdu_encrypt_type enctype; enum htt_rx_mpdu_encrypt_type enctype;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
u8 hdr_buf[64], addr[ETH_ALEN], *qos; u8 hdr_buf[64], da[ETH_ALEN], sa[ETH_ALEN], *qos;
unsigned int hdr_len; unsigned int hdr_len;
rxd = (void *)skb->data - sizeof(*rxd); rxd = (void *)skb->data - sizeof(*rxd);
...@@ -893,8 +936,8 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, ...@@ -893,8 +936,8 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
/* First frame in an A-MSDU chain has more decapped data. */ /* First frame in an A-MSDU chain has more decapped data. */
if (skb == first) { if (skb == first) {
len = round_up(ieee80211_hdrlen(hdr->frame_control), 4); len = round_up(ieee80211_hdrlen(hdr->frame_control), 4);
len += round_up(ath10k_htt_rx_crypto_param_len(enctype), len += round_up(ath10k_htt_rx_crypto_param_len(ar,
4); enctype), 4);
decap_hdr += len; decap_hdr += len;
} }
...@@ -904,10 +947,11 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, ...@@ -904,10 +947,11 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
skb_trim(skb, skb->len - FCS_LEN); skb_trim(skb, skb->len - FCS_LEN);
break; break;
case RX_MSDU_DECAP_NATIVE_WIFI: case RX_MSDU_DECAP_NATIVE_WIFI:
/* pull decapped header and copy DA */ /* pull decapped header and copy SA & DA */
hdr = (struct ieee80211_hdr *)skb->data; hdr = (struct ieee80211_hdr *)skb->data;
hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr); hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr);
memcpy(addr, ieee80211_get_DA(hdr), ETH_ALEN); memcpy(da, ieee80211_get_DA(hdr), ETH_ALEN);
memcpy(sa, ieee80211_get_SA(hdr), ETH_ALEN);
skb_pull(skb, hdr_len); skb_pull(skb, hdr_len);
/* push original 802.11 header */ /* push original 802.11 header */
...@@ -921,8 +965,11 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt, ...@@ -921,8 +965,11 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
qos = ieee80211_get_qos_ctl(hdr); qos = ieee80211_get_qos_ctl(hdr);
qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
/* original 802.11 header has a different DA */ /* original 802.11 header has a different DA and in
memcpy(ieee80211_get_DA(hdr), addr, ETH_ALEN); * case of 4addr it may also have different SA
*/
memcpy(ieee80211_get_DA(hdr), da, ETH_ALEN);
memcpy(ieee80211_get_SA(hdr), sa, ETH_ALEN);
break; break;
case RX_MSDU_DECAP_ETHERNET2_DIX: case RX_MSDU_DECAP_ETHERNET2_DIX:
/* strip ethernet header and insert decapped 802.11 /* strip ethernet header and insert decapped 802.11
...@@ -965,6 +1012,7 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt, ...@@ -965,6 +1012,7 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt,
struct ieee80211_rx_status *rx_status, struct ieee80211_rx_status *rx_status,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct ath10k *ar = htt->ar;
struct htt_rx_desc *rxd; struct htt_rx_desc *rxd;
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
enum rx_msdu_decap_format fmt; enum rx_msdu_decap_format fmt;
...@@ -974,7 +1022,7 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt, ...@@ -974,7 +1022,7 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt,
/* This shouldn't happen. If it does than it may be a FW bug. */ /* This shouldn't happen. If it does than it may be a FW bug. */
if (skb->next) { if (skb->next) {
ath10k_warn("htt rx received chained non A-MSDU frame\n"); ath10k_warn(ar, "htt rx received chained non A-MSDU frame\n");
ath10k_htt_rx_free_msdu_chain(skb->next); ath10k_htt_rx_free_msdu_chain(skb->next);
skb->next = NULL; skb->next = NULL;
} }
...@@ -1011,7 +1059,8 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt, ...@@ -1011,7 +1059,8 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt,
rfc1042 = hdr; rfc1042 = hdr;
rfc1042 += roundup(hdr_len, 4); rfc1042 += roundup(hdr_len, 4);
rfc1042 += roundup(ath10k_htt_rx_crypto_param_len(enctype), 4); rfc1042 += roundup(ath10k_htt_rx_crypto_param_len(ar,
enctype), 4);
skb_pull(skb, sizeof(struct ethhdr)); skb_pull(skb, sizeof(struct ethhdr));
memcpy(skb_push(skb, sizeof(struct rfc1042_hdr)), memcpy(skb_push(skb, sizeof(struct rfc1042_hdr)),
...@@ -1120,27 +1169,29 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt, ...@@ -1120,27 +1169,29 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt,
bool channel_set, bool channel_set,
u32 attention) u32 attention)
{ {
struct ath10k *ar = htt->ar;
if (head->len == 0) { if (head->len == 0) {
ath10k_dbg(ATH10K_DBG_HTT, ath10k_dbg(ar, ATH10K_DBG_HTT,
"htt rx dropping due to zero-len\n"); "htt rx dropping due to zero-len\n");
return false; return false;
} }
if (attention & RX_ATTENTION_FLAGS_DECRYPT_ERR) { if (attention & RX_ATTENTION_FLAGS_DECRYPT_ERR) {
ath10k_dbg(ATH10K_DBG_HTT, ath10k_dbg(ar, ATH10K_DBG_HTT,
"htt rx dropping due to decrypt-err\n"); "htt rx dropping due to decrypt-err\n");
return false; return false;
} }
if (!channel_set) { if (!channel_set) {
ath10k_warn("no channel configured; ignoring frame!\n"); ath10k_warn(ar, "no channel configured; ignoring frame!\n");
return false; return false;
} }
/* Skip mgmt frames while we handle this in WMI */ /* Skip mgmt frames while we handle this in WMI */
if (status == HTT_RX_IND_MPDU_STATUS_MGMT_CTRL || if (status == HTT_RX_IND_MPDU_STATUS_MGMT_CTRL ||
attention & RX_ATTENTION_FLAGS_MGMT_TYPE) { attention & RX_ATTENTION_FLAGS_MGMT_TYPE) {
ath10k_dbg(ATH10K_DBG_HTT, "htt rx mgmt ctrl\n"); ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx mgmt ctrl\n");
return false; return false;
} }
...@@ -1148,14 +1199,14 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt, ...@@ -1148,14 +1199,14 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt,
status != HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR && status != HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR &&
status != HTT_RX_IND_MPDU_STATUS_ERR_INV_PEER && status != HTT_RX_IND_MPDU_STATUS_ERR_INV_PEER &&
!htt->ar->monitor_started) { !htt->ar->monitor_started) {
ath10k_dbg(ATH10K_DBG_HTT, ath10k_dbg(ar, ATH10K_DBG_HTT,
"htt rx ignoring frame w/ status %d\n", "htt rx ignoring frame w/ status %d\n",
status); status);
return false; return false;
} }
if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) { if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) {
ath10k_dbg(ATH10K_DBG_HTT, ath10k_dbg(ar, ATH10K_DBG_HTT,
"htt rx CAC running\n"); "htt rx CAC running\n");
return false; return false;
} }
...@@ -1166,6 +1217,7 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt, ...@@ -1166,6 +1217,7 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt,
static void ath10k_htt_rx_handler(struct ath10k_htt *htt, static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
struct htt_rx_indication *rx) struct htt_rx_indication *rx)
{ {
struct ath10k *ar = htt->ar;
struct ieee80211_rx_status *rx_status = &htt->rx_status; struct ieee80211_rx_status *rx_status = &htt->rx_status;
struct htt_rx_indication_mpdu_range *mpdu_ranges; struct htt_rx_indication_mpdu_range *mpdu_ranges;
struct htt_rx_desc *rxd; struct htt_rx_desc *rxd;
...@@ -1211,7 +1263,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, ...@@ -1211,7 +1263,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
rx_status); rx_status);
} }
ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt rx ind: ", ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx ind: ",
rx, sizeof(*rx) + rx, sizeof(*rx) +
(sizeof(struct htt_rx_indication_mpdu_range) * (sizeof(struct htt_rx_indication_mpdu_range) *
num_mpdu_ranges)); num_mpdu_ranges));
...@@ -1233,7 +1285,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, ...@@ -1233,7 +1285,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
&attention); &attention);
if (ret < 0) { if (ret < 0) {
ath10k_warn("failed to pop amsdu from htt rx ring %d\n", ath10k_warn(ar, "failed to pop amsdu from htt rx ring %d\n",
ret); ret);
ath10k_htt_rx_free_msdu_chain(msdu_head); ath10k_htt_rx_free_msdu_chain(msdu_head);
continue; continue;
...@@ -1282,6 +1334,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, ...@@ -1282,6 +1334,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
struct htt_rx_fragment_indication *frag) struct htt_rx_fragment_indication *frag)
{ {
struct ath10k *ar = htt->ar;
struct sk_buff *msdu_head, *msdu_tail; struct sk_buff *msdu_head, *msdu_tail;
enum htt_rx_mpdu_encrypt_type enctype; enum htt_rx_mpdu_encrypt_type enctype;
struct htt_rx_desc *rxd; struct htt_rx_desc *rxd;
...@@ -1308,10 +1361,10 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, ...@@ -1308,10 +1361,10 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
&attention); &attention);
spin_unlock_bh(&htt->rx_ring.lock); spin_unlock_bh(&htt->rx_ring.lock);
ath10k_dbg(ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n"); ath10k_dbg(ar, ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n");
if (ret) { if (ret) {
ath10k_warn("failed to pop amsdu from httr rx ring for fragmented rx %d\n", ath10k_warn(ar, "failed to pop amsdu from httr rx ring for fragmented rx %d\n",
ret); ret);
ath10k_htt_rx_free_msdu_chain(msdu_head); ath10k_htt_rx_free_msdu_chain(msdu_head);
return; return;
...@@ -1328,7 +1381,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, ...@@ -1328,7 +1381,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
RX_MSDU_START_INFO1_DECAP_FORMAT); RX_MSDU_START_INFO1_DECAP_FORMAT);
if (fmt != RX_MSDU_DECAP_RAW) { if (fmt != RX_MSDU_DECAP_RAW) {
ath10k_warn("we dont support non-raw fragmented rx yet\n"); ath10k_warn(ar, "we dont support non-raw fragmented rx yet\n");
dev_kfree_skb_any(msdu_head); dev_kfree_skb_any(msdu_head);
goto end; goto end;
} }
...@@ -1340,17 +1393,17 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, ...@@ -1340,17 +1393,17 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
msdu_head->ip_summed = ath10k_htt_rx_get_csum_state(msdu_head); msdu_head->ip_summed = ath10k_htt_rx_get_csum_state(msdu_head);
if (tkip_mic_err) if (tkip_mic_err)
ath10k_warn("tkip mic error\n"); ath10k_warn(ar, "tkip mic error\n");
if (decrypt_err) { if (decrypt_err) {
ath10k_warn("decryption err in fragmented rx\n"); ath10k_warn(ar, "decryption err in fragmented rx\n");
dev_kfree_skb_any(msdu_head); dev_kfree_skb_any(msdu_head);
goto end; goto end;
} }
if (enctype != HTT_RX_MPDU_ENCRYPT_NONE) { if (enctype != HTT_RX_MPDU_ENCRYPT_NONE) {
hdrlen = ieee80211_hdrlen(hdr->frame_control); hdrlen = ieee80211_hdrlen(hdr->frame_control);
paramlen = ath10k_htt_rx_crypto_param_len(enctype); paramlen = ath10k_htt_rx_crypto_param_len(ar, enctype);
/* It is more efficient to move the header than the payload */ /* It is more efficient to move the header than the payload */
memmove((void *)msdu_head->data + paramlen, memmove((void *)msdu_head->data + paramlen,
...@@ -1364,7 +1417,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, ...@@ -1364,7 +1417,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
trim = 4; trim = 4;
/* remove crypto trailer */ /* remove crypto trailer */
trim += ath10k_htt_rx_crypto_tail_len(enctype); trim += ath10k_htt_rx_crypto_tail_len(ar, enctype);
/* last fragment of TKIP frags has MIC */ /* last fragment of TKIP frags has MIC */
if (!ieee80211_has_morefrags(hdr->frame_control) && if (!ieee80211_has_morefrags(hdr->frame_control) &&
...@@ -1372,20 +1425,20 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, ...@@ -1372,20 +1425,20 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
trim += 8; trim += 8;
if (trim > msdu_head->len) { if (trim > msdu_head->len) {
ath10k_warn("htt rx fragment: trailer longer than the frame itself? drop\n"); ath10k_warn(ar, "htt rx fragment: trailer longer than the frame itself? drop\n");
dev_kfree_skb_any(msdu_head); dev_kfree_skb_any(msdu_head);
goto end; goto end;
} }
skb_trim(msdu_head, msdu_head->len - trim); skb_trim(msdu_head, msdu_head->len - trim);
ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt rx frag mpdu: ", ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx frag mpdu: ",
msdu_head->data, msdu_head->len); msdu_head->data, msdu_head->len);
ath10k_process_rx(htt->ar, rx_status, msdu_head); ath10k_process_rx(htt->ar, rx_status, msdu_head);
end: end:
if (fw_desc_len > 0) { if (fw_desc_len > 0) {
ath10k_dbg(ATH10K_DBG_HTT, ath10k_dbg(ar, ATH10K_DBG_HTT,
"expecting more fragmented rx in one indication %d\n", "expecting more fragmented rx in one indication %d\n",
fw_desc_len); fw_desc_len);
} }
...@@ -1415,12 +1468,12 @@ static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar, ...@@ -1415,12 +1468,12 @@ static void ath10k_htt_rx_frm_tx_compl(struct ath10k *ar,
tx_done.discard = true; tx_done.discard = true;
break; break;
default: default:
ath10k_warn("unhandled tx completion status %d\n", status); ath10k_warn(ar, "unhandled tx completion status %d\n", status);
tx_done.discard = true; tx_done.discard = true;
break; break;
} }
ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion num_msdus %d\n", ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx completion num_msdus %d\n",
resp->data_tx_completion.num_msdus); resp->data_tx_completion.num_msdus);
for (i = 0; i < resp->data_tx_completion.num_msdus; i++) { for (i = 0; i < resp->data_tx_completion.num_msdus; i++) {
...@@ -1441,14 +1494,14 @@ static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp) ...@@ -1441,14 +1494,14 @@ static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp)
tid = MS(info0, HTT_RX_BA_INFO0_TID); tid = MS(info0, HTT_RX_BA_INFO0_TID);
peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID); peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
ath10k_dbg(ATH10K_DBG_HTT, ath10k_dbg(ar, ATH10K_DBG_HTT,
"htt rx addba tid %hu peer_id %hu size %hhu\n", "htt rx addba tid %hu peer_id %hu size %hhu\n",
tid, peer_id, ev->window_size); tid, peer_id, ev->window_size);
spin_lock_bh(&ar->data_lock); spin_lock_bh(&ar->data_lock);
peer = ath10k_peer_find_by_id(ar, peer_id); peer = ath10k_peer_find_by_id(ar, peer_id);
if (!peer) { if (!peer) {
ath10k_warn("received addba event for invalid peer_id: %hu\n", ath10k_warn(ar, "received addba event for invalid peer_id: %hu\n",
peer_id); peer_id);
spin_unlock_bh(&ar->data_lock); spin_unlock_bh(&ar->data_lock);
return; return;
...@@ -1456,13 +1509,13 @@ static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp) ...@@ -1456,13 +1509,13 @@ static void ath10k_htt_rx_addba(struct ath10k *ar, struct htt_resp *resp)
arvif = ath10k_get_arvif(ar, peer->vdev_id); arvif = ath10k_get_arvif(ar, peer->vdev_id);
if (!arvif) { if (!arvif) {
ath10k_warn("received addba event for invalid vdev_id: %u\n", ath10k_warn(ar, "received addba event for invalid vdev_id: %u\n",
peer->vdev_id); peer->vdev_id);
spin_unlock_bh(&ar->data_lock); spin_unlock_bh(&ar->data_lock);
return; return;
} }
ath10k_dbg(ATH10K_DBG_HTT, ath10k_dbg(ar, ATH10K_DBG_HTT,
"htt rx start rx ba session sta %pM tid %hu size %hhu\n", "htt rx start rx ba session sta %pM tid %hu size %hhu\n",
peer->addr, tid, ev->window_size); peer->addr, tid, ev->window_size);
...@@ -1481,14 +1534,14 @@ static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp) ...@@ -1481,14 +1534,14 @@ static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp)
tid = MS(info0, HTT_RX_BA_INFO0_TID); tid = MS(info0, HTT_RX_BA_INFO0_TID);
peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID); peer_id = MS(info0, HTT_RX_BA_INFO0_PEER_ID);
ath10k_dbg(ATH10K_DBG_HTT, ath10k_dbg(ar, ATH10K_DBG_HTT,
"htt rx delba tid %hu peer_id %hu\n", "htt rx delba tid %hu peer_id %hu\n",
tid, peer_id); tid, peer_id);
spin_lock_bh(&ar->data_lock); spin_lock_bh(&ar->data_lock);
peer = ath10k_peer_find_by_id(ar, peer_id); peer = ath10k_peer_find_by_id(ar, peer_id);
if (!peer) { if (!peer) {
ath10k_warn("received addba event for invalid peer_id: %hu\n", ath10k_warn(ar, "received addba event for invalid peer_id: %hu\n",
peer_id); peer_id);
spin_unlock_bh(&ar->data_lock); spin_unlock_bh(&ar->data_lock);
return; return;
...@@ -1496,13 +1549,13 @@ static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp) ...@@ -1496,13 +1549,13 @@ static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp)
arvif = ath10k_get_arvif(ar, peer->vdev_id); arvif = ath10k_get_arvif(ar, peer->vdev_id);
if (!arvif) { if (!arvif) {
ath10k_warn("received addba event for invalid vdev_id: %u\n", ath10k_warn(ar, "received addba event for invalid vdev_id: %u\n",
peer->vdev_id); peer->vdev_id);
spin_unlock_bh(&ar->data_lock); spin_unlock_bh(&ar->data_lock);
return; return;
} }
ath10k_dbg(ATH10K_DBG_HTT, ath10k_dbg(ar, ATH10K_DBG_HTT,
"htt rx stop rx ba session sta %pM tid %hu\n", "htt rx stop rx ba session sta %pM tid %hu\n",
peer->addr, tid); peer->addr, tid);
...@@ -1517,9 +1570,9 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) ...@@ -1517,9 +1570,9 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
/* confirm alignment */ /* confirm alignment */
if (!IS_ALIGNED((unsigned long)skb->data, 4)) if (!IS_ALIGNED((unsigned long)skb->data, 4))
ath10k_warn("unaligned htt message, expect trouble\n"); ath10k_warn(ar, "unaligned htt message, expect trouble\n");
ath10k_dbg(ATH10K_DBG_HTT, "htt rx, msg_type: 0x%0X\n", ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx, msg_type: 0x%0X\n",
resp->hdr.msg_type); resp->hdr.msg_type);
switch (resp->hdr.msg_type) { switch (resp->hdr.msg_type) {
case HTT_T2H_MSG_TYPE_VERSION_CONF: { case HTT_T2H_MSG_TYPE_VERSION_CONF: {
...@@ -1583,7 +1636,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) ...@@ -1583,7 +1636,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
struct ath10k *ar = htt->ar; struct ath10k *ar = htt->ar;
struct htt_security_indication *ev = &resp->security_indication; struct htt_security_indication *ev = &resp->security_indication;
ath10k_dbg(ATH10K_DBG_HTT, ath10k_dbg(ar, ATH10K_DBG_HTT,
"sec ind peer_id %d unicast %d type %d\n", "sec ind peer_id %d unicast %d type %d\n",
__le16_to_cpu(ev->peer_id), __le16_to_cpu(ev->peer_id),
!!(ev->flags & HTT_SECURITY_IS_UNICAST), !!(ev->flags & HTT_SECURITY_IS_UNICAST),
...@@ -1592,7 +1645,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) ...@@ -1592,7 +1645,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
break; break;
} }
case HTT_T2H_MSG_TYPE_RX_FRAG_IND: { case HTT_T2H_MSG_TYPE_RX_FRAG_IND: {
ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt event: ", ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ",
skb->data, skb->len); skb->data, skb->len);
ath10k_htt_rx_frag_handler(htt, &resp->rx_frag_ind); ath10k_htt_rx_frag_handler(htt, &resp->rx_frag_ind);
break; break;
...@@ -1609,7 +1662,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) ...@@ -1609,7 +1662,7 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
* sends all tx frames as already inspected so this shouldn't * sends all tx frames as already inspected so this shouldn't
* happen unless fw has a bug. * happen unless fw has a bug.
*/ */
ath10k_warn("received an unexpected htt tx inspect event\n"); ath10k_warn(ar, "received an unexpected htt tx inspect event\n");
break; break;
case HTT_T2H_MSG_TYPE_RX_ADDBA: case HTT_T2H_MSG_TYPE_RX_ADDBA:
ath10k_htt_rx_addba(ar, resp); ath10k_htt_rx_addba(ar, resp);
...@@ -1624,9 +1677,9 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) ...@@ -1624,9 +1677,9 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
break; break;
} }
default: default:
ath10k_dbg(ATH10K_DBG_HTT, "htt event (%d) not handled\n", ath10k_dbg(ar, ATH10K_DBG_HTT, "htt event (%d) not handled\n",
resp->hdr.msg_type); resp->hdr.msg_type);
ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt event: ", ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ",
skb->data, skb->len); skb->data, skb->len);
break; break;
}; };
......
...@@ -58,6 +58,7 @@ static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt) ...@@ -58,6 +58,7 @@ static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt)
int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt) int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt)
{ {
struct ath10k *ar = htt->ar;
int msdu_id; int msdu_id;
lockdep_assert_held(&htt->tx_lock); lockdep_assert_held(&htt->tx_lock);
...@@ -67,24 +68,29 @@ int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt) ...@@ -67,24 +68,29 @@ int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt)
if (msdu_id == htt->max_num_pending_tx) if (msdu_id == htt->max_num_pending_tx)
return -ENOBUFS; return -ENOBUFS;
ath10k_dbg(ATH10K_DBG_HTT, "htt tx alloc msdu_id %d\n", msdu_id); ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx alloc msdu_id %d\n", msdu_id);
__set_bit(msdu_id, htt->used_msdu_ids); __set_bit(msdu_id, htt->used_msdu_ids);
return msdu_id; return msdu_id;
} }
void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id) void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id)
{ {
struct ath10k *ar = htt->ar;
lockdep_assert_held(&htt->tx_lock); lockdep_assert_held(&htt->tx_lock);
if (!test_bit(msdu_id, htt->used_msdu_ids)) if (!test_bit(msdu_id, htt->used_msdu_ids))
ath10k_warn("trying to free unallocated msdu_id %d\n", msdu_id); ath10k_warn(ar, "trying to free unallocated msdu_id %d\n",
msdu_id);
ath10k_dbg(ATH10K_DBG_HTT, "htt tx free msdu_id %hu\n", msdu_id); ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx free msdu_id %hu\n", msdu_id);
__clear_bit(msdu_id, htt->used_msdu_ids); __clear_bit(msdu_id, htt->used_msdu_ids);
} }
int ath10k_htt_tx_alloc(struct ath10k_htt *htt) int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
{ {
struct ath10k *ar = htt->ar;
spin_lock_init(&htt->tx_lock); spin_lock_init(&htt->tx_lock);
init_waitqueue_head(&htt->empty_tx_wq); init_waitqueue_head(&htt->empty_tx_wq);
...@@ -93,7 +99,7 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt) ...@@ -93,7 +99,7 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
else else
htt->max_num_pending_tx = TARGET_NUM_MSDU_DESC; htt->max_num_pending_tx = TARGET_NUM_MSDU_DESC;
ath10k_dbg(ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n", ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n",
htt->max_num_pending_tx); htt->max_num_pending_tx);
htt->pending_tx = kzalloc(sizeof(*htt->pending_tx) * htt->pending_tx = kzalloc(sizeof(*htt->pending_tx) *
...@@ -122,6 +128,7 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt) ...@@ -122,6 +128,7 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
static void ath10k_htt_tx_free_pending(struct ath10k_htt *htt) static void ath10k_htt_tx_free_pending(struct ath10k_htt *htt)
{ {
struct ath10k *ar = htt->ar;
struct htt_tx_done tx_done = {0}; struct htt_tx_done tx_done = {0};
int msdu_id; int msdu_id;
...@@ -130,7 +137,7 @@ static void ath10k_htt_tx_free_pending(struct ath10k_htt *htt) ...@@ -130,7 +137,7 @@ static void ath10k_htt_tx_free_pending(struct ath10k_htt *htt)
if (!test_bit(msdu_id, htt->used_msdu_ids)) if (!test_bit(msdu_id, htt->used_msdu_ids))
continue; continue;
ath10k_dbg(ATH10K_DBG_HTT, "force cleanup msdu_id %hu\n", ath10k_dbg(ar, ATH10K_DBG_HTT, "force cleanup msdu_id %hu\n",
msdu_id); msdu_id);
tx_done.discard = 1; tx_done.discard = 1;
...@@ -157,6 +164,7 @@ void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) ...@@ -157,6 +164,7 @@ void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt) int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt)
{ {
struct ath10k *ar = htt->ar;
struct sk_buff *skb; struct sk_buff *skb;
struct htt_cmd *cmd; struct htt_cmd *cmd;
int len = 0; int len = 0;
...@@ -165,7 +173,7 @@ int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt) ...@@ -165,7 +173,7 @@ int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt)
len += sizeof(cmd->hdr); len += sizeof(cmd->hdr);
len += sizeof(cmd->ver_req); len += sizeof(cmd->ver_req);
skb = ath10k_htc_alloc_skb(len); skb = ath10k_htc_alloc_skb(ar, len);
if (!skb) if (!skb)
return -ENOMEM; return -ENOMEM;
...@@ -184,6 +192,7 @@ int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt) ...@@ -184,6 +192,7 @@ int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt)
int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie) int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie)
{ {
struct ath10k *ar = htt->ar;
struct htt_stats_req *req; struct htt_stats_req *req;
struct sk_buff *skb; struct sk_buff *skb;
struct htt_cmd *cmd; struct htt_cmd *cmd;
...@@ -192,7 +201,7 @@ int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie) ...@@ -192,7 +201,7 @@ int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie)
len += sizeof(cmd->hdr); len += sizeof(cmd->hdr);
len += sizeof(cmd->stats_req); len += sizeof(cmd->stats_req);
skb = ath10k_htc_alloc_skb(len); skb = ath10k_htc_alloc_skb(ar, len);
if (!skb) if (!skb)
return -ENOMEM; return -ENOMEM;
...@@ -214,7 +223,8 @@ int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie) ...@@ -214,7 +223,8 @@ int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie)
ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb); ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
if (ret) { if (ret) {
ath10k_warn("failed to send htt type stats request: %d", ret); ath10k_warn(ar, "failed to send htt type stats request: %d",
ret);
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
return ret; return ret;
} }
...@@ -224,6 +234,7 @@ int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie) ...@@ -224,6 +234,7 @@ int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie)
int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt) int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt)
{ {
struct ath10k *ar = htt->ar;
struct sk_buff *skb; struct sk_buff *skb;
struct htt_cmd *cmd; struct htt_cmd *cmd;
struct htt_rx_ring_setup_ring *ring; struct htt_rx_ring_setup_ring *ring;
...@@ -242,7 +253,7 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt) ...@@ -242,7 +253,7 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt)
len = sizeof(cmd->hdr) + sizeof(cmd->rx_setup.hdr) len = sizeof(cmd->hdr) + sizeof(cmd->rx_setup.hdr)
+ (sizeof(*ring) * num_rx_ring); + (sizeof(*ring) * num_rx_ring);
skb = ath10k_htc_alloc_skb(len); skb = ath10k_htc_alloc_skb(ar, len);
if (!skb) if (!skb)
return -ENOMEM; return -ENOMEM;
...@@ -311,6 +322,7 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, ...@@ -311,6 +322,7 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
u8 max_subfrms_ampdu, u8 max_subfrms_ampdu,
u8 max_subfrms_amsdu) u8 max_subfrms_amsdu)
{ {
struct ath10k *ar = htt->ar;
struct htt_aggr_conf *aggr_conf; struct htt_aggr_conf *aggr_conf;
struct sk_buff *skb; struct sk_buff *skb;
struct htt_cmd *cmd; struct htt_cmd *cmd;
...@@ -328,7 +340,7 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, ...@@ -328,7 +340,7 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
len = sizeof(cmd->hdr); len = sizeof(cmd->hdr);
len += sizeof(cmd->aggr_conf); len += sizeof(cmd->aggr_conf);
skb = ath10k_htc_alloc_skb(len); skb = ath10k_htc_alloc_skb(ar, len);
if (!skb) if (!skb)
return -ENOMEM; return -ENOMEM;
...@@ -340,7 +352,7 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, ...@@ -340,7 +352,7 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
aggr_conf->max_num_ampdu_subframes = max_subfrms_ampdu; aggr_conf->max_num_ampdu_subframes = max_subfrms_ampdu;
aggr_conf->max_num_amsdu_subframes = max_subfrms_amsdu; aggr_conf->max_num_amsdu_subframes = max_subfrms_amsdu;
ath10k_dbg(ATH10K_DBG_HTT, "htt h2t aggr cfg msg amsdu %d ampdu %d", ath10k_dbg(ar, ATH10K_DBG_HTT, "htt h2t aggr cfg msg amsdu %d ampdu %d",
aggr_conf->max_num_amsdu_subframes, aggr_conf->max_num_amsdu_subframes,
aggr_conf->max_num_ampdu_subframes); aggr_conf->max_num_ampdu_subframes);
...@@ -355,7 +367,8 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, ...@@ -355,7 +367,8 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
{ {
struct device *dev = htt->ar->dev; struct ath10k *ar = htt->ar;
struct device *dev = ar->dev;
struct sk_buff *txdesc = NULL; struct sk_buff *txdesc = NULL;
struct htt_cmd *cmd; struct htt_cmd *cmd;
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
...@@ -382,7 +395,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) ...@@ -382,7 +395,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
htt->pending_tx[msdu_id] = msdu; htt->pending_tx[msdu_id] = msdu;
spin_unlock_bh(&htt->tx_lock); spin_unlock_bh(&htt->tx_lock);
txdesc = ath10k_htc_alloc_skb(len); txdesc = ath10k_htc_alloc_skb(ar, len);
if (!txdesc) { if (!txdesc) {
res = -ENOMEM; res = -ENOMEM;
goto err_free_msdu_id; goto err_free_msdu_id;
...@@ -429,7 +442,8 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) ...@@ -429,7 +442,8 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
{ {
struct device *dev = htt->ar->dev; struct ath10k *ar = htt->ar;
struct device *dev = ar->dev;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu); struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(msdu);
struct ath10k_hif_sg_item sg_items[2]; struct ath10k_hif_sg_item sg_items[2];
...@@ -545,11 +559,11 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) ...@@ -545,11 +559,11 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr); skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr);
skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le32(HTT_INVALID_PEERID); skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le32(HTT_INVALID_PEERID);
ath10k_dbg(ATH10K_DBG_HTT, ath10k_dbg(ar, ATH10K_DBG_HTT,
"htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu\n", "htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu\n",
flags0, flags1, msdu->len, msdu_id, frags_paddr, flags0, flags1, msdu->len, msdu_id, frags_paddr,
(u32)skb_cb->paddr, vdev_id, tid); (u32)skb_cb->paddr, vdev_id, tid);
ath10k_dbg_dump(ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ", ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ",
msdu->data, msdu->len); msdu->data, msdu->len);
sg_items[0].transfer_id = 0; sg_items[0].transfer_id = 0;
......
...@@ -28,16 +28,19 @@ ...@@ -28,16 +28,19 @@
#define QCA988X_HW_2_0_CHIP_ID_REV 0x2 #define QCA988X_HW_2_0_CHIP_ID_REV 0x2
#define QCA988X_HW_2_0_FW_DIR "ath10k/QCA988X/hw2.0" #define QCA988X_HW_2_0_FW_DIR "ath10k/QCA988X/hw2.0"
#define QCA988X_HW_2_0_FW_FILE "firmware.bin" #define QCA988X_HW_2_0_FW_FILE "firmware.bin"
#define QCA988X_HW_2_0_FW_2_FILE "firmware-2.bin" #define QCA988X_HW_2_0_FW_3_FILE "firmware-3.bin"
#define QCA988X_HW_2_0_OTP_FILE "otp.bin" #define QCA988X_HW_2_0_OTP_FILE "otp.bin"
#define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin" #define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin"
#define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234 #define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234
#define ATH10K_FW_API2_FILE "firmware-2.bin" #define ATH10K_FW_API2_FILE "firmware-2.bin"
#define ATH10K_FW_API3_FILE "firmware-3.bin"
/* includes also the null byte */ /* includes also the null byte */
#define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K" #define ATH10K_FIRMWARE_MAGIC "QCA-ATH10K"
#define REG_DUMP_COUNT_QCA988X 60
struct ath10k_fw_ie { struct ath10k_fw_ie {
__le32 id; __le32 id;
__le32 len; __le32 len;
......
...@@ -26,12 +26,14 @@ struct ath10k_generic_iter { ...@@ -26,12 +26,14 @@ struct ath10k_generic_iter {
int ret; int ret;
}; };
struct ath10k *ath10k_mac_create(void); struct ath10k *ath10k_mac_create(size_t priv_size);
void ath10k_mac_destroy(struct ath10k *ar); void ath10k_mac_destroy(struct ath10k *ar);
int ath10k_mac_register(struct ath10k *ar); int ath10k_mac_register(struct ath10k *ar);
void ath10k_mac_unregister(struct ath10k *ar); void ath10k_mac_unregister(struct ath10k *ar);
struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id); struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id);
void ath10k_reset_scan(unsigned long ptr); void __ath10k_scan_finish(struct ath10k *ar);
void ath10k_scan_finish(struct ath10k *ar);
void ath10k_scan_timeout_work(struct work_struct *work);
void ath10k_offchan_tx_purge(struct ath10k *ar); void ath10k_offchan_tx_purge(struct ath10k *ar);
void ath10k_offchan_tx_work(struct work_struct *work); void ath10k_offchan_tx_work(struct work_struct *work);
void ath10k_mgmt_over_wmi_tx_purge(struct ath10k *ar); void ath10k_mgmt_over_wmi_tx_purge(struct ath10k *ar);
......
...@@ -23,9 +23,6 @@ ...@@ -23,9 +23,6 @@
#include "hw.h" #include "hw.h"
#include "ce.h" #include "ce.h"
/* FW dump area */
#define REG_DUMP_COUNT_QCA988X 60
/* /*
* maximum number of bytes that can be handled atomically by DiagRead/DiagWrite * maximum number of bytes that can be handled atomically by DiagRead/DiagWrite
*/ */
...@@ -103,12 +100,12 @@ struct pcie_state { ...@@ -103,12 +100,12 @@ struct pcie_state {
* NOTE: Structure is shared between Host software and Target firmware! * NOTE: Structure is shared between Host software and Target firmware!
*/ */
struct ce_pipe_config { struct ce_pipe_config {
u32 pipenum; __le32 pipenum;
u32 pipedir; __le32 pipedir;
u32 nentries; __le32 nentries;
u32 nbytes_max; __le32 nbytes_max;
u32 flags; __le32 flags;
u32 reserved; __le32 reserved;
}; };
/* /*
...@@ -130,17 +127,9 @@ struct ce_pipe_config { ...@@ -130,17 +127,9 @@ struct ce_pipe_config {
/* Establish a mapping between a service/direction and a pipe. */ /* Establish a mapping between a service/direction and a pipe. */
struct service_to_pipe { struct service_to_pipe {
u32 service_id; __le32 service_id;
u32 pipedir; __le32 pipedir;
u32 pipenum; __le32 pipenum;
};
enum ath10k_pci_features {
ATH10K_PCI_FEATURE_MSI_X = 0,
ATH10K_PCI_FEATURE_SOC_POWER_SAVE = 1,
/* keep last */
ATH10K_PCI_FEATURE_COUNT
}; };
/* Per-pipe state. */ /* Per-pipe state. */
...@@ -169,8 +158,6 @@ struct ath10k_pci { ...@@ -169,8 +158,6 @@ struct ath10k_pci {
struct ath10k *ar; struct ath10k *ar;
void __iomem *mem; void __iomem *mem;
DECLARE_BITMAP(features, ATH10K_PCI_FEATURE_COUNT);
/* /*
* Number of MSI interrupts granted, 0 --> using legacy PCI line * Number of MSI interrupts granted, 0 --> using legacy PCI line
* interrupts. * interrupts.
...@@ -179,12 +166,6 @@ struct ath10k_pci { ...@@ -179,12 +166,6 @@ struct ath10k_pci {
struct tasklet_struct intr_tq; struct tasklet_struct intr_tq;
struct tasklet_struct msi_fw_err; struct tasklet_struct msi_fw_err;
struct tasklet_struct early_irq_tasklet;
int started;
atomic_t keep_awake_count;
bool verified_awake;
struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX]; struct ath10k_pci_pipe pipe_info[CE_COUNT_MAX];
...@@ -198,27 +179,15 @@ struct ath10k_pci { ...@@ -198,27 +179,15 @@ struct ath10k_pci {
/* Map CE id to ce_state */ /* Map CE id to ce_state */
struct ath10k_ce_pipe ce_states[CE_COUNT_MAX]; struct ath10k_ce_pipe ce_states[CE_COUNT_MAX];
struct timer_list rx_post_retry;
}; };
static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar) static inline struct ath10k_pci *ath10k_pci_priv(struct ath10k *ar)
{ {
return ar->hif.priv; return (struct ath10k_pci *)ar->drv_priv;
}
static inline u32 ath10k_pci_reg_read32(struct ath10k *ar, u32 addr)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
return ioread32(ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + addr);
}
static inline void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
iowrite32(val, ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + addr);
} }
#define ATH10K_PCI_RX_POST_RETRY_MS 50
#define ATH_PCI_RESET_WAIT_MAX 10 /* ms */ #define ATH_PCI_RESET_WAIT_MAX 10 /* ms */
#define PCIE_WAKE_TIMEOUT 5000 /* 5ms */ #define PCIE_WAKE_TIMEOUT 5000 /* 5ms */
...@@ -242,35 +211,17 @@ static inline void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val) ...@@ -242,35 +211,17 @@ static inline void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val)
/* Wait up to this many Ms for a Diagnostic Access CE operation to complete */ /* Wait up to this many Ms for a Diagnostic Access CE operation to complete */
#define DIAG_ACCESS_CE_TIMEOUT_MS 10 #define DIAG_ACCESS_CE_TIMEOUT_MS 10
/* /* Target exposes its registers for direct access. However before host can
* This API allows the Host to access Target registers directly * access them it needs to make sure the target is awake (ath10k_pci_wake,
* and relatively efficiently over PCIe. * ath10k_pci_wake_wait, ath10k_pci_is_awake). Once target is awake it won't go
* This allows the Host to avoid extra overhead associated with * to sleep unless host tells it to (ath10k_pci_sleep).
* sending a message to firmware and waiting for a response message
* from firmware, as is done on other interconnects.
*
* Yet there is some complexity with direct accesses because the
* Target's power state is not known a priori. The Host must issue
* special PCIe reads/writes in order to explicitly wake the Target
* and to verify that it is awake and will remain awake.
*
* Usage:
* *
* Use ath10k_pci_read32 and ath10k_pci_write32 to access Target space. * If host tries to access target registers without waking it up it can
* These calls must be bracketed by ath10k_pci_wake and * scribble over host memory.
* ath10k_pci_sleep. A single BEGIN/END pair is adequate for
* multiple READ/WRITE operations.
* *
* Use ath10k_pci_wake to put the Target in a state in * If target is asleep waking it up may take up to even 2ms.
* which it is legal for the Host to directly access it. This
* may involve waking the Target from a low power state, which
* may take up to 2Ms!
*
* Use ath10k_pci_sleep to tell the Target that as far as
* this code path is concerned, it no longer needs to remain
* directly accessible. BEGIN/END is under a reference counter;
* multiple code paths may issue BEGIN/END on a single targid.
*/ */
static inline void ath10k_pci_write32(struct ath10k *ar, u32 offset, static inline void ath10k_pci_write32(struct ath10k *ar, u32 offset,
u32 value) u32 value)
{ {
...@@ -296,25 +247,18 @@ static inline void ath10k_pci_soc_write32(struct ath10k *ar, u32 addr, u32 val) ...@@ -296,25 +247,18 @@ static inline void ath10k_pci_soc_write32(struct ath10k *ar, u32 addr, u32 val)
ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + addr, val); ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + addr, val);
} }
int ath10k_do_pci_wake(struct ath10k *ar); static inline u32 ath10k_pci_reg_read32(struct ath10k *ar, u32 addr)
void ath10k_do_pci_sleep(struct ath10k *ar);
static inline int ath10k_pci_wake(struct ath10k *ar)
{ {
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
if (test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features)) return ioread32(ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + addr);
return ath10k_do_pci_wake(ar);
return 0;
} }
static inline void ath10k_pci_sleep(struct ath10k *ar) static inline void ath10k_pci_reg_write32(struct ath10k *ar, u32 addr, u32 val)
{ {
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
if (test_bit(ATH10K_PCI_FEATURE_SOC_POWER_SAVE, ar_pci->features)) iowrite32(val, ar_pci->mem + PCIE_LOCAL_BASE_ADDRESS + addr);
ath10k_do_pci_sleep(ar);
} }
#endif /* _PCI_H_ */ #endif /* _PCI_H_ */
/*
* Copyright (c) 2013 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/relay.h>
#include "core.h"
#include "debug.h"
static void send_fft_sample(struct ath10k *ar,
const struct fft_sample_tlv *fft_sample_tlv)
{
int length;
if (!ar->spectral.rfs_chan_spec_scan)
return;
length = __be16_to_cpu(fft_sample_tlv->length) +
sizeof(*fft_sample_tlv);
relay_write(ar->spectral.rfs_chan_spec_scan, fft_sample_tlv, length);
}
static uint8_t get_max_exp(s8 max_index, u16 max_magnitude, size_t bin_len,
u8 *data)
{
int dc_pos;
u8 max_exp;
dc_pos = bin_len / 2;
/* peak index outside of bins */
if (dc_pos < max_index || -dc_pos >= max_index)
return 0;
for (max_exp = 0; max_exp < 8; max_exp++) {
if (data[dc_pos + max_index] == (max_magnitude >> max_exp))
break;
}
/* max_exp not found */
if (data[dc_pos + max_index] != (max_magnitude >> max_exp))
return 0;
return max_exp;
}
int ath10k_spectral_process_fft(struct ath10k *ar,
struct wmi_single_phyerr_rx_event *event,
struct phyerr_fft_report *fftr,
size_t bin_len, u64 tsf)
{
struct fft_sample_ath10k *fft_sample;
u8 buf[sizeof(*fft_sample) + SPECTRAL_ATH10K_MAX_NUM_BINS];
u16 freq1, freq2, total_gain_db, base_pwr_db, length, peak_mag;
u32 reg0, reg1, nf_list1, nf_list2;
u8 chain_idx, *bins;
int dc_pos;
fft_sample = (struct fft_sample_ath10k *)&buf;
if (bin_len < 64 || bin_len > SPECTRAL_ATH10K_MAX_NUM_BINS)
return -EINVAL;
reg0 = __le32_to_cpu(fftr->reg0);
reg1 = __le32_to_cpu(fftr->reg1);
length = sizeof(*fft_sample) - sizeof(struct fft_sample_tlv) + bin_len;
fft_sample->tlv.type = ATH_FFT_SAMPLE_ATH10K;
fft_sample->tlv.length = __cpu_to_be16(length);
/* TODO: there might be a reason why the hardware reports 20/40/80 MHz,
* but the results/plots suggest that its actually 22/44/88 MHz.
*/
switch (event->hdr.chan_width_mhz) {
case 20:
fft_sample->chan_width_mhz = 22;
break;
case 40:
fft_sample->chan_width_mhz = 44;
break;
case 80:
/* TODO: As experiments with an analogue sender and various
* configuaritions (fft-sizes of 64/128/256 and 20/40/80 Mhz)
* show, the particular configuration of 80 MHz/64 bins does
* not match with the other smaples at all. Until the reason
* for that is found, don't report these samples.
*/
if (bin_len == 64)
return -EINVAL;
fft_sample->chan_width_mhz = 88;
break;
default:
fft_sample->chan_width_mhz = event->hdr.chan_width_mhz;
}
fft_sample->relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB);
fft_sample->avgpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_AVGPWR_DB);
peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG);
fft_sample->max_magnitude = __cpu_to_be16(peak_mag);
fft_sample->max_index = MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX);
fft_sample->rssi = event->hdr.rssi_combined;
total_gain_db = MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB);
base_pwr_db = MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB);
fft_sample->total_gain_db = __cpu_to_be16(total_gain_db);
fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db);
freq1 = __le16_to_cpu(event->hdr.freq1);
freq2 = __le16_to_cpu(event->hdr.freq2);
fft_sample->freq1 = __cpu_to_be16(freq1);
fft_sample->freq2 = __cpu_to_be16(freq2);
nf_list1 = __le32_to_cpu(event->hdr.nf_list_1);
nf_list2 = __le32_to_cpu(event->hdr.nf_list_2);
chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);
switch (chain_idx) {
case 0:
fft_sample->noise = __cpu_to_be16(nf_list1 & 0xffffu);
break;
case 1:
fft_sample->noise = __cpu_to_be16((nf_list1 >> 16) & 0xffffu);
break;
case 2:
fft_sample->noise = __cpu_to_be16(nf_list2 & 0xffffu);
break;
case 3:
fft_sample->noise = __cpu_to_be16((nf_list2 >> 16) & 0xffffu);
break;
}
bins = (u8 *)fftr;
bins += sizeof(*fftr);
fft_sample->tsf = __cpu_to_be64(tsf);
/* max_exp has been directly reported by previous hardware (ath9k),
* maybe its possible to get it by other means?
*/
fft_sample->max_exp = get_max_exp(fft_sample->max_index, peak_mag,
bin_len, bins);
memcpy(fft_sample->data, bins, bin_len);
/* DC value (value in the middle) is the blind spot of the spectral
* sample and invalid, interpolate it.
*/
dc_pos = bin_len / 2;
fft_sample->data[dc_pos] = (fft_sample->data[dc_pos + 1] +
fft_sample->data[dc_pos - 1]) / 2;
send_fft_sample(ar, &fft_sample->tlv);
return 0;
}
static struct ath10k_vif *ath10k_get_spectral_vdev(struct ath10k *ar)
{
struct ath10k_vif *arvif;
lockdep_assert_held(&ar->conf_mutex);
if (list_empty(&ar->arvifs))
return NULL;
/* if there already is a vif doing spectral, return that. */
list_for_each_entry(arvif, &ar->arvifs, list)
if (arvif->spectral_enabled)
return arvif;
/* otherwise, return the first vif. */
return list_first_entry(&ar->arvifs, typeof(*arvif), list);
}
static int ath10k_spectral_scan_trigger(struct ath10k *ar)
{
struct ath10k_vif *arvif;
int res;
int vdev_id;
lockdep_assert_held(&ar->conf_mutex);
arvif = ath10k_get_spectral_vdev(ar);
if (!arvif)
return -ENODEV;
vdev_id = arvif->vdev_id;
if (ar->spectral.mode == SPECTRAL_DISABLED)
return 0;
res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
WMI_SPECTRAL_ENABLE_CMD_ENABLE);
if (res < 0)
return res;
res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
WMI_SPECTRAL_TRIGGER_CMD_TRIGGER,
WMI_SPECTRAL_ENABLE_CMD_ENABLE);
if (res < 0)
return res;
return 0;
}
static int ath10k_spectral_scan_config(struct ath10k *ar,
enum ath10k_spectral_mode mode)
{
struct wmi_vdev_spectral_conf_arg arg;
struct ath10k_vif *arvif;
int vdev_id, count, res = 0;
lockdep_assert_held(&ar->conf_mutex);
arvif = ath10k_get_spectral_vdev(ar);
if (!arvif)
return -ENODEV;
vdev_id = arvif->vdev_id;
arvif->spectral_enabled = (mode != SPECTRAL_DISABLED);
ar->spectral.mode = mode;
res = ath10k_wmi_vdev_spectral_enable(ar, vdev_id,
WMI_SPECTRAL_TRIGGER_CMD_CLEAR,
WMI_SPECTRAL_ENABLE_CMD_DISABLE);
if (res < 0) {
ath10k_warn(ar, "failed to enable spectral scan: %d\n", res);
return res;
}
if (mode == SPECTRAL_DISABLED)
return 0;
if (mode == SPECTRAL_BACKGROUND)
count = WMI_SPECTRAL_COUNT_DEFAULT;
else
count = max_t(u8, 1, ar->spectral.config.count);
arg.vdev_id = vdev_id;
arg.scan_count = count;
arg.scan_period = WMI_SPECTRAL_PERIOD_DEFAULT;
arg.scan_priority = WMI_SPECTRAL_PRIORITY_DEFAULT;
arg.scan_fft_size = ar->spectral.config.fft_size;
arg.scan_gc_ena = WMI_SPECTRAL_GC_ENA_DEFAULT;
arg.scan_restart_ena = WMI_SPECTRAL_RESTART_ENA_DEFAULT;
arg.scan_noise_floor_ref = WMI_SPECTRAL_NOISE_FLOOR_REF_DEFAULT;
arg.scan_init_delay = WMI_SPECTRAL_INIT_DELAY_DEFAULT;
arg.scan_nb_tone_thr = WMI_SPECTRAL_NB_TONE_THR_DEFAULT;
arg.scan_str_bin_thr = WMI_SPECTRAL_STR_BIN_THR_DEFAULT;
arg.scan_wb_rpt_mode = WMI_SPECTRAL_WB_RPT_MODE_DEFAULT;
arg.scan_rssi_rpt_mode = WMI_SPECTRAL_RSSI_RPT_MODE_DEFAULT;
arg.scan_rssi_thr = WMI_SPECTRAL_RSSI_THR_DEFAULT;
arg.scan_pwr_format = WMI_SPECTRAL_PWR_FORMAT_DEFAULT;
arg.scan_rpt_mode = WMI_SPECTRAL_RPT_MODE_DEFAULT;
arg.scan_bin_scale = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
arg.scan_dbm_adj = WMI_SPECTRAL_DBM_ADJ_DEFAULT;
arg.scan_chn_mask = WMI_SPECTRAL_CHN_MASK_DEFAULT;
res = ath10k_wmi_vdev_spectral_conf(ar, &arg);
if (res < 0) {
ath10k_warn(ar, "failed to configure spectral scan: %d\n", res);
return res;
}
return 0;
}
static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
char *mode = "";
unsigned int len;
enum ath10k_spectral_mode spectral_mode;
mutex_lock(&ar->conf_mutex);
spectral_mode = ar->spectral.mode;
mutex_unlock(&ar->conf_mutex);
switch (spectral_mode) {
case SPECTRAL_DISABLED:
mode = "disable";
break;
case SPECTRAL_BACKGROUND:
mode = "background";
break;
case SPECTRAL_MANUAL:
mode = "manual";
break;
}
len = strlen(mode);
return simple_read_from_buffer(user_buf, count, ppos, mode, len);
}
static ssize_t write_file_spec_scan_ctl(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
char buf[32];
ssize_t len;
int res;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
mutex_lock(&ar->conf_mutex);
if (strncmp("trigger", buf, 7) == 0) {
if (ar->spectral.mode == SPECTRAL_MANUAL ||
ar->spectral.mode == SPECTRAL_BACKGROUND) {
/* reset the configuration to adopt possibly changed
* debugfs parameters
*/
res = ath10k_spectral_scan_config(ar,
ar->spectral.mode);
if (res < 0) {
ath10k_warn(ar, "failed to reconfigure spectral scan: %d\n",
res);
}
res = ath10k_spectral_scan_trigger(ar);
if (res < 0) {
ath10k_warn(ar, "failed to trigger spectral scan: %d\n",
res);
}
} else {
res = -EINVAL;
}
} else if (strncmp("background", buf, 9) == 0) {
res = ath10k_spectral_scan_config(ar, SPECTRAL_BACKGROUND);
} else if (strncmp("manual", buf, 6) == 0) {
res = ath10k_spectral_scan_config(ar, SPECTRAL_MANUAL);
} else if (strncmp("disable", buf, 7) == 0) {
res = ath10k_spectral_scan_config(ar, SPECTRAL_DISABLED);
} else {
res = -EINVAL;
}
mutex_unlock(&ar->conf_mutex);
if (res < 0)
return res;
return count;
}
static const struct file_operations fops_spec_scan_ctl = {
.read = read_file_spec_scan_ctl,
.write = write_file_spec_scan_ctl,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static ssize_t read_file_spectral_count(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
char buf[32];
unsigned int len;
u8 spectral_count;
mutex_lock(&ar->conf_mutex);
spectral_count = ar->spectral.config.count;
mutex_unlock(&ar->conf_mutex);
len = sprintf(buf, "%d\n", spectral_count);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t write_file_spectral_count(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
unsigned long val;
char buf[32];
ssize_t len;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val < 0 || val > 255)
return -EINVAL;
mutex_lock(&ar->conf_mutex);
ar->spectral.config.count = val;
mutex_unlock(&ar->conf_mutex);
return count;
}
static const struct file_operations fops_spectral_count = {
.read = read_file_spectral_count,
.write = write_file_spectral_count,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static ssize_t read_file_spectral_bins(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
char buf[32];
unsigned int len, bins, fft_size, bin_scale;
mutex_lock(&ar->conf_mutex);
fft_size = ar->spectral.config.fft_size;
bin_scale = WMI_SPECTRAL_BIN_SCALE_DEFAULT;
bins = 1 << (fft_size - bin_scale);
mutex_unlock(&ar->conf_mutex);
len = sprintf(buf, "%d\n", bins);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t write_file_spectral_bins(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
unsigned long val;
char buf[32];
ssize_t len;
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
buf[len] = '\0';
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val < 64 || val > SPECTRAL_ATH10K_MAX_NUM_BINS)
return -EINVAL;
if (!is_power_of_2(val))
return -EINVAL;
mutex_lock(&ar->conf_mutex);
ar->spectral.config.fft_size = ilog2(val);
ar->spectral.config.fft_size += WMI_SPECTRAL_BIN_SCALE_DEFAULT;
mutex_unlock(&ar->conf_mutex);
return count;
}
static const struct file_operations fops_spectral_bins = {
.read = read_file_spectral_bins,
.write = write_file_spectral_bins,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static struct dentry *create_buf_file_handler(const char *filename,
struct dentry *parent,
umode_t mode,
struct rchan_buf *buf,
int *is_global)
{
struct dentry *buf_file;
buf_file = debugfs_create_file(filename, mode, parent, buf,
&relay_file_operations);
*is_global = 1;
return buf_file;
}
static int remove_buf_file_handler(struct dentry *dentry)
{
debugfs_remove(dentry);
return 0;
}
static struct rchan_callbacks rfs_spec_scan_cb = {
.create_buf_file = create_buf_file_handler,
.remove_buf_file = remove_buf_file_handler,
};
int ath10k_spectral_start(struct ath10k *ar)
{
struct ath10k_vif *arvif;
lockdep_assert_held(&ar->conf_mutex);
list_for_each_entry(arvif, &ar->arvifs, list)
arvif->spectral_enabled = 0;
ar->spectral.mode = SPECTRAL_DISABLED;
ar->spectral.config.count = WMI_SPECTRAL_COUNT_DEFAULT;
ar->spectral.config.fft_size = WMI_SPECTRAL_FFT_SIZE_DEFAULT;
return 0;
}
int ath10k_spectral_vif_stop(struct ath10k_vif *arvif)
{
if (!arvif->spectral_enabled)
return 0;
return ath10k_spectral_scan_config(arvif->ar, SPECTRAL_DISABLED);
}
int ath10k_spectral_create(struct ath10k *ar)
{
ar->spectral.rfs_chan_spec_scan = relay_open("spectral_scan",
ar->debug.debugfs_phy,
1024, 256,
&rfs_spec_scan_cb, NULL);
debugfs_create_file("spectral_scan_ctl",
S_IRUSR | S_IWUSR,
ar->debug.debugfs_phy, ar,
&fops_spec_scan_ctl);
debugfs_create_file("spectral_count",
S_IRUSR | S_IWUSR,
ar->debug.debugfs_phy, ar,
&fops_spectral_count);
debugfs_create_file("spectral_bins",
S_IRUSR | S_IWUSR,
ar->debug.debugfs_phy, ar,
&fops_spectral_bins);
return 0;
}
void ath10k_spectral_destroy(struct ath10k *ar)
{
if (ar->spectral.rfs_chan_spec_scan) {
relay_close(ar->spectral.rfs_chan_spec_scan);
ar->spectral.rfs_chan_spec_scan = NULL;
}
}
/*
* Copyright (c) 2013 Qualcomm Atheros, Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef SPECTRAL_H
#define SPECTRAL_H
#include "../spectral_common.h"
/**
* struct ath10k_spec_scan - parameters for Atheros spectral scan
*
* @count: number of scan results requested for manual mode
* @fft_size: number of bins to be requested = 2^(fft_size - bin_scale)
*/
struct ath10k_spec_scan {
u8 count;
u8 fft_size;
};
/* enum ath10k_spectral_mode:
*
* @SPECTRAL_DISABLED: spectral mode is disabled
* @SPECTRAL_BACKGROUND: hardware sends samples when it is not busy with
* something else.
* @SPECTRAL_MANUAL: spectral scan is enabled, triggering for samples
* is performed manually.
*/
enum ath10k_spectral_mode {
SPECTRAL_DISABLED = 0,
SPECTRAL_BACKGROUND,
SPECTRAL_MANUAL,
};
#ifdef CONFIG_ATH10K_DEBUGFS
int ath10k_spectral_process_fft(struct ath10k *ar,
struct wmi_single_phyerr_rx_event *event,
struct phyerr_fft_report *fftr,
size_t bin_len, u64 tsf);
int ath10k_spectral_start(struct ath10k *ar);
int ath10k_spectral_vif_stop(struct ath10k_vif *arvif);
int ath10k_spectral_create(struct ath10k *ar);
void ath10k_spectral_destroy(struct ath10k *ar);
#else
static inline int
ath10k_spectral_process_fft(struct ath10k *ar,
struct wmi_single_phyerr_rx_event *event,
struct phyerr_fft_report *fftr,
size_t bin_len, u64 tsf)
{
return 0;
}
static inline int ath10k_spectral_start(struct ath10k *ar)
{
return 0;
}
static inline int ath10k_spectral_vif_stop(struct ath10k_vif *arvif)
{
return 0;
}
static inline int ath10k_spectral_create(struct ath10k *ar)
{
return 0;
}
static inline void ath10k_spectral_destroy(struct ath10k *ar)
{
}
#endif /* CONFIG_ATH10K_DEBUGFS */
#endif /* SPECTRAL_H */
...@@ -32,14 +32,14 @@ static void ath10k_report_offchan_tx(struct ath10k *ar, struct sk_buff *skb) ...@@ -32,14 +32,14 @@ static void ath10k_report_offchan_tx(struct ath10k *ar, struct sk_buff *skb)
* offchan_tx_skb. */ * offchan_tx_skb. */
spin_lock_bh(&ar->data_lock); spin_lock_bh(&ar->data_lock);
if (ar->offchan_tx_skb != skb) { if (ar->offchan_tx_skb != skb) {
ath10k_warn("completed old offchannel frame\n"); ath10k_warn(ar, "completed old offchannel frame\n");
goto out; goto out;
} }
complete(&ar->offchan_tx_completed); complete(&ar->offchan_tx_completed);
ar->offchan_tx_skb = NULL; /* just for sanity */ ar->offchan_tx_skb = NULL; /* just for sanity */
ath10k_dbg(ATH10K_DBG_HTT, "completed offchannel skb %p\n", skb); ath10k_dbg(ar, ATH10K_DBG_HTT, "completed offchannel skb %p\n", skb);
out: out:
spin_unlock_bh(&ar->data_lock); spin_unlock_bh(&ar->data_lock);
} }
...@@ -47,18 +47,19 @@ static void ath10k_report_offchan_tx(struct ath10k *ar, struct sk_buff *skb) ...@@ -47,18 +47,19 @@ static void ath10k_report_offchan_tx(struct ath10k *ar, struct sk_buff *skb)
void ath10k_txrx_tx_unref(struct ath10k_htt *htt, void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
const struct htt_tx_done *tx_done) const struct htt_tx_done *tx_done)
{ {
struct device *dev = htt->ar->dev; struct ath10k *ar = htt->ar;
struct device *dev = ar->dev;
struct ieee80211_tx_info *info; struct ieee80211_tx_info *info;
struct ath10k_skb_cb *skb_cb; struct ath10k_skb_cb *skb_cb;
struct sk_buff *msdu; struct sk_buff *msdu;
lockdep_assert_held(&htt->tx_lock); lockdep_assert_held(&htt->tx_lock);
ath10k_dbg(ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d\n", ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx completion msdu_id %u discard %d no_ack %d\n",
tx_done->msdu_id, !!tx_done->discard, !!tx_done->no_ack); tx_done->msdu_id, !!tx_done->discard, !!tx_done->no_ack);
if (tx_done->msdu_id >= htt->max_num_pending_tx) { if (tx_done->msdu_id >= htt->max_num_pending_tx) {
ath10k_warn("warning: msdu_id %d too big, ignoring\n", ath10k_warn(ar, "warning: msdu_id %d too big, ignoring\n",
tx_done->msdu_id); tx_done->msdu_id);
return; return;
} }
...@@ -182,7 +183,7 @@ void ath10k_peer_map_event(struct ath10k_htt *htt, ...@@ -182,7 +183,7 @@ void ath10k_peer_map_event(struct ath10k_htt *htt,
wake_up(&ar->peer_mapping_wq); wake_up(&ar->peer_mapping_wq);
} }
ath10k_dbg(ATH10K_DBG_HTT, "htt peer map vdev %d peer %pM id %d\n", ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer map vdev %d peer %pM id %d\n",
ev->vdev_id, ev->addr, ev->peer_id); ev->vdev_id, ev->addr, ev->peer_id);
set_bit(ev->peer_id, peer->peer_ids); set_bit(ev->peer_id, peer->peer_ids);
...@@ -199,12 +200,12 @@ void ath10k_peer_unmap_event(struct ath10k_htt *htt, ...@@ -199,12 +200,12 @@ void ath10k_peer_unmap_event(struct ath10k_htt *htt,
spin_lock_bh(&ar->data_lock); spin_lock_bh(&ar->data_lock);
peer = ath10k_peer_find_by_id(ar, ev->peer_id); peer = ath10k_peer_find_by_id(ar, ev->peer_id);
if (!peer) { if (!peer) {
ath10k_warn("peer-unmap-event: unknown peer id %d\n", ath10k_warn(ar, "peer-unmap-event: unknown peer id %d\n",
ev->peer_id); ev->peer_id);
goto exit; goto exit;
} }
ath10k_dbg(ATH10K_DBG_HTT, "htt peer unmap vdev %d peer %pM id %d\n", ath10k_dbg(ar, ATH10K_DBG_HTT, "htt peer unmap vdev %d peer %pM id %d\n",
peer->vdev_id, peer->addr, ev->peer_id); peer->vdev_id, peer->addr, ev->peer_id);
clear_bit(ev->peer_id, peer->peer_ids); clear_bit(ev->peer_id, peer->peer_ids);
......
...@@ -1049,7 +1049,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) ...@@ -1049,7 +1049,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
ar->hw.reserved_ram_size = le32_to_cpup(val); ar->hw.reserved_ram_size = le32_to_cpup(val);
ath6kl_dbg(ATH6KL_DBG_BOOT, ath6kl_dbg(ATH6KL_DBG_BOOT,
"found reserved ram size ie 0x%d\n", "found reserved ram size ie %d\n",
ar->hw.reserved_ram_size); ar->hw.reserved_ram_size);
break; break;
case ATH6KL_FW_IE_CAPABILITIES: case ATH6KL_FW_IE_CAPABILITIES:
......
...@@ -225,7 +225,7 @@ int ath6kl_diag_write32(struct ath6kl *ar, u32 address, __le32 value) ...@@ -225,7 +225,7 @@ int ath6kl_diag_write32(struct ath6kl *ar, u32 address, __le32 value)
ret = ath6kl_hif_diag_write32(ar, address, value); ret = ath6kl_hif_diag_write32(ar, address, value);
if (ret) { if (ret) {
ath6kl_err("failed to write 0x%x during diagnose window to 0x%d\n", ath6kl_err("failed to write 0x%x during diagnose window to 0x%x\n",
address, value); address, value);
return ret; return ret;
} }
......
...@@ -1400,6 +1400,7 @@ static const struct sdio_device_id ath6kl_sdio_devices[] = { ...@@ -1400,6 +1400,7 @@ static const struct sdio_device_id ath6kl_sdio_devices[] = {
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x1))}, {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x1))},
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6004_BASE | 0x0))}, {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6004_BASE | 0x0))},
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6004_BASE | 0x1))}, {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6004_BASE | 0x1))},
{SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6004_BASE | 0x2))},
{}, {},
}; };
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册