2019-02-19 17:45:26 +00:00
|
|
|
/* SPDX-License-Identifier: ISC */
|
2013-06-12 17:52:10 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2005-2011 Atheros Communications Inc.
|
2017-12-22 16:31:13 +00:00
|
|
|
* Copyright (c) 2011-2015,2017 Qualcomm Atheros, Inc.
|
2013-06-12 17:52:10 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _HIF_H_
|
|
|
|
#define _HIF_H_
|
|
|
|
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include "core.h"
|
2018-04-10 15:01:29 +00:00
|
|
|
#include "bmi.h"
|
2014-11-25 10:24:33 +00:00
|
|
|
#include "debug.h"
|
2013-06-12 17:52:10 +00:00
|
|
|
|
2019-06-03 15:14:52 +00:00
|
|
|
/* Types of fw logging mode */
|
|
|
|
enum ath_dbg_mode {
|
|
|
|
ATH10K_ENABLE_FW_LOG_DIAG,
|
|
|
|
ATH10K_ENABLE_FW_LOG_CE,
|
|
|
|
};
|
|
|
|
|
2014-02-27 16:50:04 +00:00
|
|
|
struct ath10k_hif_sg_item {
|
|
|
|
u16 transfer_id;
|
|
|
|
void *transfer_context; /* NULL = tx completion callback not called */
|
|
|
|
void *vaddr; /* for debugging mostly */
|
2018-04-10 15:01:27 +00:00
|
|
|
dma_addr_t paddr;
|
2014-02-27 16:50:04 +00:00
|
|
|
u16 len;
|
|
|
|
};
|
|
|
|
|
2013-06-12 17:52:10 +00:00
|
|
|
struct ath10k_hif_ops {
|
2014-02-27 16:50:04 +00:00
|
|
|
/* send a scatter-gather list to the target */
|
|
|
|
int (*tx_sg)(struct ath10k *ar, u8 pipe_id,
|
|
|
|
struct ath10k_hif_sg_item *items, int n_items);
|
2013-06-12 17:52:10 +00:00
|
|
|
|
2014-09-24 11:16:52 +00:00
|
|
|
/* read firmware memory through the diagnose interface */
|
|
|
|
int (*diag_read)(struct ath10k *ar, u32 address, void *buf,
|
|
|
|
size_t buf_len);
|
|
|
|
|
2014-11-25 10:24:48 +00:00
|
|
|
int (*diag_write)(struct ath10k *ar, u32 address, const void *data,
|
|
|
|
int nbytes);
|
2013-06-12 17:52:10 +00:00
|
|
|
/*
|
|
|
|
* API to handle HIF-specific BMI message exchanges, this API is
|
|
|
|
* synchronous and only allowed to be called from a context that
|
|
|
|
* can block (sleep)
|
|
|
|
*/
|
|
|
|
int (*exchange_bmi_msg)(struct ath10k *ar,
|
|
|
|
void *request, u32 request_len,
|
|
|
|
void *response, u32 *response_len);
|
|
|
|
|
2013-07-16 07:38:50 +00:00
|
|
|
/* Post BMI phase, after FW is loaded. Starts regular operation */
|
2013-06-12 17:52:10 +00:00
|
|
|
int (*start)(struct ath10k *ar);
|
|
|
|
|
2013-07-16 07:38:50 +00:00
|
|
|
/* Clean up what start() did. This does not revert to BMI phase. If
|
2017-02-20 14:38:50 +00:00
|
|
|
* desired so, call power_down() and power_up()
|
|
|
|
*/
|
2013-06-12 17:52:10 +00:00
|
|
|
void (*stop)(struct ath10k *ar);
|
|
|
|
|
2020-04-16 11:50:56 +00:00
|
|
|
int (*start_post)(struct ath10k *ar);
|
2019-01-29 12:03:12 +00:00
|
|
|
|
ath10k: disable TX complete indication of htt for sdio
For sdio chip, it is high latency bus, all the TX packet's content will
be tranferred from HOST memory to firmware memory via sdio bus, then it
need much more memory in firmware than low latency bus chip, for low
latency chip, such as PCI-E, it only need to transfer the TX descriptor
via PCI-E bus to firmware memory. For sdio chip, reduce the complexity of
TX logic will help TX efficiency since its memory is limited, and it will
reduce the TX circle's time of each packet and then firmware will have more
memory for TX since TX complete also need memeory.
This patch disable TX complete indication from firmware for htt data
packet, it will not have TX complete indication from firmware to ath10k.
It will cut the cost of bus bandwidth of TX complete and make the TX
logic of firmware simpler, it results in significant performance
improvement on TX path.
Udp TX throughout is 130Mbps without this patch, and it arrives
400Mbps with this patch.
The downside of this patch is the command "iw wlan0 station dump" will
show 0 for "tx retries" and "tx failed" since all tx packet's status
is success.
This patch only effect sdio chip, it will not effect PCI, SNOC etc.
Tested with QCA6174 SDIO with firmware
WLAN.RMH.4.4.1-00017-QCARMSWPZ-1
Signed-off-by: Wen Gong <wgong@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20200212080415.31265-2-wgong@codeaurora.org
2020-04-07 05:12:30 +00:00
|
|
|
int (*get_htt_tx_complete)(struct ath10k *ar);
|
|
|
|
|
2013-06-12 17:52:10 +00:00
|
|
|
int (*map_service_to_pipe)(struct ath10k *ar, u16 service_id,
|
2015-10-12 12:57:06 +00:00
|
|
|
u8 *ul_pipe, u8 *dl_pipe);
|
2013-06-12 17:52:10 +00:00
|
|
|
|
|
|
|
void (*get_default_pipe)(struct ath10k *ar, u8 *ul_pipe, u8 *dl_pipe);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check if prior sends have completed.
|
|
|
|
*
|
|
|
|
* Check whether the pipe in question has any completed
|
|
|
|
* sends that have not yet been processed.
|
|
|
|
* This function is only relevant for HIF pipes that are configured
|
|
|
|
* to be polled rather than interrupt-driven.
|
|
|
|
*/
|
|
|
|
void (*send_complete_check)(struct ath10k *ar, u8 pipe_id, int force);
|
|
|
|
|
|
|
|
u16 (*get_free_queue_number)(struct ath10k *ar, u8 pipe_id);
|
2013-07-16 07:38:50 +00:00
|
|
|
|
2014-11-25 10:24:33 +00:00
|
|
|
u32 (*read32)(struct ath10k *ar, u32 address);
|
|
|
|
|
|
|
|
void (*write32)(struct ath10k *ar, u32 address, u32 value);
|
|
|
|
|
2013-07-16 07:38:50 +00:00
|
|
|
/* Power up the device and enter BMI transfer mode for FW download */
|
2019-02-08 13:50:10 +00:00
|
|
|
int (*power_up)(struct ath10k *ar, enum ath10k_firmware_mode fw_mode);
|
2013-07-16 07:38:50 +00:00
|
|
|
|
|
|
|
/* Power down the device and free up resources. stop() must be called
|
2017-02-20 14:38:50 +00:00
|
|
|
* before this if start() was called earlier
|
|
|
|
*/
|
2013-07-16 07:38:50 +00:00
|
|
|
void (*power_down)(struct ath10k *ar);
|
2013-07-16 07:38:54 +00:00
|
|
|
|
|
|
|
int (*suspend)(struct ath10k *ar);
|
|
|
|
int (*resume)(struct ath10k *ar);
|
2016-06-02 14:59:50 +00:00
|
|
|
|
|
|
|
/* fetch calibration data from target eeprom */
|
|
|
|
int (*fetch_cal_eeprom)(struct ath10k *ar, void **data,
|
|
|
|
size_t *data_len);
|
2018-04-10 15:01:29 +00:00
|
|
|
|
|
|
|
int (*get_target_info)(struct ath10k *ar,
|
|
|
|
struct bmi_target_info *target_info);
|
2019-06-03 15:14:52 +00:00
|
|
|
int (*set_target_log_mode)(struct ath10k *ar, u8 fw_log_mode);
|
2013-06-12 17:52:10 +00:00
|
|
|
};
|
|
|
|
|
2014-02-27 16:50:04 +00:00
|
|
|
static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
|
|
|
|
struct ath10k_hif_sg_item *items,
|
|
|
|
int n_items)
|
2013-06-12 17:52:10 +00:00
|
|
|
{
|
2014-02-27 16:50:04 +00:00
|
|
|
return ar->hif.ops->tx_sg(ar, pipe_id, items, n_items);
|
2013-06-12 17:52:10 +00:00
|
|
|
}
|
|
|
|
|
2014-09-24 11:16:52 +00:00
|
|
|
static inline int ath10k_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
|
|
|
|
size_t buf_len)
|
|
|
|
{
|
|
|
|
return ar->hif.ops->diag_read(ar, address, buf, buf_len);
|
|
|
|
}
|
|
|
|
|
2014-11-25 10:24:48 +00:00
|
|
|
static inline int ath10k_hif_diag_write(struct ath10k *ar, u32 address,
|
|
|
|
const void *data, int nbytes)
|
|
|
|
{
|
|
|
|
if (!ar->hif.ops->diag_write)
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
|
|
return ar->hif.ops->diag_write(ar, address, data, nbytes);
|
|
|
|
}
|
|
|
|
|
2013-06-12 17:52:10 +00:00
|
|
|
static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar,
|
|
|
|
void *request, u32 request_len,
|
|
|
|
void *response, u32 *response_len)
|
|
|
|
{
|
|
|
|
return ar->hif.ops->exchange_bmi_msg(ar, request, request_len,
|
|
|
|
response, response_len);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int ath10k_hif_start(struct ath10k *ar)
|
|
|
|
{
|
|
|
|
return ar->hif.ops->start(ar);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void ath10k_hif_stop(struct ath10k *ar)
|
|
|
|
{
|
|
|
|
return ar->hif.ops->stop(ar);
|
|
|
|
}
|
|
|
|
|
2020-04-16 11:50:56 +00:00
|
|
|
static inline int ath10k_hif_start_post(struct ath10k *ar)
|
2019-01-29 12:03:12 +00:00
|
|
|
{
|
2020-04-16 11:50:56 +00:00
|
|
|
if (ar->hif.ops->start_post)
|
|
|
|
return ar->hif.ops->start_post(ar);
|
2019-01-29 12:03:12 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
ath10k: disable TX complete indication of htt for sdio
For sdio chip, it is high latency bus, all the TX packet's content will
be tranferred from HOST memory to firmware memory via sdio bus, then it
need much more memory in firmware than low latency bus chip, for low
latency chip, such as PCI-E, it only need to transfer the TX descriptor
via PCI-E bus to firmware memory. For sdio chip, reduce the complexity of
TX logic will help TX efficiency since its memory is limited, and it will
reduce the TX circle's time of each packet and then firmware will have more
memory for TX since TX complete also need memeory.
This patch disable TX complete indication from firmware for htt data
packet, it will not have TX complete indication from firmware to ath10k.
It will cut the cost of bus bandwidth of TX complete and make the TX
logic of firmware simpler, it results in significant performance
improvement on TX path.
Udp TX throughout is 130Mbps without this patch, and it arrives
400Mbps with this patch.
The downside of this patch is the command "iw wlan0 station dump" will
show 0 for "tx retries" and "tx failed" since all tx packet's status
is success.
This patch only effect sdio chip, it will not effect PCI, SNOC etc.
Tested with QCA6174 SDIO with firmware
WLAN.RMH.4.4.1-00017-QCARMSWPZ-1
Signed-off-by: Wen Gong <wgong@codeaurora.org>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20200212080415.31265-2-wgong@codeaurora.org
2020-04-07 05:12:30 +00:00
|
|
|
static inline int ath10k_hif_get_htt_tx_complete(struct ath10k *ar)
|
|
|
|
{
|
|
|
|
if (ar->hif.ops->get_htt_tx_complete)
|
|
|
|
return ar->hif.ops->get_htt_tx_complete(ar);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-06-12 17:52:10 +00:00
|
|
|
static inline int ath10k_hif_map_service_to_pipe(struct ath10k *ar,
|
|
|
|
u16 service_id,
|
2015-10-12 12:57:06 +00:00
|
|
|
u8 *ul_pipe, u8 *dl_pipe)
|
2013-06-12 17:52:10 +00:00
|
|
|
{
|
|
|
|
return ar->hif.ops->map_service_to_pipe(ar, service_id,
|
2015-10-12 12:57:06 +00:00
|
|
|
ul_pipe, dl_pipe);
|
2013-06-12 17:52:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void ath10k_hif_get_default_pipe(struct ath10k *ar,
|
|
|
|
u8 *ul_pipe, u8 *dl_pipe)
|
|
|
|
{
|
|
|
|
ar->hif.ops->get_default_pipe(ar, ul_pipe, dl_pipe);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void ath10k_hif_send_complete_check(struct ath10k *ar,
|
|
|
|
u8 pipe_id, int force)
|
|
|
|
{
|
2020-04-16 11:50:59 +00:00
|
|
|
if (ar->hif.ops->send_complete_check)
|
|
|
|
ar->hif.ops->send_complete_check(ar, pipe_id, force);
|
2013-06-12 17:52:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline u16 ath10k_hif_get_free_queue_number(struct ath10k *ar,
|
|
|
|
u8 pipe_id)
|
|
|
|
{
|
|
|
|
return ar->hif.ops->get_free_queue_number(ar, pipe_id);
|
|
|
|
}
|
|
|
|
|
2019-02-08 13:50:10 +00:00
|
|
|
static inline int ath10k_hif_power_up(struct ath10k *ar,
|
|
|
|
enum ath10k_firmware_mode fw_mode)
|
2013-07-16 07:38:50 +00:00
|
|
|
{
|
2019-02-08 13:50:10 +00:00
|
|
|
return ar->hif.ops->power_up(ar, fw_mode);
|
2013-07-16 07:38:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void ath10k_hif_power_down(struct ath10k *ar)
|
|
|
|
{
|
|
|
|
ar->hif.ops->power_down(ar);
|
|
|
|
}
|
|
|
|
|
2013-07-16 07:38:54 +00:00
|
|
|
static inline int ath10k_hif_suspend(struct ath10k *ar)
|
|
|
|
{
|
|
|
|
if (!ar->hif.ops->suspend)
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
|
|
return ar->hif.ops->suspend(ar);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int ath10k_hif_resume(struct ath10k *ar)
|
|
|
|
{
|
|
|
|
if (!ar->hif.ops->resume)
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
|
|
return ar->hif.ops->resume(ar);
|
|
|
|
}
|
|
|
|
|
2014-11-25 10:24:33 +00:00
|
|
|
static inline u32 ath10k_hif_read32(struct ath10k *ar, u32 address)
|
|
|
|
{
|
|
|
|
if (!ar->hif.ops->read32) {
|
|
|
|
ath10k_warn(ar, "hif read32 not supported\n");
|
|
|
|
return 0xdeaddead;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ar->hif.ops->read32(ar, address);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void ath10k_hif_write32(struct ath10k *ar,
|
|
|
|
u32 address, u32 data)
|
|
|
|
{
|
|
|
|
if (!ar->hif.ops->write32) {
|
|
|
|
ath10k_warn(ar, "hif write32 not supported\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ar->hif.ops->write32(ar, address, data);
|
|
|
|
}
|
|
|
|
|
2016-06-02 14:59:50 +00:00
|
|
|
static inline int ath10k_hif_fetch_cal_eeprom(struct ath10k *ar,
|
|
|
|
void **data,
|
|
|
|
size_t *data_len)
|
|
|
|
{
|
|
|
|
if (!ar->hif.ops->fetch_cal_eeprom)
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
|
|
return ar->hif.ops->fetch_cal_eeprom(ar, data, data_len);
|
|
|
|
}
|
|
|
|
|
2018-04-10 15:01:29 +00:00
|
|
|
static inline int ath10k_hif_get_target_info(struct ath10k *ar,
|
|
|
|
struct bmi_target_info *tgt_info)
|
|
|
|
{
|
|
|
|
if (!ar->hif.ops->get_target_info)
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
|
|
return ar->hif.ops->get_target_info(ar, tgt_info);
|
|
|
|
}
|
|
|
|
|
2019-06-03 15:14:52 +00:00
|
|
|
static inline int ath10k_hif_set_target_log_mode(struct ath10k *ar,
|
|
|
|
u8 fw_log_mode)
|
|
|
|
{
|
|
|
|
if (!ar->hif.ops->set_target_log_mode)
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
|
|
return ar->hif.ops->set_target_log_mode(ar, fw_log_mode);
|
|
|
|
}
|
2013-06-12 17:52:10 +00:00
|
|
|
#endif /* _HIF_H_ */
|