Commit 57725b5b authored by Kalle Valo's avatar Kalle Valo

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

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

ath11k

* a new driver for Qualcomm Wi-Fi 6 (IEEE 802.11ax) devices

ath10k

* significant improvements on receive throughput and firmware download
  with SDIO bus

* report signal strength for each chain also on SDIO

* set max mtu to 1500 on SDIO devices
parents e42617b8 2dc01659
......@@ -13644,6 +13644,13 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
S: Supported
F: drivers/net/wireless/ath/ath10k/
QUALCOMM ATHEROS ATH11K WIRELESS DRIVER
M: Kalle Valo <kvalo@codeaurora.org>
L: ath11k@lists.infradead.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
S: Supported
F: drivers/net/wireless/ath/ath11k/
QUALCOMM ATHEROS ATH9K WIRELESS DRIVER
M: QCA ath9k Development <ath9k-devel@qca.qualcomm.com>
L: linux-wireless@vger.kernel.org
......
......@@ -62,5 +62,6 @@ source "drivers/net/wireless/ath/ar5523/Kconfig"
source "drivers/net/wireless/ath/wil6210/Kconfig"
source "drivers/net/wireless/ath/ath10k/Kconfig"
source "drivers/net/wireless/ath/wcn36xx/Kconfig"
source "drivers/net/wireless/ath/ath11k/Kconfig"
endif
......@@ -7,6 +7,7 @@ obj-$(CONFIG_AR5523) += ar5523/
obj-$(CONFIG_WIL6210) += wil6210/
obj-$(CONFIG_ATH10K) += ath10k/
obj-$(CONFIG_WCN36XX) += wcn36xx/
obj-$(CONFIG_ATH11K) += ath11k/
obj-$(CONFIG_ATH_COMMON) += ath.o
......
......@@ -346,6 +346,52 @@ int ath10k_bmi_execute(struct ath10k *ar, u32 address, u32 param, u32 *result)
return 0;
}
static int ath10k_bmi_lz_data_large(struct ath10k *ar, const void *buffer, u32 length)
{
struct bmi_cmd *cmd;
u32 hdrlen = sizeof(cmd->id) + sizeof(cmd->lz_data);
u32 txlen;
int ret;
size_t buf_len;
ath10k_dbg(ar, ATH10K_DBG_BMI, "large bmi lz data buffer 0x%pK length %d\n",
buffer, length);
if (ar->bmi.done_sent) {
ath10k_warn(ar, "command disallowed\n");
return -EBUSY;
}
buf_len = sizeof(*cmd) + BMI_MAX_LARGE_DATA_SIZE - BMI_MAX_DATA_SIZE;
cmd = kzalloc(buf_len, GFP_KERNEL);
if (!cmd)
return -ENOMEM;
while (length) {
txlen = min(length, BMI_MAX_LARGE_DATA_SIZE - hdrlen);
WARN_ON_ONCE(txlen & 3);
cmd->id = __cpu_to_le32(BMI_LZ_DATA);
cmd->lz_data.len = __cpu_to_le32(txlen);
memcpy(cmd->lz_data.payload, buffer, txlen);
ret = ath10k_hif_exchange_bmi_msg(ar, cmd, hdrlen + txlen,
NULL, NULL);
if (ret) {
ath10k_warn(ar, "unable to write to the device\n");
return ret;
}
buffer += txlen;
length -= txlen;
}
kfree(cmd);
return 0;
}
int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length)
{
struct bmi_cmd cmd;
......@@ -430,7 +476,11 @@ int ath10k_bmi_fast_download(struct ath10k *ar,
if (trailer_len > 0)
memcpy(trailer, buffer + head_len, trailer_len);
ret = ath10k_bmi_lz_data(ar, buffer, head_len);
if (ar->hw_params.bmi_large_size_download)
ret = ath10k_bmi_lz_data_large(ar, buffer, head_len);
else
ret = ath10k_bmi_lz_data(ar, buffer, head_len);
if (ret)
return ret;
......
......@@ -45,6 +45,15 @@
sizeof(u32) + \
sizeof(u32))
/* Maximum data size used for large BMI transfers */
#define BMI_MAX_LARGE_DATA_SIZE 2048
/* len = cmd + addr + length */
#define BMI_MAX_LARGE_CMDBUF_SIZE (BMI_MAX_LARGE_DATA_SIZE + \
sizeof(u32) + \
sizeof(u32) + \
sizeof(u32))
/* BMI Commands */
enum bmi_cmd_id {
......@@ -258,6 +267,7 @@ int ath10k_bmi_write_memory(struct ath10k *ar, u32 address,
int ath10k_bmi_execute(struct ath10k *ar, u32 address, u32 param, u32 *result);
int ath10k_bmi_lz_stream_start(struct ath10k *ar, u32 address);
int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length);
int ath10k_bmi_fast_download(struct ath10k *ar, u32 address,
const void *buffer, u32 length);
int ath10k_bmi_read_soc_reg(struct ath10k *ar, u32 address, u32 *reg_val);
......
......@@ -189,6 +189,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.num_wds_entries = 0x20,
.uart_pin_workaround = true,
.tx_stats_over_pktlog = false,
.bmi_large_size_download = true,
},
{
.id = QCA6174_HW_2_1_VERSION,
......@@ -714,18 +715,6 @@ static int ath10k_init_sdio(struct ath10k *ar, enum ath10k_firmware_mode mode)
if (ret)
return ret;
/* Explicitly set fwlog prints to zero as target may turn it on
* based on scratch registers.
*/
ret = ath10k_bmi_read32(ar, hi_option_flag, &param);
if (ret)
return ret;
param |= HI_OPTION_DISABLE_DBGLOG;
ret = ath10k_bmi_write32(ar, hi_option_flag, param);
if (ret)
return ret;
return 0;
}
......@@ -3231,6 +3220,8 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
init_waitqueue_head(&ar->htt.empty_tx_wq);
init_waitqueue_head(&ar->wmi.tx_credits_wq);
skb_queue_head_init(&ar->htt.rx_indication_head);
init_completion(&ar->offchan_tx_completed);
INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work);
skb_queue_head_init(&ar->offchan_tx_queue);
......
......@@ -124,6 +124,7 @@ struct ath10k_skb_cb {
struct ath10k_skb_rxcb {
dma_addr_t paddr;
struct hlist_node hlist;
u8 eid;
};
static inline struct ath10k_skb_cb *ATH10K_SKB_CB(struct sk_buff *skb)
......@@ -1180,6 +1181,7 @@ struct ath10k {
struct {
/* protected by data_lock */
u32 rx_crc_err_drop;
u32 fw_crash_counter;
u32 fw_warm_reset_counter;
u32 fw_cold_reset_counter;
......
......@@ -1094,6 +1094,7 @@ static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
"d_rts_good",
"d_tx_power", /* in .5 dbM I think */
"d_rx_crc_err", /* fcs_bad */
"d_rx_crc_err_drop", /* frame with FCS error, dropped late in kernel */
"d_no_beacon",
"d_tx_mpdus_queued",
"d_tx_msdu_queued",
......@@ -1193,6 +1194,7 @@ void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
data[i++] = pdev_stats->rts_good;
data[i++] = pdev_stats->chan_tx_power;
data[i++] = pdev_stats->fcs_bad;
data[i++] = ar->stats.rx_crc_err_drop;
data[i++] = pdev_stats->no_beacons;
data[i++] = pdev_stats->mpdu_enqued;
data[i++] = pdev_stats->msdu_enqued;
......
......@@ -270,7 +270,7 @@ ath10k_htc_process_lookahead_bundle(struct ath10k_htc *htc,
struct ath10k *ar = htc->ar;
int bundle_cnt = len / sizeof(*report);
if (!bundle_cnt || (bundle_cnt > HTC_HOST_MAX_MSG_PER_RX_BUNDLE)) {
if (!bundle_cnt || (bundle_cnt > htc->max_msgs_per_htc_bundle)) {
ath10k_warn(ar, "Invalid lookahead bundle count: %d\n",
bundle_cnt);
return -EINVAL;
......@@ -800,8 +800,8 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
&ep->ul_pipe_id,
&ep->dl_pipe_id);
if (status) {
ath10k_warn(ar, "unsupported HTC service id: %d\n",
ep->service_id);
ath10k_dbg(ar, ATH10K_DBG_BOOT, "unsupported HTC service id: %d\n",
ep->service_id);
return status;
}
......@@ -878,8 +878,8 @@ static bool ath10k_htc_pktlog_svc_supported(struct ath10k *ar)
&ul_pipe_id,
&dl_pipe_id);
if (status) {
ath10k_warn(ar, "unsupported HTC service id: %d\n",
ATH10K_HTC_SVC_ID_HTT_LOG_MSG);
ath10k_dbg(ar, ATH10K_DBG_BOOT, "unsupported HTC pktlog service id: %d\n",
ATH10K_HTC_SVC_ID_HTT_LOG_MSG);
return false;
}
......
......@@ -12,6 +12,7 @@
#include <linux/bug.h>
#include <linux/skbuff.h>
#include <linux/timer.h>
#include <linux/bitfield.h>
struct ath10k;
......@@ -39,7 +40,7 @@ struct ath10k;
* 4-byte aligned.
*/
#define HTC_HOST_MAX_MSG_PER_RX_BUNDLE 8
#define HTC_HOST_MAX_MSG_PER_RX_BUNDLE 32
enum ath10k_htc_tx_flags {
ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE = 0x01,
......@@ -49,9 +50,27 @@ enum ath10k_htc_tx_flags {
enum ath10k_htc_rx_flags {
ATH10K_HTC_FLAGS_RECV_1MORE_BLOCK = 0x01,
ATH10K_HTC_FLAG_TRAILER_PRESENT = 0x02,
ATH10K_HTC_FLAG_BUNDLE_MASK = 0xF0
};
#define ATH10K_HTC_FLAG_BUNDLE_MASK GENMASK(7, 4)
/* bits 2-3 are for extra bundle count bits 4-5 */
#define ATH10K_HTC_BUNDLE_EXTRA_MASK GENMASK(3, 2)
#define ATH10K_HTC_BUNDLE_EXTRA_SHIFT 4
static inline unsigned int ath10k_htc_get_bundle_count(u8 max_msgs, u8 flags)
{
unsigned int count, extra_count = 0;
count = FIELD_GET(ATH10K_HTC_FLAG_BUNDLE_MASK, flags);
if (max_msgs > 16)
extra_count = FIELD_GET(ATH10K_HTC_BUNDLE_EXTRA_MASK, flags) <<
ATH10K_HTC_BUNDLE_EXTRA_SHIFT;
return count + extra_count;
}
struct ath10k_htc_hdr {
u8 eid; /* @enum ath10k_htc_ep_id */
u8 flags; /* @enum ath10k_htc_tx_flags, ath10k_htc_rx_flags */
......
......@@ -1869,6 +1869,8 @@ struct ath10k_htt {
struct ath10k *ar;
enum ath10k_htc_ep_id eid;
struct sk_buff_head rx_indication_head;
u8 target_version_major;
u8 target_version_minor;
struct completion target_version_received;
......@@ -2283,6 +2285,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu);
void ath10k_htt_rx_pktlog_completion_handler(struct ath10k *ar,
struct sk_buff *skb);
int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget);
int ath10k_htt_rx_hl_indication(struct ath10k *ar, int budget);
void ath10k_htt_set_tx_ops(struct ath10k_htt *htt);
void ath10k_htt_set_rx_ops(struct ath10k_htt *htt);
#endif
......@@ -1285,6 +1285,13 @@ static void ath10k_process_rx(struct ath10k *ar, struct sk_buff *skb)
status = IEEE80211_SKB_RXCB(skb);
if (!(ar->filter_flags & FIF_FCSFAIL) &&
status->flag & RX_FLAG_FAILED_FCS_CRC) {
ar->stats.rx_crc_err_drop++;
dev_kfree_skb_any(skb);
return;
}
ath10k_dbg(ar, ATH10K_DBG_DATA,
"rx skb %pK len %u peer %pM %s %s sn %u %s%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,
......@@ -2196,8 +2203,8 @@ static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt,
HTT_RX_IND_MPDU_STATUS_OK &&
mpdu_ranges->mpdu_range_status !=
HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR) {
ath10k_warn(ar, "MPDU range status: %d\n",
mpdu_ranges->mpdu_range_status);
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt mpdu_range_status %d\n",
mpdu_ranges->mpdu_range_status);
goto err;
}
......@@ -2235,8 +2242,10 @@ static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt,
hdr = (struct ieee80211_hdr *)skb->data;
qos = ieee80211_is_data_qos(hdr->frame_control);
rx_status = IEEE80211_SKB_RXCB(skb);
rx_status->chains |= BIT(0);
memset(rx_status, 0, sizeof(*rx_status));
if (rx->ppdu.combined_rssi == 0) {
/* SDIO firmware does not provide signal */
rx_status->signal = 0;
......@@ -2350,7 +2359,10 @@ static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt,
memcpy(skb->data + offset, &qos_ctrl, IEEE80211_QOS_CTL_LEN);
}
ieee80211_rx_ni(ar->hw, skb);
if (ar->napi.dev)
ieee80211_rx_napi(ar->hw, NULL, skb, &ar->napi);
else
ieee80211_rx_ni(ar->hw, skb);
/* We have delivered the skb to the upper layers (mac80211) so we
* must not free it.
......@@ -3751,14 +3763,12 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
break;
}
case HTT_T2H_MSG_TYPE_RX_IND:
if (ar->bus_param.dev_type == ATH10K_DEV_TYPE_HL)
return ath10k_htt_rx_proc_rx_ind_hl(htt,
&resp->rx_ind_hl,
skb,
HTT_RX_PN_CHECK,
HTT_RX_NON_TKIP_MIC);
else
if (ar->bus_param.dev_type != ATH10K_DEV_TYPE_HL) {
ath10k_htt_rx_proc_rx_ind_ll(htt, &resp->rx_ind);
} else {
skb_queue_tail(&htt->rx_indication_head, skb);
return false;
}
break;
case HTT_T2H_MSG_TYPE_PEER_MAP: {
struct htt_peer_map_event ev = {
......@@ -3948,6 +3958,37 @@ static int ath10k_htt_rx_deliver_msdu(struct ath10k *ar, int quota, int budget)
return quota;
}
int ath10k_htt_rx_hl_indication(struct ath10k *ar, int budget)
{
struct htt_resp *resp;
struct ath10k_htt *htt = &ar->htt;
struct sk_buff *skb;
bool release;
int quota;
for (quota = 0; quota < budget; quota++) {
skb = skb_dequeue(&htt->rx_indication_head);
if (!skb)
break;
resp = (struct htt_resp *)skb->data;
release = ath10k_htt_rx_proc_rx_ind_hl(htt,
&resp->rx_ind_hl,
skb,
HTT_RX_PN_CHECK,
HTT_RX_NON_TKIP_MIC);
if (release)
dev_kfree_skb_any(skb);
ath10k_dbg(ar, ATH10K_DBG_HTT, "rx indication poll pending count:%d\n",
skb_queue_len(&htt->rx_indication_head));
}
return quota;
}
EXPORT_SYMBOL(ath10k_htt_rx_hl_indication);
int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget)
{
struct ath10k_htt *htt = &ar->htt;
......
......@@ -613,6 +613,9 @@ struct ath10k_hw_params {
/* target supporting fw download via diag ce */
bool fw_diag_ce_download;
/* target supporting fw download via large size BMI */
bool bmi_large_size_download;
/* need to set uart pin if disable uart print, workaround for a
* firmware bug
*/
......
......@@ -6329,6 +6329,9 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (sta && sta->tdls)
ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
ar->wmi.peer_param->authorize, 1);
else if (sta && cmd == SET_KEY && (key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
ath10k_wmi_peer_set_param(ar, arvif->vdev_id, peer_addr,
ar->wmi.peer_param->authorize, 1);
exit:
mutex_unlock(&ar->conf_mutex);
......@@ -8908,6 +8911,7 @@ int ath10k_mac_register(struct ath10k *ar)
WMI_PNO_MAX_SCHED_SCAN_PLAN_INT;
ar->hw->wiphy->max_sched_scan_plan_iterations =
WMI_PNO_MAX_SCHED_SCAN_PLAN_ITRNS;
ar->hw->wiphy->features |= NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
}
ar->hw->vif_data_size = sizeof(struct ath10k_vif);
......
......@@ -279,7 +279,15 @@ static int ath10k_qmi_bdf_dnld_send_sync(struct ath10k_qmi *qmi)
if (ret < 0)
goto out;
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
/* end = 1 triggers a CRC check on the BDF. If this fails, we
* get a QMI_ERR_MALFORMED_MSG_V01 error, but the FW is still
* willing to use the BDF. For some platforms, all the valid
* released BDFs fail this CRC check, so attempt to detect this
* scenario and treat it as non-fatal.
*/
if (resp.resp.result != QMI_RESULT_SUCCESS_V01 &&
!(req->end == 1 &&
resp.resp.result == QMI_ERR_MALFORMED_MSG_V01)) {
ath10k_err(ar, "failed to download board data file: %d\n",
resp.resp.error);
ret = -EINVAL;
......@@ -635,7 +643,9 @@ static int ath10k_qmi_host_cap_send_sync(struct ath10k_qmi *qmi)
if (ret < 0)
goto out;
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
/* older FW didn't support this request, which is not fatal */
if (resp.resp.result != QMI_RESULT_SUCCESS_V01 &&
resp.resp.error != QMI_ERR_NOT_SUPPORTED_V01) {
ath10k_err(ar, "host capability request rejected: %d\n", resp.resp.error);
ret = -EINVAL;
goto out;
......
This diff is collapsed.
......@@ -89,10 +89,10 @@
* to the maximum value (HTC_HOST_MAX_MSG_PER_RX_BUNDLE).
*
* in this case the driver must allocate
* (HTC_HOST_MAX_MSG_PER_RX_BUNDLE * HTC_HOST_MAX_MSG_PER_RX_BUNDLE) skb's.
* (HTC_HOST_MAX_MSG_PER_RX_BUNDLE * 2) skb's.
*/
#define ATH10K_SDIO_MAX_RX_MSGS \
(HTC_HOST_MAX_MSG_PER_RX_BUNDLE * HTC_HOST_MAX_MSG_PER_RX_BUNDLE)
(HTC_HOST_MAX_MSG_PER_RX_BUNDLE * 2)
#define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL 0x00000868u
#define ATH10K_FIFO_TIMEOUT_AND_CHIP_CONTROL_DISABLE_SLEEP_OFF 0xFFFEFFFF
......@@ -126,7 +126,6 @@ struct ath10k_sdio_rx_data {
bool part_of_bundle;
bool last_in_bundle;
bool trailer_only;
int status;
};
struct ath10k_sdio_irq_proc_regs {
......@@ -138,8 +137,8 @@ struct ath10k_sdio_irq_proc_regs {
u8 rx_lookahead_valid;
u8 host_int_status2;
u8 gmbox_rx_avail;
__le32 rx_lookahead[2];
__le32 rx_gmbox_lookahead_alias[2];
__le32 rx_lookahead[2 * ATH10K_HIF_MBOX_NUM_MAX];
__le32 int_status_enable;
};
struct ath10k_sdio_irq_enable_regs {
......@@ -187,6 +186,9 @@ struct ath10k_sdio {
struct ath10k_sdio_bus_request bus_req[ATH10K_SDIO_BUS_REQUEST_MAX_NUM];
/* free list of bus requests */
struct list_head bus_req_freeq;
struct sk_buff_head rx_head;
/* protects access to bus_req_freeq */
spinlock_t lock;
......@@ -196,6 +198,13 @@ struct ath10k_sdio {
struct ath10k *ar;
struct ath10k_sdio_irq_data irq_data;
/* temporary buffer for sdio read.
* It is allocated when probe, and used for receive bundled packets,
* the read for bundled packets is not parallel, so it does not need
* protected.
*/
u8 *vsg_buffer;
/* temporary buffer for BMI requests */
u8 *bmi_buf;
......@@ -206,6 +215,8 @@ struct ath10k_sdio {
struct list_head wr_asyncq;
/* protects access to wr_asyncq */
spinlock_t wr_async_lock;
struct work_struct async_work_rx;
};
static inline struct ath10k_sdio *ath10k_sdio_priv(struct ath10k *ar)
......
......@@ -1563,13 +1563,16 @@ static int ath10k_snoc_probe(struct platform_device *pdev)
ret = ath10k_qmi_init(ar, msa_size);
if (ret) {
ath10k_warn(ar, "failed to register wlfw qmi client: %d\n", ret);
goto err_core_destroy;
goto err_power_off;
}
ath10k_dbg(ar, ATH10K_DBG_SNOC, "snoc probe\n");
return 0;
err_power_off:
ath10k_hw_power_off(ar);
err_free_irq:
ath10k_snoc_free_irq(ar);
......
......@@ -841,7 +841,7 @@ static int ath10k_wmi_tlv_op_pull_mgmt_rx_ev(struct ath10k *ar,
const struct wmi_tlv_mgmt_rx_ev *ev;
const u8 *frame;
u32 msdu_len;
int ret;
int ret, i;
tb = ath10k_wmi_tlv_parse_alloc(ar, skb->data, skb->len, GFP_ATOMIC);
if (IS_ERR(tb)) {
......@@ -865,6 +865,9 @@ static int ath10k_wmi_tlv_op_pull_mgmt_rx_ev(struct ath10k *ar,
arg->phy_mode = ev->phy_mode;
arg->rate = ev->rate;
for (i = 0; i < ARRAY_SIZE(ev->rssi); i++)
arg->rssi[i] = ev->rssi[i];
msdu_len = __le32_to_cpu(arg->buf_len);
if (skb->len < (frame - skb->data) + msdu_len) {
......@@ -3707,6 +3710,7 @@ ath10k_wmi_tlv_op_gen_config_pno_start(struct ath10k *ar,
struct wmi_tlv *tlv;
struct sk_buff *skb;
__le32 *channel_list;
u16 tlv_len;
size_t len;
void *ptr;
u32 i;
......@@ -3764,10 +3768,12 @@ ath10k_wmi_tlv_op_gen_config_pno_start(struct ath10k *ar,
/* nlo_configured_parameters(nlo_list) */
cmd->no_of_ssids = __cpu_to_le32(min_t(u8, pno->uc_networks_count,
WMI_NLO_MAX_SSIDS));
tlv_len = __le32_to_cpu(cmd->no_of_ssids) *
sizeof(struct nlo_configured_parameters);
tlv = ptr;
tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
tlv->len = __cpu_to_le16(len);
tlv->len = __cpu_to_le16(tlv_len);
ptr += sizeof(*tlv);
nlo_list = ptr;
......
......@@ -2463,10 +2463,10 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
u32 rx_status;
u32 channel;
u32 phy_mode;
u32 snr;
u32 snr, rssi;
u32 rate;
u16 fc;
int ret;
int ret, i;
ret = ath10k_wmi_pull_mgmt_rx(ar, skb, &arg);
if (ret) {
......@@ -2525,6 +2525,20 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
status->freq = ieee80211_channel_to_frequency(channel, status->band);
status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR;
BUILD_BUG_ON(ARRAY_SIZE(status->chain_signal) != ARRAY_SIZE(arg.rssi));
for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) {
status->chains &= ~BIT(i);
rssi = __le32_to_cpu(arg.rssi[i]);
ath10k_dbg(ar, ATH10K_DBG_MGMT, "mgmt rssi[%d]:%d\n", i, arg.rssi[i]);
if (rssi != ATH10K_INVALID_RSSI && rssi != 0) {
status->chain_signal[i] = ATH10K_DEFAULT_NOISE_FLOOR + rssi;
status->chains |= BIT(i);
}
}
status->rate_idx = ath10k_mac_bitrate_to_idx(sband, rate / 100);
hdr = (struct ieee80211_hdr *)skb->data;
......
......@@ -6786,6 +6786,7 @@ struct wmi_peer_delete_resp_ev_arg {
struct wmi_mac_addr peer_addr;
};
#define WMI_MGMT_RX_NUM_RSSI 4
struct wmi_mgmt_rx_ev_arg {
__le32 channel;
__le32 snr;
......@@ -6794,6 +6795,7 @@ struct wmi_mgmt_rx_ev_arg {
__le32 buf_len;
__le32 status; /* %WMI_RX_STATUS_ */
struct wmi_mgmt_rx_ext_info ext_info;
__le32 rssi[WMI_MGMT_RX_NUM_RSSI];
};
struct wmi_ch_info_ev_arg {
......
# SPDX-License-Identifier: BSD-3-Clause-Clear
config ATH11K
tristate "Qualcomm Technologies 802.11ax chipset support"
depends on MAC80211 && HAS_DMA
depends on REMOTEPROC
depends on ARCH_QCOM || COMPILE_TEST
select ATH_COMMON
select QCOM_QMI_HELPERS
---help---
This module adds support for Qualcomm Technologies 802.11ax family of
chipsets.
If you choose to build a module, it'll be called ath11k.
config ATH11K_DEBUG
bool "QCA ath11k debugging"
depends on ATH11K
---help---
Enables debug support
If unsure, say Y to make it easier to debug problems.
config ATH11K_DEBUGFS
bool "QCA ath11k debugfs support"
depends on ATH11K && DEBUG_FS
---help---
Enable ath11k debugfs support
If unsure, say Y to make it easier to debug problems.
config ATH11K_TRACING
bool "ath11k tracing support"
depends on ATH11K && EVENT_TRACING
---help---
Select this to use ath11k tracing infrastructure.
# SPDX-License-Identifier: BSD-3-Clause-Clear
obj-$(CONFIG_ATH11K) += ath11k.o
ath11k-y += core.o \
hal.o \
hal_tx.o \
hal_rx.o \
ahb.o \
wmi.o \
mac.o \
reg.o \
htc.o \
qmi.o \
dp.o \
dp_tx.o \
dp_rx.o \
debug.o \
ce.o \
peer.o
ath11k-$(CONFIG_ATH11K_DEBUGFS) += debug_htt_stats.o
ath11k-$(CONFIG_MAC80211_DEBUGFS) += debugfs_sta.o
ath11k-$(CONFIG_NL80211_TESTMODE) += testmode.o
ath11k-$(CONFIG_ATH11K_TRACING) += trace.o
# for tracing framework to find trace.h
CFLAGS_trace.o := -I$(src)
This diff is collapsed.
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
*/
#ifndef ATH11K_AHB_H
#define ATH11K_AHB_H
#include "core.h"
#define ATH11K_AHB_RECOVERY_TIMEOUT (3 * HZ)
struct ath11k_base;
static inline u32 ath11k_ahb_read32(struct ath11k_base *ab, u32 offset)
{
return ioread32(ab->mem + offset);
}
static inline void ath11k_ahb_write32(struct ath11k_base *ab, u32 offset, u32 value)
{
iowrite32(value, ab->mem + offset);
}
void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab);
void ath11k_ahb_ext_irq_disable(struct ath11k_base *ab);
int ath11k_ahb_start(struct ath11k_base *ab);
void ath11k_ahb_stop(struct ath11k_base *ab);
int ath11k_ahb_power_up(struct ath11k_base *ab);
void ath11k_ahb_power_down(struct ath11k_base *ab);
int ath11k_ahb_map_service_to_pipe(struct ath11k_base *ab, u16 service_id,
u8 *ul_pipe, u8 *dl_pipe);
int ath11k_ahb_init(void);
void ath11k_ahb_exit(void);
#endif
This diff is collapsed.
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
/*
* Copyright (c) 2018-2019 The Linux Foundation. All rights reserved.
*/
#ifndef ATH11K_CE_H
#define ATH11K_CE_H
#define CE_COUNT 12
/* Byte swap data words */
#define CE_ATTR_BYTE_SWAP_DATA 2
/* no interrupt on copy completion */
#define CE_ATTR_DIS_INTR 8
/* Host software's Copy Engine configuration. */
#ifdef __BIG_ENDIAN
#define CE_ATTR_FLAGS CE_ATTR_BYTE_SWAP_DATA
#else
#define CE_ATTR_FLAGS 0
#endif
/* Threshold to poll for tx completion in case of Interrupt disabled CE's */
#define ATH11K_CE_USAGE_THRESHOLD 32
void ath11k_ce_byte_swap(void *mem, u32 len);
/*
* Directions for interconnect pipe configuration.
* These definitions may be used during configuration and are shared
* between Host and Target.
*
* Pipe Directions are relative to the Host, so PIPEDIR_IN means
* "coming IN over air through Target to Host" as with a WiFi Rx operation.
* Conversely, PIPEDIR_OUT means "going OUT from Host through Target over air"
* as with a WiFi Tx operation. This is somewhat awkward for the "middle-man"
* Target since things that are "PIPEDIR_OUT" are coming IN to the Target
* over the interconnect.
*/
#define PIPEDIR_NONE 0
#define PIPEDIR_IN 1 /* Target-->Host, WiFi Rx direction */
#define PIPEDIR_OUT 2 /* Host->Target, WiFi Tx direction */
#define PIPEDIR_INOUT 3 /* bidirectional */
#define PIPEDIR_INOUT_H2H 4 /* bidirectional, host to host */
/* CE address/mask */
#define CE_HOST_IE_ADDRESS 0x00A1803C
#define CE_HOST_IE_2_ADDRESS 0x00A18040
#define CE_HOST_IE_3_ADDRESS CE_HOST_IE_ADDRESS
#define CE_HOST_IE_3_SHIFT 0xC
#define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) & (nentries_mask))
#define ATH11K_CE_RX_POST_RETRY_JIFFIES 50
struct ath11k_base;
/*
* Establish a mapping between a service/direction and a pipe.
* Configuration information for a Copy Engine pipe and services.
* Passed from Host to Target through QMI message and must be in
* little endian format.
*/
struct service_to_pipe {
__le32 service_id;
__le32 pipedir;
__le32 pipenum;
};
/*
* Configuration information for a Copy Engine pipe.
* Passed from Host to Target through QMI message during startup (one per CE).
*
* NOTE: Structure is shared between Host software and Target firmware!
*/
struct ce_pipe_config {
__le32 pipenum;
__le32 pipedir;
__le32 nentries;
__le32 nbytes_max;
__le32 flags;
__le32 reserved;
};
struct ce_attr {
/* CE_ATTR_* values */
unsigned int flags;
/* #entries in source ring - Must be a power of 2 */
unsigned int src_nentries;
/*
* Max source send size for this CE.
* This is also the minimum size of a destination buffer.
*/
unsigned int src_sz_max;
/* #entries in destination ring - Must be a power of 2 */
unsigned int dest_nentries;
void (*recv_cb)(struct ath11k_base *, struct sk_buff *);
};
#define CE_DESC_RING_ALIGN 8
struct ath11k_ce_ring {
/* Number of entries in this ring; must be power of 2 */
unsigned int nentries;
unsigned int nentries_mask;
/* For dest ring, this is the next index to be processed
* by software after it was/is received into.
*
* For src ring, this is the last descriptor that was sent
* and completion processed by software.
*
* Regardless of src or dest ring, this is an invariant
* (modulo ring size):
* write index >= read index >= sw_index
*/
unsigned int sw_index;
/* cached copy */
unsigned int write_index;
/* Start of DMA-coherent area reserved for descriptors */
/* Host address space */
void *base_addr_owner_space_unaligned;
/* CE address space */
u32 base_addr_ce_space_unaligned;
/* Actual start of descriptors.
* Aligned to descriptor-size boundary.
* Points into reserved DMA-coherent area, above.
*/
/* Host address space */
void *base_addr_owner_space;
/* CE address space */
u32 base_addr_ce_space;
/* HAL ring id */
u32 hal_ring_id;
/* keep last */
struct sk_buff *skb[0];
};
struct ath11k_ce_pipe {
struct ath11k_base *ab;
u16 pipe_num;
unsigned int attr_flags;
unsigned int buf_sz;
unsigned int rx_buf_needed;
void (*send_cb)(struct ath11k_ce_pipe *);
void (*recv_cb)(struct ath11k_base *, struct sk_buff *);
struct tasklet_struct intr_tq;
struct ath11k_ce_ring *src_ring;
struct ath11k_ce_ring *dest_ring;
struct ath11k_ce_ring *status_ring;
};
struct ath11k_ce {
struct ath11k_ce_pipe ce_pipe[CE_COUNT];
/* Protects rings of all ce pipes */
spinlock_t ce_lock;
};
void ath11k_ce_cleanup_pipes(struct ath11k_base *ab);
void ath11k_ce_rx_replenish_retry(struct timer_list *t);
void ath11k_ce_per_engine_service(struct ath11k_base *ab, u16 ce_id);
int ath11k_ce_send(struct ath11k_base *ab, struct sk_buff *skb, u8 pipe_id,
u16 transfer_id);
void ath11k_ce_rx_post_buf(struct ath11k_base *ab);
int ath11k_ce_init_pipes(struct ath11k_base *ab);
int ath11k_ce_alloc_pipes(struct ath11k_base *ab);
void ath11k_ce_free_pipes(struct ath11k_base *ab);
int ath11k_ce_get_attr_flags(int ce_id);
void ath11k_ce_poll_send_completed(struct ath11k_base *ab, u8 pipe_id);
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2019 The Linux Foundation. All rights reserved.
*/
#include <linux/module.h>
#define CREATE_TRACE_POINTS
#include "trace.h"
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment