Merge tag 'for-linville-20141024' of git://github.com/kvalo/ath
Conflicts: drivers/net/wireless/ath/wil6210/wil6210.h
This commit is contained in:
commit
490f0dc4d5
|
@ -443,12 +443,12 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr)
|
|||
* Guts of ath10k_ce_completed_recv_next.
|
||||
* The caller takes responsibility for any necessary locking.
|
||||
*/
|
||||
static int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp,
|
||||
unsigned int *flagsp)
|
||||
int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp,
|
||||
unsigned int *flagsp)
|
||||
{
|
||||
struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
|
||||
unsigned int nentries_mask = dest_ring->nentries_mask;
|
||||
|
@ -576,11 +576,11 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
|
|||
* Guts of ath10k_ce_completed_send_next.
|
||||
* The caller takes responsibility for any necessary locking.
|
||||
*/
|
||||
static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp)
|
||||
int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp)
|
||||
{
|
||||
struct ath10k_ce_ring *src_ring = ce_state->src_ring;
|
||||
u32 ctrl_addr = ce_state->ctrl_addr;
|
||||
|
@ -817,7 +817,10 @@ void ath10k_ce_enable_interrupts(struct ath10k *ar)
|
|||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
int ce_id;
|
||||
|
||||
for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
|
||||
/* Skip the last copy engine, CE7 the diagnostic window, as that
|
||||
* uses polling and isn't initialized for interrupts.
|
||||
*/
|
||||
for (ce_id = 0; ce_id < CE_COUNT - 1; ce_id++)
|
||||
ath10k_ce_per_engine_handler_adjust(&ar_pci->ce_states[ce_id]);
|
||||
}
|
||||
|
||||
|
@ -1020,37 +1023,10 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id,
|
|||
* initialized by software/firmware.
|
||||
*/
|
||||
int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
|
||||
const struct ce_attr *attr,
|
||||
void (*send_cb)(struct ath10k_ce_pipe *),
|
||||
void (*recv_cb)(struct ath10k_ce_pipe *))
|
||||
const struct ce_attr *attr)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Make sure there's enough CE ringbuffer entries for HTT TX to avoid
|
||||
* additional TX locking checks.
|
||||
*
|
||||
* For the lack of a better place do the check here.
|
||||
*/
|
||||
BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC >
|
||||
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
|
||||
BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC >
|
||||
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
|
||||
|
||||
spin_lock_bh(&ar_pci->ce_lock);
|
||||
ce_state->ar = ar;
|
||||
ce_state->id = ce_id;
|
||||
ce_state->ctrl_addr = ath10k_ce_base_address(ce_id);
|
||||
ce_state->attr_flags = attr->flags;
|
||||
ce_state->src_sz_max = attr->src_sz_max;
|
||||
if (attr->src_nentries)
|
||||
ce_state->send_cb = send_cb;
|
||||
if (attr->dest_nentries)
|
||||
ce_state->recv_cb = recv_cb;
|
||||
spin_unlock_bh(&ar_pci->ce_lock);
|
||||
|
||||
if (attr->src_nentries) {
|
||||
ret = ath10k_ce_init_src_ring(ar, ce_id, attr);
|
||||
if (ret) {
|
||||
|
@ -1098,12 +1074,37 @@ void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id)
|
|||
}
|
||||
|
||||
int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
|
||||
const struct ce_attr *attr)
|
||||
const struct ce_attr *attr,
|
||||
void (*send_cb)(struct ath10k_ce_pipe *),
|
||||
void (*recv_cb)(struct ath10k_ce_pipe *))
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Make sure there's enough CE ringbuffer entries for HTT TX to avoid
|
||||
* additional TX locking checks.
|
||||
*
|
||||
* For the lack of a better place do the check here.
|
||||
*/
|
||||
BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC >
|
||||
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
|
||||
BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC >
|
||||
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
|
||||
|
||||
ce_state->ar = ar;
|
||||
ce_state->id = ce_id;
|
||||
ce_state->ctrl_addr = ath10k_ce_base_address(ce_id);
|
||||
ce_state->attr_flags = attr->flags;
|
||||
ce_state->src_sz_max = attr->src_sz_max;
|
||||
|
||||
if (attr->src_nentries)
|
||||
ce_state->send_cb = send_cb;
|
||||
|
||||
if (attr->dest_nentries)
|
||||
ce_state->recv_cb = recv_cb;
|
||||
|
||||
if (attr->src_nentries) {
|
||||
ce_state->src_ring = ath10k_ce_alloc_src_ring(ar, ce_id, attr);
|
||||
if (IS_ERR(ce_state->src_ring)) {
|
||||
|
|
|
@ -192,15 +192,21 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state,
|
|||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp);
|
||||
|
||||
int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp);
|
||||
|
||||
/*==================CE Engine Initialization=======================*/
|
||||
|
||||
int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
|
||||
const struct ce_attr *attr,
|
||||
void (*send_cb)(struct ath10k_ce_pipe *),
|
||||
void (*recv_cb)(struct ath10k_ce_pipe *));
|
||||
const struct ce_attr *attr);
|
||||
void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id);
|
||||
int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
|
||||
const struct ce_attr *attr);
|
||||
const struct ce_attr *attr,
|
||||
void (*send_cb)(struct ath10k_ce_pipe *),
|
||||
void (*recv_cb)(struct ath10k_ce_pipe *));
|
||||
void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id);
|
||||
|
||||
/*==================CE Engine Shutdown=======================*/
|
||||
|
@ -213,6 +219,13 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state,
|
|||
void **per_transfer_contextp,
|
||||
u32 *bufferp);
|
||||
|
||||
int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
|
||||
void **per_transfer_contextp,
|
||||
u32 *bufferp,
|
||||
unsigned int *nbytesp,
|
||||
unsigned int *transfer_idp,
|
||||
unsigned int *flagsp);
|
||||
|
||||
/*
|
||||
* Support clean shutdown by allowing the caller to cancel
|
||||
* pending sends. Target DMA must be stopped before using
|
||||
|
|
|
@ -138,7 +138,8 @@ static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar,
|
|||
return fw;
|
||||
}
|
||||
|
||||
static int ath10k_push_board_ext_data(struct ath10k *ar)
|
||||
static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data,
|
||||
size_t data_len)
|
||||
{
|
||||
u32 board_data_size = QCA988X_BOARD_DATA_SZ;
|
||||
u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ;
|
||||
|
@ -159,14 +160,14 @@ static int ath10k_push_board_ext_data(struct ath10k *ar)
|
|||
if (board_ext_data_addr == 0)
|
||||
return 0;
|
||||
|
||||
if (ar->board_len != (board_data_size + board_ext_data_size)) {
|
||||
if (data_len != (board_data_size + board_ext_data_size)) {
|
||||
ath10k_err(ar, "invalid board (ext) data sizes %zu != %d+%d\n",
|
||||
ar->board_len, board_data_size, board_ext_data_size);
|
||||
data_len, board_data_size, board_ext_data_size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = ath10k_bmi_write_memory(ar, board_ext_data_addr,
|
||||
ar->board_data + board_data_size,
|
||||
data + board_data_size,
|
||||
board_ext_data_size);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "could not write board ext data (%d)\n", ret);
|
||||
|
@ -184,13 +185,14 @@ static int ath10k_push_board_ext_data(struct ath10k *ar)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_download_board_data(struct ath10k *ar)
|
||||
static int ath10k_download_board_data(struct ath10k *ar, const void *data,
|
||||
size_t data_len)
|
||||
{
|
||||
u32 board_data_size = QCA988X_BOARD_DATA_SZ;
|
||||
u32 address;
|
||||
int ret;
|
||||
|
||||
ret = ath10k_push_board_ext_data(ar);
|
||||
ret = ath10k_push_board_ext_data(ar, data, data_len);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "could not push board ext data (%d)\n", ret);
|
||||
goto exit;
|
||||
|
@ -202,9 +204,9 @@ static int ath10k_download_board_data(struct ath10k *ar)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
ret = ath10k_bmi_write_memory(ar, address, ar->board_data,
|
||||
ret = ath10k_bmi_write_memory(ar, address, data,
|
||||
min_t(u32, board_data_size,
|
||||
ar->board_len));
|
||||
data_len));
|
||||
if (ret) {
|
||||
ath10k_err(ar, "could not write board data (%d)\n", ret);
|
||||
goto exit;
|
||||
|
@ -220,11 +222,39 @@ exit:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_download_cal_file(struct ath10k *ar)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!ar->cal_file)
|
||||
return -ENOENT;
|
||||
|
||||
if (IS_ERR(ar->cal_file))
|
||||
return PTR_ERR(ar->cal_file);
|
||||
|
||||
ret = ath10k_download_board_data(ar, ar->cal_file->data,
|
||||
ar->cal_file->size);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to download cal_file data: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_download_and_run_otp(struct ath10k *ar)
|
||||
{
|
||||
u32 result, address = ar->hw_params.patch_load_addr;
|
||||
int ret;
|
||||
|
||||
ret = ath10k_download_board_data(ar, ar->board_data, ar->board_len);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to download board data: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* OTP is optional */
|
||||
|
||||
if (!ar->otp_data || !ar->otp_len) {
|
||||
|
@ -308,6 +338,9 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar)
|
|||
if (ar->firmware && !IS_ERR(ar->firmware))
|
||||
release_firmware(ar->firmware);
|
||||
|
||||
if (ar->cal_file && !IS_ERR(ar->cal_file))
|
||||
release_firmware(ar->cal_file);
|
||||
|
||||
ar->board = NULL;
|
||||
ar->board_data = NULL;
|
||||
ar->board_len = 0;
|
||||
|
@ -319,6 +352,27 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar)
|
|||
ar->firmware = NULL;
|
||||
ar->firmware_data = NULL;
|
||||
ar->firmware_len = 0;
|
||||
|
||||
ar->cal_file = NULL;
|
||||
}
|
||||
|
||||
static int ath10k_fetch_cal_file(struct ath10k *ar)
|
||||
{
|
||||
char filename[100];
|
||||
|
||||
/* cal-<bus>-<id>.bin */
|
||||
scnprintf(filename, sizeof(filename), "cal-%s-%s.bin",
|
||||
ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));
|
||||
|
||||
ar->cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename);
|
||||
if (IS_ERR(ar->cal_file))
|
||||
/* calibration file is optional, don't print any warnings */
|
||||
return PTR_ERR(ar->cal_file);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "found calibration file %s/%s\n",
|
||||
ATH10K_FW_DIR, filename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar)
|
||||
|
@ -562,6 +616,9 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
|
|||
{
|
||||
int ret;
|
||||
|
||||
/* calibration file is optional, don't check for any errors */
|
||||
ath10k_fetch_cal_file(ar);
|
||||
|
||||
ar->fw_api = 3;
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
|
||||
|
||||
|
@ -589,30 +646,32 @@ success:
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_init_download_firmware(struct ath10k *ar,
|
||||
enum ath10k_firmware_mode mode)
|
||||
static int ath10k_download_cal_data(struct ath10k *ar)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ath10k_download_board_data(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to download board data: %d\n", ret);
|
||||
return ret;
|
||||
ret = ath10k_download_cal_file(ar);
|
||||
if (ret == 0) {
|
||||
ar->cal_mode = ATH10K_CAL_MODE_FILE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT,
|
||||
"boot did not find a calibration file, try OTP next: %d\n",
|
||||
ret);
|
||||
|
||||
ret = ath10k_download_and_run_otp(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to run otp: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath10k_download_fw(ar, mode);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to download firmware: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ar->cal_mode = ATH10K_CAL_MODE_OTP;
|
||||
|
||||
return ret;
|
||||
done:
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using calibration mode %s\n",
|
||||
ath10k_cal_mode_str(ar->cal_mode));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_init_uart(struct ath10k *ar)
|
||||
|
@ -729,7 +788,11 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
|||
goto err;
|
||||
}
|
||||
|
||||
status = ath10k_init_download_firmware(ar, mode);
|
||||
status = ath10k_download_cal_data(ar);
|
||||
if (status)
|
||||
goto err;
|
||||
|
||||
status = ath10k_download_fw(ar, mode);
|
||||
if (status)
|
||||
goto err;
|
||||
|
||||
|
@ -846,9 +909,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
|||
goto err_hif_stop;
|
||||
|
||||
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
|
||||
ar->free_vdev_map = (1 << TARGET_10X_NUM_VDEVS) - 1;
|
||||
ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS) - 1;
|
||||
else
|
||||
ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
|
||||
ar->free_vdev_map = (1LL << TARGET_NUM_VDEVS) - 1;
|
||||
|
||||
INIT_LIST_HEAD(&ar->arvifs);
|
||||
|
||||
|
@ -1084,6 +1147,7 @@ void ath10k_core_unregister(struct ath10k *ar)
|
|||
EXPORT_SYMBOL(ath10k_core_unregister);
|
||||
|
||||
struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
|
||||
enum ath10k_bus bus,
|
||||
const struct ath10k_hif_ops *hif_ops)
|
||||
{
|
||||
struct ath10k *ar;
|
||||
|
@ -1100,6 +1164,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
|
|||
ar->dev = dev;
|
||||
|
||||
ar->hif.ops = hif_ops;
|
||||
ar->hif.bus = bus;
|
||||
|
||||
init_completion(&ar->scan.started);
|
||||
init_completion(&ar->scan.completed);
|
||||
|
|
|
@ -63,6 +63,20 @@
|
|||
|
||||
struct ath10k;
|
||||
|
||||
enum ath10k_bus {
|
||||
ATH10K_BUS_PCI,
|
||||
};
|
||||
|
||||
static inline const char *ath10k_bus_str(enum ath10k_bus bus)
|
||||
{
|
||||
switch (bus) {
|
||||
case ATH10K_BUS_PCI:
|
||||
return "pci";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
struct ath10k_skb_cb {
|
||||
dma_addr_t paddr;
|
||||
u8 vdev_id;
|
||||
|
@ -96,8 +110,6 @@ struct ath10k_bmi {
|
|||
bool done_sent;
|
||||
};
|
||||
|
||||
#define ATH10K_MAX_MEM_REQS 16
|
||||
|
||||
struct ath10k_mem_chunk {
|
||||
void *vaddr;
|
||||
dma_addr_t paddr;
|
||||
|
@ -115,17 +127,21 @@ struct ath10k_wmi {
|
|||
struct wmi_pdev_param_map *pdev_param;
|
||||
|
||||
u32 num_mem_chunks;
|
||||
struct ath10k_mem_chunk mem_chunks[ATH10K_MAX_MEM_REQS];
|
||||
struct ath10k_mem_chunk mem_chunks[WMI_MAX_MEM_REQS];
|
||||
};
|
||||
|
||||
struct ath10k_peer_stat {
|
||||
struct ath10k_fw_stats_peer {
|
||||
struct list_head list;
|
||||
|
||||
u8 peer_macaddr[ETH_ALEN];
|
||||
u32 peer_rssi;
|
||||
u32 peer_tx_rate;
|
||||
u32 peer_rx_rate; /* 10x only */
|
||||
};
|
||||
|
||||
struct ath10k_target_stats {
|
||||
struct ath10k_fw_stats_pdev {
|
||||
struct list_head list;
|
||||
|
||||
/* PDEV stats */
|
||||
s32 ch_noise_floor;
|
||||
u32 tx_frame_count;
|
||||
|
@ -180,15 +196,11 @@ struct ath10k_target_stats {
|
|||
s32 phy_errs;
|
||||
s32 phy_err_drop;
|
||||
s32 mpdu_errs;
|
||||
};
|
||||
|
||||
/* VDEV STATS */
|
||||
|
||||
/* PEER STATS */
|
||||
u8 peers;
|
||||
struct ath10k_peer_stat peer_stat[TARGET_NUM_PEERS];
|
||||
|
||||
/* TODO: Beacon filter stats */
|
||||
|
||||
struct ath10k_fw_stats {
|
||||
struct list_head pdevs;
|
||||
struct list_head peers;
|
||||
};
|
||||
|
||||
struct ath10k_dfs_stats {
|
||||
|
@ -234,6 +246,8 @@ struct ath10k_vif {
|
|||
struct sk_buff *beacon;
|
||||
/* protected by data_lock */
|
||||
bool beacon_sent;
|
||||
void *beacon_buf;
|
||||
dma_addr_t beacon_paddr;
|
||||
|
||||
struct ath10k *ar;
|
||||
struct ieee80211_vif *vif;
|
||||
|
@ -273,6 +287,7 @@ struct ath10k_vif {
|
|||
u8 force_sgi;
|
||||
bool use_cts_prot;
|
||||
int num_legacy_stations;
|
||||
int txpower;
|
||||
};
|
||||
|
||||
struct ath10k_vif_iter {
|
||||
|
@ -292,17 +307,19 @@ struct ath10k_fw_crash_data {
|
|||
struct ath10k_debug {
|
||||
struct dentry *debugfs_phy;
|
||||
|
||||
struct ath10k_target_stats target_stats;
|
||||
struct ath10k_fw_stats fw_stats;
|
||||
struct completion fw_stats_complete;
|
||||
bool fw_stats_done;
|
||||
DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_MAX);
|
||||
|
||||
struct completion event_stats_compl;
|
||||
|
||||
unsigned long htt_stats_mask;
|
||||
struct delayed_work htt_stats_dwork;
|
||||
struct ath10k_dfs_stats dfs_stats;
|
||||
struct ath_dfs_pool_stats dfs_pool_stats;
|
||||
|
||||
/* protected by conf_mutex */
|
||||
u32 fw_dbglog_mask;
|
||||
u32 pktlog_filter;
|
||||
|
||||
u8 htt_max_amsdu;
|
||||
u8 htt_max_ampdu;
|
||||
|
@ -371,6 +388,23 @@ enum ath10k_dev_flags {
|
|||
ATH10K_FLAG_CORE_REGISTERED,
|
||||
};
|
||||
|
||||
enum ath10k_cal_mode {
|
||||
ATH10K_CAL_MODE_FILE,
|
||||
ATH10K_CAL_MODE_OTP,
|
||||
};
|
||||
|
||||
static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case ATH10K_CAL_MODE_FILE:
|
||||
return "file";
|
||||
case ATH10K_CAL_MODE_OTP:
|
||||
return "otp";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
enum ath10k_scan_state {
|
||||
ATH10K_SCAN_IDLE,
|
||||
ATH10K_SCAN_STARTING,
|
||||
|
@ -421,6 +455,7 @@ struct ath10k {
|
|||
bool p2p;
|
||||
|
||||
struct {
|
||||
enum ath10k_bus bus;
|
||||
const struct ath10k_hif_ops *ops;
|
||||
} hif;
|
||||
|
||||
|
@ -456,7 +491,10 @@ struct ath10k {
|
|||
const void *firmware_data;
|
||||
size_t firmware_len;
|
||||
|
||||
const struct firmware *cal_file;
|
||||
|
||||
int fw_api;
|
||||
enum ath10k_cal_mode cal_mode;
|
||||
|
||||
struct {
|
||||
struct completion started;
|
||||
|
@ -482,7 +520,7 @@ struct ath10k {
|
|||
/* current operating channel definition */
|
||||
struct cfg80211_chan_def chandef;
|
||||
|
||||
int free_vdev_map;
|
||||
unsigned long long free_vdev_map;
|
||||
bool monitor;
|
||||
int monitor_vdev_id;
|
||||
bool monitor_started;
|
||||
|
@ -563,11 +601,19 @@ struct ath10k {
|
|||
bool utf_monitor;
|
||||
} testmode;
|
||||
|
||||
struct {
|
||||
/* protected by data_lock */
|
||||
u32 fw_crash_counter;
|
||||
u32 fw_warm_reset_counter;
|
||||
u32 fw_cold_reset_counter;
|
||||
} stats;
|
||||
|
||||
/* must be last */
|
||||
u8 drv_priv[0] __aligned(sizeof(void *));
|
||||
};
|
||||
|
||||
struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
|
||||
enum ath10k_bus bus,
|
||||
const struct ath10k_hif_ops *hif_ops);
|
||||
void ath10k_core_destroy(struct ath10k *ar);
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -38,11 +38,20 @@ enum ath10k_debug_mask {
|
|||
ATH10K_DBG_ANY = 0xffffffff,
|
||||
};
|
||||
|
||||
enum ath10k_pktlog_filter {
|
||||
ATH10K_PKTLOG_RX = 0x000000001,
|
||||
ATH10K_PKTLOG_TX = 0x000000002,
|
||||
ATH10K_PKTLOG_RCFIND = 0x000000004,
|
||||
ATH10K_PKTLOG_RCUPDATE = 0x000000008,
|
||||
ATH10K_PKTLOG_DBG_PRINT = 0x000000010,
|
||||
ATH10K_PKTLOG_ANY = 0x00000001f,
|
||||
};
|
||||
|
||||
extern unsigned int ath10k_debug_mask;
|
||||
|
||||
__printf(2, 3) int ath10k_info(struct ath10k *ar, const char *fmt, ...);
|
||||
__printf(2, 3) int ath10k_err(struct ath10k *ar, const char *fmt, ...);
|
||||
__printf(2, 3) int ath10k_warn(struct ath10k *ar, const char *fmt, ...);
|
||||
__printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...);
|
||||
__printf(2, 3) void ath10k_err(struct ath10k *ar, const char *fmt, ...);
|
||||
__printf(2, 3) void ath10k_warn(struct ath10k *ar, const char *fmt, ...);
|
||||
void ath10k_print_driver_info(struct ath10k *ar);
|
||||
|
||||
#ifdef CONFIG_ATH10K_DEBUGFS
|
||||
|
@ -53,17 +62,24 @@ void ath10k_debug_destroy(struct ath10k *ar);
|
|||
int ath10k_debug_register(struct ath10k *ar);
|
||||
void ath10k_debug_unregister(struct ath10k *ar);
|
||||
void ath10k_debug_read_service_map(struct ath10k *ar,
|
||||
void *service_map,
|
||||
const void *service_map,
|
||||
size_t map_size);
|
||||
void ath10k_debug_read_target_stats(struct ath10k *ar,
|
||||
struct wmi_stats_event *ev);
|
||||
void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb);
|
||||
struct ath10k_fw_crash_data *
|
||||
ath10k_debug_get_new_fw_crash_data(struct ath10k *ar);
|
||||
|
||||
void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len);
|
||||
|
||||
#define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++)
|
||||
|
||||
void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
u32 sset, u8 *data);
|
||||
int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif, int sset);
|
||||
void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ethtool_stats *stats, u64 *data);
|
||||
|
||||
#else
|
||||
static inline int ath10k_debug_start(struct ath10k *ar)
|
||||
{
|
||||
|
@ -93,13 +109,13 @@ static inline void ath10k_debug_unregister(struct ath10k *ar)
|
|||
}
|
||||
|
||||
static inline void ath10k_debug_read_service_map(struct ath10k *ar,
|
||||
void *service_map,
|
||||
const void *service_map,
|
||||
size_t map_size)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void ath10k_debug_read_target_stats(struct ath10k *ar,
|
||||
struct wmi_stats_event *ev)
|
||||
static inline void ath10k_debug_fw_stats_process(struct ath10k *ar,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -116,6 +132,10 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
|
|||
|
||||
#define ATH10K_DFS_STAT_INC(ar, c) do { } while (0)
|
||||
|
||||
#define ath10k_debug_get_et_strings NULL
|
||||
#define ath10k_debug_get_et_sset_count NULL
|
||||
#define ath10k_debug_get_et_stats NULL
|
||||
|
||||
#endif /* CONFIG_ATH10K_DEBUGFS */
|
||||
|
||||
#ifdef CONFIG_ATH10K_DEBUG
|
||||
|
|
|
@ -43,6 +43,10 @@ struct ath10k_hif_ops {
|
|||
int (*tx_sg)(struct ath10k *ar, u8 pipe_id,
|
||||
struct ath10k_hif_sg_item *items, int n_items);
|
||||
|
||||
/* read firmware memory through the diagnose interface */
|
||||
int (*diag_read)(struct ath10k *ar, u32 address, void *buf,
|
||||
size_t buf_len);
|
||||
|
||||
/*
|
||||
* API to handle HIF-specific BMI message exchanges, this API is
|
||||
* synchronous and only allowed to be called from a context that
|
||||
|
@ -98,6 +102,12 @@ static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
|
|||
return ar->hif.ops->tx_sg(ar, pipe_id, items, n_items);
|
||||
}
|
||||
|
||||
static inline int ath10k_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
|
||||
size_t buf_len)
|
||||
{
|
||||
return ar->hif.ops->diag_read(ar, address, buf, buf_len);
|
||||
}
|
||||
|
||||
static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar,
|
||||
void *request, u32 request_len,
|
||||
void *response, u32 *response_len)
|
||||
|
|
|
@ -725,7 +725,7 @@ static inline u8 *htt_rx_test_get_chars(struct htt_rx_test *rx_test)
|
|||
*/
|
||||
struct htt_pktlog_msg {
|
||||
u8 pad[3];
|
||||
__le32 payload[1 /* or more */];
|
||||
u8 payload[0];
|
||||
} __packed;
|
||||
|
||||
struct htt_dbg_stats_rx_reorder_stats {
|
||||
|
|
|
@ -291,6 +291,9 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt)
|
|||
htt->rx_ring.sw_rd_idx.msdu_payld = idx;
|
||||
htt->rx_ring.fill_cnt--;
|
||||
|
||||
trace_ath10k_htt_rx_pop_msdu(ar, msdu->data, msdu->len +
|
||||
skb_tailroom(msdu));
|
||||
|
||||
return msdu;
|
||||
}
|
||||
|
||||
|
@ -316,6 +319,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
|
|||
int msdu_len, msdu_chaining = 0;
|
||||
struct sk_buff *msdu, *next;
|
||||
struct htt_rx_desc *rx_desc;
|
||||
u32 tsf;
|
||||
|
||||
lockdep_assert_held(&htt->rx_ring.lock);
|
||||
|
||||
|
@ -447,6 +451,9 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
|
|||
last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) &
|
||||
RX_MSDU_END_INFO0_LAST_MSDU;
|
||||
|
||||
tsf = __le32_to_cpu(rx_desc->ppdu_end.tsf_timestamp);
|
||||
trace_ath10k_htt_rx_desc(ar, tsf, &rx_desc->attention,
|
||||
sizeof(*rx_desc) - sizeof(u32));
|
||||
if (last_msdu) {
|
||||
msdu->next = NULL;
|
||||
break;
|
||||
|
@ -1674,6 +1681,15 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
|||
case HTT_T2H_MSG_TYPE_RX_DELBA:
|
||||
ath10k_htt_rx_delba(ar, resp);
|
||||
break;
|
||||
case HTT_T2H_MSG_TYPE_PKTLOG: {
|
||||
struct ath10k_pktlog_hdr *hdr =
|
||||
(struct ath10k_pktlog_hdr *)resp->pktlog_msg.payload;
|
||||
|
||||
trace_ath10k_htt_pktlog(ar, resp->pktlog_msg.payload,
|
||||
sizeof(*hdr) +
|
||||
__le16_to_cpu(hdr->size));
|
||||
break;
|
||||
}
|
||||
case HTT_T2H_MSG_TYPE_RX_FLUSH: {
|
||||
/* Ignore this event because mac80211 takes care of Rx
|
||||
* aggregation reordering.
|
||||
|
@ -1681,8 +1697,8 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
|||
break;
|
||||
}
|
||||
default:
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt event (%d) not handled\n",
|
||||
resp->hdr.msg_type);
|
||||
ath10k_warn(ar, "htt event (%d) not handled\n",
|
||||
resp->hdr.msg_type);
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ",
|
||||
skb->data, skb->len);
|
||||
break;
|
||||
|
|
|
@ -557,12 +557,14 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
|||
skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr);
|
||||
skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le32(HTT_INVALID_PEERID);
|
||||
|
||||
trace_ath10k_htt_tx(ar, msdu_id, msdu->len, vdev_id, tid);
|
||||
ath10k_dbg(ar, ATH10K_DBG_HTT,
|
||||
"htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu\n",
|
||||
flags0, flags1, msdu->len, msdu_id, frags_paddr,
|
||||
(u32)skb_cb->paddr, vdev_id, tid);
|
||||
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ",
|
||||
msdu->data, msdu->len);
|
||||
trace_ath10k_htt_tx_msdu(ar, msdu->data, msdu->len);
|
||||
|
||||
sg_items[0].transfer_id = 0;
|
||||
sg_items[0].transfer_context = NULL;
|
||||
|
|
|
@ -20,15 +20,16 @@
|
|||
|
||||
#include "targaddrs.h"
|
||||
|
||||
#define ATH10K_FW_DIR "ath10k"
|
||||
|
||||
/* QCA988X 1.0 definitions (unsupported) */
|
||||
#define QCA988X_HW_1_0_CHIP_ID_REV 0x0
|
||||
|
||||
/* QCA988X 2.0 definitions */
|
||||
#define QCA988X_HW_2_0_VERSION 0x4100016c
|
||||
#define QCA988X_HW_2_0_CHIP_ID_REV 0x2
|
||||
#define QCA988X_HW_2_0_FW_DIR "ath10k/QCA988X/hw2.0"
|
||||
#define QCA988X_HW_2_0_FW_DIR ATH10K_FW_DIR "/QCA988X/hw2.0"
|
||||
#define QCA988X_HW_2_0_FW_FILE "firmware.bin"
|
||||
#define QCA988X_HW_2_0_FW_3_FILE "firmware-3.bin"
|
||||
#define QCA988X_HW_2_0_OTP_FILE "otp.bin"
|
||||
#define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin"
|
||||
#define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234
|
||||
|
@ -43,6 +44,8 @@
|
|||
|
||||
#define REG_DUMP_COUNT_QCA988X 60
|
||||
|
||||
#define QCA988X_CAL_DATA_LEN 2116
|
||||
|
||||
struct ath10k_fw_ie {
|
||||
__le32 id;
|
||||
__le32 len;
|
||||
|
@ -78,6 +81,15 @@ enum ath10k_mcast2ucast_mode {
|
|||
ATH10K_MCAST2UCAST_ENABLED = 1,
|
||||
};
|
||||
|
||||
struct ath10k_pktlog_hdr {
|
||||
__le16 flags;
|
||||
__le16 missed_cnt;
|
||||
__le16 log_type;
|
||||
__le16 size;
|
||||
__le32 timestamp;
|
||||
u8 payload[0];
|
||||
} __packed;
|
||||
|
||||
/* Target specific defines for MAIN firmware */
|
||||
#define TARGET_NUM_VDEVS 8
|
||||
#define TARGET_NUM_PEER_AST 2
|
||||
|
@ -279,6 +291,7 @@ enum ath10k_mcast2ucast_mode {
|
|||
#define SI_RX_DATA1_OFFSET 0x00000014
|
||||
|
||||
#define CORE_CTRL_CPU_INTR_MASK 0x00002000
|
||||
#define CORE_CTRL_PCIE_REG_31_MASK 0x00000800
|
||||
#define CORE_CTRL_ADDRESS 0x0000
|
||||
#define PCIE_INTR_ENABLE_ADDRESS 0x0008
|
||||
#define PCIE_INTR_CAUSE_ADDRESS 0x000c
|
||||
|
|
|
@ -479,6 +479,40 @@ static void ath10k_peer_cleanup_all(struct ath10k *ar)
|
|||
/* Interface management */
|
||||
/************************/
|
||||
|
||||
void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif)
|
||||
{
|
||||
struct ath10k *ar = arvif->ar;
|
||||
|
||||
lockdep_assert_held(&ar->data_lock);
|
||||
|
||||
if (!arvif->beacon)
|
||||
return;
|
||||
|
||||
if (!arvif->beacon_buf)
|
||||
dma_unmap_single(ar->dev, ATH10K_SKB_CB(arvif->beacon)->paddr,
|
||||
arvif->beacon->len, DMA_TO_DEVICE);
|
||||
|
||||
dev_kfree_skb_any(arvif->beacon);
|
||||
|
||||
arvif->beacon = NULL;
|
||||
arvif->beacon_sent = false;
|
||||
}
|
||||
|
||||
static void ath10k_mac_vif_beacon_cleanup(struct ath10k_vif *arvif)
|
||||
{
|
||||
struct ath10k *ar = arvif->ar;
|
||||
|
||||
lockdep_assert_held(&ar->data_lock);
|
||||
|
||||
ath10k_mac_vif_beacon_free(arvif);
|
||||
|
||||
if (arvif->beacon_buf) {
|
||||
dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
|
||||
arvif->beacon_buf, arvif->beacon_paddr);
|
||||
arvif->beacon_buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
|
||||
{
|
||||
int ret;
|
||||
|
@ -590,9 +624,9 @@ static int ath10k_monitor_vdev_create(struct ath10k *ar)
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bit = ffs(ar->free_vdev_map);
|
||||
bit = __ffs64(ar->free_vdev_map);
|
||||
|
||||
ar->monitor_vdev_id = bit - 1;
|
||||
ar->monitor_vdev_id = bit;
|
||||
|
||||
ret = ath10k_wmi_vdev_create(ar, ar->monitor_vdev_id,
|
||||
WMI_VDEV_TYPE_MONITOR,
|
||||
|
@ -603,7 +637,7 @@ static int ath10k_monitor_vdev_create(struct ath10k *ar)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ar->free_vdev_map &= ~(1 << ar->monitor_vdev_id);
|
||||
ar->free_vdev_map &= ~(1LL << ar->monitor_vdev_id);
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d created\n",
|
||||
ar->monitor_vdev_id);
|
||||
|
||||
|
@ -623,7 +657,7 @@ static int ath10k_monitor_vdev_delete(struct ath10k *ar)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ar->free_vdev_map |= 1 << ar->monitor_vdev_id;
|
||||
ar->free_vdev_map |= 1LL << ar->monitor_vdev_id;
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d deleted\n",
|
||||
ar->monitor_vdev_id);
|
||||
|
@ -909,15 +943,7 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif,
|
|||
arvif->is_up = false;
|
||||
|
||||
spin_lock_bh(&arvif->ar->data_lock);
|
||||
if (arvif->beacon) {
|
||||
dma_unmap_single(arvif->ar->dev,
|
||||
ATH10K_SKB_CB(arvif->beacon)->paddr,
|
||||
arvif->beacon->len, DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(arvif->beacon);
|
||||
|
||||
arvif->beacon = NULL;
|
||||
arvif->beacon_sent = false;
|
||||
}
|
||||
ath10k_mac_vif_beacon_free(arvif);
|
||||
spin_unlock_bh(&arvif->ar->data_lock);
|
||||
|
||||
return;
|
||||
|
@ -966,14 +992,6 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif,
|
|||
if (is_zero_ether_addr(arvif->bssid))
|
||||
return;
|
||||
|
||||
ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id,
|
||||
arvif->bssid);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to delete IBSS BSSID peer %pM for vdev %d: %d\n",
|
||||
arvif->bssid, arvif->vdev_id, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(arvif->bssid, 0, ETH_ALEN);
|
||||
|
||||
return;
|
||||
|
@ -1042,51 +1060,45 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
|
|||
/* Station management */
|
||||
/**********************/
|
||||
|
||||
static u32 ath10k_peer_assoc_h_listen_intval(struct ath10k *ar,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
/* Some firmware revisions have unstable STA powersave when listen
|
||||
* interval is set too high (e.g. 5). The symptoms are firmware doesn't
|
||||
* generate NullFunc frames properly even if buffered frames have been
|
||||
* indicated in Beacon TIM. Firmware would seldom wake up to pull
|
||||
* buffered frames. Often pinging the device from AP would simply fail.
|
||||
*
|
||||
* As a workaround set it to 1.
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_STATION)
|
||||
return 1;
|
||||
|
||||
return ar->hw->conf.listen_interval;
|
||||
}
|
||||
|
||||
static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
|
||||
struct ath10k_vif *arvif,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
struct wmi_peer_assoc_complete_arg *arg)
|
||||
{
|
||||
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
ether_addr_copy(arg->addr, sta->addr);
|
||||
arg->vdev_id = arvif->vdev_id;
|
||||
arg->peer_aid = sta->aid;
|
||||
arg->peer_flags |= WMI_PEER_AUTH;
|
||||
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
|
||||
/*
|
||||
* Seems FW have problems with Power Save in STA
|
||||
* mode when we setup this parameter to high (eg. 5).
|
||||
* Often we see that FW don't send NULL (with clean P flags)
|
||||
* frame even there is info about buffered frames in beacons.
|
||||
* Sometimes we have to wait more than 10 seconds before FW
|
||||
* will wakeup. Often sending one ping from AP to our device
|
||||
* just fail (more than 50%).
|
||||
*
|
||||
* Seems setting this FW parameter to 1 couse FW
|
||||
* will check every beacon and will wakup immediately
|
||||
* after detection buffered data.
|
||||
*/
|
||||
arg->peer_listen_intval = 1;
|
||||
else
|
||||
arg->peer_listen_intval = ar->hw->conf.listen_interval;
|
||||
|
||||
arg->peer_listen_intval = ath10k_peer_assoc_h_listen_intval(ar, vif);
|
||||
arg->peer_num_spatial_streams = 1;
|
||||
|
||||
/*
|
||||
* The assoc capabilities are available only in managed mode.
|
||||
*/
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_STA && bss_conf)
|
||||
arg->peer_caps = bss_conf->assoc_capability;
|
||||
arg->peer_caps = vif->bss_conf.assoc_capability;
|
||||
}
|
||||
|
||||
static void ath10k_peer_assoc_h_crypto(struct ath10k *ar,
|
||||
struct ath10k_vif *arvif,
|
||||
struct ieee80211_vif *vif,
|
||||
struct wmi_peer_assoc_complete_arg *arg)
|
||||
{
|
||||
struct ieee80211_vif *vif = arvif->vif;
|
||||
struct ieee80211_bss_conf *info = &vif->bss_conf;
|
||||
struct cfg80211_bss *bss;
|
||||
const u8 *rsnie = NULL;
|
||||
|
@ -1343,11 +1355,12 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
|
|||
}
|
||||
|
||||
static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
|
||||
struct ath10k_vif *arvif,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
struct wmi_peer_assoc_complete_arg *arg)
|
||||
{
|
||||
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
|
||||
|
||||
switch (arvif->vdev_type) {
|
||||
case WMI_VDEV_TYPE_AP:
|
||||
if (sta->wme)
|
||||
|
@ -1359,7 +1372,7 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
|
|||
}
|
||||
break;
|
||||
case WMI_VDEV_TYPE_STA:
|
||||
if (bss_conf->qos)
|
||||
if (vif->bss_conf.qos)
|
||||
arg->peer_flags |= WMI_PEER_QOS;
|
||||
break;
|
||||
default:
|
||||
|
@ -1368,7 +1381,7 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
|
|||
}
|
||||
|
||||
static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
|
||||
struct ath10k_vif *arvif,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct wmi_peer_assoc_complete_arg *arg)
|
||||
{
|
||||
|
@ -1419,22 +1432,21 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
|
|||
}
|
||||
|
||||
static int ath10k_peer_assoc_prepare(struct ath10k *ar,
|
||||
struct ath10k_vif *arvif,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
struct wmi_peer_assoc_complete_arg *arg)
|
||||
{
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
memset(arg, 0, sizeof(*arg));
|
||||
|
||||
ath10k_peer_assoc_h_basic(ar, arvif, sta, bss_conf, arg);
|
||||
ath10k_peer_assoc_h_crypto(ar, arvif, arg);
|
||||
ath10k_peer_assoc_h_basic(ar, vif, sta, arg);
|
||||
ath10k_peer_assoc_h_crypto(ar, vif, arg);
|
||||
ath10k_peer_assoc_h_rates(ar, sta, arg);
|
||||
ath10k_peer_assoc_h_ht(ar, sta, arg);
|
||||
ath10k_peer_assoc_h_vht(ar, sta, arg);
|
||||
ath10k_peer_assoc_h_qos(ar, arvif, sta, bss_conf, arg);
|
||||
ath10k_peer_assoc_h_phymode(ar, arvif, sta, arg);
|
||||
ath10k_peer_assoc_h_qos(ar, vif, sta, arg);
|
||||
ath10k_peer_assoc_h_phymode(ar, vif, sta, arg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1480,6 +1492,9 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
|
|||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n",
|
||||
arvif->vdev_id, arvif->bssid, arvif->aid);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
ap_sta = ieee80211_find_sta(vif, bss_conf->bssid);
|
||||
|
@ -1494,8 +1509,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
|
|||
* before calling ath10k_setup_peer_smps() which might sleep. */
|
||||
ht_cap = ap_sta->ht_cap;
|
||||
|
||||
ret = ath10k_peer_assoc_prepare(ar, arvif, ap_sta,
|
||||
bss_conf, &peer_arg);
|
||||
ret = ath10k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to prepare peer assoc for %pM vdev %i: %d\n",
|
||||
bss_conf->bssid, arvif->vdev_id, ret);
|
||||
|
@ -1523,6 +1537,8 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
|
|||
"mac vdev %d up (associated) bssid %pM aid %d\n",
|
||||
arvif->vdev_id, bss_conf->bssid, bss_conf->aid);
|
||||
|
||||
WARN_ON(arvif->is_up);
|
||||
|
||||
arvif->aid = bss_conf->aid;
|
||||
ether_addr_copy(arvif->bssid, bss_conf->bssid);
|
||||
|
||||
|
@ -1536,9 +1552,6 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
|
|||
arvif->is_up = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: flush TIDs
|
||||
*/
|
||||
static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
|
||||
struct ieee80211_vif *vif)
|
||||
{
|
||||
|
@ -1548,45 +1561,30 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
|
|||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
/*
|
||||
* For some reason, calling VDEV-DOWN before VDEV-STOP
|
||||
* makes the FW to send frames via HTT after disassociation.
|
||||
* No idea why this happens, even though VDEV-DOWN is supposed
|
||||
* to be analogous to link down, so just stop the VDEV.
|
||||
*/
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d stop (disassociated\n",
|
||||
arvif->vdev_id);
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n",
|
||||
arvif->vdev_id, arvif->bssid);
|
||||
|
||||
/* FIXME: check return value */
|
||||
ret = ath10k_vdev_stop(arvif);
|
||||
|
||||
/*
|
||||
* If we don't call VDEV-DOWN after VDEV-STOP FW will remain active and
|
||||
* report beacons from previously associated network through HTT.
|
||||
* This in turn would spam mac80211 WARN_ON if we bring down all
|
||||
* interfaces as it expects there is no rx when no interface is
|
||||
* running.
|
||||
*/
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d down\n", arvif->vdev_id);
|
||||
|
||||
/* FIXME: why don't we print error if wmi call fails? */
|
||||
ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "faield to down vdev %i: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
|
||||
arvif->def_wep_key_idx = 0;
|
||||
|
||||
arvif->is_started = false;
|
||||
arvif->is_up = false;
|
||||
}
|
||||
|
||||
static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif,
|
||||
struct ieee80211_sta *sta, bool reassoc)
|
||||
static int ath10k_station_assoc(struct ath10k *ar,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
bool reassoc)
|
||||
{
|
||||
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
|
||||
struct wmi_peer_assoc_complete_arg peer_arg;
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
ret = ath10k_peer_assoc_prepare(ar, arvif, sta, NULL, &peer_arg);
|
||||
ret = ath10k_peer_assoc_prepare(ar, vif, sta, &peer_arg);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to prepare WMI peer assoc for %pM vdev %i: %i\n",
|
||||
sta->addr, arvif->vdev_id, ret);
|
||||
|
@ -1601,43 +1599,51 @@ static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif,
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = ath10k_setup_peer_smps(ar, arvif, sta->addr, &sta->ht_cap);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to setup peer SMPS for vdev %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!sta->wme && !reassoc) {
|
||||
arvif->num_legacy_stations++;
|
||||
ret = ath10k_recalc_rtscts_prot(arvif);
|
||||
/* Re-assoc is run only to update supported rates for given station. It
|
||||
* doesn't make much sense to reconfigure the peer completely.
|
||||
*/
|
||||
if (!reassoc) {
|
||||
ret = ath10k_setup_peer_smps(ar, arvif, sta->addr,
|
||||
&sta->ht_cap);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n",
|
||||
ath10k_warn(ar, "failed to setup peer SMPS for vdev %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath10k_peer_assoc_qos_ap(ar, arvif, sta);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to set qos params for STA %pM for vdev %i: %d\n",
|
||||
sta->addr, arvif->vdev_id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!sta->wme) {
|
||||
arvif->num_legacy_stations++;
|
||||
ret = ath10k_recalc_rtscts_prot(arvif);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ath10k_install_peer_wep_keys(arvif, sta->addr);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ath10k_install_peer_wep_keys(arvif, sta->addr);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath10k_peer_assoc_qos_ap(ar, arvif, sta);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to set qos params for STA %pM for vdev %i: %d\n",
|
||||
sta->addr, arvif->vdev_id, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_station_disassoc(struct ath10k *ar, struct ath10k_vif *arvif,
|
||||
static int ath10k_station_disassoc(struct ath10k *ar,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta)
|
||||
{
|
||||
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
@ -1729,6 +1735,7 @@ static int ath10k_update_channel_list(struct ath10k *ar)
|
|||
ch->passive = passive;
|
||||
|
||||
ch->freq = channel->center_freq;
|
||||
ch->band_center_freq1 = channel->center_freq;
|
||||
ch->min_power = 0;
|
||||
ch->max_power = channel->max_power * 2;
|
||||
ch->max_reg_power = channel->max_reg_power * 2;
|
||||
|
@ -2376,16 +2383,8 @@ void ath10k_halt(struct ath10k *ar)
|
|||
ath10k_hif_power_down(ar);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
list_for_each_entry(arvif, &ar->arvifs, list) {
|
||||
if (!arvif->beacon)
|
||||
continue;
|
||||
|
||||
dma_unmap_single(arvif->ar->dev,
|
||||
ATH10K_SKB_CB(arvif->beacon)->paddr,
|
||||
arvif->beacon->len, DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(arvif->beacon);
|
||||
arvif->beacon = NULL;
|
||||
}
|
||||
list_for_each_entry(arvif, &ar->arvifs, list)
|
||||
ath10k_mac_vif_beacon_cleanup(arvif);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
}
|
||||
|
||||
|
@ -2677,12 +2676,68 @@ static void ath10k_config_chan(struct ath10k *ar)
|
|||
ath10k_monitor_recalc(ar);
|
||||
}
|
||||
|
||||
static int ath10k_mac_txpower_setup(struct ath10k *ar, int txpower)
|
||||
{
|
||||
int ret;
|
||||
u32 param;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac txpower %d\n", txpower);
|
||||
|
||||
param = ar->wmi.pdev_param->txpower_limit2g;
|
||||
ret = ath10k_wmi_pdev_set_param(ar, param, txpower * 2);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to set 2g txpower %d: %d\n",
|
||||
txpower, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
param = ar->wmi.pdev_param->txpower_limit5g;
|
||||
ret = ath10k_wmi_pdev_set_param(ar, param, txpower * 2);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to set 5g txpower %d: %d\n",
|
||||
txpower, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_mac_txpower_recalc(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_vif *arvif;
|
||||
int ret, txpower = -1;
|
||||
|
||||
lockdep_assert_held(&ar->conf_mutex);
|
||||
|
||||
list_for_each_entry(arvif, &ar->arvifs, list) {
|
||||
WARN_ON(arvif->txpower < 0);
|
||||
|
||||
if (txpower == -1)
|
||||
txpower = arvif->txpower;
|
||||
else
|
||||
txpower = min(txpower, arvif->txpower);
|
||||
}
|
||||
|
||||
if (WARN_ON(txpower == -1))
|
||||
return -EINVAL;
|
||||
|
||||
ret = ath10k_mac_txpower_setup(ar, txpower);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to setup tx power %d: %d\n",
|
||||
txpower, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
|
||||
{
|
||||
struct ath10k *ar = hw->priv;
|
||||
struct ieee80211_conf *conf = &hw->conf;
|
||||
int ret = 0;
|
||||
u32 param;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
|
@ -2706,25 +2761,6 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
|
|||
}
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_POWER) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac config power %d\n",
|
||||
hw->conf.power_level);
|
||||
|
||||
param = ar->wmi.pdev_param->txpower_limit2g;
|
||||
ret = ath10k_wmi_pdev_set_param(ar, param,
|
||||
hw->conf.power_level * 2);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to set 2g txpower %d: %d\n",
|
||||
hw->conf.power_level, ret);
|
||||
|
||||
param = ar->wmi.pdev_param->txpower_limit5g;
|
||||
ret = ath10k_wmi_pdev_set_param(ar, param,
|
||||
hw->conf.power_level * 2);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to set 5g txpower %d: %d\n",
|
||||
hw->conf.power_level, ret);
|
||||
}
|
||||
|
||||
if (changed & IEEE80211_CONF_CHANGE_PS)
|
||||
ath10k_config_ps(ar);
|
||||
|
||||
|
@ -2772,9 +2808,12 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
|||
ret = -EBUSY;
|
||||
goto err;
|
||||
}
|
||||
bit = ffs(ar->free_vdev_map);
|
||||
bit = __ffs64(ar->free_vdev_map);
|
||||
|
||||
arvif->vdev_id = bit - 1;
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac create vdev %i map %llx\n",
|
||||
bit, ar->free_vdev_map);
|
||||
|
||||
arvif->vdev_id = bit;
|
||||
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
|
||||
|
||||
if (ar->p2p)
|
||||
|
@ -2804,8 +2843,39 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
|||
break;
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d\n",
|
||||
arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype);
|
||||
/* Some firmware revisions don't wait for beacon tx completion before
|
||||
* sending another SWBA event. This could lead to hardware using old
|
||||
* (freed) beacon data in some cases, e.g. tx credit starvation
|
||||
* combined with missed TBTT. This is very very rare.
|
||||
*
|
||||
* On non-IOMMU-enabled hosts this could be a possible security issue
|
||||
* because hw could beacon some random data on the air. On
|
||||
* IOMMU-enabled hosts DMAR faults would occur in most cases and target
|
||||
* device would crash.
|
||||
*
|
||||
* Since there are no beacon tx completions (implicit nor explicit)
|
||||
* propagated to host the only workaround for this is to allocate a
|
||||
* DMA-coherent buffer for a lifetime of a vif and use it for all
|
||||
* beacon tx commands. Worst case for this approach is some beacons may
|
||||
* become corrupted, e.g. have garbled IEs or out-of-date TIM bitmap.
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC ||
|
||||
vif->type == NL80211_IFTYPE_AP) {
|
||||
arvif->beacon_buf = dma_zalloc_coherent(ar->dev,
|
||||
IEEE80211_MAX_FRAME_LEN,
|
||||
&arvif->beacon_paddr,
|
||||
GFP_ATOMIC);
|
||||
if (!arvif->beacon_buf) {
|
||||
ret = -ENOMEM;
|
||||
ath10k_warn(ar, "failed to allocate beacon buffer: %d\n",
|
||||
ret);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d bcnmode %s\n",
|
||||
arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype,
|
||||
arvif->beacon_buf ? "single-buf" : "per-skb");
|
||||
|
||||
ret = ath10k_wmi_vdev_create(ar, arvif->vdev_id, arvif->vdev_type,
|
||||
arvif->vdev_subtype, vif->addr);
|
||||
|
@ -2815,7 +2885,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
|||
goto err;
|
||||
}
|
||||
|
||||
ar->free_vdev_map &= ~(1 << arvif->vdev_id);
|
||||
ar->free_vdev_map &= ~(1LL << arvif->vdev_id);
|
||||
list_add(&arvif->list, &ar->arvifs);
|
||||
|
||||
vdev_param = ar->wmi.vdev_param->def_keyid;
|
||||
|
@ -2899,6 +2969,13 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
|
|||
goto err_peer_delete;
|
||||
}
|
||||
|
||||
arvif->txpower = vif->bss_conf.txpower;
|
||||
ret = ath10k_mac_txpower_recalc(ar);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to recalc tx power: %d\n", ret);
|
||||
goto err_peer_delete;
|
||||
}
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return 0;
|
||||
|
||||
|
@ -2908,10 +2985,16 @@ err_peer_delete:
|
|||
|
||||
err_vdev_delete:
|
||||
ath10k_wmi_vdev_delete(ar, arvif->vdev_id);
|
||||
ar->free_vdev_map |= 1 << arvif->vdev_id;
|
||||
ar->free_vdev_map |= 1LL << arvif->vdev_id;
|
||||
list_del(&arvif->list);
|
||||
|
||||
err:
|
||||
if (arvif->beacon_buf) {
|
||||
dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
|
||||
arvif->beacon_buf, arvif->beacon_paddr);
|
||||
arvif->beacon_buf = NULL;
|
||||
}
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return ret;
|
||||
|
@ -2929,14 +3012,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
|
|||
cancel_work_sync(&arvif->wep_key_work);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
if (arvif->beacon) {
|
||||
dma_unmap_single(arvif->ar->dev,
|
||||
ATH10K_SKB_CB(arvif->beacon)->paddr,
|
||||
arvif->beacon->len, DMA_TO_DEVICE);
|
||||
dev_kfree_skb_any(arvif->beacon);
|
||||
arvif->beacon = NULL;
|
||||
}
|
||||
|
||||
ath10k_mac_vif_beacon_cleanup(arvif);
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
ret = ath10k_spectral_vif_stop(arvif);
|
||||
|
@ -2944,7 +3020,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
|
|||
ath10k_warn(ar, "failed to stop spectral for vdev %i: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
|
||||
ar->free_vdev_map |= 1 << arvif->vdev_id;
|
||||
ar->free_vdev_map |= 1LL << arvif->vdev_id;
|
||||
list_del(&arvif->list);
|
||||
|
||||
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
|
||||
|
@ -3068,54 +3144,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
|
|||
arvif->u.ap.hidden_ssid = info->hidden_ssid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Firmware manages AP self-peer internally so make sure to not create
|
||||
* it in driver. Otherwise AP self-peer deletion may timeout later.
|
||||
*/
|
||||
if (changed & BSS_CHANGED_BSSID &&
|
||||
vif->type != NL80211_IFTYPE_AP) {
|
||||
if (!is_zero_ether_addr(info->bssid)) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac vdev %d create peer %pM\n",
|
||||
arvif->vdev_id, info->bssid);
|
||||
|
||||
ret = ath10k_peer_create(ar, arvif->vdev_id,
|
||||
info->bssid);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to add peer %pM for vdev %d when changing bssid: %i\n",
|
||||
info->bssid, arvif->vdev_id, ret);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
/*
|
||||
* this is never erased as we it for crypto key
|
||||
* clearing; this is FW requirement
|
||||
*/
|
||||
ether_addr_copy(arvif->bssid, info->bssid);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac vdev %d start %pM\n",
|
||||
arvif->vdev_id, info->bssid);
|
||||
|
||||
ret = ath10k_vdev_start(arvif);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to start vdev %i: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
arvif->is_started = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mac80211 does not keep IBSS bssid when leaving IBSS,
|
||||
* so driver need to store it. It is needed when leaving
|
||||
* IBSS in order to remove BSSID peer.
|
||||
*/
|
||||
if (vif->type == NL80211_IFTYPE_ADHOC)
|
||||
memcpy(arvif->bssid, info->bssid,
|
||||
ETH_ALEN);
|
||||
}
|
||||
}
|
||||
if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid))
|
||||
ether_addr_copy(arvif->bssid, info->bssid);
|
||||
|
||||
if (changed & BSS_CHANGED_BEACON_ENABLED)
|
||||
ath10k_control_beaconing(arvif, info);
|
||||
|
@ -3177,10 +3207,21 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
|
|||
ath10k_monitor_stop(ar);
|
||||
ath10k_bss_assoc(hw, vif, info);
|
||||
ath10k_monitor_recalc(ar);
|
||||
} else {
|
||||
ath10k_bss_disassoc(hw, vif);
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
if (changed & BSS_CHANGED_TXPOWER) {
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev_id %i txpower %d\n",
|
||||
arvif->vdev_id, info->txpower);
|
||||
|
||||
arvif->txpower = info->txpower;
|
||||
ret = ath10k_mac_txpower_recalc(ar);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to recalc tx power: %d\n", ret);
|
||||
}
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
|
@ -3453,7 +3494,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
|
|||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates\n",
|
||||
sta->addr);
|
||||
|
||||
err = ath10k_station_assoc(ar, arvif, sta, true);
|
||||
err = ath10k_station_assoc(ar, arvif->vif, sta, true);
|
||||
if (err)
|
||||
ath10k_warn(ar, "failed to reassociate station: %pM\n",
|
||||
sta->addr);
|
||||
|
@ -3489,8 +3530,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
|
|||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (old_state == IEEE80211_STA_NOTEXIST &&
|
||||
new_state == IEEE80211_STA_NONE &&
|
||||
vif->type != NL80211_IFTYPE_STATION) {
|
||||
new_state == IEEE80211_STA_NONE) {
|
||||
/*
|
||||
* New station addition.
|
||||
*/
|
||||
|
@ -3514,6 +3554,21 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
|
|||
if (ret)
|
||||
ath10k_warn(ar, "failed to add peer %pM for vdev %d when adding a new sta: %i\n",
|
||||
sta->addr, arvif->vdev_id, ret);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
WARN_ON(arvif->is_started);
|
||||
|
||||
ret = ath10k_vdev_start(arvif);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to start vdev %i: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
WARN_ON(ath10k_peer_delete(ar, arvif->vdev_id,
|
||||
sta->addr));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
arvif->is_started = true;
|
||||
}
|
||||
} else if ((old_state == IEEE80211_STA_NONE &&
|
||||
new_state == IEEE80211_STA_NOTEXIST)) {
|
||||
/*
|
||||
|
@ -3522,13 +3577,23 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
|
|||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac vdev %d peer delete %pM (sta gone)\n",
|
||||
arvif->vdev_id, sta->addr);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION) {
|
||||
WARN_ON(!arvif->is_started);
|
||||
|
||||
ret = ath10k_vdev_stop(arvif);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to stop vdev %i: %d\n",
|
||||
arvif->vdev_id, ret);
|
||||
|
||||
arvif->is_started = false;
|
||||
}
|
||||
|
||||
ret = ath10k_peer_delete(ar, arvif->vdev_id, sta->addr);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to delete peer %pM for vdev %d: %i\n",
|
||||
sta->addr, arvif->vdev_id, ret);
|
||||
|
||||
if (vif->type == NL80211_IFTYPE_STATION)
|
||||
ath10k_bss_disassoc(hw, vif);
|
||||
} else if (old_state == IEEE80211_STA_AUTH &&
|
||||
new_state == IEEE80211_STA_ASSOC &&
|
||||
(vif->type == NL80211_IFTYPE_AP ||
|
||||
|
@ -3539,7 +3604,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
|
|||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM associated\n",
|
||||
sta->addr);
|
||||
|
||||
ret = ath10k_station_assoc(ar, arvif, sta, false);
|
||||
ret = ath10k_station_assoc(ar, vif, sta, false);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to associate station %pM for vdev %i: %i\n",
|
||||
sta->addr, arvif->vdev_id, ret);
|
||||
|
@ -3553,7 +3618,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
|
|||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM disassociated\n",
|
||||
sta->addr);
|
||||
|
||||
ret = ath10k_station_disassoc(ar, arvif, sta);
|
||||
ret = ath10k_station_disassoc(ar, vif, sta);
|
||||
if (ret)
|
||||
ath10k_warn(ar, "failed to disassociate station: %pM vdev %i: %i\n",
|
||||
sta->addr, arvif->vdev_id, ret);
|
||||
|
@ -4456,6 +4521,9 @@ static const struct ieee80211_ops ath10k_ops = {
|
|||
.sta_rc_update = ath10k_sta_rc_update,
|
||||
.get_tsf = ath10k_get_tsf,
|
||||
.ampdu_action = ath10k_ampdu_action,
|
||||
.get_et_sset_count = ath10k_debug_get_et_sset_count,
|
||||
.get_et_stats = ath10k_debug_get_et_stats,
|
||||
.get_et_strings = ath10k_debug_get_et_strings,
|
||||
|
||||
CFG80211_TESTMODE_CMD(ath10k_tm_cmd)
|
||||
|
||||
|
@ -4800,15 +4868,6 @@ int ath10k_mac_register(struct ath10k *ar)
|
|||
BIT(NL80211_IFTYPE_STATION) |
|
||||
BIT(NL80211_IFTYPE_AP);
|
||||
|
||||
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
|
||||
/* TODO: Have to deal with 2x2 chips if/when the come out. */
|
||||
ar->supp_tx_chainmask = TARGET_10X_TX_CHAIN_MASK;
|
||||
ar->supp_rx_chainmask = TARGET_10X_RX_CHAIN_MASK;
|
||||
} else {
|
||||
ar->supp_tx_chainmask = TARGET_TX_CHAIN_MASK;
|
||||
ar->supp_rx_chainmask = TARGET_RX_CHAIN_MASK;
|
||||
}
|
||||
|
||||
ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask;
|
||||
ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask;
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ void ath10k_offchan_tx_work(struct work_struct *work);
|
|||
void ath10k_mgmt_over_wmi_tx_purge(struct ath10k *ar);
|
||||
void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work);
|
||||
void ath10k_halt(struct ath10k *ar);
|
||||
void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif);
|
||||
|
||||
static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
|
||||
{
|
||||
|
|
|
@ -485,6 +485,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
|
|||
void *data_buf = NULL;
|
||||
int i;
|
||||
|
||||
spin_lock_bh(&ar_pci->ce_lock);
|
||||
|
||||
ce_diag = ar_pci->ce_diag;
|
||||
|
||||
/*
|
||||
|
@ -511,7 +513,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
|
|||
nbytes = min_t(unsigned int, remaining_bytes,
|
||||
DIAG_TRANSFER_LIMIT);
|
||||
|
||||
ret = ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data);
|
||||
ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data);
|
||||
if (ret != 0)
|
||||
goto done;
|
||||
|
||||
|
@ -527,15 +529,15 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
|
|||
address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci->mem,
|
||||
address);
|
||||
|
||||
ret = ath10k_ce_send(ce_diag, NULL, (u32)address, nbytes, 0,
|
||||
0);
|
||||
ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)address, nbytes, 0,
|
||||
0);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
i = 0;
|
||||
while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id) != 0) {
|
||||
while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id) != 0) {
|
||||
mdelay(1);
|
||||
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
|
||||
ret = -EBUSY;
|
||||
|
@ -554,9 +556,9 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
|
|||
}
|
||||
|
||||
i = 0;
|
||||
while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id, &flags) != 0) {
|
||||
while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id, &flags) != 0) {
|
||||
mdelay(1);
|
||||
|
||||
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
|
||||
|
@ -591,6 +593,8 @@ done:
|
|||
dma_free_coherent(ar->dev, orig_nbytes, data_buf,
|
||||
ce_data_base);
|
||||
|
||||
spin_unlock_bh(&ar_pci->ce_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -648,6 +652,8 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
|
|||
dma_addr_t ce_data_base = 0;
|
||||
int i;
|
||||
|
||||
spin_lock_bh(&ar_pci->ce_lock);
|
||||
|
||||
ce_diag = ar_pci->ce_diag;
|
||||
|
||||
/*
|
||||
|
@ -688,7 +694,7 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
|
|||
nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT);
|
||||
|
||||
/* 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, NULL, address);
|
||||
if (ret != 0)
|
||||
goto done;
|
||||
|
||||
|
@ -696,15 +702,15 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
|
|||
* Request CE to send caller-supplied data that
|
||||
* was copied to bounce buffer to Target(!) address.
|
||||
*/
|
||||
ret = ath10k_ce_send(ce_diag, NULL, (u32)ce_data,
|
||||
nbytes, 0, 0);
|
||||
ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)ce_data,
|
||||
nbytes, 0, 0);
|
||||
if (ret != 0)
|
||||
goto done;
|
||||
|
||||
i = 0;
|
||||
while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id) != 0) {
|
||||
while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id) != 0) {
|
||||
mdelay(1);
|
||||
|
||||
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
|
||||
|
@ -724,9 +730,9 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address,
|
|||
}
|
||||
|
||||
i = 0;
|
||||
while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id, &flags) != 0) {
|
||||
while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
|
||||
&completed_nbytes,
|
||||
&id, &flags) != 0) {
|
||||
mdelay(1);
|
||||
|
||||
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
|
||||
|
@ -760,6 +766,8 @@ done:
|
|||
ath10k_warn(ar, "failed to write diag value at 0x%x: %d\n",
|
||||
address, ret);
|
||||
|
||||
spin_unlock_bh(&ar_pci->ce_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -861,6 +869,12 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state)
|
|||
}
|
||||
|
||||
skb_put(skb, nbytes);
|
||||
|
||||
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);
|
||||
|
||||
cb->rx_completion(ar, skb, pipe_info->pipe_num);
|
||||
}
|
||||
|
||||
|
@ -936,6 +950,12 @@ err:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
|
||||
size_t buf_len)
|
||||
{
|
||||
return ath10k_pci_diag_read_mem(ar, address, buf, buf_len);
|
||||
}
|
||||
|
||||
static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
|
@ -986,6 +1006,8 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar)
|
|||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
ar->stats.fw_crash_counter++;
|
||||
|
||||
crash_data = ath10k_debug_get_new_fw_crash_data(ar);
|
||||
|
||||
if (crash_data)
|
||||
|
@ -1121,15 +1143,38 @@ static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar,
|
|||
&dl_is_polled);
|
||||
}
|
||||
|
||||
static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS);
|
||||
val &= ~CORE_CTRL_PCIE_REG_31_MASK;
|
||||
|
||||
ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val);
|
||||
}
|
||||
|
||||
static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS);
|
||||
val |= CORE_CTRL_PCIE_REG_31_MASK;
|
||||
|
||||
ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val);
|
||||
}
|
||||
|
||||
static void ath10k_pci_irq_disable(struct ath10k *ar)
|
||||
{
|
||||
ath10k_ce_disable_interrupts(ar);
|
||||
ath10k_pci_disable_and_clear_legacy_irq(ar);
|
||||
ath10k_pci_irq_msi_fw_mask(ar);
|
||||
}
|
||||
|
||||
static void ath10k_pci_irq_sync(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
int i;
|
||||
|
||||
ath10k_ce_disable_interrupts(ar);
|
||||
ath10k_pci_disable_and_clear_legacy_irq(ar);
|
||||
/* FIXME: How to mask all MSI interrupts? */
|
||||
|
||||
for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++)
|
||||
synchronize_irq(ar_pci->pdev->irq + i);
|
||||
}
|
||||
|
@ -1138,7 +1183,7 @@ static void ath10k_pci_irq_enable(struct ath10k *ar)
|
|||
{
|
||||
ath10k_ce_enable_interrupts(ar);
|
||||
ath10k_pci_enable_legacy_irq(ar);
|
||||
/* FIXME: How to unmask all MSI interrupts? */
|
||||
ath10k_pci_irq_msi_fw_unmask(ar);
|
||||
}
|
||||
|
||||
static int ath10k_pci_hif_start(struct ath10k *ar)
|
||||
|
@ -1266,6 +1311,7 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
|
|||
ath10k_pci_warm_reset(ar);
|
||||
|
||||
ath10k_pci_irq_disable(ar);
|
||||
ath10k_pci_irq_sync(ar);
|
||||
ath10k_pci_flush(ar);
|
||||
}
|
||||
|
||||
|
@ -1569,23 +1615,40 @@ static int ath10k_pci_init_config(struct ath10k *ar)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ath10k_pci_alloc_ce(struct ath10k *ar)
|
||||
static int ath10k_pci_alloc_pipes(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
struct ath10k_pci_pipe *pipe;
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < CE_COUNT; i++) {
|
||||
ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i]);
|
||||
pipe = &ar_pci->pipe_info[i];
|
||||
pipe->ce_hdl = &ar_pci->ce_states[i];
|
||||
pipe->pipe_num = i;
|
||||
pipe->hif_ce_state = ar;
|
||||
|
||||
ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i],
|
||||
ath10k_pci_ce_send_done,
|
||||
ath10k_pci_ce_recv_data);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to allocate copy engine pipe %d: %d\n",
|
||||
i, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Last CE is Diagnostic Window */
|
||||
if (i == CE_COUNT - 1) {
|
||||
ar_pci->ce_diag = pipe->ce_hdl;
|
||||
continue;
|
||||
}
|
||||
|
||||
pipe->buf_sz = (size_t)(host_ce_config_wlan[i].src_sz_max);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_pci_free_ce(struct ath10k *ar)
|
||||
static void ath10k_pci_free_pipes(struct ath10k *ar)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -1593,39 +1656,17 @@ static void ath10k_pci_free_ce(struct ath10k *ar)
|
|||
ath10k_ce_free_pipe(ar, i);
|
||||
}
|
||||
|
||||
static int ath10k_pci_ce_init(struct ath10k *ar)
|
||||
static int ath10k_pci_init_pipes(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
struct ath10k_pci_pipe *pipe_info;
|
||||
const struct ce_attr *attr;
|
||||
int pipe_num, ret;
|
||||
int i, ret;
|
||||
|
||||
for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
|
||||
pipe_info = &ar_pci->pipe_info[pipe_num];
|
||||
pipe_info->ce_hdl = &ar_pci->ce_states[pipe_num];
|
||||
pipe_info->pipe_num = pipe_num;
|
||||
pipe_info->hif_ce_state = ar;
|
||||
attr = &host_ce_config_wlan[pipe_num];
|
||||
|
||||
ret = ath10k_ce_init_pipe(ar, pipe_num, attr,
|
||||
ath10k_pci_ce_send_done,
|
||||
ath10k_pci_ce_recv_data);
|
||||
for (i = 0; i < CE_COUNT; i++) {
|
||||
ret = ath10k_ce_init_pipe(ar, i, &host_ce_config_wlan[i]);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to initialize copy engine pipe %d: %d\n",
|
||||
pipe_num, ret);
|
||||
i, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pipe_num == CE_COUNT - 1) {
|
||||
/*
|
||||
* Reserve the ultimate CE for
|
||||
* diagnostic Window support
|
||||
*/
|
||||
ar_pci->ce_diag = pipe_info->ce_hdl;
|
||||
continue;
|
||||
}
|
||||
|
||||
pipe_info->buf_sz = (size_t)(attr->src_sz_max);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1672,6 +1713,12 @@ static int ath10k_pci_warm_reset(struct ath10k *ar)
|
|||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n");
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
ar->stats.fw_warm_reset_counter++;
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
/* debug */
|
||||
val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
|
||||
PCIE_INTR_CAUSE_ADDRESS);
|
||||
|
@ -1773,7 +1820,7 @@ static int __ath10k_pci_hif_power_up(struct ath10k *ar, bool cold_reset)
|
|||
goto err;
|
||||
}
|
||||
|
||||
ret = ath10k_pci_ce_init(ar);
|
||||
ret = ath10k_pci_init_pipes(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to initialize CE: %d\n", ret);
|
||||
goto err;
|
||||
|
@ -1921,6 +1968,7 @@ static int ath10k_pci_hif_resume(struct ath10k *ar)
|
|||
|
||||
static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
|
||||
.tx_sg = ath10k_pci_hif_tx_sg,
|
||||
.diag_read = ath10k_pci_hif_diag_read,
|
||||
.exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg,
|
||||
.start = ath10k_pci_hif_start,
|
||||
.stop = ath10k_pci_hif_stop,
|
||||
|
@ -2250,14 +2298,14 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar)
|
|||
|
||||
if (ar_pci->num_msi_intrs == 0)
|
||||
/* Fix potential race by repeating CORE_BASE writes */
|
||||
ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS +
|
||||
PCIE_INTR_ENABLE_ADDRESS,
|
||||
PCIE_INTR_FIRMWARE_MASK |
|
||||
PCIE_INTR_CE_MASK_ALL);
|
||||
ath10k_pci_enable_legacy_irq(ar);
|
||||
|
||||
mdelay(10);
|
||||
} while (time_before(jiffies, timeout));
|
||||
|
||||
ath10k_pci_disable_and_clear_legacy_irq(ar);
|
||||
ath10k_pci_irq_msi_fw_mask(ar);
|
||||
|
||||
if (val == 0xffffffff) {
|
||||
ath10k_err(ar, "failed to read device register, device is gone\n");
|
||||
return -EIO;
|
||||
|
@ -2287,6 +2335,12 @@ static int ath10k_pci_cold_reset(struct ath10k *ar)
|
|||
|
||||
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n");
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
ar->stats.fw_cold_reset_counter++;
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
/* Put Target, including PCIe, into RESET. */
|
||||
val = ath10k_pci_reg_read32(ar, SOC_GLOBAL_RESET_ADDRESS);
|
||||
val |= 1;
|
||||
|
@ -2400,6 +2454,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
|||
u32 chip_id;
|
||||
|
||||
ar = ath10k_core_create(sizeof(*ar_pci), &pdev->dev,
|
||||
ATH10K_BUS_PCI,
|
||||
&ath10k_pci_hif_ops);
|
||||
if (!ar) {
|
||||
dev_err(&pdev->dev, "failed to allocate core\n");
|
||||
|
@ -2435,7 +2490,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
|||
goto err_sleep;
|
||||
}
|
||||
|
||||
ret = ath10k_pci_alloc_ce(ar);
|
||||
ret = ath10k_pci_alloc_pipes(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to allocate copy engine pipes: %d\n",
|
||||
ret);
|
||||
|
@ -2443,25 +2498,12 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
|||
}
|
||||
|
||||
ath10k_pci_ce_deinit(ar);
|
||||
|
||||
ret = ath10k_ce_disable_interrupts(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to disable copy engine interrupts: %d\n",
|
||||
ret);
|
||||
goto err_free_ce;
|
||||
}
|
||||
|
||||
/* Workaround: There's no known way to mask all possible interrupts via
|
||||
* device CSR. The only way to make sure device doesn't assert
|
||||
* interrupts is to reset it. Interrupts are then disabled on host
|
||||
* after handlers are registered.
|
||||
*/
|
||||
ath10k_pci_warm_reset(ar);
|
||||
ath10k_pci_irq_disable(ar);
|
||||
|
||||
ret = ath10k_pci_init_irq(ar);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to init irqs: %d\n", ret);
|
||||
goto err_free_ce;
|
||||
goto err_free_pipes;
|
||||
}
|
||||
|
||||
ath10k_info(ar, "pci irq %s interrupts %d irq_mode %d reset_mode %d\n",
|
||||
|
@ -2474,9 +2516,6 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
|
|||
goto err_deinit_irq;
|
||||
}
|
||||
|
||||
/* This shouldn't race as the device has been reset above. */
|
||||
ath10k_pci_irq_disable(ar);
|
||||
|
||||
ret = ath10k_core_register(ar, chip_id);
|
||||
if (ret) {
|
||||
ath10k_err(ar, "failed to register driver core: %d\n", ret);
|
||||
|
@ -2492,8 +2531,8 @@ err_free_irq:
|
|||
err_deinit_irq:
|
||||
ath10k_pci_deinit_irq(ar);
|
||||
|
||||
err_free_ce:
|
||||
ath10k_pci_free_ce(ar);
|
||||
err_free_pipes:
|
||||
ath10k_pci_free_pipes(ar);
|
||||
|
||||
err_sleep:
|
||||
ath10k_pci_sleep(ar);
|
||||
|
@ -2527,7 +2566,7 @@ static void ath10k_pci_remove(struct pci_dev *pdev)
|
|||
ath10k_pci_kill_tasklet(ar);
|
||||
ath10k_pci_deinit_irq(ar);
|
||||
ath10k_pci_ce_deinit(ar);
|
||||
ath10k_pci_free_ce(ar);
|
||||
ath10k_pci_free_pipes(ar);
|
||||
ath10k_pci_sleep(ar);
|
||||
ath10k_pci_release(ar);
|
||||
ath10k_core_destroy(ar);
|
||||
|
@ -2565,5 +2604,7 @@ module_exit(ath10k_pci_exit);
|
|||
MODULE_AUTHOR("Qualcomm Atheros");
|
||||
MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_3_FILE);
|
||||
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_FILE);
|
||||
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API2_FILE);
|
||||
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API3_FILE);
|
||||
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE);
|
||||
|
|
|
@ -56,14 +56,14 @@ static uint8_t get_max_exp(s8 max_index, u16 max_magnitude, size_t bin_len,
|
|||
}
|
||||
|
||||
int ath10k_spectral_process_fft(struct ath10k *ar,
|
||||
struct wmi_single_phyerr_rx_event *event,
|
||||
struct phyerr_fft_report *fftr,
|
||||
const struct wmi_phyerr *phyerr,
|
||||
const struct phyerr_fft_report *fftr,
|
||||
size_t bin_len, u64 tsf)
|
||||
{
|
||||
struct fft_sample_ath10k *fft_sample;
|
||||
u8 buf[sizeof(*fft_sample) + SPECTRAL_ATH10K_MAX_NUM_BINS];
|
||||
u16 freq1, freq2, total_gain_db, base_pwr_db, length, peak_mag;
|
||||
u32 reg0, reg1, nf_list1, nf_list2;
|
||||
u32 reg0, reg1;
|
||||
u8 chain_idx, *bins;
|
||||
int dc_pos;
|
||||
|
||||
|
@ -82,7 +82,7 @@ int ath10k_spectral_process_fft(struct ath10k *ar,
|
|||
/* TODO: there might be a reason why the hardware reports 20/40/80 MHz,
|
||||
* but the results/plots suggest that its actually 22/44/88 MHz.
|
||||
*/
|
||||
switch (event->hdr.chan_width_mhz) {
|
||||
switch (phyerr->chan_width_mhz) {
|
||||
case 20:
|
||||
fft_sample->chan_width_mhz = 22;
|
||||
break;
|
||||
|
@ -101,7 +101,7 @@ int ath10k_spectral_process_fft(struct ath10k *ar,
|
|||
fft_sample->chan_width_mhz = 88;
|
||||
break;
|
||||
default:
|
||||
fft_sample->chan_width_mhz = event->hdr.chan_width_mhz;
|
||||
fft_sample->chan_width_mhz = phyerr->chan_width_mhz;
|
||||
}
|
||||
|
||||
fft_sample->relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB);
|
||||
|
@ -110,36 +110,22 @@ int ath10k_spectral_process_fft(struct ath10k *ar,
|
|||
peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG);
|
||||
fft_sample->max_magnitude = __cpu_to_be16(peak_mag);
|
||||
fft_sample->max_index = MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX);
|
||||
fft_sample->rssi = event->hdr.rssi_combined;
|
||||
fft_sample->rssi = phyerr->rssi_combined;
|
||||
|
||||
total_gain_db = MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB);
|
||||
base_pwr_db = MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB);
|
||||
fft_sample->total_gain_db = __cpu_to_be16(total_gain_db);
|
||||
fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db);
|
||||
|
||||
freq1 = __le16_to_cpu(event->hdr.freq1);
|
||||
freq2 = __le16_to_cpu(event->hdr.freq2);
|
||||
freq1 = __le16_to_cpu(phyerr->freq1);
|
||||
freq2 = __le16_to_cpu(phyerr->freq2);
|
||||
fft_sample->freq1 = __cpu_to_be16(freq1);
|
||||
fft_sample->freq2 = __cpu_to_be16(freq2);
|
||||
|
||||
nf_list1 = __le32_to_cpu(event->hdr.nf_list_1);
|
||||
nf_list2 = __le32_to_cpu(event->hdr.nf_list_2);
|
||||
chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);
|
||||
|
||||
switch (chain_idx) {
|
||||
case 0:
|
||||
fft_sample->noise = __cpu_to_be16(nf_list1 & 0xffffu);
|
||||
break;
|
||||
case 1:
|
||||
fft_sample->noise = __cpu_to_be16((nf_list1 >> 16) & 0xffffu);
|
||||
break;
|
||||
case 2:
|
||||
fft_sample->noise = __cpu_to_be16(nf_list2 & 0xffffu);
|
||||
break;
|
||||
case 3:
|
||||
fft_sample->noise = __cpu_to_be16((nf_list2 >> 16) & 0xffffu);
|
||||
break;
|
||||
}
|
||||
fft_sample->noise = __cpu_to_be16(
|
||||
__le16_to_cpu(phyerr->nf_chains[chain_idx]));
|
||||
|
||||
bins = (u8 *)fftr;
|
||||
bins += sizeof(*fftr);
|
||||
|
|
|
@ -47,8 +47,8 @@ enum ath10k_spectral_mode {
|
|||
#ifdef CONFIG_ATH10K_DEBUGFS
|
||||
|
||||
int ath10k_spectral_process_fft(struct ath10k *ar,
|
||||
struct wmi_single_phyerr_rx_event *event,
|
||||
struct phyerr_fft_report *fftr,
|
||||
const struct wmi_phyerr *phyerr,
|
||||
const struct phyerr_fft_report *fftr,
|
||||
size_t bin_len, u64 tsf);
|
||||
int ath10k_spectral_start(struct ath10k *ar);
|
||||
int ath10k_spectral_vif_stop(struct ath10k_vif *arvif);
|
||||
|
@ -59,8 +59,8 @@ void ath10k_spectral_destroy(struct ath10k *ar);
|
|||
|
||||
static inline int
|
||||
ath10k_spectral_process_fft(struct ath10k *ar,
|
||||
struct wmi_single_phyerr_rx_event *event,
|
||||
struct phyerr_fft_report *fftr,
|
||||
const struct wmi_phyerr *phyerr,
|
||||
const struct phyerr_fft_report *fftr,
|
||||
size_t bin_len, u64 tsf)
|
||||
{
|
||||
return 0;
|
||||
|
|
|
@ -254,6 +254,169 @@ TRACE_EVENT(ath10k_wmi_dbglog,
|
|||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(ath10k_htt_pktlog,
|
||||
TP_PROTO(struct ath10k *ar, void *buf, u16 buf_len),
|
||||
|
||||
TP_ARGS(ar, buf, buf_len),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(device, dev_name(ar->dev))
|
||||
__string(driver, dev_driver_string(ar->dev))
|
||||
__field(u16, buf_len)
|
||||
__dynamic_array(u8, pktlog, buf_len)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(device, dev_name(ar->dev));
|
||||
__assign_str(driver, dev_driver_string(ar->dev));
|
||||
__entry->buf_len = buf_len;
|
||||
memcpy(__get_dynamic_array(pktlog), buf, buf_len);
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s %s size %hu",
|
||||
__get_str(driver),
|
||||
__get_str(device),
|
||||
__entry->buf_len
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(ath10k_htt_rx_desc,
|
||||
TP_PROTO(struct ath10k *ar, u32 tsf, void *rxdesc, u16 len),
|
||||
|
||||
TP_ARGS(ar, tsf, rxdesc, len),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(device, dev_name(ar->dev))
|
||||
__string(driver, dev_driver_string(ar->dev))
|
||||
__field(u32, tsf)
|
||||
__field(u16, len)
|
||||
__dynamic_array(u8, rxdesc, len)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(device, dev_name(ar->dev));
|
||||
__assign_str(driver, dev_driver_string(ar->dev));
|
||||
__entry->tsf = tsf;
|
||||
__entry->len = len;
|
||||
memcpy(__get_dynamic_array(rxdesc), rxdesc, len);
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s %s %u len %hu",
|
||||
__get_str(driver),
|
||||
__get_str(device),
|
||||
__entry->tsf,
|
||||
__entry->len
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(ath10k_htt_tx,
|
||||
TP_PROTO(struct ath10k *ar, u16 msdu_id, u16 msdu_len,
|
||||
u8 vdev_id, u8 tid),
|
||||
|
||||
TP_ARGS(ar, msdu_id, msdu_len, vdev_id, tid),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(device, dev_name(ar->dev))
|
||||
__string(driver, dev_driver_string(ar->dev))
|
||||
__field(u16, msdu_id)
|
||||
__field(u16, msdu_len)
|
||||
__field(u8, vdev_id)
|
||||
__field(u8, tid)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(device, dev_name(ar->dev));
|
||||
__assign_str(driver, dev_driver_string(ar->dev));
|
||||
__entry->msdu_id = msdu_id;
|
||||
__entry->msdu_len = msdu_len;
|
||||
__entry->vdev_id = vdev_id;
|
||||
__entry->tid = tid;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s %s msdu_id %d msdu_len %d vdev_id %d tid %d",
|
||||
__get_str(driver),
|
||||
__get_str(device),
|
||||
__entry->msdu_id,
|
||||
__entry->msdu_len,
|
||||
__entry->vdev_id,
|
||||
__entry->tid
|
||||
)
|
||||
);
|
||||
|
||||
TRACE_EVENT(ath10k_txrx_tx_unref,
|
||||
TP_PROTO(struct ath10k *ar, u16 msdu_id),
|
||||
|
||||
TP_ARGS(ar, msdu_id),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(device, dev_name(ar->dev))
|
||||
__string(driver, dev_driver_string(ar->dev))
|
||||
__field(u16, msdu_id)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(device, dev_name(ar->dev));
|
||||
__assign_str(driver, dev_driver_string(ar->dev));
|
||||
__entry->msdu_id = msdu_id;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s %s msdu_id %d",
|
||||
__get_str(driver),
|
||||
__get_str(device),
|
||||
__entry->msdu_id
|
||||
)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(ath10k_data_event,
|
||||
TP_PROTO(struct ath10k *ar, void *data, size_t len),
|
||||
|
||||
TP_ARGS(ar, data, len),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(device, dev_name(ar->dev))
|
||||
__string(driver, dev_driver_string(ar->dev))
|
||||
__field(size_t, len)
|
||||
__dynamic_array(u8, data, len)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(device, dev_name(ar->dev));
|
||||
__assign_str(driver, dev_driver_string(ar->dev));
|
||||
__entry->len = len;
|
||||
memcpy(__get_dynamic_array(data), data, len);
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s %s len %zu\n",
|
||||
__get_str(driver),
|
||||
__get_str(device),
|
||||
__entry->len
|
||||
)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(ath10k_data_event, ath10k_htt_tx_msdu,
|
||||
TP_PROTO(struct ath10k *ar, void *data, size_t len),
|
||||
TP_ARGS(ar, data, len)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(ath10k_data_event, ath10k_htt_rx_pop_msdu,
|
||||
TP_PROTO(struct ath10k *ar, void *data, size_t len),
|
||||
TP_ARGS(ar, data, len)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(ath10k_data_event, ath10k_wmi_mgmt_tx,
|
||||
TP_PROTO(struct ath10k *ar, void *data, size_t len),
|
||||
TP_ARGS(ar, data, len)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(ath10k_data_event, ath10k_wmi_bcn_tx,
|
||||
TP_PROTO(struct ath10k *ar, void *data, size_t len),
|
||||
TP_ARGS(ar, data, len)
|
||||
);
|
||||
#endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/
|
||||
|
||||
/* we don't want to use include/trace/events */
|
||||
|
|
|
@ -78,6 +78,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt,
|
|||
|
||||
info = IEEE80211_SKB_CB(msdu);
|
||||
memset(&info->status, 0, sizeof(info->status));
|
||||
trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id);
|
||||
|
||||
if (tx_done->discard) {
|
||||
ieee80211_free_txskb(htt->ar->hw, msdu);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1428,11 +1428,11 @@ struct wmi_service_ready_event {
|
|||
* where FW can access this memory directly (or) by DMA.
|
||||
*/
|
||||
__le32 num_mem_reqs;
|
||||
struct wlan_host_mem_req mem_reqs[1];
|
||||
struct wlan_host_mem_req mem_reqs[0];
|
||||
} __packed;
|
||||
|
||||
/* This is the definition from 10.X firmware branch */
|
||||
struct wmi_service_ready_event_10x {
|
||||
struct wmi_10x_service_ready_event {
|
||||
__le32 sw_version;
|
||||
__le32 abi_version;
|
||||
|
||||
|
@ -1467,7 +1467,7 @@ struct wmi_service_ready_event_10x {
|
|||
*/
|
||||
__le32 num_mem_reqs;
|
||||
|
||||
struct wlan_host_mem_req mem_reqs[1];
|
||||
struct wlan_host_mem_req mem_reqs[0];
|
||||
} __packed;
|
||||
|
||||
#define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ)
|
||||
|
@ -1883,38 +1883,26 @@ struct host_memory_chunk {
|
|||
__le32 size;
|
||||
} __packed;
|
||||
|
||||
struct wmi_host_mem_chunks {
|
||||
__le32 count;
|
||||
/* some fw revisions require at least 1 chunk regardless of count */
|
||||
struct host_memory_chunk items[1];
|
||||
} __packed;
|
||||
|
||||
struct wmi_init_cmd {
|
||||
struct wmi_resource_config resource_config;
|
||||
__le32 num_host_mem_chunks;
|
||||
|
||||
/*
|
||||
* variable number of host memory chunks.
|
||||
* This should be the last element in the structure
|
||||
*/
|
||||
struct host_memory_chunk host_mem_chunks[1];
|
||||
struct wmi_host_mem_chunks mem_chunks;
|
||||
} __packed;
|
||||
|
||||
/* _10x stucture is from 10.X FW API */
|
||||
struct wmi_init_cmd_10x {
|
||||
struct wmi_resource_config_10x resource_config;
|
||||
__le32 num_host_mem_chunks;
|
||||
|
||||
/*
|
||||
* variable number of host memory chunks.
|
||||
* This should be the last element in the structure
|
||||
*/
|
||||
struct host_memory_chunk host_mem_chunks[1];
|
||||
struct wmi_host_mem_chunks mem_chunks;
|
||||
} __packed;
|
||||
|
||||
struct wmi_init_cmd_10_2 {
|
||||
struct wmi_resource_config_10_2 resource_config;
|
||||
__le32 num_host_mem_chunks;
|
||||
|
||||
/*
|
||||
* variable number of host memory chunks.
|
||||
* This should be the last element in the structure
|
||||
*/
|
||||
struct host_memory_chunk host_mem_chunks[1];
|
||||
struct wmi_host_mem_chunks mem_chunks;
|
||||
} __packed;
|
||||
|
||||
struct wmi_chan_list_entry {
|
||||
|
@ -1974,7 +1962,7 @@ enum wmi_scan_priority {
|
|||
WMI_SCAN_PRIORITY_COUNT /* number of priorities supported */
|
||||
};
|
||||
|
||||
struct wmi_start_scan_cmd {
|
||||
struct wmi_start_scan_common {
|
||||
/* Scan ID */
|
||||
__le32 scan_id;
|
||||
/* Scan requestor ID */
|
||||
|
@ -2032,95 +2020,25 @@ struct wmi_start_scan_cmd {
|
|||
__le32 probe_delay;
|
||||
/* Scan control flags */
|
||||
__le32 scan_ctrl_flags;
|
||||
} __packed;
|
||||
|
||||
/* Burst duration time in msecs */
|
||||
__le32 burst_duration;
|
||||
/*
|
||||
* TLV (tag length value ) paramerters follow the scan_cmd structure.
|
||||
* TLV can contain channel list, bssid list, ssid list and
|
||||
* ie. the TLV tags are defined above;
|
||||
struct wmi_start_scan_tlvs {
|
||||
/* TLV parameters. These includes channel list, ssid list, bssid list,
|
||||
* extra ies.
|
||||
*/
|
||||
u8 tlvs[0];
|
||||
} __packed;
|
||||
|
||||
struct wmi_start_scan_cmd {
|
||||
struct wmi_start_scan_common common;
|
||||
__le32 burst_duration_ms;
|
||||
struct wmi_start_scan_tlvs tlvs;
|
||||
} __packed;
|
||||
|
||||
/* This is the definition from 10.X firmware branch */
|
||||
struct wmi_start_scan_cmd_10x {
|
||||
/* Scan ID */
|
||||
__le32 scan_id;
|
||||
|
||||
/* Scan requestor ID */
|
||||
__le32 scan_req_id;
|
||||
|
||||
/* VDEV id(interface) that is requesting scan */
|
||||
__le32 vdev_id;
|
||||
|
||||
/* Scan Priority, input to scan scheduler */
|
||||
__le32 scan_priority;
|
||||
|
||||
/* Scan events subscription */
|
||||
__le32 notify_scan_events;
|
||||
|
||||
/* dwell time in msec on active channels */
|
||||
__le32 dwell_time_active;
|
||||
|
||||
/* dwell time in msec on passive channels */
|
||||
__le32 dwell_time_passive;
|
||||
|
||||
/*
|
||||
* min time in msec on the BSS channel,only valid if atleast one
|
||||
* VDEV is active
|
||||
*/
|
||||
__le32 min_rest_time;
|
||||
|
||||
/*
|
||||
* max rest time in msec on the BSS channel,only valid if at least
|
||||
* one VDEV is active
|
||||
*/
|
||||
/*
|
||||
* the scanner will rest on the bss channel at least min_rest_time
|
||||
* after min_rest_time the scanner will start checking for tx/rx
|
||||
* activity on all VDEVs. if there is no activity the scanner will
|
||||
* switch to off channel. if there is activity the scanner will let
|
||||
* the radio on the bss channel until max_rest_time expires.at
|
||||
* max_rest_time scanner will switch to off channel irrespective of
|
||||
* activity. activity is determined by the idle_time parameter.
|
||||
*/
|
||||
__le32 max_rest_time;
|
||||
|
||||
/*
|
||||
* time before sending next set of probe requests.
|
||||
* The scanner keeps repeating probe requests transmission with
|
||||
* period specified by repeat_probe_time.
|
||||
* The number of probe requests specified depends on the ssid_list
|
||||
* and bssid_list
|
||||
*/
|
||||
__le32 repeat_probe_time;
|
||||
|
||||
/* time in msec between 2 consequetive probe requests with in a set. */
|
||||
__le32 probe_spacing_time;
|
||||
|
||||
/*
|
||||
* data inactivity time in msec on bss channel that will be used by
|
||||
* scanner for measuring the inactivity.
|
||||
*/
|
||||
__le32 idle_time;
|
||||
|
||||
/* maximum time in msec allowed for scan */
|
||||
__le32 max_scan_time;
|
||||
|
||||
/*
|
||||
* delay in msec before sending first probe request after switching
|
||||
* to a channel
|
||||
*/
|
||||
__le32 probe_delay;
|
||||
|
||||
/* Scan control flags */
|
||||
__le32 scan_ctrl_flags;
|
||||
|
||||
/*
|
||||
* TLV (tag length value ) paramerters follow the scan_cmd structure.
|
||||
* TLV can contain channel list, bssid list, ssid list and
|
||||
* ie. the TLV tags are defined above;
|
||||
*/
|
||||
struct wmi_10x_start_scan_cmd {
|
||||
struct wmi_start_scan_common common;
|
||||
struct wmi_start_scan_tlvs tlvs;
|
||||
} __packed;
|
||||
|
||||
struct wmi_ssid_arg {
|
||||
|
@ -2306,94 +2224,25 @@ struct wmi_mgmt_rx_event_v2 {
|
|||
#define PHY_ERROR_FALSE_RADAR_EXT 0x24
|
||||
#define PHY_ERROR_RADAR 0x05
|
||||
|
||||
struct wmi_single_phyerr_rx_hdr {
|
||||
/* TSF timestamp */
|
||||
struct wmi_phyerr {
|
||||
__le32 tsf_timestamp;
|
||||
|
||||
/*
|
||||
* Current freq1, freq2
|
||||
*
|
||||
* [7:0]: freq1[lo]
|
||||
* [15:8] : freq1[hi]
|
||||
* [23:16]: freq2[lo]
|
||||
* [31:24]: freq2[hi]
|
||||
*/
|
||||
__le16 freq1;
|
||||
__le16 freq2;
|
||||
|
||||
/*
|
||||
* Combined RSSI over all chains and channel width for this PHY error
|
||||
*
|
||||
* [7:0]: RSSI combined
|
||||
* [15:8]: Channel width (MHz)
|
||||
* [23:16]: PHY error code
|
||||
* [24:16]: reserved (future use)
|
||||
*/
|
||||
u8 rssi_combined;
|
||||
u8 chan_width_mhz;
|
||||
u8 phy_err_code;
|
||||
u8 rsvd0;
|
||||
|
||||
/*
|
||||
* RSSI on chain 0 through 3
|
||||
*
|
||||
* This is formatted the same as the PPDU_START RX descriptor
|
||||
* field:
|
||||
*
|
||||
* [7:0]: pri20
|
||||
* [15:8]: sec20
|
||||
* [23:16]: sec40
|
||||
* [31:24]: sec80
|
||||
*/
|
||||
|
||||
__le32 rssi_chain0;
|
||||
__le32 rssi_chain1;
|
||||
__le32 rssi_chain2;
|
||||
__le32 rssi_chain3;
|
||||
|
||||
/*
|
||||
* Last calibrated NF value for chain 0 through 3
|
||||
*
|
||||
* nf_list_1:
|
||||
*
|
||||
* + [15:0] - chain 0
|
||||
* + [31:16] - chain 1
|
||||
*
|
||||
* nf_list_2:
|
||||
*
|
||||
* + [15:0] - chain 2
|
||||
* + [31:16] - chain 3
|
||||
*/
|
||||
__le32 nf_list_1;
|
||||
__le32 nf_list_2;
|
||||
|
||||
/* Length of the frame */
|
||||
__le32 rssi_chains[4];
|
||||
__le16 nf_chains[4];
|
||||
__le32 buf_len;
|
||||
u8 buf[0];
|
||||
} __packed;
|
||||
|
||||
struct wmi_single_phyerr_rx_event {
|
||||
/* Phy error event header */
|
||||
struct wmi_single_phyerr_rx_hdr hdr;
|
||||
/* frame buffer */
|
||||
u8 bufp[0];
|
||||
} __packed;
|
||||
|
||||
struct wmi_comb_phyerr_rx_hdr {
|
||||
/* Phy error phy error count */
|
||||
__le32 num_phyerr_events;
|
||||
struct wmi_phyerr_event {
|
||||
__le32 num_phyerrs;
|
||||
__le32 tsf_l32;
|
||||
__le32 tsf_u32;
|
||||
} __packed;
|
||||
|
||||
struct wmi_comb_phyerr_rx_event {
|
||||
/* Phy error phy error count */
|
||||
struct wmi_comb_phyerr_rx_hdr hdr;
|
||||
/*
|
||||
* frame buffer - contains multiple payloads in the order:
|
||||
* header - payload, header - payload...
|
||||
* (The header is of type: wmi_single_phyerr_rx_hdr)
|
||||
*/
|
||||
u8 bufp[0];
|
||||
struct wmi_phyerr phyerrs[0];
|
||||
} __packed;
|
||||
|
||||
#define PHYERR_TLV_SIG 0xBB
|
||||
|
@ -2908,11 +2757,6 @@ enum wmi_tp_scale {
|
|||
WMI_TP_SCALE_SIZE = 5, /* max num of enum */
|
||||
};
|
||||
|
||||
struct wmi_set_channel_cmd {
|
||||
/* channel (only frequency and mode info are used) */
|
||||
struct wmi_channel chan;
|
||||
} __packed;
|
||||
|
||||
struct wmi_pdev_chanlist_update_event {
|
||||
/* number of channels */
|
||||
__le32 num_chan;
|
||||
|
@ -2943,6 +2787,10 @@ struct wmi_pdev_set_channel_cmd {
|
|||
struct wmi_channel chan;
|
||||
} __packed;
|
||||
|
||||
struct wmi_pdev_pktlog_enable_cmd {
|
||||
__le32 ev_bitmap;
|
||||
} __packed;
|
||||
|
||||
/* Customize the DSCP (bit) to TID (0-7) mapping for QOS */
|
||||
#define WMI_DSCP_MAP_MAX (64)
|
||||
struct wmi_pdev_set_dscp_tid_map_cmd {
|
||||
|
@ -3177,7 +3025,7 @@ struct wmi_stats_event {
|
|||
* PDEV statistics
|
||||
* TODO: add all PDEV stats here
|
||||
*/
|
||||
struct wmi_pdev_stats_old {
|
||||
struct wmi_pdev_stats {
|
||||
__le32 chan_nf; /* Channel noise floor */
|
||||
__le32 tx_frame_count; /* TX frame count */
|
||||
__le32 rx_frame_count; /* RX frame count */
|
||||
|
@ -3188,15 +3036,8 @@ struct wmi_pdev_stats_old {
|
|||
struct wal_dbg_stats wal; /* WAL dbg stats */
|
||||
} __packed;
|
||||
|
||||
struct wmi_pdev_stats_10x {
|
||||
__le32 chan_nf; /* Channel noise floor */
|
||||
__le32 tx_frame_count; /* TX frame count */
|
||||
__le32 rx_frame_count; /* RX frame count */
|
||||
__le32 rx_clear_count; /* rx clear count */
|
||||
__le32 cycle_count; /* cycle count */
|
||||
__le32 phy_err_count; /* Phy error count */
|
||||
__le32 chan_tx_pwr; /* channel tx power */
|
||||
struct wal_dbg_stats wal; /* WAL dbg stats */
|
||||
struct wmi_10x_pdev_stats {
|
||||
struct wmi_pdev_stats old;
|
||||
__le32 ack_rx_bad;
|
||||
__le32 rts_bad;
|
||||
__le32 rts_good;
|
||||
|
@ -3217,16 +3058,14 @@ struct wmi_vdev_stats {
|
|||
* peer statistics.
|
||||
* TODO: add more stats
|
||||
*/
|
||||
struct wmi_peer_stats_old {
|
||||
struct wmi_peer_stats {
|
||||
struct wmi_mac_addr peer_macaddr;
|
||||
__le32 peer_rssi;
|
||||
__le32 peer_tx_rate;
|
||||
} __packed;
|
||||
|
||||
struct wmi_peer_stats_10x {
|
||||
struct wmi_mac_addr peer_macaddr;
|
||||
__le32 peer_rssi;
|
||||
__le32 peer_tx_rate;
|
||||
struct wmi_10x_peer_stats {
|
||||
struct wmi_peer_stats old;
|
||||
__le32 peer_rx_rate;
|
||||
} __packed;
|
||||
|
||||
|
@ -4719,8 +4558,26 @@ struct wmi_dbglog_cfg_cmd {
|
|||
/* By default disable power save for IBSS */
|
||||
#define ATH10K_DEFAULT_ATIM 0
|
||||
|
||||
#define WMI_MAX_MEM_REQS 16
|
||||
|
||||
struct wmi_svc_rdy_ev_arg {
|
||||
__le32 min_tx_power;
|
||||
__le32 max_tx_power;
|
||||
__le32 ht_cap;
|
||||
__le32 vht_cap;
|
||||
__le32 sw_ver0;
|
||||
__le32 sw_ver1;
|
||||
__le32 phy_capab;
|
||||
__le32 num_rf_chains;
|
||||
__le32 eeprom_rd;
|
||||
__le32 num_mem_reqs;
|
||||
const __le32 *service_map;
|
||||
const struct wlan_host_mem_req *mem_reqs[WMI_MAX_MEM_REQS];
|
||||
};
|
||||
|
||||
struct ath10k;
|
||||
struct ath10k_vif;
|
||||
struct ath10k_fw_stats;
|
||||
|
||||
int ath10k_wmi_attach(struct ath10k *ar);
|
||||
void ath10k_wmi_detach(struct ath10k *ar);
|
||||
|
@ -4732,8 +4589,6 @@ int ath10k_wmi_connect(struct ath10k *ar);
|
|||
struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len);
|
||||
int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
|
||||
|
||||
int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
|
||||
const struct wmi_channel_arg *);
|
||||
int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt);
|
||||
int ath10k_wmi_pdev_resume_target(struct ath10k *ar);
|
||||
int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g,
|
||||
|
@ -4794,5 +4649,9 @@ int ath10k_wmi_force_fw_hang(struct ath10k *ar,
|
|||
enum wmi_force_fw_hang_type type, u32 delay_ms);
|
||||
int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb);
|
||||
int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable);
|
||||
int ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb,
|
||||
struct ath10k_fw_stats *stats);
|
||||
int ath10k_wmi_pdev_pktlog_enable(struct ath10k *ar, u32 ev_list);
|
||||
int ath10k_wmi_pdev_pktlog_disable(struct ath10k *ar);
|
||||
|
||||
#endif /* _WMI_H_ */
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
#define ATH6KL_MAX_IE 256
|
||||
|
||||
__printf(2, 3) int ath6kl_printk(const char *level, const char *fmt, ...);
|
||||
__printf(2, 3) void ath6kl_printk(const char *level, const char *fmt, ...);
|
||||
|
||||
/*
|
||||
* Reflects the version of binary interface exposed by ATH6KL target
|
||||
|
|
|
@ -37,76 +37,64 @@ struct ath6kl_fwlog_slot {
|
|||
|
||||
#define ATH6KL_FWLOG_VALID_MASK 0x1ffff
|
||||
|
||||
int ath6kl_printk(const char *level, const char *fmt, ...)
|
||||
void ath6kl_printk(const char *level, const char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf;
|
||||
va_list args;
|
||||
int rtn;
|
||||
|
||||
va_start(args, fmt);
|
||||
|
||||
vaf.fmt = fmt;
|
||||
vaf.va = &args;
|
||||
|
||||
rtn = printk("%sath6kl: %pV", level, &vaf);
|
||||
printk("%sath6kl: %pV", level, &vaf);
|
||||
|
||||
va_end(args);
|
||||
|
||||
return rtn;
|
||||
}
|
||||
EXPORT_SYMBOL(ath6kl_printk);
|
||||
|
||||
int ath6kl_info(const char *fmt, ...)
|
||||
void ath6kl_info(const char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf = {
|
||||
.fmt = fmt,
|
||||
};
|
||||
va_list args;
|
||||
int ret;
|
||||
|
||||
va_start(args, fmt);
|
||||
vaf.va = &args;
|
||||
ret = ath6kl_printk(KERN_INFO, "%pV", &vaf);
|
||||
ath6kl_printk(KERN_INFO, "%pV", &vaf);
|
||||
trace_ath6kl_log_info(&vaf);
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ath6kl_info);
|
||||
|
||||
int ath6kl_err(const char *fmt, ...)
|
||||
void ath6kl_err(const char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf = {
|
||||
.fmt = fmt,
|
||||
};
|
||||
va_list args;
|
||||
int ret;
|
||||
|
||||
va_start(args, fmt);
|
||||
vaf.va = &args;
|
||||
ret = ath6kl_printk(KERN_ERR, "%pV", &vaf);
|
||||
ath6kl_printk(KERN_ERR, "%pV", &vaf);
|
||||
trace_ath6kl_log_err(&vaf);
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ath6kl_err);
|
||||
|
||||
int ath6kl_warn(const char *fmt, ...)
|
||||
void ath6kl_warn(const char *fmt, ...)
|
||||
{
|
||||
struct va_format vaf = {
|
||||
.fmt = fmt,
|
||||
};
|
||||
va_list args;
|
||||
int ret;
|
||||
|
||||
va_start(args, fmt);
|
||||
vaf.va = &args;
|
||||
ret = ath6kl_printk(KERN_WARNING, "%pV", &vaf);
|
||||
ath6kl_printk(KERN_WARNING, "%pV", &vaf);
|
||||
trace_ath6kl_log_warn(&vaf);
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ath6kl_warn);
|
||||
|
||||
|
|
|
@ -50,10 +50,10 @@ enum ATH6K_DEBUG_MASK {
|
|||
};
|
||||
|
||||
extern unsigned int debug_mask;
|
||||
__printf(2, 3) int ath6kl_printk(const char *level, const char *fmt, ...);
|
||||
__printf(1, 2) int ath6kl_info(const char *fmt, ...);
|
||||
__printf(1, 2) int ath6kl_err(const char *fmt, ...);
|
||||
__printf(1, 2) int ath6kl_warn(const char *fmt, ...);
|
||||
__printf(2, 3) void ath6kl_printk(const char *level, const char *fmt, ...);
|
||||
__printf(1, 2) void ath6kl_info(const char *fmt, ...);
|
||||
__printf(1, 2) void ath6kl_err(const char *fmt, ...);
|
||||
__printf(1, 2) void ath6kl_warn(const char *fmt, ...);
|
||||
|
||||
enum ath6kl_war {
|
||||
ATH6KL_WAR_INVALID_RATE,
|
||||
|
@ -81,10 +81,9 @@ int ath6kl_debug_init_fs(struct ath6kl *ar);
|
|||
void ath6kl_debug_cleanup(struct ath6kl *ar);
|
||||
|
||||
#else
|
||||
static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask,
|
||||
const char *fmt, ...)
|
||||
static inline void ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask,
|
||||
|
|
|
@ -463,8 +463,11 @@ struct wil6210_priv {
|
|||
#define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr))
|
||||
#define wil_to_pcie_dev(i) (&i->pdev->dev)
|
||||
|
||||
__printf(2, 3)
|
||||
void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...);
|
||||
__printf(2, 3)
|
||||
void wil_err(struct wil6210_priv *wil, const char *fmt, ...);
|
||||
__printf(2, 3)
|
||||
void wil_info(struct wil6210_priv *wil, const char *fmt, ...);
|
||||
#define wil_dbg(wil, fmt, arg...) do { \
|
||||
netdev_dbg(wil_to_ndev(wil), fmt, ##arg); \
|
||||
|
|
Loading…
Reference in New Issue