提交 bddf5904 编写于 作者: D David S. Miller

Merge tag 'wireless-drivers-next-for-davem-2016-04-11' of...

Merge tag 'wireless-drivers-next-for-davem-2016-04-11' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next

Kalle Valo says:

====================
wireless-drivers patches for 4.7

Major changes:

iwlwifi

* support for Link Quality measurement
* more work 9000 devices and MSIx
* continuation of the Dynamic Queue Allocation work
* make the paging less memory hungry
* 9000 new Rx path
* removal of IWLWIFI_UAPSD Kconfig option

ath10k

* implement push-pull tx model using mac80211 software queuing support
* enable scan in AP mode (NL80211_FEATURE_AP_SCAN)

wil6210

* add basic PBSS (Personal Basic Service Set) support
* add initial P2P support
* add oob_mode module parameter
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
...@@ -5,12 +5,18 @@ Required properties: ...@@ -5,12 +5,18 @@ Required properties:
* "qcom,ath10k" * "qcom,ath10k"
* "qcom,ipq4019-wifi" * "qcom,ipq4019-wifi"
PCI based devices uses compatible string "qcom,ath10k" and takes only PCI based devices uses compatible string "qcom,ath10k" and takes calibration
calibration data via "qcom,ath10k-calibration-data". Rest of the properties data along with board specific data via "qcom,ath10k-calibration-data".
are not applicable for PCI based devices. Rest of the properties are not applicable for PCI based devices.
AHB based devices (i.e. ipq4019) uses compatible string "qcom,ipq4019-wifi" AHB based devices (i.e. ipq4019) uses compatible string "qcom,ipq4019-wifi"
and also uses most of the properties defined in this doc. and also uses most of the properties defined in this doc (except
"qcom,ath10k-calibration-data"). It uses "qcom,ath10k-pre-calibration-data"
to carry pre calibration data.
In general, entry "qcom,ath10k-pre-calibration-data" and
"qcom,ath10k-calibration-data" conflict with each other and only one
can be provided per device.
Optional properties: Optional properties:
- reg: Address and length of the register set for the device. - reg: Address and length of the register set for the device.
...@@ -35,8 +41,11 @@ Optional properties: ...@@ -35,8 +41,11 @@ Optional properties:
- qcom,msi_addr: MSI interrupt address. - qcom,msi_addr: MSI interrupt address.
- qcom,msi_base: Base value to add before writing MSI data into - qcom,msi_base: Base value to add before writing MSI data into
MSI address register. MSI address register.
- qcom,ath10k-calibration-data : calibration data as an array, the - qcom,ath10k-calibration-data : calibration data + board specific data
length can vary between hw versions as an array, the length can vary between
hw versions.
- qcom,ath10k-pre-calibration-data : pre calibration data as an array,
the length can vary between hw versions.
Example (to supply the calibration data alone): Example (to supply the calibration data alone):
...@@ -105,5 +114,5 @@ wifi0: wifi@a000000 { ...@@ -105,5 +114,5 @@ wifi0: wifi@a000000 {
"legacy"; "legacy";
qcom,msi_addr = <0x0b006040>; qcom,msi_addr = <0x0b006040>;
qcom,msi_base = <0x40>; qcom,msi_base = <0x40>;
qcom,ath10k-calibration-data = [ 01 02 03 ... ]; qcom,ath10k-pre-calibration-data = [ 01 02 03 ... ];
}; };
...@@ -411,7 +411,8 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) ...@@ -411,7 +411,8 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
lockdep_assert_held(&ar_pci->ce_lock); lockdep_assert_held(&ar_pci->ce_lock);
if (CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0) if ((pipe->id != 5) &&
CE_RING_DELTA(nentries_mask, write_index, sw_index - 1) == 0)
return -ENOSPC; return -ENOSPC;
desc->addr = __cpu_to_le32(paddr); desc->addr = __cpu_to_le32(paddr);
...@@ -425,6 +426,19 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) ...@@ -425,6 +426,19 @@ int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
return 0; return 0;
} }
void ath10k_ce_rx_update_write_idx(struct ath10k_ce_pipe *pipe, u32 nentries)
{
struct ath10k *ar = pipe->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;
u32 ctrl_addr = pipe->ctrl_addr;
write_index = CE_RING_IDX_ADD(nentries_mask, write_index, nentries);
ath10k_ce_dest_ring_write_index_set(ar, ctrl_addr, write_index);
dest_ring->write_index = write_index;
}
int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
{ {
struct ath10k *ar = pipe->ar; struct ath10k *ar = pipe->ar;
...@@ -444,14 +458,10 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) ...@@ -444,14 +458,10 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
*/ */
int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
void **per_transfer_contextp, void **per_transfer_contextp,
u32 *bufferp, unsigned int *nbytesp)
unsigned int *nbytesp,
unsigned int *transfer_idp,
unsigned int *flagsp)
{ {
struct ath10k_ce_ring *dest_ring = ce_state->dest_ring; struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
unsigned int nentries_mask = dest_ring->nentries_mask; unsigned int nentries_mask = dest_ring->nentries_mask;
struct ath10k *ar = ce_state->ar;
unsigned int sw_index = dest_ring->sw_index; unsigned int sw_index = dest_ring->sw_index;
struct ce_desc *base = dest_ring->base_addr_owner_space; struct ce_desc *base = dest_ring->base_addr_owner_space;
...@@ -476,21 +486,17 @@ int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, ...@@ -476,21 +486,17 @@ int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
desc->nbytes = 0; desc->nbytes = 0;
/* Return data from completed destination descriptor */ /* Return data from completed destination descriptor */
*bufferp = __le32_to_cpu(sdesc.addr);
*nbytesp = nbytes; *nbytesp = nbytes;
*transfer_idp = MS(__le16_to_cpu(sdesc.flags), CE_DESC_FLAGS_META_DATA);
if (__le16_to_cpu(sdesc.flags) & CE_DESC_FLAGS_BYTE_SWAP)
*flagsp = CE_RECV_FLAG_SWAPPED;
else
*flagsp = 0;
if (per_transfer_contextp) if (per_transfer_contextp)
*per_transfer_contextp = *per_transfer_contextp =
dest_ring->per_transfer_context[sw_index]; dest_ring->per_transfer_context[sw_index];
/* sanity */ /* Copy engine 5 (HTT Rx) will reuse the same transfer context.
dest_ring->per_transfer_context[sw_index] = NULL; * So update transfer context all CEs except CE5.
*/
if (ce_state->id != 5)
dest_ring->per_transfer_context[sw_index] = NULL;
/* Update sw_index */ /* Update sw_index */
sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
...@@ -501,10 +507,7 @@ int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, ...@@ -501,10 +507,7 @@ int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state, int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
void **per_transfer_contextp, void **per_transfer_contextp,
u32 *bufferp, unsigned int *nbytesp)
unsigned int *nbytesp,
unsigned int *transfer_idp,
unsigned int *flagsp)
{ {
struct ath10k *ar = ce_state->ar; struct ath10k *ar = ce_state->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
...@@ -513,8 +516,7 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state, ...@@ -513,8 +516,7 @@ int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
spin_lock_bh(&ar_pci->ce_lock); spin_lock_bh(&ar_pci->ce_lock);
ret = ath10k_ce_completed_recv_next_nolock(ce_state, ret = ath10k_ce_completed_recv_next_nolock(ce_state,
per_transfer_contextp, per_transfer_contextp,
bufferp, nbytesp, nbytesp);
transfer_idp, flagsp);
spin_unlock_bh(&ar_pci->ce_lock); spin_unlock_bh(&ar_pci->ce_lock);
return ret; return ret;
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
/* Maximum number of Copy Engine's supported */ /* Maximum number of Copy Engine's supported */
#define CE_COUNT_MAX 12 #define CE_COUNT_MAX 12
#define CE_HTT_H2T_MSG_SRC_NENTRIES 4096 #define CE_HTT_H2T_MSG_SRC_NENTRIES 8192
/* Descriptor rings must be aligned to this boundary */ /* Descriptor rings must be aligned to this boundary */
#define CE_DESC_RING_ALIGN 8 #define CE_DESC_RING_ALIGN 8
...@@ -166,6 +166,7 @@ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe); ...@@ -166,6 +166,7 @@ int ath10k_ce_num_free_src_entries(struct ath10k_ce_pipe *pipe);
int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe); int __ath10k_ce_rx_num_free_bufs(struct ath10k_ce_pipe *pipe);
int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr); int __ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr);
int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr); int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr);
void ath10k_ce_rx_update_write_idx(struct ath10k_ce_pipe *pipe, u32 nentries);
/* recv flags */ /* recv flags */
/* Data is byte-swapped */ /* Data is byte-swapped */
...@@ -177,10 +178,7 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr); ...@@ -177,10 +178,7 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr);
*/ */
int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state, int ath10k_ce_completed_recv_next(struct ath10k_ce_pipe *ce_state,
void **per_transfer_contextp, void **per_transfer_contextp,
u32 *bufferp, unsigned int *nbytesp);
unsigned int *nbytesp,
unsigned int *transfer_idp,
unsigned int *flagsp);
/* /*
* Supply data for the next completed unprocessed send descriptor. * Supply data for the next completed unprocessed send descriptor.
* Pops 1 completed send buffer from Source ring. * Pops 1 completed send buffer from Source ring.
...@@ -212,10 +210,7 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, ...@@ -212,10 +210,7 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
void **per_transfer_contextp, void **per_transfer_contextp,
u32 *bufferp, unsigned int *nbytesp);
unsigned int *nbytesp,
unsigned int *transfer_idp,
unsigned int *flagsp);
/* /*
* Support clean shutdown by allowing the caller to cancel * Support clean shutdown by allowing the caller to cancel
...@@ -416,6 +411,8 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) ...@@ -416,6 +411,8 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id)
(((int)(toidx)-(int)(fromidx)) & (nentries_mask)) (((int)(toidx)-(int)(fromidx)) & (nentries_mask))
#define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) & (nentries_mask)) #define CE_RING_IDX_INCR(nentries_mask, idx) (((idx) + 1) & (nentries_mask))
#define CE_RING_IDX_ADD(nentries_mask, idx, num) \
(((idx) + (num)) & (nentries_mask))
#define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB \ #define CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB \
ar->regs->ce_wrap_intr_sum_host_msi_lsb ar->regs->ce_wrap_intr_sum_host_msi_lsb
......
...@@ -60,6 +60,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { ...@@ -60,6 +60,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.channel_counters_freq_hz = 88000, .channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0, .max_probe_resp_desc_thres = 0,
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER, .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
.cal_data_len = 2116,
.fw = { .fw = {
.dir = QCA988X_HW_2_0_FW_DIR, .dir = QCA988X_HW_2_0_FW_DIR,
.fw = QCA988X_HW_2_0_FW_FILE, .fw = QCA988X_HW_2_0_FW_FILE,
...@@ -78,6 +79,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { ...@@ -78,6 +79,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.otp_exe_param = 0, .otp_exe_param = 0,
.channel_counters_freq_hz = 88000, .channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0, .max_probe_resp_desc_thres = 0,
.cal_data_len = 8124,
.fw = { .fw = {
.dir = QCA6174_HW_2_1_FW_DIR, .dir = QCA6174_HW_2_1_FW_DIR,
.fw = QCA6174_HW_2_1_FW_FILE, .fw = QCA6174_HW_2_1_FW_FILE,
...@@ -97,6 +99,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { ...@@ -97,6 +99,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.channel_counters_freq_hz = 88000, .channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0, .max_probe_resp_desc_thres = 0,
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER, .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
.cal_data_len = 8124,
.fw = { .fw = {
.dir = QCA6174_HW_2_1_FW_DIR, .dir = QCA6174_HW_2_1_FW_DIR,
.fw = QCA6174_HW_2_1_FW_FILE, .fw = QCA6174_HW_2_1_FW_FILE,
...@@ -116,6 +119,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { ...@@ -116,6 +119,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.channel_counters_freq_hz = 88000, .channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0, .max_probe_resp_desc_thres = 0,
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER, .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
.cal_data_len = 8124,
.fw = { .fw = {
.dir = QCA6174_HW_3_0_FW_DIR, .dir = QCA6174_HW_3_0_FW_DIR,
.fw = QCA6174_HW_3_0_FW_FILE, .fw = QCA6174_HW_3_0_FW_FILE,
...@@ -135,6 +139,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { ...@@ -135,6 +139,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.channel_counters_freq_hz = 88000, .channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0, .max_probe_resp_desc_thres = 0,
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER, .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_AFTER,
.cal_data_len = 8124,
.fw = { .fw = {
/* uses same binaries as hw3.0 */ /* uses same binaries as hw3.0 */
.dir = QCA6174_HW_3_0_FW_DIR, .dir = QCA6174_HW_3_0_FW_DIR,
...@@ -156,11 +161,10 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { ...@@ -156,11 +161,10 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.channel_counters_freq_hz = 150000, .channel_counters_freq_hz = 150000,
.max_probe_resp_desc_thres = 24, .max_probe_resp_desc_thres = 24,
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE, .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
.num_msdu_desc = 1424,
.qcache_active_peers = 50,
.tx_chain_mask = 0xf, .tx_chain_mask = 0xf,
.rx_chain_mask = 0xf, .rx_chain_mask = 0xf,
.max_spatial_stream = 4, .max_spatial_stream = 4,
.cal_data_len = 12064,
.fw = { .fw = {
.dir = QCA99X0_HW_2_0_FW_DIR, .dir = QCA99X0_HW_2_0_FW_DIR,
.fw = QCA99X0_HW_2_0_FW_FILE, .fw = QCA99X0_HW_2_0_FW_FILE,
...@@ -179,6 +183,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { ...@@ -179,6 +183,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.otp_exe_param = 0, .otp_exe_param = 0,
.channel_counters_freq_hz = 88000, .channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0, .max_probe_resp_desc_thres = 0,
.cal_data_len = 8124,
.fw = { .fw = {
.dir = QCA9377_HW_1_0_FW_DIR, .dir = QCA9377_HW_1_0_FW_DIR,
.fw = QCA9377_HW_1_0_FW_FILE, .fw = QCA9377_HW_1_0_FW_FILE,
...@@ -197,6 +202,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { ...@@ -197,6 +202,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.otp_exe_param = 0, .otp_exe_param = 0,
.channel_counters_freq_hz = 88000, .channel_counters_freq_hz = 88000,
.max_probe_resp_desc_thres = 0, .max_probe_resp_desc_thres = 0,
.cal_data_len = 8124,
.fw = { .fw = {
.dir = QCA9377_HW_1_0_FW_DIR, .dir = QCA9377_HW_1_0_FW_DIR,
.fw = QCA9377_HW_1_0_FW_FILE, .fw = QCA9377_HW_1_0_FW_FILE,
...@@ -217,11 +223,10 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { ...@@ -217,11 +223,10 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.channel_counters_freq_hz = 125000, .channel_counters_freq_hz = 125000,
.max_probe_resp_desc_thres = 24, .max_probe_resp_desc_thres = 24,
.hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE, .hw_4addr_pad = ATH10K_HW_4ADDR_PAD_BEFORE,
.num_msdu_desc = 2500,
.qcache_active_peers = 35,
.tx_chain_mask = 0x3, .tx_chain_mask = 0x3,
.rx_chain_mask = 0x3, .rx_chain_mask = 0x3,
.max_spatial_stream = 2, .max_spatial_stream = 2,
.cal_data_len = 12064,
.fw = { .fw = {
.dir = QCA4019_HW_1_0_FW_DIR, .dir = QCA4019_HW_1_0_FW_DIR,
.fw = QCA4019_HW_1_0_FW_FILE, .fw = QCA4019_HW_1_0_FW_FILE,
...@@ -466,18 +471,18 @@ static int ath10k_download_board_data(struct ath10k *ar, const void *data, ...@@ -466,18 +471,18 @@ static int ath10k_download_board_data(struct ath10k *ar, const void *data,
return ret; return ret;
} }
static int ath10k_download_cal_file(struct ath10k *ar) static int ath10k_download_cal_file(struct ath10k *ar,
const struct firmware *file)
{ {
int ret; int ret;
if (!ar->cal_file) if (!file)
return -ENOENT; return -ENOENT;
if (IS_ERR(ar->cal_file)) if (IS_ERR(file))
return PTR_ERR(ar->cal_file); return PTR_ERR(file);
ret = ath10k_download_board_data(ar, ar->cal_file->data, ret = ath10k_download_board_data(ar, file->data, file->size);
ar->cal_file->size);
if (ret) { if (ret) {
ath10k_err(ar, "failed to download cal_file data: %d\n", ret); ath10k_err(ar, "failed to download cal_file data: %d\n", ret);
return ret; return ret;
...@@ -488,7 +493,7 @@ static int ath10k_download_cal_file(struct ath10k *ar) ...@@ -488,7 +493,7 @@ static int ath10k_download_cal_file(struct ath10k *ar)
return 0; return 0;
} }
static int ath10k_download_cal_dt(struct ath10k *ar) static int ath10k_download_cal_dt(struct ath10k *ar, const char *dt_name)
{ {
struct device_node *node; struct device_node *node;
int data_len; int data_len;
...@@ -502,13 +507,12 @@ static int ath10k_download_cal_dt(struct ath10k *ar) ...@@ -502,13 +507,12 @@ static int ath10k_download_cal_dt(struct ath10k *ar)
*/ */
return -ENOENT; return -ENOENT;
if (!of_get_property(node, "qcom,ath10k-calibration-data", if (!of_get_property(node, dt_name, &data_len)) {
&data_len)) {
/* The calibration data node is optional */ /* The calibration data node is optional */
return -ENOENT; return -ENOENT;
} }
if (data_len != QCA988X_CAL_DATA_LEN) { if (data_len != ar->hw_params.cal_data_len) {
ath10k_warn(ar, "invalid calibration data length in DT: %d\n", ath10k_warn(ar, "invalid calibration data length in DT: %d\n",
data_len); data_len);
ret = -EMSGSIZE; ret = -EMSGSIZE;
...@@ -521,8 +525,7 @@ static int ath10k_download_cal_dt(struct ath10k *ar) ...@@ -521,8 +525,7 @@ static int ath10k_download_cal_dt(struct ath10k *ar)
goto out; goto out;
} }
ret = of_property_read_u8_array(node, "qcom,ath10k-calibration-data", ret = of_property_read_u8_array(node, dt_name, data, data_len);
data, data_len);
if (ret) { if (ret) {
ath10k_warn(ar, "failed to read calibration data from DT: %d\n", ath10k_warn(ar, "failed to read calibration data from DT: %d\n",
ret); ret);
...@@ -726,6 +729,14 @@ static int ath10k_fetch_cal_file(struct ath10k *ar) ...@@ -726,6 +729,14 @@ static int ath10k_fetch_cal_file(struct ath10k *ar)
{ {
char filename[100]; char filename[100];
/* pre-cal-<bus>-<id>.bin */
scnprintf(filename, sizeof(filename), "pre-cal-%s-%s.bin",
ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));
ar->pre_cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename);
if (!IS_ERR(ar->pre_cal_file))
goto success;
/* cal-<bus>-<id>.bin */ /* cal-<bus>-<id>.bin */
scnprintf(filename, sizeof(filename), "cal-%s-%s.bin", scnprintf(filename, sizeof(filename), "cal-%s-%s.bin",
ath10k_bus_str(ar->hif.bus), dev_name(ar->dev)); ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));
...@@ -734,7 +745,7 @@ static int ath10k_fetch_cal_file(struct ath10k *ar) ...@@ -734,7 +745,7 @@ static int ath10k_fetch_cal_file(struct ath10k *ar)
if (IS_ERR(ar->cal_file)) if (IS_ERR(ar->cal_file))
/* calibration file is optional, don't print any warnings */ /* calibration file is optional, don't print any warnings */
return PTR_ERR(ar->cal_file); return PTR_ERR(ar->cal_file);
success:
ath10k_dbg(ar, ATH10K_DBG_BOOT, "found calibration file %s/%s\n", ath10k_dbg(ar, ATH10K_DBG_BOOT, "found calibration file %s/%s\n",
ATH10K_FW_DIR, filename); ATH10K_FW_DIR, filename);
...@@ -1258,11 +1269,77 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) ...@@ -1258,11 +1269,77 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
return 0; return 0;
} }
static int ath10k_core_pre_cal_download(struct ath10k *ar)
{
int ret;
ret = ath10k_download_cal_file(ar, ar->pre_cal_file);
if (ret == 0) {
ar->cal_mode = ATH10K_PRE_CAL_MODE_FILE;
goto success;
}
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"boot did not find a pre calibration file, try DT next: %d\n",
ret);
ret = ath10k_download_cal_dt(ar, "qcom,ath10k-pre-calibration-data");
if (ret) {
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"unable to load pre cal data from DT: %d\n", ret);
return ret;
}
ar->cal_mode = ATH10K_PRE_CAL_MODE_DT;
success:
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using calibration mode %s\n",
ath10k_cal_mode_str(ar->cal_mode));
return 0;
}
static int ath10k_core_pre_cal_config(struct ath10k *ar)
{
int ret;
ret = ath10k_core_pre_cal_download(ar);
if (ret) {
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"failed to load pre cal data: %d\n", ret);
return ret;
}
ret = ath10k_core_get_board_id_from_otp(ar);
if (ret) {
ath10k_err(ar, "failed to get board id: %d\n", ret);
return ret;
}
ret = ath10k_download_and_run_otp(ar);
if (ret) {
ath10k_err(ar, "failed to run otp: %d\n", ret);
return ret;
}
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"pre cal configuration done successfully\n");
return 0;
}
static int ath10k_download_cal_data(struct ath10k *ar) static int ath10k_download_cal_data(struct ath10k *ar)
{ {
int ret; int ret;
ret = ath10k_download_cal_file(ar); ret = ath10k_core_pre_cal_config(ar);
if (ret == 0)
return 0;
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"pre cal download procedure failed, try cal file: %d\n",
ret);
ret = ath10k_download_cal_file(ar, ar->cal_file);
if (ret == 0) { if (ret == 0) {
ar->cal_mode = ATH10K_CAL_MODE_FILE; ar->cal_mode = ATH10K_CAL_MODE_FILE;
goto done; goto done;
...@@ -1272,7 +1349,7 @@ static int ath10k_download_cal_data(struct ath10k *ar) ...@@ -1272,7 +1349,7 @@ static int ath10k_download_cal_data(struct ath10k *ar)
"boot did not find a calibration file, try DT next: %d\n", "boot did not find a calibration file, try DT next: %d\n",
ret); ret);
ret = ath10k_download_cal_dt(ar); ret = ath10k_download_cal_dt(ar, "qcom,ath10k-calibration-data");
if (ret == 0) { if (ret == 0) {
ar->cal_mode = ATH10K_CAL_MODE_DT; ar->cal_mode = ATH10K_CAL_MODE_DT;
goto done; goto done;
...@@ -1509,7 +1586,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) ...@@ -1509,7 +1586,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
case ATH10K_FW_WMI_OP_VERSION_10_1: case ATH10K_FW_WMI_OP_VERSION_10_1:
case ATH10K_FW_WMI_OP_VERSION_10_2: case ATH10K_FW_WMI_OP_VERSION_10_2:
case ATH10K_FW_WMI_OP_VERSION_10_2_4: case ATH10K_FW_WMI_OP_VERSION_10_2_4:
if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) { if (ath10k_peer_stats_enabled(ar)) {
ar->max_num_peers = TARGET_10X_TX_STATS_NUM_PEERS; ar->max_num_peers = TARGET_10X_TX_STATS_NUM_PEERS;
ar->max_num_stations = TARGET_10X_TX_STATS_NUM_STATIONS; ar->max_num_stations = TARGET_10X_TX_STATS_NUM_STATIONS;
} else { } else {
...@@ -1538,9 +1615,15 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) ...@@ -1538,9 +1615,15 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
ar->num_active_peers = TARGET_10_4_ACTIVE_PEERS; ar->num_active_peers = TARGET_10_4_ACTIVE_PEERS;
ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS; ar->max_num_vdevs = TARGET_10_4_NUM_VDEVS;
ar->num_tids = TARGET_10_4_TGT_NUM_TIDS; ar->num_tids = TARGET_10_4_TGT_NUM_TIDS;
ar->htt.max_num_pending_tx = ar->hw_params.num_msdu_desc; ar->fw_stats_req_mask = WMI_10_4_STAT_PEER |
ar->fw_stats_req_mask = WMI_STAT_PEER; WMI_10_4_STAT_PEER_EXTD;
ar->max_spatial_stream = ar->hw_params.max_spatial_stream; ar->max_spatial_stream = ar->hw_params.max_spatial_stream;
if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
ar->fw_features))
ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC_PFC;
else
ar->htt.max_num_pending_tx = TARGET_10_4_NUM_MSDU_DESC;
break; break;
case ATH10K_FW_WMI_OP_VERSION_UNSET: case ATH10K_FW_WMI_OP_VERSION_UNSET:
case ATH10K_FW_WMI_OP_VERSION_MAX: case ATH10K_FW_WMI_OP_VERSION_MAX:
...@@ -1578,6 +1661,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar) ...@@ -1578,6 +1661,7 @@ static int ath10k_core_init_firmware_features(struct ath10k *ar)
int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
{ {
int status; int status;
u32 val;
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
...@@ -1698,6 +1782,21 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) ...@@ -1698,6 +1782,21 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n", ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n",
ar->hw->wiphy->fw_version); ar->hw->wiphy->fw_version);
if (test_bit(WMI_SERVICE_EXT_RES_CFG_SUPPORT, ar->wmi.svc_map)) {
val = 0;
if (ath10k_peer_stats_enabled(ar))
val = WMI_10_4_PEER_STATS;
status = ath10k_wmi_ext_resource_config(ar,
WMI_HOST_PLATFORM_HIGH_PERF, val);
if (status) {
ath10k_err(ar,
"failed to send ext resource cfg command : %d\n",
status);
goto err_hif_stop;
}
}
status = ath10k_wmi_cmd_init(ar); status = ath10k_wmi_cmd_init(ar);
if (status) { if (status) {
ath10k_err(ar, "could not send WMI init command (%d)\n", ath10k_err(ar, "could not send WMI init command (%d)\n",
...@@ -1834,11 +1933,20 @@ static int ath10k_core_probe_fw(struct ath10k *ar) ...@@ -1834,11 +1933,20 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
ath10k_debug_print_hwfw_info(ar); ath10k_debug_print_hwfw_info(ar);
ret = ath10k_core_pre_cal_download(ar);
if (ret) {
/* pre calibration data download is not necessary
* for all the chipsets. Ignore failures and continue.
*/
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"could not load pre cal data: %d\n", ret);
}
ret = ath10k_core_get_board_id_from_otp(ar); ret = ath10k_core_get_board_id_from_otp(ar);
if (ret && ret != -EOPNOTSUPP) { if (ret && ret != -EOPNOTSUPP) {
ath10k_err(ar, "failed to get board id from otp: %d\n", ath10k_err(ar, "failed to get board id from otp: %d\n",
ret); ret);
return ret; goto err_free_firmware_files;
} }
ret = ath10k_core_fetch_board_file(ar); ret = ath10k_core_fetch_board_file(ar);
...@@ -2048,7 +2156,9 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, ...@@ -2048,7 +2156,9 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
mutex_init(&ar->conf_mutex); mutex_init(&ar->conf_mutex);
spin_lock_init(&ar->data_lock); spin_lock_init(&ar->data_lock);
spin_lock_init(&ar->txqs_lock);
INIT_LIST_HEAD(&ar->txqs);
INIT_LIST_HEAD(&ar->peers); INIT_LIST_HEAD(&ar->peers);
init_waitqueue_head(&ar->peer_mapping_wq); init_waitqueue_head(&ar->peer_mapping_wq);
init_waitqueue_head(&ar->htt.empty_tx_wq); init_waitqueue_head(&ar->htt.empty_tx_wq);
......
...@@ -98,6 +98,7 @@ struct ath10k_skb_cb { ...@@ -98,6 +98,7 @@ struct ath10k_skb_cb {
u8 eid; u8 eid;
u16 msdu_id; u16 msdu_id;
struct ieee80211_vif *vif; struct ieee80211_vif *vif;
struct ieee80211_txq *txq;
} __packed; } __packed;
struct ath10k_skb_rxcb { struct ath10k_skb_rxcb {
...@@ -297,6 +298,9 @@ struct ath10k_dfs_stats { ...@@ -297,6 +298,9 @@ struct ath10k_dfs_stats {
struct ath10k_peer { struct ath10k_peer {
struct list_head list; struct list_head list;
struct ieee80211_vif *vif;
struct ieee80211_sta *sta;
int vdev_id; int vdev_id;
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
DECLARE_BITMAP(peer_ids, ATH10K_MAX_NUM_PEER_IDS); DECLARE_BITMAP(peer_ids, ATH10K_MAX_NUM_PEER_IDS);
...@@ -305,6 +309,12 @@ struct ath10k_peer { ...@@ -305,6 +309,12 @@ struct ath10k_peer {
struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
}; };
struct ath10k_txq {
struct list_head list;
unsigned long num_fw_queued;
unsigned long num_push_allowed;
};
struct ath10k_sta { struct ath10k_sta {
struct ath10k_vif *arvif; struct ath10k_vif *arvif;
...@@ -313,6 +323,7 @@ struct ath10k_sta { ...@@ -313,6 +323,7 @@ struct ath10k_sta {
u32 bw; u32 bw;
u32 nss; u32 nss;
u32 smps; u32 smps;
u16 peer_id;
struct work_struct update_wk; struct work_struct update_wk;
...@@ -335,6 +346,7 @@ struct ath10k_vif { ...@@ -335,6 +346,7 @@ struct ath10k_vif {
struct list_head list; struct list_head list;
u32 vdev_id; u32 vdev_id;
u16 peer_id;
enum wmi_vdev_type vdev_type; enum wmi_vdev_type vdev_type;
enum wmi_vdev_subtype vdev_subtype; enum wmi_vdev_subtype vdev_subtype;
u32 beacon_interval; u32 beacon_interval;
...@@ -549,12 +561,17 @@ enum ath10k_dev_flags { ...@@ -549,12 +561,17 @@ enum ath10k_dev_flags {
/* Bluetooth coexistance enabled */ /* Bluetooth coexistance enabled */
ATH10K_FLAG_BTCOEX, ATH10K_FLAG_BTCOEX,
/* Per Station statistics service */
ATH10K_FLAG_PEER_STATS,
}; };
enum ath10k_cal_mode { enum ath10k_cal_mode {
ATH10K_CAL_MODE_FILE, ATH10K_CAL_MODE_FILE,
ATH10K_CAL_MODE_OTP, ATH10K_CAL_MODE_OTP,
ATH10K_CAL_MODE_DT, ATH10K_CAL_MODE_DT,
ATH10K_PRE_CAL_MODE_FILE,
ATH10K_PRE_CAL_MODE_DT,
}; };
enum ath10k_crypt_mode { enum ath10k_crypt_mode {
...@@ -573,6 +590,10 @@ static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode) ...@@ -573,6 +590,10 @@ static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
return "otp"; return "otp";
case ATH10K_CAL_MODE_DT: case ATH10K_CAL_MODE_DT:
return "dt"; return "dt";
case ATH10K_PRE_CAL_MODE_FILE:
return "pre-cal-file";
case ATH10K_PRE_CAL_MODE_DT:
return "pre-cal-dt";
} }
return "unknown"; return "unknown";
...@@ -680,11 +701,10 @@ struct ath10k { ...@@ -680,11 +701,10 @@ struct ath10k {
/* The padding bytes's location is different on various chips */ /* The padding bytes's location is different on various chips */
enum ath10k_hw_4addr_pad hw_4addr_pad; enum ath10k_hw_4addr_pad hw_4addr_pad;
u32 num_msdu_desc;
u32 qcache_active_peers;
u32 tx_chain_mask; u32 tx_chain_mask;
u32 rx_chain_mask; u32 rx_chain_mask;
u32 max_spatial_stream; u32 max_spatial_stream;
u32 cal_data_len;
struct ath10k_hw_params_fw { struct ath10k_hw_params_fw {
const char *dir; const char *dir;
...@@ -708,6 +728,7 @@ struct ath10k { ...@@ -708,6 +728,7 @@ struct ath10k {
const void *firmware_data; const void *firmware_data;
size_t firmware_len; size_t firmware_len;
const struct firmware *pre_cal_file;
const struct firmware *cal_file; const struct firmware *cal_file;
struct { struct {
...@@ -756,6 +777,9 @@ struct ath10k { ...@@ -756,6 +777,9 @@ struct ath10k {
/* current operating channel definition */ /* current operating channel definition */
struct cfg80211_chan_def chandef; struct cfg80211_chan_def chandef;
/* currently configured operating channel in firmware */
struct ieee80211_channel *tgt_oper_chan;
unsigned long long free_vdev_map; unsigned long long free_vdev_map;
struct ath10k_vif *monitor_arvif; struct ath10k_vif *monitor_arvif;
bool monitor; bool monitor;
...@@ -786,9 +810,13 @@ struct ath10k { ...@@ -786,9 +810,13 @@ struct ath10k {
/* protects shared structure data */ /* protects shared structure data */
spinlock_t data_lock; spinlock_t data_lock;
/* protects: ar->txqs, artxq->list */
spinlock_t txqs_lock;
struct list_head txqs;
struct list_head arvifs; struct list_head arvifs;
struct list_head peers; struct list_head peers;
struct ath10k_peer *peer_map[ATH10K_MAX_NUM_PEER_IDS];
wait_queue_head_t peer_mapping_wq; wait_queue_head_t peer_mapping_wq;
/* protected by conf_mutex */ /* protected by conf_mutex */
...@@ -876,6 +904,15 @@ struct ath10k { ...@@ -876,6 +904,15 @@ struct ath10k {
u8 drv_priv[0] __aligned(sizeof(void *)); u8 drv_priv[0] __aligned(sizeof(void *));
}; };
static inline bool ath10k_peer_stats_enabled(struct ath10k *ar)
{
if (test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) &&
test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map))
return true;
return false;
}
struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
enum ath10k_bus bus, enum ath10k_bus bus,
enum ath10k_hw_rev hw_rev, enum ath10k_hw_rev hw_rev,
......
...@@ -127,6 +127,7 @@ EXPORT_SYMBOL(ath10k_info); ...@@ -127,6 +127,7 @@ EXPORT_SYMBOL(ath10k_info);
void ath10k_debug_print_hwfw_info(struct ath10k *ar) void ath10k_debug_print_hwfw_info(struct ath10k *ar)
{ {
char fw_features[128] = {}; char fw_features[128] = {};
u32 crc = 0;
ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features)); ath10k_core_get_fw_features_str(ar, fw_features, sizeof(fw_features));
...@@ -143,11 +144,14 @@ void ath10k_debug_print_hwfw_info(struct ath10k *ar) ...@@ -143,11 +144,14 @@ void ath10k_debug_print_hwfw_info(struct ath10k *ar)
config_enabled(CONFIG_ATH10K_DFS_CERTIFIED), config_enabled(CONFIG_ATH10K_DFS_CERTIFIED),
config_enabled(CONFIG_NL80211_TESTMODE)); config_enabled(CONFIG_NL80211_TESTMODE));
if (ar->firmware)
crc = crc32_le(0, ar->firmware->data, ar->firmware->size);
ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n", ath10k_info(ar, "firmware ver %s api %d features %s crc32 %08x\n",
ar->hw->wiphy->fw_version, ar->hw->wiphy->fw_version,
ar->fw_api, ar->fw_api,
fw_features, fw_features,
crc32_le(0, ar->firmware->data, ar->firmware->size)); crc);
} }
void ath10k_debug_print_board_info(struct ath10k *ar) void ath10k_debug_print_board_info(struct ath10k *ar)
...@@ -319,7 +323,7 @@ static void ath10k_debug_fw_stats_reset(struct ath10k *ar) ...@@ -319,7 +323,7 @@ static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
{ {
struct ath10k_fw_stats stats = {}; struct ath10k_fw_stats stats = {};
bool is_start, is_started, is_end, peer_stats_svc; bool is_start, is_started, is_end;
size_t num_peers; size_t num_peers;
size_t num_vdevs; size_t num_vdevs;
int ret; int ret;
...@@ -346,13 +350,11 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) ...@@ -346,13 +350,11 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
* b) consume stat update events until another one with pdev stats is * b) consume stat update events until another one with pdev stats is
* delivered which is treated as end-of-data and is itself discarded * delivered which is treated as end-of-data and is itself discarded
*/ */
if (ath10k_peer_stats_enabled(ar))
peer_stats_svc = test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map);
if (peer_stats_svc)
ath10k_sta_update_rx_duration(ar, &stats.peers); ath10k_sta_update_rx_duration(ar, &stats.peers);
if (ar->debug.fw_stats_done) { if (ar->debug.fw_stats_done) {
if (!peer_stats_svc) if (!ath10k_peer_stats_enabled(ar))
ath10k_warn(ar, "received unsolicited stats update event\n"); ath10k_warn(ar, "received unsolicited stats update event\n");
goto free; goto free;
...@@ -1447,7 +1449,7 @@ static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file) ...@@ -1447,7 +1449,7 @@ static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
goto err; goto err;
} }
buf = vmalloc(QCA988X_CAL_DATA_LEN); buf = vmalloc(ar->hw_params.cal_data_len);
if (!buf) { if (!buf) {
ret = -ENOMEM; ret = -ENOMEM;
goto err; goto err;
...@@ -1462,7 +1464,7 @@ static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file) ...@@ -1462,7 +1464,7 @@ static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
} }
ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf, ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf,
QCA988X_CAL_DATA_LEN); ar->hw_params.cal_data_len);
if (ret) { if (ret) {
ath10k_warn(ar, "failed to read calibration data: %d\n", ret); ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
goto err_vfree; goto err_vfree;
...@@ -1487,10 +1489,11 @@ static ssize_t ath10k_debug_cal_data_read(struct file *file, ...@@ -1487,10 +1489,11 @@ static ssize_t ath10k_debug_cal_data_read(struct file *file,
char __user *user_buf, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct ath10k *ar = file->private_data;
void *buf = file->private_data; void *buf = file->private_data;
return simple_read_from_buffer(user_buf, count, ppos, return simple_read_from_buffer(user_buf, count, ppos,
buf, QCA988X_CAL_DATA_LEN); buf, ar->hw_params.cal_data_len);
} }
static int ath10k_debug_cal_data_release(struct inode *inode, static int ath10k_debug_cal_data_release(struct inode *inode,
...@@ -2019,7 +2022,12 @@ static ssize_t ath10k_write_pktlog_filter(struct file *file, ...@@ -2019,7 +2022,12 @@ static ssize_t ath10k_write_pktlog_filter(struct file *file,
goto out; goto out;
} }
if (filter && (filter != ar->debug.pktlog_filter)) { if (filter == ar->debug.pktlog_filter) {
ret = count;
goto out;
}
if (filter) {
ret = ath10k_wmi_pdev_pktlog_enable(ar, filter); ret = ath10k_wmi_pdev_pktlog_enable(ar, filter);
if (ret) { if (ret) {
ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n", ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n",
...@@ -2174,6 +2182,73 @@ static const struct file_operations fops_btcoex = { ...@@ -2174,6 +2182,73 @@ static const struct file_operations fops_btcoex = {
.open = simple_open .open = simple_open
}; };
static ssize_t ath10k_write_peer_stats(struct file *file,
const char __user *ubuf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
char buf[32];
size_t buf_size;
int ret = 0;
bool val;
buf_size = min(count, (sizeof(buf) - 1));
if (copy_from_user(buf, ubuf, buf_size))
return -EFAULT;
buf[buf_size] = '\0';
if (strtobool(buf, &val) != 0)
return -EINVAL;
mutex_lock(&ar->conf_mutex);
if (ar->state != ATH10K_STATE_ON &&
ar->state != ATH10K_STATE_RESTARTED) {
ret = -ENETDOWN;
goto exit;
}
if (!(test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags) ^ val))
goto exit;
if (val)
set_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
else
clear_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags);
ath10k_info(ar, "restarting firmware due to Peer stats change");
queue_work(ar->workqueue, &ar->restart_work);
ret = count;
exit:
mutex_unlock(&ar->conf_mutex);
return ret;
}
static ssize_t ath10k_read_peer_stats(struct file *file, char __user *ubuf,
size_t count, loff_t *ppos)
{
char buf[32];
struct ath10k *ar = file->private_data;
int len = 0;
mutex_lock(&ar->conf_mutex);
len = scnprintf(buf, sizeof(buf) - len, "%d\n",
test_bit(ATH10K_FLAG_PEER_STATS, &ar->dev_flags));
mutex_unlock(&ar->conf_mutex);
return simple_read_from_buffer(ubuf, count, ppos, buf, len);
}
static const struct file_operations fops_peer_stats = {
.read = ath10k_read_peer_stats,
.write = ath10k_write_peer_stats,
.open = simple_open
};
static ssize_t ath10k_debug_fw_checksums_read(struct file *file, static ssize_t ath10k_debug_fw_checksums_read(struct file *file,
char __user *user_buf, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
...@@ -2337,6 +2412,11 @@ int ath10k_debug_register(struct ath10k *ar) ...@@ -2337,6 +2412,11 @@ int ath10k_debug_register(struct ath10k *ar)
debugfs_create_file("btcoex", S_IRUGO | S_IWUSR, debugfs_create_file("btcoex", S_IRUGO | S_IWUSR,
ar->debug.debugfs_phy, ar, &fops_btcoex); ar->debug.debugfs_phy, ar, &fops_btcoex);
if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map))
debugfs_create_file("peer_stats", S_IRUGO | S_IWUSR,
ar->debug.debugfs_phy, ar,
&fops_peer_stats);
debugfs_create_file("fw_checksums", S_IRUSR, debugfs_create_file("fw_checksums", S_IRUSR,
ar->debug.debugfs_phy, ar, &fops_fw_checksums); ar->debug.debugfs_phy, ar, &fops_fw_checksums);
......
...@@ -149,7 +149,7 @@ int ath10k_htt_connect(struct ath10k_htt *htt) ...@@ -149,7 +149,7 @@ int ath10k_htt_connect(struct ath10k_htt *htt)
memset(&conn_resp, 0, sizeof(conn_resp)); memset(&conn_resp, 0, sizeof(conn_resp));
conn_req.ep_ops.ep_tx_complete = ath10k_htt_htc_tx_complete; conn_req.ep_ops.ep_tx_complete = ath10k_htt_htc_tx_complete;
conn_req.ep_ops.ep_rx_complete = ath10k_htt_t2h_msg_handler; conn_req.ep_ops.ep_rx_complete = ath10k_htt_htc_t2h_msg_handler;
/* connect to control service */ /* connect to control service */
conn_req.service_id = ATH10K_HTC_SVC_ID_HTT_DATA_MSG; conn_req.service_id = ATH10K_HTC_SVC_ID_HTT_DATA_MSG;
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/dmapool.h> #include <linux/dmapool.h>
#include <linux/hashtable.h> #include <linux/hashtable.h>
#include <linux/kfifo.h>
#include <net/mac80211.h> #include <net/mac80211.h>
#include "htc.h" #include "htc.h"
...@@ -1461,6 +1462,14 @@ struct htt_tx_mode_switch_ind { ...@@ -1461,6 +1462,14 @@ struct htt_tx_mode_switch_ind {
struct htt_tx_mode_switch_record records[0]; struct htt_tx_mode_switch_record records[0];
} __packed; } __packed;
struct htt_channel_change {
u8 pad[3];
__le32 freq;
__le32 center_freq1;
__le32 center_freq2;
__le32 phymode;
} __packed;
union htt_rx_pn_t { union htt_rx_pn_t {
/* WEP: 24-bit PN */ /* WEP: 24-bit PN */
u32 pn24; u32 pn24;
...@@ -1511,16 +1520,22 @@ struct htt_resp { ...@@ -1511,16 +1520,22 @@ struct htt_resp {
struct htt_tx_fetch_ind tx_fetch_ind; struct htt_tx_fetch_ind tx_fetch_ind;
struct htt_tx_fetch_confirm tx_fetch_confirm; struct htt_tx_fetch_confirm tx_fetch_confirm;
struct htt_tx_mode_switch_ind tx_mode_switch_ind; struct htt_tx_mode_switch_ind tx_mode_switch_ind;
struct htt_channel_change chan_change;
}; };
} __packed; } __packed;
/*** host side structures follow ***/ /*** host side structures follow ***/
struct htt_tx_done { struct htt_tx_done {
u32 msdu_id; u16 msdu_id;
bool discard; u16 status;
bool no_ack; };
bool success;
enum htt_tx_compl_state {
HTT_TX_COMPL_STATE_NONE,
HTT_TX_COMPL_STATE_ACK,
HTT_TX_COMPL_STATE_NOACK,
HTT_TX_COMPL_STATE_DISCARD,
}; };
struct htt_peer_map_event { struct htt_peer_map_event {
...@@ -1641,17 +1656,20 @@ struct ath10k_htt { ...@@ -1641,17 +1656,20 @@ struct ath10k_htt {
struct idr pending_tx; struct idr pending_tx;
wait_queue_head_t empty_tx_wq; wait_queue_head_t empty_tx_wq;
/* FIFO for storing tx done status {ack, no-ack, discard} and msdu id */
DECLARE_KFIFO_PTR(txdone_fifo, struct htt_tx_done);
/* set if host-fw communication goes haywire /* set if host-fw communication goes haywire
* used to avoid further failures */ * used to avoid further failures */
bool rx_confused; bool rx_confused;
struct tasklet_struct rx_replenish_task; atomic_t num_mpdus_ready;
/* This is used to group tx/rx completions separately and process them /* This is used to group tx/rx completions separately and process them
* in batches to reduce cache stalls */ * in batches to reduce cache stalls */
struct tasklet_struct txrx_compl_task; struct tasklet_struct txrx_compl_task;
struct sk_buff_head tx_compl_q;
struct sk_buff_head rx_compl_q; struct sk_buff_head rx_compl_q;
struct sk_buff_head rx_in_ord_compl_q; struct sk_buff_head rx_in_ord_compl_q;
struct sk_buff_head tx_fetch_ind_q;
/* rx_status template */ /* rx_status template */
struct ieee80211_rx_status rx_status; struct ieee80211_rx_status rx_status;
...@@ -1667,10 +1685,13 @@ struct ath10k_htt { ...@@ -1667,10 +1685,13 @@ struct ath10k_htt {
} txbuf; } txbuf;
struct { struct {
bool enabled;
struct htt_q_state *vaddr; struct htt_q_state *vaddr;
dma_addr_t paddr; dma_addr_t paddr;
u16 num_push_allowed;
u16 num_peers; u16 num_peers;
u16 num_tids; u16 num_tids;
enum htt_tx_mode_switch_mode mode;
enum htt_q_depth_type type; enum htt_q_depth_type type;
} tx_q_state; } tx_q_state;
}; };
...@@ -1715,7 +1736,7 @@ struct htt_rx_desc { ...@@ -1715,7 +1736,7 @@ struct htt_rx_desc {
/* Refill a bunch of RX buffers for each refill round so that FW/HW can handle /* Refill a bunch of RX buffers for each refill round so that FW/HW can handle
* aggregated traffic more nicely. */ * aggregated traffic more nicely. */
#define ATH10K_HTT_MAX_NUM_REFILL 16 #define ATH10K_HTT_MAX_NUM_REFILL 100
/* /*
* DMA_MAP expects the buffer to be an integral number of cache lines. * DMA_MAP expects the buffer to be an integral number of cache lines.
...@@ -1743,7 +1764,8 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar); ...@@ -1743,7 +1764,8 @@ int ath10k_htt_rx_ring_refill(struct ath10k *ar);
void ath10k_htt_rx_free(struct ath10k_htt *htt); void ath10k_htt_rx_free(struct ath10k_htt *htt);
void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb); void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb);
void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb); void ath10k_htt_htc_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb);
bool ath10k_htt_t2h_msg_handler(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);
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);
int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt); int ath10k_htt_send_frag_desc_bank_cfg(struct ath10k_htt *htt);
...@@ -1752,8 +1774,23 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, ...@@ -1752,8 +1774,23 @@ 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);
void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb); void ath10k_htt_hif_tx_complete(struct ath10k *ar, struct sk_buff *skb);
int ath10k_htt_tx_fetch_resp(struct ath10k *ar,
__le32 token,
__le16 fetch_seq_num,
struct htt_tx_fetch_record *records,
size_t num_records);
void ath10k_htt_tx_txq_update(struct ieee80211_hw *hw,
struct ieee80211_txq *txq);
void ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw,
struct ieee80211_txq *txq);
void ath10k_htt_tx_txq_sync(struct ath10k *ar);
void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt);
int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt);
void ath10k_htt_tx_mgmt_dec_pending(struct ath10k_htt *htt);
int ath10k_htt_tx_mgmt_inc_pending(struct ath10k_htt *htt, bool is_mgmt,
bool is_presp);
void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc);
int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb); int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb);
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);
int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *); int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *);
......
...@@ -22,53 +22,183 @@ ...@@ -22,53 +22,183 @@
#include "txrx.h" #include "txrx.h"
#include "debug.h" #include "debug.h"
void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, bool limit_mgmt_desc) static u8 ath10k_htt_tx_txq_calc_size(size_t count)
{ {
if (limit_mgmt_desc) int exp;
htt->num_pending_mgmt_tx--; int factor;
exp = 0;
factor = count >> 7;
while (factor >= 64 && exp < 4) {
factor >>= 3;
exp++;
}
if (exp == 4)
return 0xff;
if (count > 0)
factor = max(1, factor);
return SM(exp, HTT_TX_Q_STATE_ENTRY_EXP) |
SM(factor, HTT_TX_Q_STATE_ENTRY_FACTOR);
}
static void __ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw,
struct ieee80211_txq *txq)
{
struct ath10k *ar = hw->priv;
struct ath10k_sta *arsta = (void *)txq->sta->drv_priv;
struct ath10k_vif *arvif = (void *)txq->vif->drv_priv;
unsigned long frame_cnt;
unsigned long byte_cnt;
int idx;
u32 bit;
u16 peer_id;
u8 tid;
u8 count;
lockdep_assert_held(&ar->htt.tx_lock);
if (!ar->htt.tx_q_state.enabled)
return;
if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH_PULL)
return;
if (txq->sta)
peer_id = arsta->peer_id;
else
peer_id = arvif->peer_id;
tid = txq->tid;
bit = BIT(peer_id % 32);
idx = peer_id / 32;
ieee80211_txq_get_depth(txq, &frame_cnt, &byte_cnt);
count = ath10k_htt_tx_txq_calc_size(byte_cnt);
if (unlikely(peer_id >= ar->htt.tx_q_state.num_peers) ||
unlikely(tid >= ar->htt.tx_q_state.num_tids)) {
ath10k_warn(ar, "refusing to update txq for peer_id %hu tid %hhu due to out of bounds\n",
peer_id, tid);
return;
}
ar->htt.tx_q_state.vaddr->count[tid][peer_id] = count;
ar->htt.tx_q_state.vaddr->map[tid][idx] &= ~bit;
ar->htt.tx_q_state.vaddr->map[tid][idx] |= count ? bit : 0;
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx txq state update peer_id %hu tid %hhu count %hhu\n",
peer_id, tid, count);
}
static void __ath10k_htt_tx_txq_sync(struct ath10k *ar)
{
u32 seq;
size_t size;
lockdep_assert_held(&ar->htt.tx_lock);
if (!ar->htt.tx_q_state.enabled)
return;
if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH_PULL)
return;
seq = le32_to_cpu(ar->htt.tx_q_state.vaddr->seq);
seq++;
ar->htt.tx_q_state.vaddr->seq = cpu_to_le32(seq);
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt tx txq state update commit seq %u\n",
seq);
size = sizeof(*ar->htt.tx_q_state.vaddr);
dma_sync_single_for_device(ar->dev,
ar->htt.tx_q_state.paddr,
size,
DMA_TO_DEVICE);
}
void ath10k_htt_tx_txq_recalc(struct ieee80211_hw *hw,
struct ieee80211_txq *txq)
{
struct ath10k *ar = hw->priv;
spin_lock_bh(&ar->htt.tx_lock);
__ath10k_htt_tx_txq_recalc(hw, txq);
spin_unlock_bh(&ar->htt.tx_lock);
}
void ath10k_htt_tx_txq_sync(struct ath10k *ar)
{
spin_lock_bh(&ar->htt.tx_lock);
__ath10k_htt_tx_txq_sync(ar);
spin_unlock_bh(&ar->htt.tx_lock);
}
void ath10k_htt_tx_txq_update(struct ieee80211_hw *hw,
struct ieee80211_txq *txq)
{
struct ath10k *ar = hw->priv;
spin_lock_bh(&ar->htt.tx_lock);
__ath10k_htt_tx_txq_recalc(hw, txq);
__ath10k_htt_tx_txq_sync(ar);
spin_unlock_bh(&ar->htt.tx_lock);
}
void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt)
{
lockdep_assert_held(&htt->tx_lock);
htt->num_pending_tx--; htt->num_pending_tx--;
if (htt->num_pending_tx == htt->max_num_pending_tx - 1) if (htt->num_pending_tx == htt->max_num_pending_tx - 1)
ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL); ath10k_mac_tx_unlock(htt->ar, ATH10K_TX_PAUSE_Q_FULL);
} }
static void ath10k_htt_tx_dec_pending(struct ath10k_htt *htt, int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt)
bool limit_mgmt_desc)
{ {
spin_lock_bh(&htt->tx_lock); lockdep_assert_held(&htt->tx_lock);
__ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
spin_unlock_bh(&htt->tx_lock); if (htt->num_pending_tx >= htt->max_num_pending_tx)
return -EBUSY;
htt->num_pending_tx++;
if (htt->num_pending_tx == htt->max_num_pending_tx)
ath10k_mac_tx_lock(htt->ar, ATH10K_TX_PAUSE_Q_FULL);
return 0;
} }
static int ath10k_htt_tx_inc_pending(struct ath10k_htt *htt, int ath10k_htt_tx_mgmt_inc_pending(struct ath10k_htt *htt, bool is_mgmt,
bool limit_mgmt_desc, bool is_probe_resp) bool is_presp)
{ {
struct ath10k *ar = htt->ar; struct ath10k *ar = htt->ar;
int ret = 0;
spin_lock_bh(&htt->tx_lock); lockdep_assert_held(&htt->tx_lock);
if (htt->num_pending_tx >= htt->max_num_pending_tx) { if (!is_mgmt || !ar->hw_params.max_probe_resp_desc_thres)
ret = -EBUSY; return 0;
goto exit;
}
if (limit_mgmt_desc) { if (is_presp &&
if (is_probe_resp && (htt->num_pending_mgmt_tx > ar->hw_params.max_probe_resp_desc_thres < htt->num_pending_mgmt_tx)
ar->hw_params.max_probe_resp_desc_thres)) { return -EBUSY;
ret = -EBUSY;
goto exit;
}
htt->num_pending_mgmt_tx++;
}
htt->num_pending_tx++; htt->num_pending_mgmt_tx++;
if (htt->num_pending_tx == htt->max_num_pending_tx)
ath10k_mac_tx_lock(htt->ar, ATH10K_TX_PAUSE_Q_FULL);
exit: return 0;
spin_unlock_bh(&htt->tx_lock); }
return ret;
void ath10k_htt_tx_mgmt_dec_pending(struct ath10k_htt *htt)
{
lockdep_assert_held(&htt->tx_lock);
if (!htt->ar->hw_params.max_probe_resp_desc_thres)
return;
htt->num_pending_mgmt_tx--;
} }
int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb) int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb)
...@@ -209,8 +339,18 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt) ...@@ -209,8 +339,18 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
goto free_frag_desc; goto free_frag_desc;
} }
size = roundup_pow_of_two(htt->max_num_pending_tx);
ret = kfifo_alloc(&htt->txdone_fifo, size, GFP_KERNEL);
if (ret) {
ath10k_err(ar, "failed to alloc txdone fifo: %d\n", ret);
goto free_txq;
}
return 0; return 0;
free_txq:
ath10k_htt_tx_free_txq(htt);
free_frag_desc: free_frag_desc:
ath10k_htt_tx_free_cont_frag_desc(htt); ath10k_htt_tx_free_cont_frag_desc(htt);
...@@ -234,8 +374,8 @@ static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx) ...@@ -234,8 +374,8 @@ static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx)
ath10k_dbg(ar, ATH10K_DBG_HTT, "force cleanup msdu_id %hu\n", msdu_id); ath10k_dbg(ar, ATH10K_DBG_HTT, "force cleanup msdu_id %hu\n", msdu_id);
tx_done.discard = 1;
tx_done.msdu_id = msdu_id; tx_done.msdu_id = msdu_id;
tx_done.status = HTT_TX_COMPL_STATE_DISCARD;
ath10k_txrx_tx_unref(htt, &tx_done); ath10k_txrx_tx_unref(htt, &tx_done);
...@@ -258,6 +398,8 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt) ...@@ -258,6 +398,8 @@ void ath10k_htt_tx_free(struct ath10k_htt *htt)
ath10k_htt_tx_free_txq(htt); ath10k_htt_tx_free_txq(htt);
ath10k_htt_tx_free_cont_frag_desc(htt); ath10k_htt_tx_free_cont_frag_desc(htt);
WARN_ON(!kfifo_is_empty(&htt->txdone_fifo));
kfifo_free(&htt->txdone_fifo);
} }
void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb) void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
...@@ -535,6 +677,55 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt, ...@@ -535,6 +677,55 @@ int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
return 0; return 0;
} }
int ath10k_htt_tx_fetch_resp(struct ath10k *ar,
__le32 token,
__le16 fetch_seq_num,
struct htt_tx_fetch_record *records,
size_t num_records)
{
struct sk_buff *skb;
struct htt_cmd *cmd;
const u16 resp_id = 0;
int len = 0;
int ret;
/* Response IDs are echo-ed back only for host driver convienence
* purposes. They aren't used for anything in the driver yet so use 0.
*/
len += sizeof(cmd->hdr);
len += sizeof(cmd->tx_fetch_resp);
len += sizeof(cmd->tx_fetch_resp.records[0]) * num_records;
skb = ath10k_htc_alloc_skb(ar, len);
if (!skb)
return -ENOMEM;
skb_put(skb, len);
cmd = (struct htt_cmd *)skb->data;
cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_TX_FETCH_RESP;
cmd->tx_fetch_resp.resp_id = cpu_to_le16(resp_id);
cmd->tx_fetch_resp.fetch_seq_num = fetch_seq_num;
cmd->tx_fetch_resp.num_records = cpu_to_le16(num_records);
cmd->tx_fetch_resp.token = token;
memcpy(cmd->tx_fetch_resp.records, records,
sizeof(records[0]) * num_records);
ret = ath10k_htc_send(&ar->htc, ar->htt.eid, skb);
if (ret) {
ath10k_warn(ar, "failed to submit htc command: %d\n", ret);
goto err_free_skb;
}
return 0;
err_free_skb:
dev_kfree_skb_any(skb);
return ret;
}
static u8 ath10k_htt_tx_get_vdev_id(struct ath10k *ar, struct sk_buff *skb) static u8 ath10k_htt_tx_get_vdev_id(struct ath10k *ar, struct sk_buff *skb)
{ {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
...@@ -576,20 +767,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) ...@@ -576,20 +767,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
int msdu_id = -1; int msdu_id = -1;
int res; int res;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msdu->data;
bool limit_mgmt_desc = false;
bool is_probe_resp = false;
if (ar->hw_params.max_probe_resp_desc_thres) {
limit_mgmt_desc = true;
if (ieee80211_is_probe_resp(hdr->frame_control))
is_probe_resp = true;
}
res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp);
if (res)
goto err;
len += sizeof(cmd->hdr); len += sizeof(cmd->hdr);
len += sizeof(cmd->mgmt_tx); len += sizeof(cmd->mgmt_tx);
...@@ -598,7 +775,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) ...@@ -598,7 +775,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
res = ath10k_htt_tx_alloc_msdu_id(htt, msdu); res = ath10k_htt_tx_alloc_msdu_id(htt, msdu);
spin_unlock_bh(&htt->tx_lock); spin_unlock_bh(&htt->tx_lock);
if (res < 0) if (res < 0)
goto err_tx_dec; goto err;
msdu_id = res; msdu_id = res;
...@@ -649,8 +826,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) ...@@ -649,8 +826,6 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
spin_lock_bh(&htt->tx_lock); spin_lock_bh(&htt->tx_lock);
ath10k_htt_tx_free_msdu_id(htt, msdu_id); ath10k_htt_tx_free_msdu_id(htt, msdu_id);
spin_unlock_bh(&htt->tx_lock); spin_unlock_bh(&htt->tx_lock);
err_tx_dec:
ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
err: err:
return res; return res;
} }
...@@ -677,26 +852,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode, ...@@ -677,26 +852,12 @@ int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
u32 frags_paddr = 0; u32 frags_paddr = 0;
u32 txbuf_paddr; u32 txbuf_paddr;
struct htt_msdu_ext_desc *ext_desc = NULL; struct htt_msdu_ext_desc *ext_desc = NULL;
bool limit_mgmt_desc = false;
bool is_probe_resp = false;
if (unlikely(ieee80211_is_mgmt(hdr->frame_control)) &&
ar->hw_params.max_probe_resp_desc_thres) {
limit_mgmt_desc = true;
if (ieee80211_is_probe_resp(hdr->frame_control))
is_probe_resp = true;
}
res = ath10k_htt_tx_inc_pending(htt, limit_mgmt_desc, is_probe_resp);
if (res)
goto err;
spin_lock_bh(&htt->tx_lock); spin_lock_bh(&htt->tx_lock);
res = ath10k_htt_tx_alloc_msdu_id(htt, msdu); res = ath10k_htt_tx_alloc_msdu_id(htt, msdu);
spin_unlock_bh(&htt->tx_lock); spin_unlock_bh(&htt->tx_lock);
if (res < 0) if (res < 0)
goto err_tx_dec; goto err;
msdu_id = res; msdu_id = res;
...@@ -862,11 +1023,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode, ...@@ -862,11 +1023,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode,
err_unmap_msdu: err_unmap_msdu:
dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE);
err_free_msdu_id: err_free_msdu_id:
spin_lock_bh(&htt->tx_lock);
ath10k_htt_tx_free_msdu_id(htt, msdu_id); ath10k_htt_tx_free_msdu_id(htt, msdu_id);
spin_unlock_bh(&htt->tx_lock);
err_tx_dec:
ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc);
err: err:
return res; return res;
} }
...@@ -134,8 +134,6 @@ enum qca9377_chip_id_rev { ...@@ -134,8 +134,6 @@ enum qca9377_chip_id_rev {
#define REG_DUMP_COUNT_QCA988X 60 #define REG_DUMP_COUNT_QCA988X 60
#define QCA988X_CAL_DATA_LEN 2116
struct ath10k_fw_ie { struct ath10k_fw_ie {
__le32 id; __le32 id;
__le32 len; __le32 len;
...@@ -431,10 +429,14 @@ enum ath10k_hw_4addr_pad { ...@@ -431,10 +429,14 @@ enum ath10k_hw_4addr_pad {
#define TARGET_10_4_ACTIVE_PEERS 0 #define TARGET_10_4_ACTIVE_PEERS 0
#define TARGET_10_4_NUM_QCACHE_PEERS_MAX 512 #define TARGET_10_4_NUM_QCACHE_PEERS_MAX 512
#define TARGET_10_4_QCACHE_ACTIVE_PEERS 50
#define TARGET_10_4_QCACHE_ACTIVE_PEERS_PFC 35
#define TARGET_10_4_NUM_OFFLOAD_PEERS 0 #define TARGET_10_4_NUM_OFFLOAD_PEERS 0
#define TARGET_10_4_NUM_OFFLOAD_REORDER_BUFFS 0 #define TARGET_10_4_NUM_OFFLOAD_REORDER_BUFFS 0
#define TARGET_10_4_NUM_PEER_KEYS 2 #define TARGET_10_4_NUM_PEER_KEYS 2
#define TARGET_10_4_TGT_NUM_TIDS ((TARGET_10_4_NUM_PEERS) * 2) #define TARGET_10_4_TGT_NUM_TIDS ((TARGET_10_4_NUM_PEERS) * 2)
#define TARGET_10_4_NUM_MSDU_DESC (1024 + 400)
#define TARGET_10_4_NUM_MSDU_DESC_PFC 2500
#define TARGET_10_4_AST_SKID_LIMIT 32 #define TARGET_10_4_AST_SKID_LIMIT 32
/* 100 ms for video, best-effort, and background */ /* 100 ms for video, best-effort, and background */
......
...@@ -75,6 +75,12 @@ void ath10k_mac_tx_unlock(struct ath10k *ar, int reason); ...@@ -75,6 +75,12 @@ void ath10k_mac_tx_unlock(struct ath10k *ar, int reason);
void ath10k_mac_vif_tx_lock(struct ath10k_vif *arvif, int reason); void ath10k_mac_vif_tx_lock(struct ath10k_vif *arvif, int reason);
void ath10k_mac_vif_tx_unlock(struct ath10k_vif *arvif, int reason); void ath10k_mac_vif_tx_unlock(struct ath10k_vif *arvif, int reason);
bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar); bool ath10k_mac_tx_frm_has_freq(struct ath10k *ar);
void ath10k_mac_tx_push_pending(struct ath10k *ar);
int ath10k_mac_tx_push_txq(struct ieee80211_hw *hw,
struct ieee80211_txq *txq);
struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar,
u16 peer_id,
u8 tid);
static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
{ {
......
...@@ -809,7 +809,8 @@ static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) ...@@ -809,7 +809,8 @@ static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe)
spin_lock_bh(&ar_pci->ce_lock); spin_lock_bh(&ar_pci->ce_lock);
num = __ath10k_ce_rx_num_free_bufs(ce_pipe); num = __ath10k_ce_rx_num_free_bufs(ce_pipe);
spin_unlock_bh(&ar_pci->ce_lock); spin_unlock_bh(&ar_pci->ce_lock);
while (num--) {
while (num >= 0) {
ret = __ath10k_pci_rx_post_buf(pipe); ret = __ath10k_pci_rx_post_buf(pipe);
if (ret) { if (ret) {
if (ret == -ENOSPC) if (ret == -ENOSPC)
...@@ -819,6 +820,7 @@ static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe) ...@@ -819,6 +820,7 @@ static void ath10k_pci_rx_post_pipe(struct ath10k_pci_pipe *pipe)
ATH10K_PCI_RX_POST_RETRY_MS); ATH10K_PCI_RX_POST_RETRY_MS);
break; break;
} }
num--;
} }
} }
...@@ -870,10 +872,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, ...@@ -870,10 +872,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
{ {
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ret = 0; int ret = 0;
u32 buf; u32 *buf;
unsigned int completed_nbytes, orig_nbytes, remaining_bytes; unsigned int completed_nbytes, orig_nbytes, remaining_bytes;
unsigned int id;
unsigned int flags;
struct ath10k_ce_pipe *ce_diag; struct ath10k_ce_pipe *ce_diag;
/* Host buffer address in CE space */ /* Host buffer address in CE space */
u32 ce_data; u32 ce_data;
...@@ -909,7 +909,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, ...@@ -909,7 +909,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
nbytes = min_t(unsigned int, remaining_bytes, nbytes = min_t(unsigned int, remaining_bytes,
DIAG_TRANSFER_LIMIT); DIAG_TRANSFER_LIMIT);
ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data); ret = __ath10k_ce_rx_post_buf(ce_diag, &ce_data, ce_data);
if (ret != 0) if (ret != 0)
goto done; goto done;
...@@ -940,9 +940,10 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, ...@@ -940,9 +940,10 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
} }
i = 0; i = 0;
while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, while (ath10k_ce_completed_recv_next_nolock(ce_diag,
&completed_nbytes, (void **)&buf,
&id, &flags) != 0) { &completed_nbytes)
!= 0) {
mdelay(1); mdelay(1);
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
...@@ -956,7 +957,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, ...@@ -956,7 +957,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
goto done; goto done;
} }
if (buf != ce_data) { if (*buf != ce_data) {
ret = -EIO; ret = -EIO;
goto done; goto done;
} }
...@@ -1026,10 +1027,8 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, ...@@ -1026,10 +1027,8 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
{ {
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ret = 0; int ret = 0;
u32 buf; u32 *buf;
unsigned int completed_nbytes, orig_nbytes, remaining_bytes; unsigned int completed_nbytes, orig_nbytes, remaining_bytes;
unsigned int id;
unsigned int flags;
struct ath10k_ce_pipe *ce_diag; struct ath10k_ce_pipe *ce_diag;
void *data_buf = NULL; void *data_buf = NULL;
u32 ce_data; /* Host buffer address in CE space */ u32 ce_data; /* Host buffer address in CE space */
...@@ -1078,7 +1077,7 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, ...@@ -1078,7 +1077,7 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT); nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT);
/* Set up to receive directly into Target(!) address */ /* Set up to receive directly into Target(!) address */
ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, address); ret = __ath10k_ce_rx_post_buf(ce_diag, &address, address);
if (ret != 0) if (ret != 0)
goto done; goto done;
...@@ -1103,9 +1102,10 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, ...@@ -1103,9 +1102,10 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
} }
i = 0; i = 0;
while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, while (ath10k_ce_completed_recv_next_nolock(ce_diag,
&completed_nbytes, (void **)&buf,
&id, &flags) != 0) { &completed_nbytes)
!= 0) {
mdelay(1); mdelay(1);
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
...@@ -1119,7 +1119,7 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, ...@@ -1119,7 +1119,7 @@ int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
goto done; goto done;
} }
if (buf != address) { if (*buf != address) {
ret = -EIO; ret = -EIO;
goto done; goto done;
} }
...@@ -1181,15 +1181,11 @@ static void ath10k_pci_process_rx_cb(struct ath10k_ce_pipe *ce_state, ...@@ -1181,15 +1181,11 @@ static void ath10k_pci_process_rx_cb(struct ath10k_ce_pipe *ce_state,
struct sk_buff *skb; struct sk_buff *skb;
struct sk_buff_head list; struct sk_buff_head list;
void *transfer_context; void *transfer_context;
u32 ce_data;
unsigned int nbytes, max_nbytes; unsigned int nbytes, max_nbytes;
unsigned int transfer_id;
unsigned int flags;
__skb_queue_head_init(&list); __skb_queue_head_init(&list);
while (ath10k_ce_completed_recv_next(ce_state, &transfer_context, while (ath10k_ce_completed_recv_next(ce_state, &transfer_context,
&ce_data, &nbytes, &transfer_id, &nbytes) == 0) {
&flags) == 0) {
skb = transfer_context; skb = transfer_context;
max_nbytes = skb->len + skb_tailroom(skb); max_nbytes = skb->len + skb_tailroom(skb);
dma_unmap_single(ar->dev, ATH10K_SKB_RXCB(skb)->paddr, dma_unmap_single(ar->dev, ATH10K_SKB_RXCB(skb)->paddr,
...@@ -1218,6 +1214,63 @@ static void ath10k_pci_process_rx_cb(struct ath10k_ce_pipe *ce_state, ...@@ -1218,6 +1214,63 @@ static void ath10k_pci_process_rx_cb(struct ath10k_ce_pipe *ce_state,
ath10k_pci_rx_post_pipe(pipe_info); ath10k_pci_rx_post_pipe(pipe_info);
} }
static void ath10k_pci_process_htt_rx_cb(struct ath10k_ce_pipe *ce_state,
void (*callback)(struct ath10k *ar,
struct sk_buff *skb))
{
struct ath10k *ar = ce_state->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_pci_pipe *pipe_info = &ar_pci->pipe_info[ce_state->id];
struct ath10k_ce_pipe *ce_pipe = pipe_info->ce_hdl;
struct sk_buff *skb;
struct sk_buff_head list;
void *transfer_context;
unsigned int nbytes, max_nbytes, nentries;
int orig_len;
/* No need to aquire ce_lock for CE5, since this is the only place CE5
* is processed other than init and deinit. Before releasing CE5
* buffers, interrupts are disabled. Thus CE5 access is serialized.
*/
__skb_queue_head_init(&list);
while (ath10k_ce_completed_recv_next_nolock(ce_state, &transfer_context,
&nbytes) == 0) {
skb = transfer_context;
max_nbytes = skb->len + skb_tailroom(skb);
if (unlikely(max_nbytes < nbytes)) {
ath10k_warn(ar, "rxed more than expected (nbytes %d, max %d)",
nbytes, max_nbytes);
continue;
}
dma_sync_single_for_cpu(ar->dev, ATH10K_SKB_RXCB(skb)->paddr,
max_nbytes, DMA_FROM_DEVICE);
skb_put(skb, nbytes);
__skb_queue_tail(&list, skb);
}
nentries = skb_queue_len(&list);
while ((skb = __skb_dequeue(&list))) {
ath10k_dbg(ar, ATH10K_DBG_PCI, "pci rx ce pipe %d len %d\n",
ce_state->id, skb->len);
ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ",
skb->data, skb->len);
orig_len = skb->len;
callback(ar, skb);
skb_push(skb, orig_len - skb->len);
skb_reset_tail_pointer(skb);
skb_trim(skb, 0);
/*let device gain the buffer again*/
dma_sync_single_for_device(ar->dev, ATH10K_SKB_RXCB(skb)->paddr,
skb->len + skb_tailroom(skb),
DMA_FROM_DEVICE);
}
ath10k_ce_rx_update_write_idx(ce_pipe, nentries);
}
/* Called by lower (CE) layer when data is received from the Target. */ /* Called by lower (CE) layer when data is received from the Target. */
static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state) static void ath10k_pci_htc_rx_cb(struct ath10k_ce_pipe *ce_state)
{ {
...@@ -1274,7 +1327,7 @@ static void ath10k_pci_htt_rx_cb(struct ath10k_ce_pipe *ce_state) ...@@ -1274,7 +1327,7 @@ static void ath10k_pci_htt_rx_cb(struct ath10k_ce_pipe *ce_state)
*/ */
ath10k_ce_per_engine_service(ce_state->ar, 4); ath10k_ce_per_engine_service(ce_state->ar, 4);
ath10k_pci_process_rx_cb(ce_state, ath10k_pci_htt_rx_deliver); ath10k_pci_process_htt_rx_cb(ce_state, ath10k_pci_htt_rx_deliver);
} }
int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id, int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
...@@ -1835,13 +1888,10 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state) ...@@ -1835,13 +1888,10 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
{ {
struct ath10k *ar = ce_state->ar; struct ath10k *ar = ce_state->ar;
struct bmi_xfer *xfer; struct bmi_xfer *xfer;
u32 ce_data;
unsigned int nbytes; unsigned int nbytes;
unsigned int transfer_id;
unsigned int flags;
if (ath10k_ce_completed_recv_next(ce_state, (void **)&xfer, &ce_data, if (ath10k_ce_completed_recv_next(ce_state, (void **)&xfer,
&nbytes, &transfer_id, &flags)) &nbytes))
return; return;
if (WARN_ON_ONCE(!xfer)) if (WARN_ON_ONCE(!xfer))
......
...@@ -49,25 +49,25 @@ static void ath10k_report_offchan_tx(struct ath10k *ar, struct sk_buff *skb) ...@@ -49,25 +49,25 @@ static void ath10k_report_offchan_tx(struct ath10k *ar, struct sk_buff *skb)
spin_unlock_bh(&ar->data_lock); spin_unlock_bh(&ar->data_lock);
} }
void ath10k_txrx_tx_unref(struct ath10k_htt *htt, int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
const struct htt_tx_done *tx_done) const struct htt_tx_done *tx_done)
{ {
struct ath10k *ar = htt->ar; struct ath10k *ar = htt->ar;
struct device *dev = ar->dev; struct device *dev = ar->dev;
struct ieee80211_tx_info *info; struct ieee80211_tx_info *info;
struct ieee80211_txq *txq;
struct ath10k_skb_cb *skb_cb; struct ath10k_skb_cb *skb_cb;
struct ath10k_txq *artxq;
struct sk_buff *msdu; struct sk_buff *msdu;
bool limit_mgmt_desc = false;
ath10k_dbg(ar, ATH10K_DBG_HTT, ath10k_dbg(ar, ATH10K_DBG_HTT,
"htt tx completion msdu_id %u discard %d no_ack %d success %d\n", "htt tx completion msdu_id %u status %d\n",
tx_done->msdu_id, !!tx_done->discard, tx_done->msdu_id, tx_done->status);
!!tx_done->no_ack, !!tx_done->success);
if (tx_done->msdu_id >= htt->max_num_pending_tx) { if (tx_done->msdu_id >= htt->max_num_pending_tx) {
ath10k_warn(ar, "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 -EINVAL;
} }
spin_lock_bh(&htt->tx_lock); spin_lock_bh(&htt->tx_lock);
...@@ -76,17 +76,18 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, ...@@ -76,17 +76,18 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
ath10k_warn(ar, "received tx completion for invalid msdu_id: %d\n", ath10k_warn(ar, "received tx completion for invalid msdu_id: %d\n",
tx_done->msdu_id); tx_done->msdu_id);
spin_unlock_bh(&htt->tx_lock); spin_unlock_bh(&htt->tx_lock);
return; return -ENOENT;
} }
skb_cb = ATH10K_SKB_CB(msdu); skb_cb = ATH10K_SKB_CB(msdu);
txq = skb_cb->txq;
artxq = (void *)txq->drv_priv;
if (unlikely(skb_cb->flags & ATH10K_SKB_F_MGMT) && if (txq)
ar->hw_params.max_probe_resp_desc_thres) artxq->num_fw_queued--;
limit_mgmt_desc = true;
ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id); ath10k_htt_tx_free_msdu_id(htt, tx_done->msdu_id);
__ath10k_htt_tx_dec_pending(htt, limit_mgmt_desc); ath10k_htt_tx_dec_pending(htt);
if (htt->num_pending_tx == 0) if (htt->num_pending_tx == 0)
wake_up(&htt->empty_tx_wq); wake_up(&htt->empty_tx_wq);
spin_unlock_bh(&htt->tx_lock); spin_unlock_bh(&htt->tx_lock);
...@@ -99,22 +100,24 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, ...@@ -99,22 +100,24 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
memset(&info->status, 0, sizeof(info->status)); memset(&info->status, 0, sizeof(info->status));
trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id); trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id);
if (tx_done->discard) { if (tx_done->status == HTT_TX_COMPL_STATE_DISCARD) {
ieee80211_free_txskb(htt->ar->hw, msdu); ieee80211_free_txskb(htt->ar->hw, msdu);
return; return 0;
} }
if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
info->flags |= IEEE80211_TX_STAT_ACK; info->flags |= IEEE80211_TX_STAT_ACK;
if (tx_done->no_ack) if (tx_done->status == HTT_TX_COMPL_STATE_NOACK)
info->flags &= ~IEEE80211_TX_STAT_ACK; info->flags &= ~IEEE80211_TX_STAT_ACK;
if (tx_done->success && (info->flags & IEEE80211_TX_CTL_NO_ACK)) if ((tx_done->status == HTT_TX_COMPL_STATE_ACK) &&
(info->flags & IEEE80211_TX_CTL_NO_ACK))
info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED; info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
ieee80211_tx_status(htt->ar->hw, msdu); ieee80211_tx_status(htt->ar->hw, msdu);
/* we do not own the msdu anymore */ /* we do not own the msdu anymore */
return 0;
} }
struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id, struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
...@@ -203,6 +206,7 @@ void ath10k_peer_map_event(struct ath10k_htt *htt, ...@@ -203,6 +206,7 @@ void ath10k_peer_map_event(struct ath10k_htt *htt,
ath10k_dbg(ar, 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);
ar->peer_map[ev->peer_id] = peer;
set_bit(ev->peer_id, peer->peer_ids); set_bit(ev->peer_id, peer->peer_ids);
exit: exit:
spin_unlock_bh(&ar->data_lock); spin_unlock_bh(&ar->data_lock);
...@@ -225,6 +229,7 @@ void ath10k_peer_unmap_event(struct ath10k_htt *htt, ...@@ -225,6 +229,7 @@ void ath10k_peer_unmap_event(struct ath10k_htt *htt,
ath10k_dbg(ar, 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);
ar->peer_map[ev->peer_id] = NULL;
clear_bit(ev->peer_id, peer->peer_ids); clear_bit(ev->peer_id, peer->peer_ids);
if (bitmap_empty(peer->peer_ids, ATH10K_MAX_NUM_PEER_IDS)) { if (bitmap_empty(peer->peer_ids, ATH10K_MAX_NUM_PEER_IDS)) {
......
...@@ -19,8 +19,8 @@ ...@@ -19,8 +19,8 @@
#include "htt.h" #include "htt.h"
void ath10k_txrx_tx_unref(struct ath10k_htt *htt, int ath10k_txrx_tx_unref(struct ath10k_htt *htt,
const struct htt_tx_done *tx_done); const struct htt_tx_done *tx_done);
struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id, struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
const u8 *addr); const u8 *addr);
......
...@@ -186,6 +186,9 @@ struct wmi_ops { ...@@ -186,6 +186,9 @@ struct wmi_ops {
u8 enable, u8 enable,
u32 detect_level, u32 detect_level,
u32 detect_margin); u32 detect_margin);
struct sk_buff *(*ext_resource_config)(struct ath10k *ar,
enum wmi_host_platform_type type,
u32 fw_feature_bitmap);
int (*get_vdev_subtype)(struct ath10k *ar, int (*get_vdev_subtype)(struct ath10k *ar,
enum wmi_vdev_subtype subtype); enum wmi_vdev_subtype subtype);
}; };
...@@ -1329,6 +1332,26 @@ ath10k_wmi_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable, ...@@ -1329,6 +1332,26 @@ ath10k_wmi_pdev_enable_adaptive_cca(struct ath10k *ar, u8 enable,
ar->wmi.cmd->pdev_enable_adaptive_cca_cmdid); ar->wmi.cmd->pdev_enable_adaptive_cca_cmdid);
} }
static inline int
ath10k_wmi_ext_resource_config(struct ath10k *ar,
enum wmi_host_platform_type type,
u32 fw_feature_bitmap)
{
struct sk_buff *skb;
if (!ar->wmi.ops->ext_resource_config)
return -EOPNOTSUPP;
skb = ar->wmi.ops->ext_resource_config(ar, type,
fw_feature_bitmap);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->ext_resource_cfg_cmdid);
}
static inline int static inline int
ath10k_wmi_get_vdev_subtype(struct ath10k *ar, enum wmi_vdev_subtype subtype) ath10k_wmi_get_vdev_subtype(struct ath10k *ar, enum wmi_vdev_subtype subtype)
{ {
......
...@@ -705,6 +705,7 @@ static struct wmi_cmd_map wmi_10_4_cmd_map = { ...@@ -705,6 +705,7 @@ static struct wmi_cmd_map wmi_10_4_cmd_map = {
.set_cca_params_cmdid = WMI_10_4_SET_CCA_PARAMS_CMDID, .set_cca_params_cmdid = WMI_10_4_SET_CCA_PARAMS_CMDID,
.pdev_bss_chan_info_request_cmdid = .pdev_bss_chan_info_request_cmdid =
WMI_10_4_PDEV_BSS_CHAN_INFO_REQUEST_CMDID, WMI_10_4_PDEV_BSS_CHAN_INFO_REQUEST_CMDID,
.ext_resource_cfg_cmdid = WMI_10_4_EXT_RESOURCE_CFG_CMDID,
}; };
/* MAIN WMI VDEV param map */ /* MAIN WMI VDEV param map */
...@@ -2099,34 +2100,6 @@ int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb) ...@@ -2099,34 +2100,6 @@ int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb)
return 0; return 0;
} }
static inline enum ieee80211_band phy_mode_to_band(u32 phy_mode)
{
enum ieee80211_band band;
switch (phy_mode) {
case MODE_11A:
case MODE_11NA_HT20:
case MODE_11NA_HT40:
case MODE_11AC_VHT20:
case MODE_11AC_VHT40:
case MODE_11AC_VHT80:
band = IEEE80211_BAND_5GHZ;
break;
case MODE_11G:
case MODE_11B:
case MODE_11GONLY:
case MODE_11NG_HT20:
case MODE_11NG_HT40:
case MODE_11AC_VHT20_2G:
case MODE_11AC_VHT40_2G:
case MODE_11AC_VHT80_2G:
default:
band = IEEE80211_BAND_2GHZ;
}
return band;
}
/* If keys are configured, HW decrypts all frames /* If keys are configured, HW decrypts all frames
* with protected bit set. Mark such frames as decrypted. * with protected bit set. Mark such frames as decrypted.
*/ */
...@@ -2167,8 +2140,10 @@ static int ath10k_wmi_op_pull_mgmt_rx_ev(struct ath10k *ar, struct sk_buff *skb, ...@@ -2167,8 +2140,10 @@ static int ath10k_wmi_op_pull_mgmt_rx_ev(struct ath10k *ar, struct sk_buff *skb,
struct wmi_mgmt_rx_event_v1 *ev_v1; struct wmi_mgmt_rx_event_v1 *ev_v1;
struct wmi_mgmt_rx_event_v2 *ev_v2; struct wmi_mgmt_rx_event_v2 *ev_v2;
struct wmi_mgmt_rx_hdr_v1 *ev_hdr; struct wmi_mgmt_rx_hdr_v1 *ev_hdr;
struct wmi_mgmt_rx_ext_info *ext_info;
size_t pull_len; size_t pull_len;
u32 msdu_len; u32 msdu_len;
u32 len;
if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features)) { if (test_bit(ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX, ar->fw_features)) {
ev_v2 = (struct wmi_mgmt_rx_event_v2 *)skb->data; ev_v2 = (struct wmi_mgmt_rx_event_v2 *)skb->data;
...@@ -2195,6 +2170,12 @@ static int ath10k_wmi_op_pull_mgmt_rx_ev(struct ath10k *ar, struct sk_buff *skb, ...@@ -2195,6 +2170,12 @@ static int ath10k_wmi_op_pull_mgmt_rx_ev(struct ath10k *ar, struct sk_buff *skb,
if (skb->len < msdu_len) if (skb->len < msdu_len)
return -EPROTO; return -EPROTO;
if (le32_to_cpu(arg->status) & WMI_RX_STATUS_EXT_INFO) {
len = ALIGN(le32_to_cpu(arg->buf_len), 4);
ext_info = (struct wmi_mgmt_rx_ext_info *)(skb->data + len);
memcpy(&arg->ext_info, ext_info,
sizeof(struct wmi_mgmt_rx_ext_info));
}
/* the WMI buffer might've ended up being padded to 4 bytes due to HTC /* the WMI buffer might've ended up being padded to 4 bytes due to HTC
* trailer with credit update. Trim the excess garbage. * trailer with credit update. Trim the excess garbage.
*/ */
...@@ -2211,6 +2192,8 @@ static int ath10k_wmi_10_4_op_pull_mgmt_rx_ev(struct ath10k *ar, ...@@ -2211,6 +2192,8 @@ static int ath10k_wmi_10_4_op_pull_mgmt_rx_ev(struct ath10k *ar,
struct wmi_10_4_mgmt_rx_hdr *ev_hdr; struct wmi_10_4_mgmt_rx_hdr *ev_hdr;
size_t pull_len; size_t pull_len;
u32 msdu_len; u32 msdu_len;
struct wmi_mgmt_rx_ext_info *ext_info;
u32 len;
ev = (struct wmi_10_4_mgmt_rx_event *)skb->data; ev = (struct wmi_10_4_mgmt_rx_event *)skb->data;
ev_hdr = &ev->hdr; ev_hdr = &ev->hdr;
...@@ -2231,6 +2214,13 @@ static int ath10k_wmi_10_4_op_pull_mgmt_rx_ev(struct ath10k *ar, ...@@ -2231,6 +2214,13 @@ static int ath10k_wmi_10_4_op_pull_mgmt_rx_ev(struct ath10k *ar,
if (skb->len < msdu_len) if (skb->len < msdu_len)
return -EPROTO; return -EPROTO;
if (le32_to_cpu(arg->status) & WMI_RX_STATUS_EXT_INFO) {
len = ALIGN(le32_to_cpu(arg->buf_len), 4);
ext_info = (struct wmi_mgmt_rx_ext_info *)(skb->data + len);
memcpy(&arg->ext_info, ext_info,
sizeof(struct wmi_mgmt_rx_ext_info));
}
/* Make sure bytes added for padding are removed. */ /* Make sure bytes added for padding are removed. */
skb_trim(skb, msdu_len); skb_trim(skb, msdu_len);
...@@ -2281,6 +2271,11 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -2281,6 +2271,11 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
if (rx_status & WMI_RX_STATUS_ERR_MIC) if (rx_status & WMI_RX_STATUS_ERR_MIC)
status->flag |= RX_FLAG_MMIC_ERROR; status->flag |= RX_FLAG_MMIC_ERROR;
if (rx_status & WMI_RX_STATUS_EXT_INFO) {
status->mactime =
__le64_to_cpu(arg.ext_info.rx_mac_timestamp);
status->flag |= RX_FLAG_MACTIME_END;
}
/* Hardware can Rx CCK rates on 5GHz. In that case phy_mode is set to /* Hardware can Rx CCK rates on 5GHz. In that case phy_mode is set to
* MODE_11B. This means phy_mode is not a reliable source for the band * MODE_11B. This means phy_mode is not a reliable source for the band
* of mgmt rx. * of mgmt rx.
...@@ -2310,6 +2305,12 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -2310,6 +2305,12 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
hdr = (struct ieee80211_hdr *)skb->data; hdr = (struct ieee80211_hdr *)skb->data;
fc = le16_to_cpu(hdr->frame_control); fc = le16_to_cpu(hdr->frame_control);
/* Firmware is guaranteed to report all essential management frames via
* WMI while it can deliver some extra via HTT. Since there can be
* duplicates split the reporting wrt monitor/sniffing.
*/
status->flag |= RX_FLAG_SKIP_MONITOR;
ath10k_wmi_handle_wep_reauth(ar, skb, status); ath10k_wmi_handle_wep_reauth(ar, skb, status);
/* FW delivers WEP Shared Auth frame with Protected Bit set and /* FW delivers WEP Shared Auth frame with Protected Bit set and
...@@ -2612,6 +2613,16 @@ void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src, ...@@ -2612,6 +2613,16 @@ void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src,
dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate); dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate);
} }
static void
ath10k_wmi_10_4_pull_peer_stats(const struct wmi_10_4_peer_stats *src,
struct ath10k_fw_stats_peer *dst)
{
ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
dst->peer_rssi = __le32_to_cpu(src->peer_rssi);
dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate);
dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
}
static int ath10k_wmi_main_op_pull_fw_stats(struct ath10k *ar, static int ath10k_wmi_main_op_pull_fw_stats(struct ath10k *ar,
struct sk_buff *skb, struct sk_buff *skb,
struct ath10k_fw_stats *stats) struct ath10k_fw_stats *stats)
...@@ -2865,11 +2876,8 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar, ...@@ -2865,11 +2876,8 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar,
const struct wmi_10_2_4_ext_peer_stats *src; const struct wmi_10_2_4_ext_peer_stats *src;
struct ath10k_fw_stats_peer *dst; struct ath10k_fw_stats_peer *dst;
int stats_len; int stats_len;
bool ext_peer_stats_support;
ext_peer_stats_support = test_bit(WMI_SERVICE_PEER_STATS, if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map))
ar->wmi.svc_map);
if (ext_peer_stats_support)
stats_len = sizeof(struct wmi_10_2_4_ext_peer_stats); stats_len = sizeof(struct wmi_10_2_4_ext_peer_stats);
else else
stats_len = sizeof(struct wmi_10_2_4_peer_stats); stats_len = sizeof(struct wmi_10_2_4_peer_stats);
...@@ -2886,7 +2894,7 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar, ...@@ -2886,7 +2894,7 @@ static int ath10k_wmi_10_2_4_op_pull_fw_stats(struct ath10k *ar,
dst->peer_rx_rate = __le32_to_cpu(src->common.peer_rx_rate); dst->peer_rx_rate = __le32_to_cpu(src->common.peer_rx_rate);
if (ext_peer_stats_support) if (ath10k_peer_stats_enabled(ar))
dst->rx_duration = __le32_to_cpu(src->rx_duration); dst->rx_duration = __le32_to_cpu(src->rx_duration);
/* FIXME: expose 10.2 specific values */ /* FIXME: expose 10.2 specific values */
...@@ -2905,6 +2913,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar, ...@@ -2905,6 +2913,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
u32 num_pdev_ext_stats; u32 num_pdev_ext_stats;
u32 num_vdev_stats; u32 num_vdev_stats;
u32 num_peer_stats; u32 num_peer_stats;
u32 stats_id;
int i; int i;
if (!skb_pull(skb, sizeof(*ev))) if (!skb_pull(skb, sizeof(*ev)))
...@@ -2914,6 +2923,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar, ...@@ -2914,6 +2923,7 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats); num_pdev_ext_stats = __le32_to_cpu(ev->num_pdev_ext_stats);
num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
num_peer_stats = __le32_to_cpu(ev->num_peer_stats); num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
stats_id = __le32_to_cpu(ev->stats_id);
for (i = 0; i < num_pdev_stats; i++) { for (i = 0; i < num_pdev_stats; i++) {
const struct wmi_10_4_pdev_stats *src; const struct wmi_10_4_pdev_stats *src;
...@@ -2953,22 +2963,28 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar, ...@@ -2953,22 +2963,28 @@ static int ath10k_wmi_10_4_op_pull_fw_stats(struct ath10k *ar,
/* fw doesn't implement vdev stats */ /* fw doesn't implement vdev stats */
for (i = 0; i < num_peer_stats; i++) { for (i = 0; i < num_peer_stats; i++) {
const struct wmi_10_4_peer_stats *src; const struct wmi_10_4_peer_extd_stats *src;
struct ath10k_fw_stats_peer *dst; struct ath10k_fw_stats_peer *dst;
int stats_len;
bool extd_peer_stats = !!(stats_id & WMI_10_4_STAT_PEER_EXTD);
if (extd_peer_stats)
stats_len = sizeof(struct wmi_10_4_peer_extd_stats);
else
stats_len = sizeof(struct wmi_10_4_peer_stats);
src = (void *)skb->data; src = (void *)skb->data;
if (!skb_pull(skb, sizeof(*src))) if (!skb_pull(skb, stats_len))
return -EPROTO; return -EPROTO;
dst = kzalloc(sizeof(*dst), GFP_ATOMIC); dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
if (!dst) if (!dst)
continue; continue;
ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr); ath10k_wmi_10_4_pull_peer_stats(&src->common, dst);
dst->peer_rssi = __le32_to_cpu(src->peer_rssi);
dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate);
dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
/* FIXME: expose 10.4 specific values */ /* FIXME: expose 10.4 specific values */
if (extd_peer_stats)
dst->rx_duration = __le32_to_cpu(src->rx_duration);
list_add_tail(&dst->list, &stats->peers); list_add_tail(&dst->list, &stats->peers);
} }
...@@ -4617,10 +4633,16 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work) ...@@ -4617,10 +4633,16 @@ static void ath10k_wmi_event_service_ready_work(struct work_struct *work)
} }
if (test_bit(WMI_SERVICE_PEER_CACHING, ar->wmi.svc_map)) { if (test_bit(WMI_SERVICE_PEER_CACHING, ar->wmi.svc_map)) {
if (test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
ar->fw_features))
ar->num_active_peers = TARGET_10_4_QCACHE_ACTIVE_PEERS_PFC +
ar->max_num_vdevs;
else
ar->num_active_peers = TARGET_10_4_QCACHE_ACTIVE_PEERS +
ar->max_num_vdevs;
ar->max_num_peers = TARGET_10_4_NUM_QCACHE_PEERS_MAX + ar->max_num_peers = TARGET_10_4_NUM_QCACHE_PEERS_MAX +
ar->max_num_vdevs; ar->max_num_vdevs;
ar->num_active_peers = ar->hw_params.qcache_active_peers +
ar->max_num_vdevs;
ar->num_tids = ar->num_active_peers * 2; ar->num_tids = ar->num_active_peers * 2;
ar->max_num_stations = TARGET_10_4_NUM_QCACHE_PEERS_MAX; ar->max_num_stations = TARGET_10_4_NUM_QCACHE_PEERS_MAX;
} }
...@@ -5517,7 +5539,8 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar) ...@@ -5517,7 +5539,8 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS);
config.num_peer_keys = __cpu_to_le32(TARGET_10X_NUM_PEER_KEYS); config.num_peer_keys = __cpu_to_le32(TARGET_10X_NUM_PEER_KEYS);
if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) {
if (ath10k_peer_stats_enabled(ar)) {
config.num_peers = __cpu_to_le32(TARGET_10X_TX_STATS_NUM_PEERS); config.num_peers = __cpu_to_le32(TARGET_10X_TX_STATS_NUM_PEERS);
config.num_tids = __cpu_to_le32(TARGET_10X_TX_STATS_NUM_TIDS); config.num_tids = __cpu_to_le32(TARGET_10X_TX_STATS_NUM_TIDS);
} else { } else {
...@@ -5579,7 +5602,7 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar) ...@@ -5579,7 +5602,7 @@ static struct sk_buff *ath10k_wmi_10_2_op_gen_init(struct ath10k *ar)
test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map)) test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map))
features |= WMI_10_2_COEX_GPIO; features |= WMI_10_2_COEX_GPIO;
if (test_bit(WMI_SERVICE_PEER_STATS, ar->wmi.svc_map)) if (ath10k_peer_stats_enabled(ar))
features |= WMI_10_2_PEER_STATS; features |= WMI_10_2_PEER_STATS;
cmd->resource_config.feature_mask = __cpu_to_le32(features); cmd->resource_config.feature_mask = __cpu_to_le32(features);
...@@ -7484,6 +7507,28 @@ static int ath10k_wmi_10_4_op_get_vdev_subtype(struct ath10k *ar, ...@@ -7484,6 +7507,28 @@ static int ath10k_wmi_10_4_op_get_vdev_subtype(struct ath10k *ar,
return -ENOTSUPP; return -ENOTSUPP;
} }
static struct sk_buff *
ath10k_wmi_10_4_ext_resource_config(struct ath10k *ar,
enum wmi_host_platform_type type,
u32 fw_feature_bitmap)
{
struct wmi_ext_resource_config_10_4_cmd *cmd;
struct sk_buff *skb;
skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
if (!skb)
return ERR_PTR(-ENOMEM);
cmd = (struct wmi_ext_resource_config_10_4_cmd *)skb->data;
cmd->host_platform_config = __cpu_to_le32(type);
cmd->fw_feature_bitmap = __cpu_to_le32(fw_feature_bitmap);
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi ext resource config host type %d firmware feature bitmap %08x\n",
type, fw_feature_bitmap);
return skb;
}
static const struct wmi_ops wmi_ops = { static const struct wmi_ops wmi_ops = {
.rx = ath10k_wmi_op_rx, .rx = ath10k_wmi_op_rx,
.map_svc = wmi_main_svc_map, .map_svc = wmi_main_svc_map,
...@@ -7810,6 +7855,7 @@ static const struct wmi_ops wmi_10_4_ops = { ...@@ -7810,6 +7855,7 @@ static const struct wmi_ops wmi_10_4_ops = {
.gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp, .gen_addba_set_resp = ath10k_wmi_op_gen_addba_set_resp,
.gen_delba_send = ath10k_wmi_op_gen_delba_send, .gen_delba_send = ath10k_wmi_op_gen_delba_send,
.fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill, .fw_stats_fill = ath10k_wmi_10_4_op_fw_stats_fill,
.ext_resource_config = ath10k_wmi_10_4_ext_resource_config,
/* shared with 10.2 */ /* shared with 10.2 */
.gen_request_stats = ath10k_wmi_op_gen_request_stats, .gen_request_stats = ath10k_wmi_op_gen_request_stats,
......
...@@ -816,6 +816,7 @@ struct wmi_cmd_map { ...@@ -816,6 +816,7 @@ struct wmi_cmd_map {
u32 set_cca_params_cmdid; u32 set_cca_params_cmdid;
u32 pdev_bss_chan_info_request_cmdid; u32 pdev_bss_chan_info_request_cmdid;
u32 pdev_enable_adaptive_cca_cmdid; u32 pdev_enable_adaptive_cca_cmdid;
u32 ext_resource_cfg_cmdid;
}; };
/* /*
...@@ -2667,6 +2668,31 @@ struct wmi_resource_config_10_4 { ...@@ -2667,6 +2668,31 @@ struct wmi_resource_config_10_4 {
__le32 qwrap_config; __le32 qwrap_config;
} __packed; } __packed;
/**
* enum wmi_10_4_feature_mask - WMI 10.4 feature enable/disable flags
* @WMI_10_4_LTEU_SUPPORT: LTEU config
* @WMI_10_4_COEX_GPIO_SUPPORT: COEX GPIO config
* @WMI_10_4_AUX_RADIO_SPECTRAL_INTF: AUX Radio Enhancement for spectral scan
* @WMI_10_4_AUX_RADIO_CHAN_LOAD_INTF: AUX Radio Enhancement for chan load scan
* @WMI_10_4_BSS_CHANNEL_INFO_64: BSS channel info stats
* @WMI_10_4_PEER_STATS: Per station stats
*/
enum wmi_10_4_feature_mask {
WMI_10_4_LTEU_SUPPORT = BIT(0),
WMI_10_4_COEX_GPIO_SUPPORT = BIT(1),
WMI_10_4_AUX_RADIO_SPECTRAL_INTF = BIT(2),
WMI_10_4_AUX_RADIO_CHAN_LOAD_INTF = BIT(3),
WMI_10_4_BSS_CHANNEL_INFO_64 = BIT(4),
WMI_10_4_PEER_STATS = BIT(5),
};
struct wmi_ext_resource_config_10_4_cmd {
/* contains enum wmi_host_platform_type */
__le32 host_platform_config;
/* see enum wmi_10_4_feature_mask */
__le32 fw_feature_bitmap;
};
/* strucutre describing host memory chunk. */ /* strucutre describing host memory chunk. */
struct host_memory_chunk { struct host_memory_chunk {
/* id of the request that is passed up in service ready */ /* id of the request that is passed up in service ready */
...@@ -3037,11 +3063,17 @@ struct wmi_10_4_mgmt_rx_event { ...@@ -3037,11 +3063,17 @@ struct wmi_10_4_mgmt_rx_event {
u8 buf[0]; u8 buf[0];
} __packed; } __packed;
struct wmi_mgmt_rx_ext_info {
__le64 rx_mac_timestamp;
} __packed __aligned(4);
#define WMI_RX_STATUS_OK 0x00 #define WMI_RX_STATUS_OK 0x00
#define WMI_RX_STATUS_ERR_CRC 0x01 #define WMI_RX_STATUS_ERR_CRC 0x01
#define WMI_RX_STATUS_ERR_DECRYPT 0x08 #define WMI_RX_STATUS_ERR_DECRYPT 0x08
#define WMI_RX_STATUS_ERR_MIC 0x10 #define WMI_RX_STATUS_ERR_MIC 0x10
#define WMI_RX_STATUS_ERR_KEY_CACHE_MISS 0x20 #define WMI_RX_STATUS_ERR_KEY_CACHE_MISS 0x20
/* Extension data at the end of mgmt frame */
#define WMI_RX_STATUS_EXT_INFO 0x40
#define PHY_ERROR_GEN_SPECTRAL_SCAN 0x26 #define PHY_ERROR_GEN_SPECTRAL_SCAN 0x26
#define PHY_ERROR_GEN_FALSE_RADAR_EXT 0x24 #define PHY_ERROR_GEN_FALSE_RADAR_EXT 0x24
...@@ -4072,6 +4104,13 @@ enum wmi_stats_id { ...@@ -4072,6 +4104,13 @@ enum wmi_stats_id {
WMI_STAT_VDEV_RATE = BIT(5), WMI_STAT_VDEV_RATE = BIT(5),
}; };
enum wmi_10_4_stats_id {
WMI_10_4_STAT_PEER = BIT(0),
WMI_10_4_STAT_AP = BIT(1),
WMI_10_4_STAT_INST = BIT(2),
WMI_10_4_STAT_PEER_EXTD = BIT(3),
};
struct wlan_inst_rssi_args { struct wlan_inst_rssi_args {
__le16 cfg_retry_count; __le16 cfg_retry_count;
__le16 retry_count; __le16 retry_count;
...@@ -4271,6 +4310,15 @@ struct wmi_10_4_peer_stats { ...@@ -4271,6 +4310,15 @@ struct wmi_10_4_peer_stats {
__le32 peer_rssi_changed; __le32 peer_rssi_changed;
} __packed; } __packed;
struct wmi_10_4_peer_extd_stats {
struct wmi_10_4_peer_stats common;
struct wmi_mac_addr peer_macaddr;
__le32 inactive_time;
__le32 peer_chain_rssi;
__le32 rx_duration;
__le32 reserved[10];
} __packed;
struct wmi_10_2_pdev_ext_stats { struct wmi_10_2_pdev_ext_stats {
__le32 rx_rssi_comb; __le32 rx_rssi_comb;
__le32 rx_rssi[4]; __le32 rx_rssi[4];
...@@ -6116,6 +6164,7 @@ struct wmi_mgmt_rx_ev_arg { ...@@ -6116,6 +6164,7 @@ struct wmi_mgmt_rx_ev_arg {
__le32 phy_mode; __le32 phy_mode;
__le32 buf_len; __le32 buf_len;
__le32 status; /* %WMI_RX_STATUS_ */ __le32 status; /* %WMI_RX_STATUS_ */
struct wmi_mgmt_rx_ext_info ext_info;
}; };
struct wmi_ch_info_ev_arg { struct wmi_ch_info_ev_arg {
...@@ -6401,6 +6450,11 @@ struct wmi_pdev_set_adaptive_cca_params { ...@@ -6401,6 +6450,11 @@ struct wmi_pdev_set_adaptive_cca_params {
__le32 cca_detect_margin; __le32 cca_detect_margin;
} __packed; } __packed;
enum wmi_host_platform_type {
WMI_HOST_PLATFORM_HIGH_PERF,
WMI_HOST_PLATFORM_LOW_PERF,
};
struct ath10k; struct ath10k;
struct ath10k_vif; struct ath10k_vif;
struct ath10k_fw_stats_pdev; struct ath10k_fw_stats_pdev;
......
...@@ -77,7 +77,7 @@ static const struct pci_device_id ath5k_led_devices[] = { ...@@ -77,7 +77,7 @@ static const struct pci_device_id ath5k_led_devices[] = {
/* HP Compaq CQ60-206US (ddreggors@jumptv.com) */ /* HP Compaq CQ60-206US (ddreggors@jumptv.com) */
{ ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137a), ATH_LED(3, 1) }, { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137a), ATH_LED(3, 1) },
/* HP Compaq C700 (nitrousnrg@gmail.com) */ /* HP Compaq C700 (nitrousnrg@gmail.com) */
{ ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) }, { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 0) },
/* LiteOn AR5BXB63 (magooz@salug.it) */ /* LiteOn AR5BXB63 (magooz@salug.it) */
{ ATH_SDEVICE(PCI_VENDOR_ID_ATHEROS, 0x3067), ATH_LED(3, 0) }, { ATH_SDEVICE(PCI_VENDOR_ID_ATHEROS, 0x3067), ATH_LED(3, 0) },
/* IBM-specific AR5212 (all others) */ /* IBM-specific AR5212 (all others) */
......
...@@ -1446,7 +1446,7 @@ ath5k_hw_channel(struct ath5k_hw *ah, ...@@ -1446,7 +1446,7 @@ ath5k_hw_channel(struct ath5k_hw *ah,
"channel frequency (%u MHz) out of supported " "channel frequency (%u MHz) out of supported "
"band range\n", "band range\n",
channel->center_freq); channel->center_freq);
return -EINVAL; return -EINVAL;
} }
/* /*
......
...@@ -634,7 +634,7 @@ ath5k_hw_on_hold(struct ath5k_hw *ah) ...@@ -634,7 +634,7 @@ ath5k_hw_on_hold(struct ath5k_hw *ah)
ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
usleep_range(2000, 2500); usleep_range(2000, 2500);
} else { } else {
ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
AR5K_RESET_CTL_BASEBAND | bus_flags); AR5K_RESET_CTL_BASEBAND | bus_flags);
...@@ -699,7 +699,7 @@ ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) ...@@ -699,7 +699,7 @@ ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel)
ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU |
AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA |
AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI);
usleep_range(2000, 2500); usleep_range(2000, 2500);
} else { } else {
if (ath5k_get_bus_type(ah) == ATH_AHB) if (ath5k_get_bus_type(ah) == ATH_AHB)
ret = ath5k_hw_wisoc_reset(ah, AR5K_RESET_CTL_PCU | ret = ath5k_hw_wisoc_reset(ah, AR5K_RESET_CTL_PCU |
......
...@@ -1584,6 +1584,11 @@ static int ath6kl_wmi_txe_notify_event_rx(struct wmi *wmi, u8 *datap, int len, ...@@ -1584,6 +1584,11 @@ static int ath6kl_wmi_txe_notify_event_rx(struct wmi *wmi, u8 *datap, int len,
if (len < sizeof(*ev)) if (len < sizeof(*ev))
return -EINVAL; return -EINVAL;
if (vif->nw_type != INFRA_NETWORK ||
!test_bit(ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY,
vif->ar->fw_capabilities))
return -EOPNOTSUPP;
if (vif->sme_state != SME_CONNECTED) if (vif->sme_state != SME_CONNECTED)
return -ENOTCONN; return -ENOTCONN;
......
...@@ -331,7 +331,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = { ...@@ -331,7 +331,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = {
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
{0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220},
{0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
...@@ -351,7 +351,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = { ...@@ -351,7 +351,7 @@ static const u32 ar9300_2p2_baseband_postamble[][5] = {
{0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
{0x0000a2d0, 0x00041983, 0x00041983, 0x00041981, 0x00041982}, {0x0000a2d0, 0x00041983, 0x00041983, 0x00041981, 0x00041982},
{0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
......
...@@ -1203,12 +1203,12 @@ static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah) ...@@ -1203,12 +1203,12 @@ static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah)
static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
{ {
int offset[8] = {0}, total = 0, test; int offset[8] = {0}, total = 0, test;
int agc_out, i, peak_detect_threshold; int agc_out, i, peak_detect_threshold = 0;
if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) if (AR_SREV_9550(ah) || AR_SREV_9531(ah))
peak_detect_threshold = 8; peak_detect_threshold = 8;
else else if (AR_SREV_9561(ah))
peak_detect_threshold = 0; peak_detect_threshold = 11;
/* /*
* Turn off LNA/SW. * Turn off LNA/SW.
...@@ -1249,17 +1249,14 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g) ...@@ -1249,17 +1249,14 @@ static void ar9003_hw_manual_peak_cal(struct ath_hw *ah, u8 chain, bool is_2g)
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0); AR_PHY_65NM_RXRF_AGC_AGC2G_CALDAC_OVR, 0x0);
if (AR_SREV_9003_PCOEM(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) || if (is_2g)
AR_SREV_9561(ah)) { REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
if (is_2g) AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR,
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), peak_detect_threshold);
AR_PHY_65NM_RXRF_AGC_AGC2G_DBDAC_OVR, else
peak_detect_threshold); REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain),
else AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR,
REG_RMW_FIELD(ah, AR_PHY_65NM_RXRF_AGC(chain), peak_detect_threshold);
AR_PHY_65NM_RXRF_AGC_AGC5G_DBDAC_OVR,
peak_detect_threshold);
}
for (i = 6; i > 0; i--) { for (i = 6; i > 0; i--) {
offset[i] = BIT(i - 1); offset[i] = BIT(i - 1);
...@@ -1311,9 +1308,6 @@ static void ar9003_hw_do_pcoem_manual_peak_cal(struct ath_hw *ah, ...@@ -1311,9 +1308,6 @@ static void ar9003_hw_do_pcoem_manual_peak_cal(struct ath_hw *ah,
struct ath9k_hw_cal_data *caldata = ah->caldata; struct ath9k_hw_cal_data *caldata = ah->caldata;
int i; int i;
if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah) && !AR_SREV_9485(ah))
return;
if ((ah->caps.hw_caps & ATH9K_HW_CAP_RTT) && !run_rtt_cal) if ((ah->caps.hw_caps & ATH9K_HW_CAP_RTT) && !run_rtt_cal)
return; return;
...@@ -1641,14 +1635,12 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah, ...@@ -1641,14 +1635,12 @@ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
skip_tx_iqcal: skip_tx_iqcal:
if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) { if (run_agc_cal || !(ah->ah_flags & AH_FASTCC)) {
if (AR_SREV_9330_11(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah) || for (i = 0; i < AR9300_MAX_CHAINS; i++) {
AR_SREV_9561(ah)) { if (!(ah->rxchainmask & (1 << i)))
for (i = 0; i < AR9300_MAX_CHAINS; i++) { continue;
if (!(ah->rxchainmask & (1 << i)))
continue; ar9003_hw_manual_peak_cal(ah, i,
ar9003_hw_manual_peak_cal(ah, i, IS_CHAN_2GHZ(chan));
IS_CHAN_2GHZ(chan));
}
} }
/* /*
...@@ -1709,7 +1701,7 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah) ...@@ -1709,7 +1701,7 @@ void ar9003_hw_attach_calib_ops(struct ath_hw *ah)
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
struct ath_hw_ops *ops = ath9k_hw_ops(ah); struct ath_hw_ops *ops = ath9k_hw_ops(ah);
if (AR_SREV_9485(ah) || AR_SREV_9462(ah) || AR_SREV_9565(ah)) if (AR_SREV_9003_PCOEM(ah))
priv_ops->init_cal = ar9003_hw_init_cal_pcoem; priv_ops->init_cal = ar9003_hw_init_cal_pcoem;
else else
priv_ops->init_cal = ar9003_hw_init_cal_soc; priv_ops->init_cal = ar9003_hw_init_cal_soc;
......
...@@ -3590,8 +3590,8 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) ...@@ -3590,8 +3590,8 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
else else
gpio = AR9300_EXT_LNA_CTL_GPIO_AR9485; gpio = AR9300_EXT_LNA_CTL_GPIO_AR9485;
ath9k_hw_cfg_output(ah, gpio, ath9k_hw_gpio_request_out(ah, gpio, NULL,
AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED); AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED);
} }
value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz); value = ar9003_hw_ant_ctrl_common_get(ah, is2ghz);
...@@ -4097,16 +4097,16 @@ static void ar9003_hw_thermometer_apply(struct ath_hw *ah) ...@@ -4097,16 +4097,16 @@ static void ar9003_hw_thermometer_apply(struct ath_hw *ah)
REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on); AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on);
therm_on = (thermometer < 0) ? 0 : (thermometer == 0); therm_on = thermometer == 0;
REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4, REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4,
AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on);
if (pCap->chip_chainmask & BIT(1)) { if (pCap->chip_chainmask & BIT(1)) {
therm_on = (thermometer < 0) ? 0 : (thermometer == 1); therm_on = thermometer == 1;
REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4, REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4,
AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on);
} }
if (pCap->chip_chainmask & BIT(2)) { if (pCap->chip_chainmask & BIT(2)) {
therm_on = (thermometer < 0) ? 0 : (thermometer == 2); therm_on = thermometer == 2;
REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on);
} }
......
...@@ -427,21 +427,34 @@ static void ar9003_mci_observation_set_up(struct ath_hw *ah) ...@@ -427,21 +427,34 @@ static void ar9003_mci_observation_set_up(struct ath_hw *ah)
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
if (mci->config & ATH_MCI_CONFIG_MCI_OBS_MCI) { if (mci->config & ATH_MCI_CONFIG_MCI_OBS_MCI) {
ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA); ath9k_hw_gpio_request_out(ah, 3, NULL,
ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK); AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_DATA);
ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA); ath9k_hw_gpio_request_out(ah, 2, NULL,
ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK); AR_GPIO_OUTPUT_MUX_AS_MCI_WLAN_CLK);
ath9k_hw_gpio_request_out(ah, 1, NULL,
AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
ath9k_hw_gpio_request_out(ah, 0, NULL,
AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);
} else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_TXRX) { } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_TXRX) {
ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX); ath9k_hw_gpio_request_out(ah, 3, NULL,
ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX); AR_GPIO_OUTPUT_MUX_AS_WL_IN_TX);
ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX); ath9k_hw_gpio_request_out(ah, 2, NULL,
ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX); AR_GPIO_OUTPUT_MUX_AS_WL_IN_RX);
ath9k_hw_cfg_output(ah, 5, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ath9k_hw_gpio_request_out(ah, 1, NULL,
AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
ath9k_hw_gpio_request_out(ah, 0, NULL,
AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX);
ath9k_hw_gpio_request_out(ah, 5, NULL,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
} else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_BT) { } else if (mci->config & ATH_MCI_CONFIG_MCI_OBS_BT) {
ath9k_hw_cfg_output(ah, 3, AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX); ath9k_hw_gpio_request_out(ah, 3, NULL,
ath9k_hw_cfg_output(ah, 2, AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX); AR_GPIO_OUTPUT_MUX_AS_BT_IN_TX);
ath9k_hw_cfg_output(ah, 1, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA); ath9k_hw_gpio_request_out(ah, 2, NULL,
ath9k_hw_cfg_output(ah, 0, AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK); AR_GPIO_OUTPUT_MUX_AS_BT_IN_RX);
ath9k_hw_gpio_request_out(ah, 1, NULL,
AR_GPIO_OUTPUT_MUX_AS_MCI_BT_DATA);
ath9k_hw_gpio_request_out(ah, 0, NULL,
AR_GPIO_OUTPUT_MUX_AS_MCI_BT_CLK);
} else } else
return; return;
......
...@@ -1337,11 +1337,11 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, ...@@ -1337,11 +1337,11 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
chan->channel, chan->channel,
aniState->mrcCCK ? "on" : "off", aniState->mrcCCK ? "on" : "off",
is_on ? "on" : "off"); is_on ? "on" : "off");
if (is_on) if (is_on)
ah->stats.ast_ani_ccklow++; ah->stats.ast_ani_ccklow++;
else else
ah->stats.ast_ani_cckhigh++; ah->stats.ast_ani_cckhigh++;
aniState->mrcCCK = is_on; aniState->mrcCCK = is_on;
} }
break; break;
} }
......
...@@ -40,7 +40,7 @@ static const u32 ar9331_1p1_baseband_postamble[][5] = { ...@@ -40,7 +40,7 @@ static const u32 ar9331_1p1_baseband_postamble[][5] = {
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
{0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222}, {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220},
{0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324}, {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
...@@ -59,7 +59,7 @@ static const u32 ar9331_1p1_baseband_postamble[][5] = { ...@@ -59,7 +59,7 @@ static const u32 ar9331_1p1_baseband_postamble[][5] = {
{0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18}, {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
{0x0000a2d0, 0x00071982, 0x00071982, 0x00071982, 0x00071982}, {0x0000a2d0, 0x00071982, 0x00071982, 0x00071982, 0x00071982},
{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
......
...@@ -345,7 +345,7 @@ static const u32 ar9331_1p2_baseband_postamble[][5] = { ...@@ -345,7 +345,7 @@ static const u32 ar9331_1p2_baseband_postamble[][5] = {
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00003221, 0x00003221},
{0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946222, 0xcf946222}, {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220},
{0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324}, {0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
...@@ -364,7 +364,7 @@ static const u32 ar9331_1p2_baseband_postamble[][5] = { ...@@ -364,7 +364,7 @@ static const u32 ar9331_1p2_baseband_postamble[][5] = {
{0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a284, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
{0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981}, {0x0000a2d0, 0x00071981, 0x00071981, 0x00071981, 0x00071981},
{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
......
...@@ -245,7 +245,7 @@ static const u32 ar9340_1p0_baseband_postamble[][5] = { ...@@ -245,7 +245,7 @@ static const u32 ar9340_1p0_baseband_postamble[][5] = {
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
{0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220},
{0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
...@@ -265,7 +265,7 @@ static const u32 ar9340_1p0_baseband_postamble[][5] = { ...@@ -265,7 +265,7 @@ static const u32 ar9340_1p0_baseband_postamble[][5] = {
{0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
{0x0000a288, 0x00000220, 0x00000220, 0x00000110, 0x00000110}, {0x0000a288, 0x00000220, 0x00000220, 0x00000110, 0x00000110},
{0x0000a28c, 0x00011111, 0x00011111, 0x00022222, 0x00022222}, {0x0000a28c, 0x00011111, 0x00011111, 0x00022222, 0x00022222},
{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
{0x0000a2d0, 0x00041983, 0x00041983, 0x00041982, 0x00041982}, {0x0000a2d0, 0x00041983, 0x00041983, 0x00041982, 0x00041982},
{0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a}, {0x0000a2d8, 0x7999a83a, 0x7999a83a, 0x7999a83a, 0x7999a83a},
{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
......
...@@ -59,7 +59,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { ...@@ -59,7 +59,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003a5, 0x000003a5, 0x000003a5, 0x000003a5}, {0x00009e20, 0x000003a5, 0x000003a5, 0x000003a5, 0x000003a5},
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
{0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c780, 0xcfd5c280},
{0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
...@@ -79,7 +79,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = { ...@@ -79,7 +79,7 @@ static const u32 ar9462_2p0_baseband_postamble[][5] = {
{0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
{0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
{0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
......
...@@ -239,7 +239,7 @@ static const u32 ar9462_2p1_baseband_postamble[][5] = { ...@@ -239,7 +239,7 @@ static const u32 ar9462_2p1_baseband_postamble[][5] = {
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003a5, 0x000003a5, 0x000003a5, 0x000003a5}, {0x00009e20, 0x000003a5, 0x000003a5, 0x000003a5, 0x000003a5},
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
{0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c782, 0xcfd5c282}, {0x00009e3c, 0xcf946220, 0xcf946220, 0xcfd5c780, 0xcfd5c280},
{0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27}, {0x00009e44, 0x62321e27, 0x62321e27, 0xfe291e27, 0xfe291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
...@@ -259,7 +259,7 @@ static const u32 ar9462_2p1_baseband_postamble[][5] = { ...@@ -259,7 +259,7 @@ static const u32 ar9462_2p1_baseband_postamble[][5] = {
{0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
{0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982}, {0x0000a2d0, 0x00041981, 0x00041981, 0x00041981, 0x00041982},
{0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
......
...@@ -1026,7 +1026,7 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = { ...@@ -1026,7 +1026,7 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = {
{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e}, {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e},
{0x00009e14, 0x31395d53, 0x31396053, 0x312e6053, 0x312e5d53}, {0x00009e14, 0x31395d53, 0x31396053, 0x312e6053, 0x312e5d53},
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
{0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0}, {0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0},
...@@ -1044,7 +1044,7 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = { ...@@ -1044,7 +1044,7 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = {
{0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0}, {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0},
{0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
{0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982}, {0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982},
{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
......
...@@ -988,7 +988,7 @@ static const u32 qca953x_2p0_baseband_postamble[][5] = { ...@@ -988,7 +988,7 @@ static const u32 qca953x_2p0_baseband_postamble[][5] = {
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
{0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcf946222, 0xcf946222}, {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcf946220, 0xcf946220},
{0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
...@@ -1008,7 +1008,7 @@ static const u32 qca953x_2p0_baseband_postamble[][5] = { ...@@ -1008,7 +1008,7 @@ static const u32 qca953x_2p0_baseband_postamble[][5] = {
{0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18},
{0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33}, {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33},
{0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982}, {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982},
{0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
......
...@@ -83,7 +83,7 @@ static const u32 ar955x_1p0_baseband_postamble[][5] = { ...@@ -83,7 +83,7 @@ static const u32 ar955x_1p0_baseband_postamble[][5] = {
{0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, {0x0000a284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18}, {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
{0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33}, {0x0000a2cc, 0x18c50033, 0x18c43433, 0x18c41033, 0x18c44c33},
{0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982}, {0x0000a2d0, 0x00041982, 0x00041982, 0x00041982, 0x00041982},
{0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
......
...@@ -347,7 +347,7 @@ static const u32 ar9565_1p0_baseband_postamble[][5] = { ...@@ -347,7 +347,7 @@ static const u32 ar9565_1p0_baseband_postamble[][5] = {
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003a4, 0x000003a4}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003a4, 0x000003a4},
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
{0x00009e3c, 0xcf946222, 0xcf946222, 0xcf946220, 0xcf946220}, {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220},
{0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
......
...@@ -220,7 +220,7 @@ static const u32 qca956x_1p0_baseband_postamble[][5] = { ...@@ -220,7 +220,7 @@ static const u32 qca956x_1p0_baseband_postamble[][5] = {
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003a6, 0x000003a6}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003a6, 0x000003a6},
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
{0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcf946222, 0xcf946222}, {0x00009e3c, 0xcfa10820, 0xcfa10820, 0xcf946220, 0xcf946220},
{0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
......
...@@ -1290,7 +1290,7 @@ static const u32 ar9580_1p0_baseband_postamble[][5] = { ...@@ -1290,7 +1290,7 @@ static const u32 ar9580_1p0_baseband_postamble[][5] = {
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c}, {0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce}, {0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021}, {0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
{0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222}, {0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946220, 0xcf946220},
{0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27}, {0x00009e44, 0x02321e27, 0x02321e27, 0x02291e27, 0x02291e27},
{0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000}, {0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
...@@ -1310,7 +1310,7 @@ static const u32 ar9580_1p0_baseband_postamble[][5] = { ...@@ -1310,7 +1310,7 @@ static const u32 ar9580_1p0_baseband_postamble[][5] = {
{0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150}, {0x0000a284, 0x00000000, 0x00000000, 0x00000150, 0x00000150},
{0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110}, {0x0000a288, 0x00000110, 0x00000110, 0x00000110, 0x00000110},
{0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222}, {0x0000a28c, 0x00022222, 0x00022222, 0x00022222, 0x00022222},
{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, {0x0000a2c4, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18},
{0x0000a2d0, 0x00041983, 0x00041983, 0x00041981, 0x00041982}, {0x0000a2d0, 0x00041983, 0x00041983, 0x00041981, 0x00041982},
{0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b}, {0x0000a2d8, 0x7999a83b, 0x7999a83b, 0x7999a83b, 0x7999a83b},
{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
......
...@@ -813,7 +813,6 @@ static inline int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size) ...@@ -813,7 +813,6 @@ static inline int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
#ifdef CONFIG_MAC80211_LEDS #ifdef CONFIG_MAC80211_LEDS
void ath_init_leds(struct ath_softc *sc); void ath_init_leds(struct ath_softc *sc);
void ath_deinit_leds(struct ath_softc *sc); void ath_deinit_leds(struct ath_softc *sc);
void ath_fill_led_pin(struct ath_softc *sc);
#else #else
static inline void ath_init_leds(struct ath_softc *sc) static inline void ath_init_leds(struct ath_softc *sc)
{ {
...@@ -822,9 +821,6 @@ static inline void ath_init_leds(struct ath_softc *sc) ...@@ -822,9 +821,6 @@ static inline void ath_init_leds(struct ath_softc *sc)
static inline void ath_deinit_leds(struct ath_softc *sc) static inline void ath_deinit_leds(struct ath_softc *sc)
{ {
} }
static inline void ath_fill_led_pin(struct ath_softc *sc)
{
}
#endif #endif
/************************/ /************************/
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
*/ */
#include <linux/export.h> #include <linux/export.h>
#include <linux/types.h>
#include <linux/ath9k_platform.h>
#include "hw.h" #include "hw.h"
enum ath_bt_mode { enum ath_bt_mode {
...@@ -34,6 +36,8 @@ struct ath_btcoex_config { ...@@ -34,6 +36,8 @@ struct ath_btcoex_config {
u8 bt_priority_time; u8 bt_priority_time;
u8 bt_first_slot_time; u8 bt_first_slot_time;
bool bt_hold_rx_clear; bool bt_hold_rx_clear;
u8 wl_active_time;
u8 wl_qc_time;
}; };
static const u32 ar9003_wlan_weights[ATH_BTCOEX_STOMP_MAX] static const u32 ar9003_wlan_weights[ATH_BTCOEX_STOMP_MAX]
...@@ -65,31 +69,71 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum) ...@@ -65,31 +69,71 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
.bt_priority_time = 2, .bt_priority_time = 2,
.bt_first_slot_time = 5, .bt_first_slot_time = 5,
.bt_hold_rx_clear = true, .bt_hold_rx_clear = true,
.wl_active_time = 0x20,
.wl_qc_time = 0x20,
}; };
bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity; bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity;
u8 time_extend = ath_bt_config.bt_time_extend;
u8 first_slot_time = ath_bt_config.bt_first_slot_time;
if (AR_SREV_9300_20_OR_LATER(ah)) if (AR_SREV_9300_20_OR_LATER(ah))
rxclear_polarity = !ath_bt_config.bt_rxclear_polarity; rxclear_polarity = !ath_bt_config.bt_rxclear_polarity;
if (AR_SREV_SOC(ah)) {
first_slot_time = 0x1d;
time_extend = 0xa;
btcoex_hw->bt_coex_mode3 =
SM(ath_bt_config.wl_active_time, AR_BT_WL_ACTIVE_TIME) |
SM(ath_bt_config.wl_qc_time, AR_BT_WL_QC_TIME);
btcoex_hw->bt_coex_mode2 =
AR_BT_PROTECT_BT_AFTER_WAKEUP |
AR_BT_PHY_ERR_BT_COLL_ENABLE;
}
btcoex_hw->bt_coex_mode = btcoex_hw->bt_coex_mode =
(btcoex_hw->bt_coex_mode & AR_BT_QCU_THRESH) | (btcoex_hw->bt_coex_mode & AR_BT_QCU_THRESH) |
SM(ath_bt_config.bt_time_extend, AR_BT_TIME_EXTEND) | SM(time_extend, AR_BT_TIME_EXTEND) |
SM(ath_bt_config.bt_txstate_extend, AR_BT_TXSTATE_EXTEND) | SM(ath_bt_config.bt_txstate_extend, AR_BT_TXSTATE_EXTEND) |
SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) | SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) |
SM(ath_bt_config.bt_mode, AR_BT_MODE) | SM(ath_bt_config.bt_mode, AR_BT_MODE) |
SM(ath_bt_config.bt_quiet_collision, AR_BT_QUIET) | SM(ath_bt_config.bt_quiet_collision, AR_BT_QUIET) |
SM(rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) | SM(rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) |
SM(ath_bt_config.bt_priority_time, AR_BT_PRIORITY_TIME) | SM(ath_bt_config.bt_priority_time, AR_BT_PRIORITY_TIME) |
SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) | SM(first_slot_time, AR_BT_FIRST_SLOT_TIME) |
SM(qnum, AR_BT_QCU_THRESH); SM(qnum, AR_BT_QCU_THRESH);
btcoex_hw->bt_coex_mode2 = btcoex_hw->bt_coex_mode2 |=
SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) | SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) |
SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) | SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) |
AR_BT_DISABLE_BT_ANT; AR_BT_DISABLE_BT_ANT;
} }
EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw); EXPORT_SYMBOL(ath9k_hw_init_btcoex_hw);
static void ath9k_hw_btcoex_pin_init(struct ath_hw *ah, u8 wlanactive_gpio,
u8 btactive_gpio, u8 btpriority_gpio)
{
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
struct ath9k_platform_data *pdata = ah->dev->platform_data;
if (btcoex_hw->scheme != ATH_BTCOEX_CFG_2WIRE &&
btcoex_hw->scheme != ATH_BTCOEX_CFG_3WIRE)
return;
/* bt priority GPIO will be ignored by 2 wire scheme */
if (pdata && (pdata->bt_active_pin || pdata->bt_priority_pin ||
pdata->wlan_active_pin)) {
btcoex_hw->btactive_gpio = pdata->bt_active_pin;
btcoex_hw->wlanactive_gpio = pdata->wlan_active_pin;
btcoex_hw->btpriority_gpio = pdata->bt_priority_pin;
} else {
btcoex_hw->btactive_gpio = btactive_gpio;
btcoex_hw->wlanactive_gpio = wlanactive_gpio;
btcoex_hw->btpriority_gpio = btpriority_gpio;
}
}
void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah) void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah)
{ {
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
...@@ -107,19 +151,19 @@ void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah) ...@@ -107,19 +151,19 @@ void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah)
btcoex_hw->scheme = ATH_BTCOEX_CFG_MCI; btcoex_hw->scheme = ATH_BTCOEX_CFG_MCI;
} else if (AR_SREV_9300_20_OR_LATER(ah)) { } else if (AR_SREV_9300_20_OR_LATER(ah)) {
btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE;
btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9300;
btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9300;
btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO_9300;
} else if (AR_SREV_9280_20_OR_LATER(ah)) {
btcoex_hw->btactive_gpio = ATH_BTACTIVE_GPIO_9280;
btcoex_hw->wlanactive_gpio = ATH_WLANACTIVE_GPIO_9280;
if (AR_SREV_9285(ah)) { ath9k_hw_btcoex_pin_init(ah, ATH_WLANACTIVE_GPIO_9300,
ATH_BTACTIVE_GPIO_9300,
ATH_BTPRIORITY_GPIO_9300);
} else if (AR_SREV_9280_20_OR_LATER(ah)) {
if (AR_SREV_9285(ah))
btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE; btcoex_hw->scheme = ATH_BTCOEX_CFG_3WIRE;
btcoex_hw->btpriority_gpio = ATH_BTPRIORITY_GPIO_9285; else
} else {
btcoex_hw->scheme = ATH_BTCOEX_CFG_2WIRE; btcoex_hw->scheme = ATH_BTCOEX_CFG_2WIRE;
}
ath9k_hw_btcoex_pin_init(ah, ATH_WLANACTIVE_GPIO_9280,
ATH_BTACTIVE_GPIO_9280,
ATH_BTPRIORITY_GPIO_9285);
} }
} }
EXPORT_SYMBOL(ath9k_hw_btcoex_init_scheme); EXPORT_SYMBOL(ath9k_hw_btcoex_init_scheme);
...@@ -137,12 +181,14 @@ void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah) ...@@ -137,12 +181,14 @@ void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah)
AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB); AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB);
/* Set input mux for bt_active to gpio pin */ /* Set input mux for bt_active to gpio pin */
REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, if (!AR_SREV_SOC(ah))
AR_GPIO_INPUT_MUX1_BT_ACTIVE, REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
btcoex_hw->btactive_gpio); AR_GPIO_INPUT_MUX1_BT_ACTIVE,
btcoex_hw->btactive_gpio);
/* Configure the desired gpio port for input */ /* Configure the desired gpio port for input */
ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btactive_gpio); ath9k_hw_gpio_request_in(ah, btcoex_hw->btactive_gpio,
"ath9k-btactive");
} }
EXPORT_SYMBOL(ath9k_hw_btcoex_init_2wire); EXPORT_SYMBOL(ath9k_hw_btcoex_init_2wire);
...@@ -157,21 +203,33 @@ void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah) ...@@ -157,21 +203,33 @@ void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah)
/* Set input mux for bt_prority_async and /* Set input mux for bt_prority_async and
* bt_active_async to GPIO pins */ * bt_active_async to GPIO pins */
REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, if (!AR_SREV_SOC(ah)) {
AR_GPIO_INPUT_MUX1_BT_ACTIVE, REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
btcoex_hw->btactive_gpio); AR_GPIO_INPUT_MUX1_BT_ACTIVE,
btcoex_hw->btactive_gpio);
REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1,
AR_GPIO_INPUT_MUX1_BT_PRIORITY, AR_GPIO_INPUT_MUX1_BT_PRIORITY,
btcoex_hw->btpriority_gpio); btcoex_hw->btpriority_gpio);
}
/* Configure the desired GPIO ports for input */ /* Configure the desired GPIO ports for input */
ath9k_hw_gpio_request_in(ah, btcoex_hw->btactive_gpio,
ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btactive_gpio); "ath9k-btactive");
ath9k_hw_cfg_gpio_input(ah, btcoex_hw->btpriority_gpio); ath9k_hw_gpio_request_in(ah, btcoex_hw->btpriority_gpio,
"ath9k-btpriority");
} }
EXPORT_SYMBOL(ath9k_hw_btcoex_init_3wire); EXPORT_SYMBOL(ath9k_hw_btcoex_init_3wire);
void ath9k_hw_btcoex_deinit(struct ath_hw *ah)
{
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
ath9k_hw_gpio_free(ah, btcoex_hw->btactive_gpio);
ath9k_hw_gpio_free(ah, btcoex_hw->btpriority_gpio);
ath9k_hw_gpio_free(ah, btcoex_hw->wlanactive_gpio);
}
EXPORT_SYMBOL(ath9k_hw_btcoex_deinit);
void ath9k_hw_btcoex_init_mci(struct ath_hw *ah) void ath9k_hw_btcoex_init_mci(struct ath_hw *ah)
{ {
ah->btcoex_hw.mci.ready = false; ah->btcoex_hw.mci.ready = false;
...@@ -201,8 +259,9 @@ static void ath9k_hw_btcoex_enable_2wire(struct ath_hw *ah) ...@@ -201,8 +259,9 @@ static void ath9k_hw_btcoex_enable_2wire(struct ath_hw *ah)
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
/* Configure the desired GPIO port for TX_FRAME output */ /* Configure the desired GPIO port for TX_FRAME output */
ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio, ath9k_hw_gpio_request_out(ah, btcoex_hw->wlanactive_gpio,
AR_GPIO_OUTPUT_MUX_AS_TX_FRAME); "ath9k-wlanactive",
AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
} }
/* /*
...@@ -247,13 +306,13 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, ...@@ -247,13 +306,13 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
txprio_shift[i-1]); txprio_shift[i-1]);
} }
} }
/* Last WLAN weight has to be adjusted wrt tx priority */ /* Last WLAN weight has to be adjusted wrt tx priority */
if (concur_tx) { if (concur_tx) {
btcoex_hw->wlan_weight[i-1] &= ~(0xff << txprio_shift[i-1]); btcoex_hw->wlan_weight[i-1] &= ~(0xff << txprio_shift[i-1]);
btcoex_hw->wlan_weight[i-1] |= (btcoex_hw->tx_prio[stomp_type] btcoex_hw->wlan_weight[i-1] |= (btcoex_hw->tx_prio[stomp_type]
<< txprio_shift[i-1]); << txprio_shift[i-1]);
} }
} }
EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight);
...@@ -268,9 +327,14 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) ...@@ -268,9 +327,14 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah)
* Program coex mode and weight registers to * Program coex mode and weight registers to
* enable coex 3-wire * enable coex 3-wire
*/ */
if (AR_SREV_SOC(ah))
REG_CLR_BIT(ah, AR_BT_COEX_MODE2, AR_BT_PHY_ERR_BT_COLL_ENABLE);
REG_WRITE(ah, AR_BT_COEX_MODE, btcoex->bt_coex_mode); REG_WRITE(ah, AR_BT_COEX_MODE, btcoex->bt_coex_mode);
REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex->bt_coex_mode2); REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex->bt_coex_mode2);
if (AR_SREV_SOC(ah))
REG_WRITE(ah, AR_BT_COEX_MODE3, btcoex->bt_coex_mode3);
if (AR_SREV_9300_20_OR_LATER(ah)) { if (AR_SREV_9300_20_OR_LATER(ah)) {
REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, btcoex->wlan_weight[0]); REG_WRITE(ah, AR_BT_COEX_WL_WEIGHTS0, btcoex->wlan_weight[0]);
...@@ -281,8 +345,6 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) ...@@ -281,8 +345,6 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah)
} else } else
REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex->bt_coex_weights); REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex->bt_coex_weights);
if (AR_SREV_9271(ah)) { if (AR_SREV_9271(ah)) {
val = REG_READ(ah, 0x50040); val = REG_READ(ah, 0x50040);
val &= 0xFFFFFEFF; val &= 0xFFFFFEFF;
...@@ -292,8 +354,9 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah) ...@@ -292,8 +354,9 @@ static void ath9k_hw_btcoex_enable_3wire(struct ath_hw *ah)
REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); REG_RMW_FIELD(ah, AR_QUIET1, AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1);
REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
ath9k_hw_cfg_output(ah, btcoex->wlanactive_gpio, ath9k_hw_gpio_request_out(ah, btcoex->wlanactive_gpio,
AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL); "ath9k-wlanactive",
AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL);
} }
static void ath9k_hw_btcoex_enable_mci(struct ath_hw *ah) static void ath9k_hw_btcoex_enable_mci(struct ath_hw *ah)
...@@ -339,7 +402,8 @@ void ath9k_hw_btcoex_enable(struct ath_hw *ah) ...@@ -339,7 +402,8 @@ void ath9k_hw_btcoex_enable(struct ath_hw *ah)
break; break;
} }
if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_MCI) { if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_MCI &&
!AR_SREV_SOC(ah)) {
REG_RMW(ah, AR_GPIO_PDPU, REG_RMW(ah, AR_GPIO_PDPU,
(0x2 << (btcoex_hw->btactive_gpio * 2)), (0x2 << (btcoex_hw->btactive_gpio * 2)),
(0x3 << (btcoex_hw->btactive_gpio * 2))); (0x3 << (btcoex_hw->btactive_gpio * 2)));
...@@ -364,8 +428,8 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah) ...@@ -364,8 +428,8 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah)
if (!AR_SREV_9300_20_OR_LATER(ah)) if (!AR_SREV_9300_20_OR_LATER(ah))
ath9k_hw_set_gpio(ah, btcoex_hw->wlanactive_gpio, 0); ath9k_hw_set_gpio(ah, btcoex_hw->wlanactive_gpio, 0);
ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio, ath9k_hw_gpio_request_out(ah, btcoex_hw->wlanactive_gpio,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT); NULL, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
if (btcoex_hw->scheme == ATH_BTCOEX_CFG_3WIRE) { if (btcoex_hw->scheme == ATH_BTCOEX_CFG_3WIRE) {
REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE); REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE);
......
...@@ -115,6 +115,7 @@ struct ath_btcoex_hw { ...@@ -115,6 +115,7 @@ struct ath_btcoex_hw {
u32 bt_coex_mode; /* Register setting for AR_BT_COEX_MODE */ u32 bt_coex_mode; /* Register setting for AR_BT_COEX_MODE */
u32 bt_coex_weights; /* Register setting for AR_BT_COEX_WEIGHT */ u32 bt_coex_weights; /* Register setting for AR_BT_COEX_WEIGHT */
u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */
u32 bt_coex_mode3; /* Register setting for AR_BT_COEX_MODE3 */
u32 bt_weight[AR9300_NUM_BT_WEIGHTS]; u32 bt_weight[AR9300_NUM_BT_WEIGHTS];
u32 wlan_weight[AR9300_NUM_WLAN_WEIGHTS]; u32 wlan_weight[AR9300_NUM_WLAN_WEIGHTS];
u8 tx_prio[ATH_BTCOEX_STOMP_MAX]; u8 tx_prio[ATH_BTCOEX_STOMP_MAX];
...@@ -123,6 +124,7 @@ struct ath_btcoex_hw { ...@@ -123,6 +124,7 @@ struct ath_btcoex_hw {
void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah); void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah);
void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah); void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah);
void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah); void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah);
void ath9k_hw_btcoex_deinit(struct ath_hw *ah);
void ath9k_hw_btcoex_init_mci(struct ath_hw *ah); void ath9k_hw_btcoex_init_mci(struct ath_hw *ah);
void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum); void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum);
void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
......
...@@ -916,10 +916,21 @@ static int open_file_regdump(struct inode *inode, struct file *file) ...@@ -916,10 +916,21 @@ static int open_file_regdump(struct inode *inode, struct file *file)
struct ath_softc *sc = inode->i_private; struct ath_softc *sc = inode->i_private;
unsigned int len = 0; unsigned int len = 0;
u8 *buf; u8 *buf;
int i; int i, j = 0;
unsigned long num_regs, regdump_len, max_reg_offset; unsigned long num_regs, regdump_len, max_reg_offset;
const struct reg_hole {
u32 start;
u32 end;
} reg_hole_list[] = {
{0x0200, 0x07fc},
{0x0c00, 0x0ffc},
{0x2000, 0x3ffc},
{0x4100, 0x6ffc},
{0x705c, 0x7ffc},
{0x0000, 0x0000}
};
max_reg_offset = AR_SREV_9300_20_OR_LATER(sc->sc_ah) ? 0x16bd4 : 0xb500; max_reg_offset = AR_SREV_9300_20_OR_LATER(sc->sc_ah) ? 0x8800 : 0xb500;
num_regs = max_reg_offset / 4 + 1; num_regs = max_reg_offset / 4 + 1;
regdump_len = num_regs * REGDUMP_LINE_SIZE + 1; regdump_len = num_regs * REGDUMP_LINE_SIZE + 1;
buf = vmalloc(regdump_len); buf = vmalloc(regdump_len);
...@@ -927,9 +938,16 @@ static int open_file_regdump(struct inode *inode, struct file *file) ...@@ -927,9 +938,16 @@ static int open_file_regdump(struct inode *inode, struct file *file)
return -ENOMEM; return -ENOMEM;
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
for (i = 0; i < num_regs; i++) for (i = 0; i < num_regs; i++) {
if (reg_hole_list[j].start == i << 2) {
i = reg_hole_list[j].end >> 2;
j++;
continue;
}
len += scnprintf(buf + len, regdump_len - len, len += scnprintf(buf + len, regdump_len - len,
"0x%06x 0x%08x\n", i << 2, REG_READ(sc->sc_ah, i << 2)); "0x%06x 0x%08x\n", i << 2, REG_READ(sc->sc_ah, i << 2));
}
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
file->private_data = buf; file->private_data = buf;
......
...@@ -21,6 +21,33 @@ ...@@ -21,6 +21,33 @@
/********************************/ /********************************/
#ifdef CONFIG_MAC80211_LEDS #ifdef CONFIG_MAC80211_LEDS
void ath_fill_led_pin(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
/* Set default led pin if invalid */
if (ah->led_pin < 0) {
if (AR_SREV_9287(ah))
ah->led_pin = ATH_LED_PIN_9287;
else if (AR_SREV_9485(ah))
ah->led_pin = ATH_LED_PIN_9485;
else if (AR_SREV_9300(ah))
ah->led_pin = ATH_LED_PIN_9300;
else if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
ah->led_pin = ATH_LED_PIN_9462;
else
ah->led_pin = ATH_LED_PIN_DEF;
}
/* Configure gpio for output */
ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led",
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
/* LED off, active low */
ath9k_hw_set_gpio(ah, ah->led_pin, ah->config.led_active_high ? 0 : 1);
}
static void ath_led_brightness(struct led_classdev *led_cdev, static void ath_led_brightness(struct led_classdev *led_cdev,
enum led_brightness brightness) enum led_brightness brightness)
{ {
...@@ -40,6 +67,8 @@ void ath_deinit_leds(struct ath_softc *sc) ...@@ -40,6 +67,8 @@ void ath_deinit_leds(struct ath_softc *sc)
ath_led_brightness(&sc->led_cdev, LED_OFF); ath_led_brightness(&sc->led_cdev, LED_OFF);
led_classdev_unregister(&sc->led_cdev); led_classdev_unregister(&sc->led_cdev);
ath9k_hw_gpio_free(sc->sc_ah, sc->sc_ah->led_pin);
} }
void ath_init_leds(struct ath_softc *sc) void ath_init_leds(struct ath_softc *sc)
...@@ -49,6 +78,8 @@ void ath_init_leds(struct ath_softc *sc) ...@@ -49,6 +78,8 @@ void ath_init_leds(struct ath_softc *sc)
if (AR_SREV_9100(sc->sc_ah)) if (AR_SREV_9100(sc->sc_ah))
return; return;
ath_fill_led_pin(sc);
if (!ath9k_led_blink) if (!ath9k_led_blink)
sc->led_cdev.default_trigger = sc->led_cdev.default_trigger =
ieee80211_get_radio_led_name(sc->hw); ieee80211_get_radio_led_name(sc->hw);
...@@ -64,37 +95,6 @@ void ath_init_leds(struct ath_softc *sc) ...@@ -64,37 +95,6 @@ void ath_init_leds(struct ath_softc *sc)
sc->led_registered = true; sc->led_registered = true;
} }
void ath_fill_led_pin(struct ath_softc *sc)
{
struct ath_hw *ah = sc->sc_ah;
if (AR_SREV_9100(ah))
return;
if (ah->led_pin >= 0) {
if (!((1 << ah->led_pin) & AR_GPIO_OE_OUT_MASK))
ath9k_hw_request_gpio(ah, ah->led_pin, "ath9k-led");
return;
}
if (AR_SREV_9287(ah))
ah->led_pin = ATH_LED_PIN_9287;
else if (AR_SREV_9485(sc->sc_ah))
ah->led_pin = ATH_LED_PIN_9485;
else if (AR_SREV_9300(sc->sc_ah))
ah->led_pin = ATH_LED_PIN_9300;
else if (AR_SREV_9462(sc->sc_ah) || AR_SREV_9565(sc->sc_ah))
ah->led_pin = ATH_LED_PIN_9462;
else
ah->led_pin = ATH_LED_PIN_DEF;
/* Configure gpio 1 for output */
ath9k_hw_cfg_output(ah, ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
/* LED off, active low */
ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 0 : 1);
}
#endif #endif
/*******************/ /*******************/
...@@ -402,6 +402,13 @@ void ath9k_deinit_btcoex(struct ath_softc *sc) ...@@ -402,6 +402,13 @@ void ath9k_deinit_btcoex(struct ath_softc *sc)
if (ath9k_hw_mci_is_enabled(ah)) if (ath9k_hw_mci_is_enabled(ah))
ath_mci_cleanup(sc); ath_mci_cleanup(sc);
else {
enum ath_btcoex_scheme scheme = ath9k_hw_get_btcoex_scheme(ah);
if (scheme == ATH_BTCOEX_CFG_2WIRE ||
scheme == ATH_BTCOEX_CFG_3WIRE)
ath9k_hw_btcoex_deinit(sc->sc_ah);
}
} }
int ath9k_init_btcoex(struct ath_softc *sc) int ath9k_init_btcoex(struct ath_softc *sc)
......
...@@ -527,7 +527,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev, ...@@ -527,7 +527,7 @@ static void ath9k_hif_usb_rx_stream(struct hif_device_usb *hif_dev,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER]; struct sk_buff *nskb, *skb_pool[MAX_PKT_NUM_IN_TRANSFER];
int index = 0, i = 0, len = skb->len; int index = 0, i, len = skb->len;
int rx_remain_len, rx_pkt_len; int rx_remain_len, rx_pkt_len;
u16 pool_index = 0; u16 pool_index = 0;
u8 *ptr; u8 *ptr;
......
...@@ -253,17 +253,19 @@ void ath9k_deinit_leds(struct ath9k_htc_priv *priv) ...@@ -253,17 +253,19 @@ void ath9k_deinit_leds(struct ath9k_htc_priv *priv)
ath9k_led_brightness(&priv->led_cdev, LED_OFF); ath9k_led_brightness(&priv->led_cdev, LED_OFF);
led_classdev_unregister(&priv->led_cdev); led_classdev_unregister(&priv->led_cdev);
cancel_work_sync(&priv->led_work); cancel_work_sync(&priv->led_work);
ath9k_hw_gpio_free(priv->ah, priv->ah->led_pin);
} }
void ath9k_configure_leds(struct ath9k_htc_priv *priv) void ath9k_configure_leds(struct ath9k_htc_priv *priv)
{ {
/* Configure gpio 1 for output */ /* Configure gpio 1 for output */
ath9k_hw_cfg_output(priv->ah, priv->ah->led_pin, ath9k_hw_gpio_request_out(priv->ah, priv->ah->led_pin,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT); "ath9k-led",
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
/* LED off, active low */ /* LED off, active low */
ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1); ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
} }
void ath9k_init_leds(struct ath9k_htc_priv *priv) void ath9k_init_leds(struct ath9k_htc_priv *priv)
......
...@@ -262,11 +262,11 @@ static void ath9k_multi_regread(void *hw_priv, u32 *addr, ...@@ -262,11 +262,11 @@ static void ath9k_multi_regread(void *hw_priv, u32 *addr,
__be32 tmpval[8]; __be32 tmpval[8];
int i, ret; int i, ret;
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
tmpaddr[i] = cpu_to_be32(addr[i]); tmpaddr[i] = cpu_to_be32(addr[i]);
} }
ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID, ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
(u8 *)tmpaddr , sizeof(u32) * count, (u8 *)tmpaddr , sizeof(u32) * count,
(u8 *)tmpval, sizeof(u32) * count, (u8 *)tmpval, sizeof(u32) * count,
100); 100);
...@@ -275,9 +275,9 @@ static void ath9k_multi_regread(void *hw_priv, u32 *addr, ...@@ -275,9 +275,9 @@ static void ath9k_multi_regread(void *hw_priv, u32 *addr,
"Multiple REGISTER READ FAILED (count: %d)\n", count); "Multiple REGISTER READ FAILED (count: %d)\n", count);
} }
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
val[i] = be32_to_cpu(tmpval[i]); val[i] = be32_to_cpu(tmpval[i]);
} }
} }
static void ath9k_regwrite_multi(struct ath_common *common) static void ath9k_regwrite_multi(struct ath_common *common)
......
...@@ -1582,8 +1582,10 @@ static void ath9k_hw_apply_gpio_override(struct ath_hw *ah) ...@@ -1582,8 +1582,10 @@ static void ath9k_hw_apply_gpio_override(struct ath_hw *ah)
if (!(gpio_mask & 1)) if (!(gpio_mask & 1))
continue; continue;
ath9k_hw_cfg_output(ah, i, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); ath9k_hw_gpio_request_out(ah, i, NULL,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
ath9k_hw_set_gpio(ah, i, !!(ah->gpio_val & BIT(i))); ath9k_hw_set_gpio(ah, i, !!(ah->gpio_val & BIT(i)));
ath9k_hw_gpio_free(ah, i);
} }
} }
...@@ -1958,7 +1960,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, ...@@ -1958,7 +1960,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
ath9k_hw_init_qos(ah); ath9k_hw_init_qos(ah);
if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); ath9k_hw_gpio_request_in(ah, ah->rfkill_gpio, "ath9k-rfkill");
ath9k_hw_init_global_settings(ah); ath9k_hw_init_global_settings(ah);
...@@ -2385,6 +2387,61 @@ static bool ath9k_hw_dfs_tested(struct ath_hw *ah) ...@@ -2385,6 +2387,61 @@ static bool ath9k_hw_dfs_tested(struct ath_hw *ah)
} }
} }
static void ath9k_gpio_cap_init(struct ath_hw *ah)
{
struct ath9k_hw_capabilities *pCap = &ah->caps;
if (AR_SREV_9271(ah)) {
pCap->num_gpio_pins = AR9271_NUM_GPIO;
pCap->gpio_mask = AR9271_GPIO_MASK;
} else if (AR_DEVID_7010(ah)) {
pCap->num_gpio_pins = AR7010_NUM_GPIO;
pCap->gpio_mask = AR7010_GPIO_MASK;
} else if (AR_SREV_9287(ah)) {
pCap->num_gpio_pins = AR9287_NUM_GPIO;
pCap->gpio_mask = AR9287_GPIO_MASK;
} else if (AR_SREV_9285(ah)) {
pCap->num_gpio_pins = AR9285_NUM_GPIO;
pCap->gpio_mask = AR9285_GPIO_MASK;
} else if (AR_SREV_9280(ah)) {
pCap->num_gpio_pins = AR9280_NUM_GPIO;
pCap->gpio_mask = AR9280_GPIO_MASK;
} else if (AR_SREV_9300(ah)) {
pCap->num_gpio_pins = AR9300_NUM_GPIO;
pCap->gpio_mask = AR9300_GPIO_MASK;
} else if (AR_SREV_9330(ah)) {
pCap->num_gpio_pins = AR9330_NUM_GPIO;
pCap->gpio_mask = AR9330_GPIO_MASK;
} else if (AR_SREV_9340(ah)) {
pCap->num_gpio_pins = AR9340_NUM_GPIO;
pCap->gpio_mask = AR9340_GPIO_MASK;
} else if (AR_SREV_9462(ah)) {
pCap->num_gpio_pins = AR9462_NUM_GPIO;
pCap->gpio_mask = AR9462_GPIO_MASK;
} else if (AR_SREV_9485(ah)) {
pCap->num_gpio_pins = AR9485_NUM_GPIO;
pCap->gpio_mask = AR9485_GPIO_MASK;
} else if (AR_SREV_9531(ah)) {
pCap->num_gpio_pins = AR9531_NUM_GPIO;
pCap->gpio_mask = AR9531_GPIO_MASK;
} else if (AR_SREV_9550(ah)) {
pCap->num_gpio_pins = AR9550_NUM_GPIO;
pCap->gpio_mask = AR9550_GPIO_MASK;
} else if (AR_SREV_9561(ah)) {
pCap->num_gpio_pins = AR9561_NUM_GPIO;
pCap->gpio_mask = AR9561_GPIO_MASK;
} else if (AR_SREV_9565(ah)) {
pCap->num_gpio_pins = AR9565_NUM_GPIO;
pCap->gpio_mask = AR9565_GPIO_MASK;
} else if (AR_SREV_9580(ah)) {
pCap->num_gpio_pins = AR9580_NUM_GPIO;
pCap->gpio_mask = AR9580_GPIO_MASK;
} else {
pCap->num_gpio_pins = AR_NUM_GPIO;
pCap->gpio_mask = AR_GPIO_MASK;
}
}
int ath9k_hw_fill_cap_info(struct ath_hw *ah) int ath9k_hw_fill_cap_info(struct ath_hw *ah)
{ {
struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath9k_hw_capabilities *pCap = &ah->caps;
...@@ -2478,20 +2535,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) ...@@ -2478,20 +2535,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
else else
pCap->hw_caps &= ~ATH9K_HW_CAP_HT; pCap->hw_caps &= ~ATH9K_HW_CAP_HT;
if (AR_SREV_9271(ah)) ath9k_gpio_cap_init(ah);
pCap->num_gpio_pins = AR9271_NUM_GPIO;
else if (AR_DEVID_7010(ah))
pCap->num_gpio_pins = AR7010_NUM_GPIO;
else if (AR_SREV_9300_20_OR_LATER(ah))
pCap->num_gpio_pins = AR9300_NUM_GPIO;
else if (AR_SREV_9287_11_OR_LATER(ah))
pCap->num_gpio_pins = AR9287_NUM_GPIO;
else if (AR_SREV_9285_12_OR_LATER(ah))
pCap->num_gpio_pins = AR9285_NUM_GPIO;
else if (AR_SREV_9280_20_OR_LATER(ah))
pCap->num_gpio_pins = AR928X_NUM_GPIO;
else
pCap->num_gpio_pins = AR_NUM_GPIO;
if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah))
pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX; pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX;
...@@ -2612,8 +2656,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) ...@@ -2612,8 +2656,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
/* GPIO / RFKILL / Antennae */ /* GPIO / RFKILL / Antennae */
/****************************/ /****************************/
static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah, static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah, u32 gpio, u32 type)
u32 gpio, u32 type)
{ {
int addr; int addr;
u32 gpio_shift, tmp; u32 gpio_shift, tmp;
...@@ -2627,8 +2670,8 @@ static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah, ...@@ -2627,8 +2670,8 @@ static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah,
gpio_shift = (gpio % 6) * 5; gpio_shift = (gpio % 6) * 5;
if (AR_SREV_9280_20_OR_LATER(ah) if (AR_SREV_9280_20_OR_LATER(ah) ||
|| (addr != AR_GPIO_OUTPUT_MUX1)) { (addr != AR_GPIO_OUTPUT_MUX1)) {
REG_RMW(ah, addr, (type << gpio_shift), REG_RMW(ah, addr, (type << gpio_shift),
(0x1f << gpio_shift)); (0x1f << gpio_shift));
} else { } else {
...@@ -2640,106 +2683,144 @@ static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah, ...@@ -2640,106 +2683,144 @@ static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah,
} }
} }
void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio) /* BSP should set the corresponding MUX register correctly.
*/
static void ath9k_hw_gpio_cfg_soc(struct ath_hw *ah, u32 gpio, bool out,
const char *label)
{ {
u32 gpio_shift; if (ah->caps.gpio_requested & BIT(gpio))
return;
BUG_ON(gpio >= ah->caps.num_gpio_pins); /* may be requested by BSP, free anyway */
gpio_free(gpio);
if (AR_DEVID_7010(ah)) { if (gpio_request_one(gpio, out ? GPIOF_OUT_INIT_LOW : GPIOF_IN, label))
gpio_shift = gpio;
REG_RMW(ah, AR7010_GPIO_OE,
(AR7010_GPIO_OE_AS_INPUT << gpio_shift),
(AR7010_GPIO_OE_MASK << gpio_shift));
return; return;
}
gpio_shift = gpio << 1; ah->caps.gpio_requested |= BIT(gpio);
REG_RMW(ah,
AR_GPIO_OE_OUT,
(AR_GPIO_OE_OUT_DRV_NO << gpio_shift),
(AR_GPIO_OE_OUT_DRV << gpio_shift));
} }
EXPORT_SYMBOL(ath9k_hw_cfg_gpio_input);
u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) static void ath9k_hw_gpio_cfg_wmac(struct ath_hw *ah, u32 gpio, bool out,
u32 ah_signal_type)
{ {
#define MS_REG_READ(x, y) \ u32 gpio_set, gpio_shift = gpio;
(MS(REG_READ(ah, AR_GPIO_IN_OUT), x##_GPIO_IN_VAL) & (AR_GPIO_BIT(y)))
if (gpio >= ah->caps.num_gpio_pins)
return 0xffffffff;
if (AR_DEVID_7010(ah)) { if (AR_DEVID_7010(ah)) {
u32 val; gpio_set = out ?
val = REG_READ(ah, AR7010_GPIO_IN); AR7010_GPIO_OE_AS_OUTPUT : AR7010_GPIO_OE_AS_INPUT;
return (MS(val, AR7010_GPIO_IN_VAL) & AR_GPIO_BIT(gpio)) == 0; REG_RMW(ah, AR7010_GPIO_OE, gpio_set << gpio_shift,
} else if (AR_SREV_9300_20_OR_LATER(ah)) AR7010_GPIO_OE_MASK << gpio_shift);
return (MS(REG_READ(ah, AR_GPIO_IN), AR9300_GPIO_IN_VAL) & } else if (AR_SREV_SOC(ah)) {
AR_GPIO_BIT(gpio)) != 0; gpio_set = out ? 1 : 0;
else if (AR_SREV_9271(ah)) REG_RMW(ah, AR_GPIO_OE_OUT, gpio_set << gpio_shift,
return MS_REG_READ(AR9271, gpio) != 0; gpio_set << gpio_shift);
else if (AR_SREV_9287_11_OR_LATER(ah)) } else {
return MS_REG_READ(AR9287, gpio) != 0; gpio_shift = gpio << 1;
else if (AR_SREV_9285_12_OR_LATER(ah)) gpio_set = out ?
return MS_REG_READ(AR9285, gpio) != 0; AR_GPIO_OE_OUT_DRV_ALL : AR_GPIO_OE_OUT_DRV_NO;
else if (AR_SREV_9280_20_OR_LATER(ah)) REG_RMW(ah, AR_GPIO_OE_OUT, gpio_set << gpio_shift,
return MS_REG_READ(AR928X, gpio) != 0; AR_GPIO_OE_OUT_DRV << gpio_shift);
else
return MS_REG_READ(AR, gpio) != 0; if (out)
ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type);
}
} }
EXPORT_SYMBOL(ath9k_hw_gpio_get);
void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, static void ath9k_hw_gpio_request(struct ath_hw *ah, u32 gpio, bool out,
u32 ah_signal_type) const char *label, u32 ah_signal_type)
{ {
u32 gpio_shift; WARN_ON(gpio >= ah->caps.num_gpio_pins);
if (AR_DEVID_7010(ah)) { if (BIT(gpio) & ah->caps.gpio_mask)
gpio_shift = gpio; ath9k_hw_gpio_cfg_wmac(ah, gpio, out, ah_signal_type);
REG_RMW(ah, AR7010_GPIO_OE, else if (AR_SREV_SOC(ah))
(AR7010_GPIO_OE_AS_OUTPUT << gpio_shift), ath9k_hw_gpio_cfg_soc(ah, gpio, out, label);
(AR7010_GPIO_OE_MASK << gpio_shift)); else
return; WARN_ON(1);
} }
ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type); void ath9k_hw_gpio_request_in(struct ath_hw *ah, u32 gpio, const char *label)
gpio_shift = 2 * gpio; {
REG_RMW(ah, ath9k_hw_gpio_request(ah, gpio, false, label, 0);
AR_GPIO_OE_OUT,
(AR_GPIO_OE_OUT_DRV_ALL << gpio_shift),
(AR_GPIO_OE_OUT_DRV << gpio_shift));
} }
EXPORT_SYMBOL(ath9k_hw_cfg_output); EXPORT_SYMBOL(ath9k_hw_gpio_request_in);
void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val) void ath9k_hw_gpio_request_out(struct ath_hw *ah, u32 gpio, const char *label,
u32 ah_signal_type)
{ {
if (AR_DEVID_7010(ah)) { ath9k_hw_gpio_request(ah, gpio, true, label, ah_signal_type);
val = val ? 0 : 1; }
REG_RMW(ah, AR7010_GPIO_OUT, ((val&1) << gpio), EXPORT_SYMBOL(ath9k_hw_gpio_request_out);
AR_GPIO_BIT(gpio));
void ath9k_hw_gpio_free(struct ath_hw *ah, u32 gpio)
{
if (!AR_SREV_SOC(ah))
return; return;
WARN_ON(gpio >= ah->caps.num_gpio_pins);
if (ah->caps.gpio_requested & BIT(gpio)) {
gpio_free(gpio);
ah->caps.gpio_requested &= ~BIT(gpio);
} }
}
EXPORT_SYMBOL(ath9k_hw_gpio_free);
if (AR_SREV_9271(ah)) u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio)
val = ~val; {
u32 val = 0xffffffff;
if ((1 << gpio) & AR_GPIO_OE_OUT_MASK) #define MS_REG_READ(x, y) \
REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio), (MS(REG_READ(ah, AR_GPIO_IN_OUT), x##_GPIO_IN_VAL) & BIT(y))
AR_GPIO_BIT(gpio));
else WARN_ON(gpio >= ah->caps.num_gpio_pins);
gpio_set_value(gpio, val & 1);
if (BIT(gpio) & ah->caps.gpio_mask) {
if (AR_SREV_9271(ah))
val = MS_REG_READ(AR9271, gpio);
else if (AR_SREV_9287(ah))
val = MS_REG_READ(AR9287, gpio);
else if (AR_SREV_9285(ah))
val = MS_REG_READ(AR9285, gpio);
else if (AR_SREV_9280(ah))
val = MS_REG_READ(AR928X, gpio);
else if (AR_DEVID_7010(ah))
val = REG_READ(ah, AR7010_GPIO_IN) & BIT(gpio);
else if (AR_SREV_9300_20_OR_LATER(ah))
val = REG_READ(ah, AR_GPIO_IN) & BIT(gpio);
else
val = MS_REG_READ(AR, gpio);
} else if (BIT(gpio) & ah->caps.gpio_requested) {
val = gpio_get_value(gpio) & BIT(gpio);
} else {
WARN_ON(1);
}
return val;
} }
EXPORT_SYMBOL(ath9k_hw_set_gpio); EXPORT_SYMBOL(ath9k_hw_gpio_get);
void ath9k_hw_request_gpio(struct ath_hw *ah, u32 gpio, const char *label) void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val)
{ {
if (gpio >= ah->caps.num_gpio_pins) WARN_ON(gpio >= ah->caps.num_gpio_pins);
return;
if (AR_DEVID_7010(ah) || AR_SREV_9271(ah))
val = !val;
else
val = !!val;
gpio_request_one(gpio, GPIOF_DIR_OUT | GPIOF_INIT_LOW, label); if (BIT(gpio) & ah->caps.gpio_mask) {
u32 out_addr = AR_DEVID_7010(ah) ?
AR7010_GPIO_OUT : AR_GPIO_IN_OUT;
REG_RMW(ah, out_addr, val << gpio, BIT(gpio));
} else if (BIT(gpio) & ah->caps.gpio_requested) {
gpio_set_value(gpio, val);
} else {
WARN_ON(1);
}
} }
EXPORT_SYMBOL(ath9k_hw_request_gpio); EXPORT_SYMBOL(ath9k_hw_set_gpio);
void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna) void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna)
{ {
......
...@@ -160,7 +160,6 @@ ...@@ -160,7 +160,6 @@
#define AR_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA 0x1e #define AR_GPIO_OUTPUT_MUX_AS_RUCKUS_DATA 0x1e
#define AR_GPIOD_MASK 0x00001FFF #define AR_GPIOD_MASK 0x00001FFF
#define AR_GPIO_BIT(_gpio) (1 << (_gpio))
#define BASE_ACTIVATE_DELAY 100 #define BASE_ACTIVATE_DELAY 100
#define RTC_PLL_SETTLE_DELAY (AR_SREV_9340(ah) ? 1000 : 100) #define RTC_PLL_SETTLE_DELAY (AR_SREV_9340(ah) ? 1000 : 100)
...@@ -301,6 +300,8 @@ struct ath9k_hw_capabilities { ...@@ -301,6 +300,8 @@ struct ath9k_hw_capabilities {
u8 max_txchains; u8 max_txchains;
u8 max_rxchains; u8 max_rxchains;
u8 num_gpio_pins; u8 num_gpio_pins;
u32 gpio_mask;
u32 gpio_requested;
u8 rx_hp_qdepth; u8 rx_hp_qdepth;
u8 rx_lp_qdepth; u8 rx_lp_qdepth;
u8 rx_status_len; u8 rx_status_len;
...@@ -1019,12 +1020,12 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah); ...@@ -1019,12 +1020,12 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah);
u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan);
/* GPIO / RFKILL / Antennae */ /* GPIO / RFKILL / Antennae */
void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio); void ath9k_hw_gpio_request_in(struct ath_hw *ah, u32 gpio, const char *label);
void ath9k_hw_gpio_request_out(struct ath_hw *ah, u32 gpio, const char *label,
u32 ah_signal_type);
void ath9k_hw_gpio_free(struct ath_hw *ah, u32 gpio);
u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio); u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio);
void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio,
u32 ah_signal_type);
void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val); void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val);
void ath9k_hw_request_gpio(struct ath_hw *ah, u32 gpio, const char *label);
void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna); void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna);
/* General Operation */ /* General Operation */
......
...@@ -660,7 +660,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, ...@@ -660,7 +660,6 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
ath9k_cmn_init_crypto(sc->sc_ah); ath9k_cmn_init_crypto(sc->sc_ah);
ath9k_init_misc(sc); ath9k_init_misc(sc);
ath_fill_led_pin(sc);
ath_chanctx_init(sc); ath_chanctx_init(sc);
ath9k_offchannel_init(sc); ath9k_offchannel_init(sc);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册