diff options
Diffstat (limited to 'drivers/net/wireless/ath')
75 files changed, 1588 insertions, 889 deletions
diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig index db1ca629cbd6..b4241cf9b7ed 100644 --- a/drivers/net/wireless/ath/ath10k/Kconfig +++ b/drivers/net/wireless/ath/ath10k/Kconfig @@ -3,6 +3,7 @@ config ATH10K depends on MAC80211 && HAS_DMA select ATH_COMMON select CRC32 + select WANT_DEV_COREDUMP ---help--- This module adds support for wireless adapters based on Atheros IEEE 802.11ac family of chipsets. diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index 766c63bf05c4..45226dbee5ce 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -33,6 +33,9 @@ static const struct of_device_id ath10k_ahb_of_match[] = { MODULE_DEVICE_TABLE(of, ath10k_ahb_of_match); +#define QCA4019_SRAM_ADDR 0x000C0000 +#define QCA4019_SRAM_LEN 0x00040000 /* 256 kb */ + static inline struct ath10k_ahb *ath10k_ahb_priv(struct ath10k *ar) { return &((struct ath10k_pci *)ar->drv_priv)->ahb[0]; @@ -699,6 +702,25 @@ out: return ret; } +static u32 ath10k_ahb_qca4019_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr) +{ + u32 val = 0, region = addr & 0xfffff; + + val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS); + + if (region >= QCA4019_SRAM_ADDR && region <= + (QCA4019_SRAM_ADDR + QCA4019_SRAM_LEN)) { + /* SRAM contents for QCA4019 can be directly accessed and + * no conversions are required + */ + val |= region; + } else { + val |= 0x100000 | region; + } + + return val; +} + static const struct ath10k_hif_ops ath10k_ahb_hif_ops = { .tx_sg = ath10k_pci_hif_tx_sg, .diag_read = ath10k_pci_hif_diag_read, @@ -766,6 +788,7 @@ static int ath10k_ahb_probe(struct platform_device *pdev) ar_pci->mem_len = ar_ahb->mem_len; ar_pci->ar = ar; ar_pci->bus_ops = &ath10k_ahb_bus_ops; + ar_pci->targ_cpu_to_ce_addr = ath10k_ahb_qca4019_targ_cpu_to_ce_addr; ret = ath10k_pci_setup_resource(ar); if (ret) { diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 0b4d79659884..4045657e0a6e 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -958,10 +958,10 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id, * coherent DMA are unsupported */ dest_ring->base_addr_owner_space_unaligned = - dma_alloc_coherent(ar->dev, - (nentries * sizeof(struct ce_desc) + - CE_DESC_RING_ALIGN), - &base_addr, GFP_KERNEL); + dma_zalloc_coherent(ar->dev, + (nentries * sizeof(struct ce_desc) + + CE_DESC_RING_ALIGN), + &base_addr, GFP_KERNEL); if (!dest_ring->base_addr_owner_space_unaligned) { kfree(dest_ring); return ERR_PTR(-ENOMEM); @@ -969,13 +969,6 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id, dest_ring->base_addr_ce_space_unaligned = base_addr; - /* - * Correctly initialize memory to 0 to prevent garbage - * data crashing system when download firmware - */ - memset(dest_ring->base_addr_owner_space_unaligned, 0, - nentries * sizeof(struct ce_desc) + CE_DESC_RING_ALIGN); - dest_ring->base_addr_owner_space = PTR_ALIGN( dest_ring->base_addr_owner_space_unaligned, CE_DESC_RING_ALIGN); @@ -1130,3 +1123,42 @@ void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id) ce_state->src_ring = NULL; ce_state->dest_ring = NULL; } + +void ath10k_ce_dump_registers(struct ath10k *ar, + struct ath10k_fw_crash_data *crash_data) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_ce_crash_data ce; + u32 addr, id; + + lockdep_assert_held(&ar->data_lock); + + ath10k_err(ar, "Copy Engine register dump:\n"); + + spin_lock_bh(&ar_pci->ce_lock); + for (id = 0; id < CE_COUNT; id++) { + addr = ath10k_ce_base_address(ar, id); + ce.base_addr = cpu_to_le32(addr); + + ce.src_wr_idx = + cpu_to_le32(ath10k_ce_src_ring_write_index_get(ar, addr)); + ce.src_r_idx = + cpu_to_le32(ath10k_ce_src_ring_read_index_get(ar, addr)); + ce.dst_wr_idx = + cpu_to_le32(ath10k_ce_dest_ring_write_index_get(ar, addr)); + ce.dst_r_idx = + cpu_to_le32(ath10k_ce_dest_ring_read_index_get(ar, addr)); + + if (crash_data) + crash_data->ce_crash_data[id] = ce; + + ath10k_err(ar, "[%02d]: 0x%08x %3u %3u %3u %3u", id, + le32_to_cpu(ce.base_addr), + le32_to_cpu(ce.src_wr_idx), + le32_to_cpu(ce.src_r_idx), + le32_to_cpu(ce.dst_wr_idx), + le32_to_cpu(ce.dst_r_idx)); + } + + spin_unlock_bh(&ar_pci->ce_lock); +} diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index dfc098606bee..e76a98242b98 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -20,8 +20,6 @@ #include "hif.h" -/* Maximum number of Copy Engine's supported */ -#define CE_COUNT_MAX 12 #define CE_HTT_H2T_MSG_SRC_NENTRIES 8192 /* Descriptor rings must be aligned to this boundary */ @@ -228,6 +226,8 @@ void ath10k_ce_per_engine_service_any(struct ath10k *ar); void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id); int ath10k_ce_disable_interrupts(struct ath10k *ar); void ath10k_ce_enable_interrupts(struct ath10k *ar); +void ath10k_ce_dump_registers(struct ath10k *ar, + struct ath10k_fw_crash_data *crash_data); /* ce_attr.flags values */ /* Use NonSnooping PCIe accesses? */ diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 874c2a755c66..dd902b43f8f7 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -349,7 +349,7 @@ void ath10k_core_get_fw_features_str(struct ath10k *ar, char *buf, size_t buf_len) { - unsigned int len = 0; + size_t len = 0; int i; for (i = 0; i < ATH10K_FW_FEATURE_COUNT; i++) { @@ -454,7 +454,10 @@ static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar, dir = "."; snprintf(filename, sizeof(filename), "%s/%s", dir, file); - ret = request_firmware(&fw, filename, ar->dev); + ret = request_firmware_direct(&fw, filename, ar->dev); + ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot fw request '%s': %d\n", + filename, ret); + if (ret) return ERR_PTR(ret); @@ -696,7 +699,8 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar) if ((result & ATH10K_BMI_BOARD_ID_STATUS_MASK) != 0 || (board_id == 0)) { - ath10k_warn(ar, "board id is not exist in otp, ignore it\n"); + ath10k_dbg(ar, ATH10K_DBG_BOOT, + "board id does not exist in otp, ignore it\n"); return -EOPNOTSUPP; } @@ -1094,7 +1098,8 @@ static int ath10k_core_fetch_board_file(struct ath10k *ar) ar->bd_api = 1; ret = ath10k_core_fetch_board_data_api_1(ar); if (ret) { - ath10k_err(ar, "failed to fetch board data\n"); + ath10k_err(ar, "failed to fetch board-2.bin or board.bin from %s\n", + ar->hw_params.fw.dir); return ret; } @@ -1115,12 +1120,8 @@ int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name, /* first fetch the firmware file (firmware-*.bin) */ fw_file->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, name); - if (IS_ERR(fw_file->firmware)) { - ath10k_err(ar, "could not fetch firmware file '%s/%s': %ld\n", - ar->hw_params.fw.dir, name, - PTR_ERR(fw_file->firmware)); + if (IS_ERR(fw_file->firmware)) return PTR_ERR(fw_file->firmware); - } data = fw_file->firmware->data; len = fw_file->firmware->size; @@ -1284,44 +1285,39 @@ err: return ret; } +static void ath10k_core_get_fw_name(struct ath10k *ar, char *fw_name, + size_t fw_name_len, int fw_api) +{ + scnprintf(fw_name, fw_name_len, "%s-%d.bin", ATH10K_FW_FILE_BASE, fw_api); +} + static int ath10k_core_fetch_firmware_files(struct ath10k *ar) { - int ret; + int ret, i; + char fw_name[100]; /* calibration file is optional, don't check for any errors */ ath10k_fetch_cal_file(ar); - ar->fw_api = 5; - ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); - - ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API5_FILE, - &ar->normal_mode_fw.fw_file); - if (ret == 0) - goto success; - - ar->fw_api = 4; - ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); - - ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API4_FILE, - &ar->normal_mode_fw.fw_file); - if (ret == 0) - goto success; + for (i = ATH10K_FW_API_MAX; i >= ATH10K_FW_API_MIN; i--) { + ar->fw_api = i; + ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", + ar->fw_api); - ar->fw_api = 3; - ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); + ath10k_core_get_fw_name(ar, fw_name, sizeof(fw_name), ar->fw_api); + ret = ath10k_core_fetch_firmware_api_n(ar, fw_name, + &ar->normal_mode_fw.fw_file); + if (!ret) + goto success; + } - ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API3_FILE, - &ar->normal_mode_fw.fw_file); - if (ret == 0) - goto success; + /* we end up here if we couldn't fetch any firmware */ - ar->fw_api = 2; - ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); + ath10k_err(ar, "Failed to find firmware-N.bin (N between %d and %d) from %s: %d", + ATH10K_FW_API_MIN, ATH10K_FW_API_MAX, ar->hw_params.fw.dir, + ret); - ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API2_FILE, - &ar->normal_mode_fw.fw_file); - if (ret) - return ret; + return ret; success: ath10k_dbg(ar, ATH10K_DBG_BOOT, "using fw api %d\n", ar->fw_api); @@ -1922,7 +1918,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, ath10k_dbg(ar, ATH10K_DBG_BOOT, "firmware %s booted\n", ar->hw->wiphy->fw_version); - if (test_bit(WMI_SERVICE_EXT_RES_CFG_SUPPORT, ar->wmi.svc_map)) { + if (test_bit(WMI_SERVICE_EXT_RES_CFG_SUPPORT, ar->wmi.svc_map) && + mode == ATH10K_FIRMWARE_MODE_NORMAL) { val = 0; if (ath10k_peer_stats_enabled(ar)) val = WMI_10_4_PEER_STATS; @@ -1975,10 +1972,13 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, * possible to implicitly make it correct by creating a dummy vdev and * then deleting it. */ - status = ath10k_core_reset_rx_filter(ar); - if (status) { - ath10k_err(ar, "failed to reset rx filter: %d\n", status); - goto err_hif_stop; + if (mode == ATH10K_FIRMWARE_MODE_NORMAL) { + status = ath10k_core_reset_rx_filter(ar); + if (status) { + ath10k_err(ar, + "failed to reset rx filter: %d\n", status); + goto err_hif_stop; + } } /* If firmware indicates Full Rx Reorder support it must be used in a diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index c7664d6569fa..757242ef52ac 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -314,6 +314,7 @@ struct ath10k_peer { struct ieee80211_vif *vif; struct ieee80211_sta *sta; + bool removed; int vdev_id; u8 addr[ETH_ALEN]; DECLARE_BITMAP(peer_ids, ATH10K_MAX_NUM_PEER_IDS); @@ -419,6 +420,21 @@ struct ath10k_vif_iter { struct ath10k_vif *arvif; }; +/* Copy Engine register dump, protected by ce-lock */ +struct ath10k_ce_crash_data { + __le32 base_addr; + __le32 src_wr_idx; + __le32 src_r_idx; + __le32 dst_wr_idx; + __le32 dst_r_idx; +}; + +struct ath10k_ce_crash_hdr { + __le32 ce_count; + __le32 reserved[3]; /* for future use */ + struct ath10k_ce_crash_data entries[]; +}; + /* used for crash-dump storage, protected by data-lock */ struct ath10k_fw_crash_data { bool crashed_since_read; @@ -426,6 +442,7 @@ struct ath10k_fw_crash_data { uuid_le uuid; struct timespec timestamp; __le32 registers[REG_DUMP_COUNT_QCA988X]; + struct ath10k_ce_crash_data ce_crash_data[CE_COUNT_MAX]; }; struct ath10k_debug { diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index e1a70dffc52a..fb0ade3adb07 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -41,6 +41,7 @@ */ enum ath10k_fw_crash_dump_type { ATH10K_FW_CRASH_DUMP_REGISTERS = 0, + ATH10K_FW_CRASH_DUMP_CE_DATA = 1, ATH10K_FW_CRASH_DUMP_MAX, }; @@ -236,7 +237,7 @@ static ssize_t ath10k_read_wmi_services(struct file *file, { struct ath10k *ar = file->private_data; char *buf; - unsigned int len = 0, buf_len = 4096; + size_t len = 0, buf_len = 4096; const char *name; ssize_t ret_cnt; bool enabled; @@ -400,6 +401,7 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) * prevent firmware from DoS-ing the host. */ ath10k_fw_stats_peers_free(&ar->debug.fw_stats.peers); + ath10k_fw_extd_stats_peers_free(&ar->debug.fw_stats.peers_extd); ath10k_warn(ar, "dropping fw peer stats\n"); goto free; } @@ -410,10 +412,12 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) goto free; } + if (!list_empty(&stats.peers)) + list_splice_tail_init(&stats.peers_extd, + &ar->debug.fw_stats.peers_extd); + list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers); list_splice_tail_init(&stats.vdevs, &ar->debug.fw_stats.vdevs); - list_splice_tail_init(&stats.peers_extd, - &ar->debug.fw_stats.peers_extd); } complete(&ar->debug.fw_stats_complete); @@ -525,7 +529,7 @@ static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { const char *buf = file->private_data; - unsigned int len = strlen(buf); + size_t len = strlen(buf); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -543,17 +547,16 @@ static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file, size_t count, loff_t *ppos) { struct ath10k *ar = file->private_data; - int ret, len, buf_len; + int ret; + size_t len = 0, buf_len = 500; char *buf; - buf_len = 500; buf = kmalloc(buf_len, GFP_KERNEL); if (!buf) return -ENOMEM; spin_lock_bh(&ar->data_lock); - len = 0; len += scnprintf(buf + len, buf_len - len, "fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter); len += scnprintf(buf + len, buf_len - len, @@ -692,7 +695,7 @@ static ssize_t ath10k_read_chip_id(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath10k *ar = file->private_data; - unsigned int len; + size_t len; char buf[50]; len = scnprintf(buf, sizeof(buf), "0x%08x\n", ar->chip_id); @@ -726,14 +729,17 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar, bool mark_read) { struct ath10k_fw_crash_data *crash_data = ar->debug.fw_crash_data; + struct ath10k_ce_crash_hdr *ce_hdr; struct ath10k_dump_file_data *dump_data; struct ath10k_tlv_dump_data *dump_tlv; - int hdr_len = sizeof(*dump_data); - unsigned int len, sofar = 0; + size_t hdr_len = sizeof(*dump_data); + size_t len, sofar = 0; unsigned char *buf; len = hdr_len; len += sizeof(*dump_tlv) + sizeof(crash_data->registers); + len += sizeof(*dump_tlv) + sizeof(*ce_hdr) + + CE_COUNT * sizeof(ce_hdr->entries[0]); sofar += hdr_len; @@ -792,6 +798,18 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar, sizeof(crash_data->registers)); sofar += sizeof(*dump_tlv) + sizeof(crash_data->registers); + dump_tlv = (struct ath10k_tlv_dump_data *)(buf + sofar); + dump_tlv->type = cpu_to_le32(ATH10K_FW_CRASH_DUMP_CE_DATA); + dump_tlv->tlv_len = cpu_to_le32(sizeof(*ce_hdr) + + CE_COUNT * sizeof(ce_hdr->entries[0])); + ce_hdr = (struct ath10k_ce_crash_hdr *)(dump_tlv->tlv_data); + ce_hdr->ce_count = cpu_to_le32(CE_COUNT); + memset(ce_hdr->reserved, 0, sizeof(ce_hdr->reserved)); + memcpy(ce_hdr->entries, crash_data->ce_crash_data, + CE_COUNT * sizeof(ce_hdr->entries[0])); + sofar += sizeof(*dump_tlv) + sizeof(*ce_hdr) + + CE_COUNT * sizeof(ce_hdr->entries[0]); + ar->debug.fw_crash_data->crashed_since_read = !mark_read; spin_unlock_bh(&ar->data_lock); @@ -881,7 +899,7 @@ static ssize_t ath10k_reg_addr_read(struct file *file, { struct ath10k *ar = file->private_data; u8 buf[32]; - unsigned int len = 0; + size_t len = 0; u32 reg_addr; mutex_lock(&ar->conf_mutex); @@ -929,7 +947,7 @@ static ssize_t ath10k_reg_value_read(struct file *file, { struct ath10k *ar = file->private_data; u8 buf[48]; - unsigned int len; + size_t len; u32 reg_addr, reg_val; int ret; @@ -1152,7 +1170,7 @@ static ssize_t ath10k_read_htt_stats_mask(struct file *file, { struct ath10k *ar = file->private_data; char buf[32]; - unsigned int len; + size_t len; len = scnprintf(buf, sizeof(buf), "%lu\n", ar->debug.htt_stats_mask); @@ -1206,7 +1224,7 @@ static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file, struct ath10k *ar = file->private_data; char buf[64]; u8 amsdu, ampdu; - unsigned int len; + size_t len; mutex_lock(&ar->conf_mutex); @@ -1266,7 +1284,7 @@ static ssize_t ath10k_read_fw_dbglog(struct file *file, size_t count, loff_t *ppos) { struct ath10k *ar = file->private_data; - unsigned int len; + size_t len; char buf[96]; len = scnprintf(buf, sizeof(buf), "0x%16llx %u\n", @@ -1592,11 +1610,10 @@ static ssize_t ath10k_read_ani_enable(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { struct ath10k *ar = file->private_data; - int len = 0; + size_t len; char buf[32]; - len = scnprintf(buf, sizeof(buf) - len, "%d\n", - ar->ani_enabled); + len = scnprintf(buf, sizeof(buf), "%d\n", ar->ani_enabled); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -1621,11 +1638,10 @@ static ssize_t ath10k_read_nf_cal_period(struct file *file, size_t count, loff_t *ppos) { struct ath10k *ar = file->private_data; - unsigned int len; + size_t len; char buf[32]; - len = scnprintf(buf, sizeof(buf), "%d\n", - ar->debug.nf_cal_period); + len = scnprintf(buf, sizeof(buf), "%d\n", ar->debug.nf_cal_period); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -1721,9 +1737,10 @@ void ath10k_debug_tpc_stats_process(struct ath10k *ar, } static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats, - unsigned int j, char *buf, unsigned int *len) + unsigned int j, char *buf, size_t *len) { - unsigned int i, buf_len; + int i; + size_t buf_len; static const char table_str[][5] = { "CDD", "STBC", "TXBF" }; @@ -1763,7 +1780,8 @@ static void ath10k_tpc_stats_fill(struct ath10k *ar, struct ath10k_tpc_stats *tpc_stats, char *buf) { - unsigned int len, j, buf_len; + int j; + size_t len, buf_len; len = 0; buf_len = ATH10K_TPC_CONFIG_BUF_SIZE; @@ -1897,7 +1915,7 @@ static ssize_t ath10k_tpc_stats_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { const char *buf = file->private_data; - unsigned int len = strlen(buf); + size_t len = strlen(buf); return simple_read_from_buffer(user_buf, count, ppos, buf, len); } @@ -2321,7 +2339,7 @@ static ssize_t ath10k_debug_fw_checksums_read(struct file *file, size_t count, loff_t *ppos) { struct ath10k *ar = file->private_data; - unsigned int len = 0, buf_len = 4096; + size_t len = 0, buf_len = 4096; ssize_t ret_cnt; char *buf; @@ -2537,7 +2555,7 @@ void ath10k_dbg_dump(struct ath10k *ar, const void *buf, size_t len) { char linebuf[256]; - unsigned int linebuflen; + size_t linebuflen; const void *ptr; if (ath10k_debug_mask & mask) { diff --git a/drivers/net/wireless/ath/ath10k/debugfs_sta.c b/drivers/net/wireless/ath/ath10k/debugfs_sta.c index fce6f8137d33..7353e7ea88f1 100644 --- a/drivers/net/wireless/ath/ath10k/debugfs_sta.c +++ b/drivers/net/wireless/ath/ath10k/debugfs_sta.c @@ -306,6 +306,69 @@ static const struct file_operations fops_delba = { .llseek = default_llseek, }; +static ssize_t ath10k_dbg_sta_read_peer_debug_trigger(struct file *file, + char __user *user_buf, + size_t count, + loff_t *ppos) +{ + struct ieee80211_sta *sta = file->private_data; + struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; + struct ath10k *ar = arsta->arvif->ar; + char buf[8]; + int len = 0; + + mutex_lock(&ar->conf_mutex); + len = scnprintf(buf, sizeof(buf) - len, + "Write 1 to once trigger the debug logs\n"); + mutex_unlock(&ar->conf_mutex); + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t +ath10k_dbg_sta_write_peer_debug_trigger(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ieee80211_sta *sta = file->private_data; + struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; + struct ath10k *ar = arsta->arvif->ar; + u8 peer_debug_trigger; + int ret; + + if (kstrtou8_from_user(user_buf, count, 0, &peer_debug_trigger)) + return -EINVAL; + + if (peer_debug_trigger != 1) + return -EINVAL; + + mutex_lock(&ar->conf_mutex); + + if (ar->state != ATH10K_STATE_ON) { + ret = -ENETDOWN; + goto out; + } + + ret = ath10k_wmi_peer_set_param(ar, arsta->arvif->vdev_id, sta->addr, + WMI_PEER_DEBUG, peer_debug_trigger); + if (ret) { + ath10k_warn(ar, "failed to set param to trigger peer tid logs for station ret: %d\n", + ret); + goto out; + } +out: + mutex_unlock(&ar->conf_mutex); + return count; +} + +static const struct file_operations fops_peer_debug_trigger = { + .open = simple_open, + .read = ath10k_dbg_sta_read_peer_debug_trigger, + .write = ath10k_dbg_sta_write_peer_debug_trigger, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct dentry *dir) { @@ -314,4 +377,6 @@ void ath10k_sta_add_debugfs(struct ieee80211_hw *hw, struct ieee80211_vif *vif, debugfs_create_file("addba", S_IWUSR, dir, sta, &fops_addba); debugfs_create_file("addba_resp", S_IWUSR, dir, sta, &fops_addba_resp); debugfs_create_file("delba", S_IWUSR, dir, sta, &fops_delba); + debugfs_create_file("peer_debug_trigger", 0600, dir, sta, + &fops_peer_debug_trigger); } diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index 175aae38c375..9f6a915f91bf 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -474,33 +474,16 @@ static void ath10k_htc_reset_endpoint_states(struct ath10k_htc *htc) } } -static void ath10k_htc_setup_target_buffer_assignments(struct ath10k_htc *htc) -{ - struct ath10k_htc_svc_tx_credits *entry; - - entry = &htc->service_tx_alloc[0]; - - /* - * for PCIE allocate all credists/HTC buffers to WMI. - * no buffers are used/required for data. data always - * remains on host. - */ - entry++; - entry->service_id = ATH10K_HTC_SVC_ID_WMI_CONTROL; - entry->credit_allocation = htc->total_transmit_credits; -} - static u8 ath10k_htc_get_credit_allocation(struct ath10k_htc *htc, u16 service_id) { u8 allocation = 0; - int i; - for (i = 0; i < ATH10K_HTC_EP_COUNT; i++) { - if (htc->service_tx_alloc[i].service_id == service_id) - allocation = - htc->service_tx_alloc[i].credit_allocation; - } + /* The WMI control service is the only service with flow control. + * Let it have all transmit credits. + */ + if (service_id == ATH10K_HTC_SVC_ID_WMI_CONTROL) + allocation = htc->total_transmit_credits; return allocation; } @@ -574,8 +557,6 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc) return -ECOMM; } - ath10k_htc_setup_target_buffer_assignments(htc); - /* setup our pseudo HTC control endpoint connection */ memset(&conn_req, 0, sizeof(conn_req)); memset(&conn_resp, 0, sizeof(conn_resp)); @@ -726,12 +707,6 @@ setup: ep->max_tx_queue_depth = conn_req->max_send_queue_depth; ep->max_ep_message_len = __le16_to_cpu(resp_msg->max_msg_size); ep->tx_credits = tx_alloc; - ep->tx_credit_size = htc->target_credit_size; - ep->tx_credits_per_max_message = ep->max_ep_message_len / - htc->target_credit_size; - - if (ep->max_ep_message_len % htc->target_credit_size) - ep->tx_credits_per_max_message++; /* copy all the callbacks */ ep->ep_ops = conn_req->ep_ops; diff --git a/drivers/net/wireless/ath/ath10k/htc.h b/drivers/net/wireless/ath/ath10k/htc.h index 0c55cd92a951..6ababa345e2b 100644 --- a/drivers/net/wireless/ath/ath10k/htc.h +++ b/drivers/net/wireless/ath/ath10k/htc.h @@ -314,8 +314,6 @@ struct ath10k_htc_ep { u8 seq_no; /* for debugging */ int tx_credits; - int tx_credit_size; - int tx_credits_per_max_message; bool tx_credit_flow_enabled; }; @@ -339,7 +337,6 @@ struct ath10k_htc { struct completion ctl_resp; int total_transmit_credits; - struct ath10k_htc_svc_tx_credits service_tx_alloc[ATH10K_HTC_EP_COUNT]; int target_credit_size; }; diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 44b25cf00553..90c2f72666b8 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h @@ -1636,7 +1636,7 @@ struct ath10k_htt { int size; /* size - 1 */ - unsigned size_mask; + unsigned int size_mask; /* how many rx buffers to keep in the ring */ int fill_level; @@ -1657,7 +1657,7 @@ struct ath10k_htt { /* where HTT SW has processed bufs filled by rx MAC DMA */ struct { - unsigned msdu_payld; + unsigned int msdu_payld; } sw_rd_idx; /* @@ -1820,7 +1820,7 @@ int ath10k_htt_tx_mgmt_inc_pending(struct ath10k_htt *htt, bool is_mgmt, int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt, struct sk_buff *skb); void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id); -int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *); +int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu); int ath10k_htt_tx(struct ath10k_htt *htt, enum ath10k_hw_txrx_mode txmode, struct sk_buff *msdu); diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 86d082cf4eef..02a3fc81fbe3 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -702,6 +702,10 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, /* 80MHZ */ case 2: status->vht_flag |= RX_VHT_FLAG_80MHZ; + break; + case 3: + status->vht_flag |= RX_VHT_FLAG_160MHZ; + break; } status->flag |= RX_FLAG_VHT; @@ -926,7 +930,7 @@ static void ath10k_process_rx(struct ath10k *ar, *status = *rx_status; ath10k_dbg(ar, ATH10K_DBG_DATA, - "rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%llx fcs-err %i mic-err %i amsdu-more %i\n", + "rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%llx fcs-err %i mic-err %i amsdu-more %i\n", skb, skb->len, ieee80211_get_SA(hdr), @@ -940,6 +944,7 @@ static void ath10k_process_rx(struct ath10k *ar, status->flag & RX_FLAG_VHT ? "vht" : "", status->flag & RX_FLAG_40MHZ ? "40" : "", status->vht_flag & RX_VHT_FLAG_80MHZ ? "80" : "", + status->vht_flag & RX_VHT_FLAG_160MHZ ? "160" : "", status->flag & RX_FLAG_SHORT_GI ? "sgi " : "", status->rate_idx, status->vht_nss, @@ -2231,6 +2236,8 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar, return; } + memset(&arsta->txrate, 0, sizeof(arsta->txrate)); + if (txrate.flags == WMI_RATE_PREAMBLE_CCK || txrate.flags == WMI_RATE_PREAMBLE_OFDM) { rate = ATH10K_HW_LEGACY_RATE(peer_stats->ratecode); @@ -2245,7 +2252,7 @@ ath10k_update_per_peer_tx_stats(struct ath10k *ar, rate *= 10; if (rate == 60 && txrate.flags == WMI_RATE_PREAMBLE_CCK) rate = rate - 5; - arsta->txrate.legacy = rate * 10; + arsta->txrate.legacy = rate; } else if (txrate.flags == WMI_RATE_PREAMBLE_HT) { arsta->txrate.flags = RATE_INFO_FLAGS_MCS; arsta->txrate.mcs = txrate.mcs; @@ -2451,8 +2458,7 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) u32 phymode = __le32_to_cpu(resp->chan_change.phymode); u32 freq = __le32_to_cpu(resp->chan_change.freq); - ar->tgt_oper_chan = - __ieee80211_get_channel(ar->hw->wiphy, freq); + ar->tgt_oper_chan = ieee80211_get_channel(ar->hw->wiphy, freq); ath10k_dbg(ar, ATH10K_DBG_HTT, "htt chan change freq %u phymode %s\n", freq, ath10k_wmi_phymode_str(phymode)); @@ -2486,7 +2492,7 @@ bool ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ", skb->data, skb->len); break; - }; + } return true; } EXPORT_SYMBOL(ath10k_htt_t2h_msg_handler); diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 7feffec531cc..f0fda0f2b3b4 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -128,6 +128,10 @@ enum qca9377_chip_id_rev { #define QCA4019_HW_1_0_BOARD_DATA_FILE "board.bin" #define QCA4019_HW_1_0_PATCH_LOAD_ADDR 0x1234 +#define ATH10K_FW_FILE_BASE "firmware" +#define ATH10K_FW_API_MAX 5 +#define ATH10K_FW_API_MIN 2 + #define ATH10K_FW_API2_FILE "firmware-2.bin" #define ATH10K_FW_API3_FILE "firmware-3.bin" @@ -578,6 +582,9 @@ ath10k_rx_desc_get_l3_pad_bytes(struct ath10k_hw_params *hw, #define TARGET_10_4_IPHDR_PAD_CONFIG 1 #define TARGET_10_4_QWRAP_CONFIG 0 +/* Maximum number of Copy Engine's supported */ +#define CE_COUNT_MAX 12 + /* Number of Copy Engines supported */ #define CE_COUNT ar->hw_values->ce_count diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index d1b7edba5e49..3029f257a19a 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -569,10 +569,14 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef) case NL80211_CHAN_WIDTH_80: phymode = MODE_11AC_VHT80; break; + case NL80211_CHAN_WIDTH_160: + phymode = MODE_11AC_VHT160; + break; + case NL80211_CHAN_WIDTH_80P80: + phymode = MODE_11AC_VHT80_80; + break; case NL80211_CHAN_WIDTH_5: case NL80211_CHAN_WIDTH_10: - case NL80211_CHAN_WIDTH_80P80: - case NL80211_CHAN_WIDTH_160: phymode = MODE_UNKNOWN; break; } @@ -971,6 +975,7 @@ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) arg.vdev_id = vdev_id; arg.channel.freq = channel->center_freq; arg.channel.band_center_freq1 = chandef->center_freq1; + arg.channel.band_center_freq2 = chandef->center_freq2; /* TODO setup this dynamically, what in case we don't have any vifs? */ @@ -1417,6 +1422,7 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif, arg.channel.freq = chandef->chan->center_freq; arg.channel.band_center_freq1 = chandef->center_freq1; + arg.channel.band_center_freq2 = chandef->center_freq2; arg.channel.mode = chan_to_phymode(chandef); arg.channel.min_power = 0; @@ -1987,7 +1993,7 @@ static void ath10k_mac_handle_beacon_iter(void *data, u8 *mac, { struct sk_buff *skb = data; struct ieee80211_mgmt *mgmt = (void *)skb->data; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; if (vif->type != NL80211_IFTYPE_STATION) return; @@ -2010,7 +2016,7 @@ static void ath10k_mac_handle_beacon_miss_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { u32 *vdev_id = data; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct ath10k *ar = arvif->ar; struct ieee80211_hw *hw = ar->hw; @@ -2077,7 +2083,7 @@ static void ath10k_peer_assoc_h_basic(struct ath10k *ar, struct ieee80211_sta *sta, struct wmi_peer_assoc_complete_arg *arg) { - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; u32 aid; lockdep_assert_held(&ar->conf_mutex); @@ -2153,7 +2159,7 @@ static void ath10k_peer_assoc_h_rates(struct ath10k *ar, struct ieee80211_sta *sta, struct wmi_peer_assoc_complete_arg *arg) { - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates; struct cfg80211_chan_def def; const struct ieee80211_supported_band *sband; @@ -2216,7 +2222,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar, struct wmi_peer_assoc_complete_arg *arg) { const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct cfg80211_chan_def def; enum nl80211_band band; const u8 *ht_mcs_mask; @@ -2440,7 +2446,7 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar, struct wmi_peer_assoc_complete_arg *arg) { const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct cfg80211_chan_def def; enum nl80211_band band; const u16 *vht_mcs_mask; @@ -2480,6 +2486,9 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar, if (sta->bandwidth == IEEE80211_STA_RX_BW_80) arg->peer_flags |= ar->wmi.peer_flags->bw80; + if (sta->bandwidth == IEEE80211_STA_RX_BW_160) + arg->peer_flags |= ar->wmi.peer_flags->bw160; + arg->peer_vht_rates.rx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.rx_highest); arg->peer_vht_rates.rx_mcs_set = @@ -2498,7 +2507,7 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar, struct ieee80211_sta *sta, struct wmi_peer_assoc_complete_arg *arg) { - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; switch (arvif->vdev_type) { case WMI_VDEV_TYPE_AP: @@ -2533,12 +2542,39 @@ static bool ath10k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta) ATH10K_MAC_FIRST_OFDM_RATE_IDX; } +static enum wmi_phy_mode ath10k_mac_get_phymode_vht(struct ath10k *ar, + struct ieee80211_sta *sta) +{ + if (sta->bandwidth == IEEE80211_STA_RX_BW_160) { + switch (sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) { + case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: + return MODE_11AC_VHT160; + case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ: + return MODE_11AC_VHT80_80; + default: + /* not sure if this is a valid case? */ + return MODE_11AC_VHT160; + } + } + + if (sta->bandwidth == IEEE80211_STA_RX_BW_80) + return MODE_11AC_VHT80; + + if (sta->bandwidth == IEEE80211_STA_RX_BW_40) + return MODE_11AC_VHT40; + + if (sta->bandwidth == IEEE80211_STA_RX_BW_20) + return MODE_11AC_VHT20; + + return MODE_UNKNOWN; +} + static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta, struct wmi_peer_assoc_complete_arg *arg) { - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct cfg80211_chan_def def; enum nl80211_band band; const u8 *ht_mcs_mask; @@ -2579,12 +2615,7 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, */ if (sta->vht_cap.vht_supported && !ath10k_peer_assoc_h_vht_masked(vht_mcs_mask)) { - if (sta->bandwidth == IEEE80211_STA_RX_BW_80) - phymode = MODE_11AC_VHT80; - else if (sta->bandwidth == IEEE80211_STA_RX_BW_40) - phymode = MODE_11AC_VHT40; - else if (sta->bandwidth == IEEE80211_STA_RX_BW_20) - phymode = MODE_11AC_VHT20; + phymode = ath10k_mac_get_phymode_vht(ar, sta); } else if (sta->ht_cap.ht_supported && !ath10k_peer_assoc_h_ht_masked(ht_mcs_mask)) { if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) @@ -2658,7 +2689,7 @@ static int ath10k_mac_vif_recalc_txbf(struct ath10k *ar, struct ieee80211_vif *vif, struct ieee80211_sta_vht_cap vht_cap) { - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; int ret; u32 param; u32 value; @@ -2725,7 +2756,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, struct ieee80211_bss_conf *bss_conf) { struct ath10k *ar = hw->priv; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct ieee80211_sta_ht_cap ht_cap; struct ieee80211_sta_vht_cap vht_cap; struct wmi_peer_assoc_complete_arg peer_arg; @@ -2818,7 +2849,7 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct ath10k *ar = hw->priv; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct ieee80211_sta_vht_cap vht_cap = {}; int ret; @@ -2851,7 +2882,7 @@ static int ath10k_station_assoc(struct ath10k *ar, struct ieee80211_sta *sta, bool reassoc) { - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct wmi_peer_assoc_complete_arg peer_arg; int ret = 0; @@ -2918,7 +2949,7 @@ 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); + struct ath10k_vif *arvif = (void *)vif->drv_priv; int ret = 0; lockdep_assert_held(&ar->conf_mutex); @@ -3144,7 +3175,7 @@ static void ath10k_mac_tx_unlock_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { struct ath10k *ar = data; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; if (arvif->tx_paused) return; @@ -3231,7 +3262,7 @@ struct ath10k_mac_tx_pause { static void ath10k_mac_handle_tx_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct ath10k_mac_tx_pause *arg = data; if (arvif->vdev_id != arg->vdev_id) @@ -3327,7 +3358,7 @@ static bool ath10k_tx_h_use_hwcrypto(struct ieee80211_vif *vif, return false; if (vif) - return !ath10k_vif_to_arvif(vif)->nohwcrypt; + return !((struct ath10k_vif *)vif->drv_priv)->nohwcrypt; return true; } @@ -3392,7 +3423,7 @@ static void ath10k_tx_h_add_p2p_noa_ie(struct ath10k *ar, struct sk_buff *skb) { struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; /* This is case only for P2P_GO */ if (vif->type != NL80211_IFTYPE_AP || !vif->p2p) @@ -3774,6 +3805,9 @@ struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar, if (!peer) return NULL; + if (peer->removed) + return NULL; + if (peer->sta) return peer->sta->txq[tid]; else if (peer->vif) @@ -4311,6 +4345,13 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) vht_cap.cap |= val; } + /* Currently the firmware seems to be buggy, don't enable 80+80 + * mode until that's resolved. + */ + if ((ar->vht_cap_info & IEEE80211_VHT_CAP_SHORT_GI_160) && + !(ar->vht_cap_info & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) + vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; + mcs_map = 0; for (i = 0; i < 8; i++) { if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i))) @@ -4808,7 +4849,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct ath10k *ar = hw->priv; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct ath10k_peer *peer; enum wmi_sta_powersave_param param; int ret = 0; @@ -5144,7 +5185,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) { struct ath10k *ar = hw->priv; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct ath10k_peer *peer; int ret; int i; @@ -5279,7 +5320,7 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, u32 changed) { struct ath10k *ar = hw->priv; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; int ret = 0; u32 vdev_param, pdev_param, slottime, preamble; @@ -5471,7 +5512,7 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw, struct ieee80211_scan_request *hw_req) { struct ath10k *ar = hw->priv; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct cfg80211_scan_request *req = &hw_req->req; struct wmi_start_scan_arg arg; int ret = 0; @@ -5603,7 +5644,7 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key) { struct ath10k *ar = hw->priv; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct ath10k_peer *peer; const u8 *peer_addr; bool is_wep = key->cipher == WLAN_CIPHER_SUITE_WEP40 || @@ -5742,7 +5783,7 @@ static void ath10k_set_default_unicast_key(struct ieee80211_hw *hw, int keyidx) { struct ath10k *ar = hw->priv; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; int ret; mutex_lock(&arvif->ar->conf_mutex); @@ -5923,7 +5964,7 @@ static int ath10k_mac_tdls_vif_stations_count(struct ieee80211_hw *hw, static void ath10k_mac_tdls_vifs_count_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; int *num_tdls_vifs = data; if (vif->type != NL80211_IFTYPE_STATION) @@ -5951,7 +5992,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, enum ieee80211_sta_state new_state) { struct ath10k *ar = hw->priv; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; struct ath10k_peer *peer; int ret = 0; @@ -6186,7 +6227,7 @@ exit: static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif, u16 ac, bool enable) { - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct wmi_sta_uapsd_auto_trig_arg arg = {}; u32 prio = 0, acc = 0; u32 value = 0; @@ -6294,7 +6335,7 @@ static int ath10k_conf_tx(struct ieee80211_hw *hw, const struct ieee80211_tx_queue_params *params) { struct ath10k *ar = hw->priv; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct wmi_wmm_params_arg *p = NULL; int ret; @@ -6368,7 +6409,7 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw, enum ieee80211_roc_type type) { struct ath10k *ar = hw->priv; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct wmi_start_scan_arg arg; int ret = 0; u32 scan_time_msec; @@ -6868,7 +6909,7 @@ static int ath10k_mac_op_set_bitrate_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif, const struct cfg80211_bitrate_mask *mask) { - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct cfg80211_chan_def def; struct ath10k *ar = arvif->ar; enum nl80211_band band; @@ -6969,6 +7010,9 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw, bw = WMI_PEER_CHWIDTH_80MHZ; break; case IEEE80211_STA_RX_BW_160: + bw = WMI_PEER_CHWIDTH_160MHZ; + break; + default: ath10k_warn(ar, "Invalid bandwidth %d in rc update for %pM\n", sta->bandwidth, sta->addr); bw = WMI_PEER_CHWIDTH_20MHZ; @@ -7016,7 +7060,7 @@ static void ath10k_offset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif, s64 tsf_offset) { struct ath10k *ar = hw->priv; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; u32 offset, vdev_param; int ret; @@ -7041,7 +7085,7 @@ static int ath10k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_ampdu_params *params) { struct ath10k *ar = hw->priv; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct ieee80211_sta *sta = params->sta; enum ieee80211_ampdu_mlme_action action = params->action; u16 tid = params->tid; @@ -7139,7 +7183,7 @@ ath10k_mac_update_vif_chan(struct ath10k *ar, ath10k_monitor_stop(ar); for (i = 0; i < n_vifs; i++) { - arvif = ath10k_vif_to_arvif(vifs[i].vif); + arvif = (void *)vifs[i].vif->drv_priv; ath10k_dbg(ar, ATH10K_DBG_MAC, "mac chanctx switch vdev_id %i freq %hu->%hu width %d->%d\n", @@ -7172,7 +7216,7 @@ ath10k_mac_update_vif_chan(struct ath10k *ar, spin_unlock_bh(&ar->data_lock); for (i = 0; i < n_vifs; i++) { - arvif = ath10k_vif_to_arvif(vifs[i].vif); + arvif = (void *)vifs[i].vif->drv_priv; if (WARN_ON(!arvif->is_started)) continue; @@ -7476,6 +7520,20 @@ ath10k_mac_op_switch_vif_chanctx(struct ieee80211_hw *hw, return 0; } +static void ath10k_mac_op_sta_pre_rcu_remove(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta) +{ + struct ath10k *ar; + struct ath10k_peer *peer; + + ar = hw->priv; + + list_for_each_entry(peer, &ar->peers, list) + if (peer->sta == sta) + peer->removed = true; +} + static const struct ieee80211_ops ath10k_ops = { .tx = ath10k_mac_op_tx, .wake_tx_queue = ath10k_mac_op_wake_tx_queue, @@ -7516,6 +7574,7 @@ static const struct ieee80211_ops ath10k_ops = { .assign_vif_chanctx = ath10k_mac_op_assign_vif_chanctx, .unassign_vif_chanctx = ath10k_mac_op_unassign_vif_chanctx, .switch_vif_chanctx = ath10k_mac_op_switch_vif_chanctx, + .sta_pre_rcu_remove = ath10k_mac_op_sta_pre_rcu_remove, CFG80211_TESTMODE_CMD(ath10k_tm_cmd) @@ -7814,7 +7873,7 @@ static void ath10k_get_arvif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { struct ath10k_vif_iter *arvif_iter = data; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; if (arvif->vdev_id == arvif_iter->vdev_id) arvif_iter->arvif = arvif; diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h index 1bd29ecfcdcc..553747bc19ed 100644 --- a/drivers/net/wireless/ath/ath10k/mac.h +++ b/drivers/net/wireless/ath/ath10k/mac.h @@ -83,17 +83,12 @@ struct ieee80211_txq *ath10k_mac_txq_lookup(struct ath10k *ar, u8 tid); int ath10k_mac_ext_resource_config(struct ath10k *ar, u32 val); -static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) -{ - return (struct ath10k_vif *)vif->drv_priv; -} - static inline void ath10k_tx_h_seq_no(struct ieee80211_vif *vif, struct sk_buff *skb) { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { if (arvif->tx_seq_no == 0) diff --git a/drivers/net/wireless/ath/ath10k/p2p.c b/drivers/net/wireless/ath/ath10k/p2p.c index c0b6ffaf3ec1..7e621ee194e3 100644 --- a/drivers/net/wireless/ath/ath10k/p2p.c +++ b/drivers/net/wireless/ath/ath10k/p2p.c @@ -132,7 +132,7 @@ struct ath10k_p2p_noa_arg { static void ath10k_p2p_noa_update_vdev_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; struct ath10k_p2p_noa_arg *arg = data; if (arvif->vdev_id != arg->vdev_id) diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 93b9790cfe8d..6094372307aa 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -840,31 +840,35 @@ void ath10k_pci_rx_replenish_retry(unsigned long ptr) ath10k_pci_rx_post(ar); } -static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr) +static u32 ath10k_pci_qca988x_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr) { - u32 val = 0; + u32 val = 0, region = addr & 0xfffff; - switch (ar->hw_rev) { - case ATH10K_HW_QCA988X: - case ATH10K_HW_QCA9887: - case ATH10K_HW_QCA6174: - case ATH10K_HW_QCA9377: - val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + - CORE_CTRL_ADDRESS) & - 0x7ff) << 21; - break; - case ATH10K_HW_QCA9888: - case ATH10K_HW_QCA99X0: - case ATH10K_HW_QCA9984: - case ATH10K_HW_QCA4019: - val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS); - break; - } + val = (ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS) + & 0x7ff) << 21; + val |= 0x100000 | region; + return val; +} - val |= 0x100000 | (addr & 0xfffff); +static u32 ath10k_pci_qca99x0_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr) +{ + u32 val = 0, region = addr & 0xfffff; + + val = ath10k_pci_read32(ar, PCIE_BAR_REG_ADDRESS); + val |= 0x100000 | region; return val; } +static u32 ath10k_pci_targ_cpu_to_ce_addr(struct ath10k *ar, u32 addr) +{ + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + + if (WARN_ON_ONCE(!ar_pci->targ_cpu_to_ce_addr)) + return -ENOTSUPP; + + return ar_pci->targ_cpu_to_ce_addr(ar, addr); +} + /* * Diagnostic read/write access is provided for startup/config/debug usage. * Caller must guarantee proper alignment, when applicable, and single user @@ -896,7 +900,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, */ alloc_nbytes = min_t(unsigned int, nbytes, DIAG_TRANSFER_LIMIT); - data_buf = (unsigned char *)dma_alloc_coherent(ar->dev, + data_buf = (unsigned char *)dma_zalloc_coherent(ar->dev, alloc_nbytes, &ce_data_base, GFP_ATOMIC); @@ -905,7 +909,6 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, ret = -ENOMEM; goto done; } - memset(data_buf, 0, alloc_nbytes); remaining_bytes = nbytes; ce_data = ce_data_base; @@ -1474,6 +1477,7 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar) ath10k_err(ar, "firmware crashed! (uuid %s)\n", uuid); ath10k_print_driver_info(ar); ath10k_pci_dump_registers(ar, crash_data); + ath10k_ce_dump_registers(ar, crash_data); spin_unlock_bh(&ar->data_lock); @@ -1590,7 +1594,7 @@ void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) /* TODO: Find appropriate register configuration for QCA99X0 * to mask irq/MSI. */ - break; + break; } } @@ -1647,6 +1651,8 @@ static int ath10k_pci_hif_start(struct ath10k *ar) ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif start\n"); + napi_enable(&ar->napi); + ath10k_pci_irq_enable(ar); ath10k_pci_rx_post(ar); @@ -1937,7 +1943,7 @@ static int ath10k_pci_wake_target_cpu(struct ath10k *ar) { u32 addr, val; - addr = SOC_CORE_BASE_ADDRESS | CORE_CTRL_ADDRESS; + addr = SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS; val = ath10k_pci_read32(ar, addr); val |= CORE_CTRL_CPU_INTR_MASK; ath10k_pci_write32(ar, addr, val); @@ -2531,7 +2537,6 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar) ath10k_err(ar, "could not wake up target CPU: %d\n", ret); goto err_ce; } - napi_enable(&ar->napi); return 0; @@ -2799,7 +2804,7 @@ static int ath10k_pci_napi_poll(struct napi_struct *ctx, int budget) done = ath10k_htt_txrx_compl_task(ar, budget); if (done < budget) { - napi_complete(ctx); + napi_complete_done(ctx, done); /* In case of MSI, it is possible that interrupts are received * while NAPI poll is inprogress. So pending interrupts that are * received after processing all copy engine pipes by NAPI poll @@ -3170,6 +3175,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, bool pci_ps; int (*pci_soft_reset)(struct ath10k *ar); int (*pci_hard_reset)(struct ath10k *ar); + u32 (*targ_cpu_to_ce_addr)(struct ath10k *ar, u32 addr); switch (pci_dev->device) { case QCA988X_2_0_DEVICE_ID: @@ -3177,12 +3183,14 @@ static int ath10k_pci_probe(struct pci_dev *pdev, pci_ps = false; pci_soft_reset = ath10k_pci_warm_reset; pci_hard_reset = ath10k_pci_qca988x_chip_reset; + targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr; break; case QCA9887_1_0_DEVICE_ID: hw_rev = ATH10K_HW_QCA9887; pci_ps = false; pci_soft_reset = ath10k_pci_warm_reset; pci_hard_reset = ath10k_pci_qca988x_chip_reset; + targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr; break; case QCA6164_2_1_DEVICE_ID: case QCA6174_2_1_DEVICE_ID: @@ -3190,30 +3198,35 @@ static int ath10k_pci_probe(struct pci_dev *pdev, pci_ps = true; pci_soft_reset = ath10k_pci_warm_reset; pci_hard_reset = ath10k_pci_qca6174_chip_reset; + targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr; break; case QCA99X0_2_0_DEVICE_ID: hw_rev = ATH10K_HW_QCA99X0; pci_ps = false; pci_soft_reset = ath10k_pci_qca99x0_soft_chip_reset; pci_hard_reset = ath10k_pci_qca99x0_chip_reset; + targ_cpu_to_ce_addr = ath10k_pci_qca99x0_targ_cpu_to_ce_addr; break; case QCA9984_1_0_DEVICE_ID: hw_rev = ATH10K_HW_QCA9984; pci_ps = false; pci_soft_reset = ath10k_pci_qca99x0_soft_chip_reset; pci_hard_reset = ath10k_pci_qca99x0_chip_reset; + targ_cpu_to_ce_addr = ath10k_pci_qca99x0_targ_cpu_to_ce_addr; break; case QCA9888_2_0_DEVICE_ID: hw_rev = ATH10K_HW_QCA9888; pci_ps = false; pci_soft_reset = ath10k_pci_qca99x0_soft_chip_reset; pci_hard_reset = ath10k_pci_qca99x0_chip_reset; + targ_cpu_to_ce_addr = ath10k_pci_qca99x0_targ_cpu_to_ce_addr; break; case QCA9377_1_0_DEVICE_ID: hw_rev = ATH10K_HW_QCA9377; pci_ps = true; pci_soft_reset = NULL; pci_hard_reset = ath10k_pci_qca6174_chip_reset; + targ_cpu_to_ce_addr = ath10k_pci_qca988x_targ_cpu_to_ce_addr; break; default: WARN_ON(1); @@ -3240,6 +3253,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ar_pci->bus_ops = &ath10k_pci_bus_ops; ar_pci->pci_soft_reset = pci_soft_reset; ar_pci->pci_hard_reset = pci_hard_reset; + ar_pci->targ_cpu_to_ce_addr = targ_cpu_to_ce_addr; ar->id.vendor = pdev->vendor; ar->id.device = pdev->device; diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 9854ad56b2de..c1e08ad63940 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -25,11 +25,6 @@ #include "ahb.h" /* - * maximum number of bytes that can be handled atomically by DiagRead/DiagWrite - */ -#define DIAG_TRANSFER_LIMIT 2048 - -/* * maximum number of bytes that can be * handled atomically by DiagRead/DiagWrite */ @@ -238,6 +233,11 @@ struct ath10k_pci { /* Chip specific pci full reset function */ int (*pci_hard_reset)(struct ath10k *ar); + /* chip specific methods for converting target CPU virtual address + * space to CE address space + */ + u32 (*targ_cpu_to_ce_addr)(struct ath10k *ar, u32 addr); + /* Keep this entry in the last, memory for struct ath10k_ahb is * allocated (ahb support enabled case) in the continuation of * this struct. diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c index 2ffc1fe4923b..c061d6958bd1 100644 --- a/drivers/net/wireless/ath/ath10k/spectral.c +++ b/drivers/net/wireless/ath/ath10k/spectral.c @@ -278,7 +278,7 @@ static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf, { struct ath10k *ar = file->private_data; char *mode = ""; - unsigned int len; + size_t len; enum ath10k_spectral_mode spectral_mode; mutex_lock(&ar->conf_mutex); @@ -370,7 +370,7 @@ static ssize_t read_file_spectral_count(struct file *file, { struct ath10k *ar = file->private_data; char buf[32]; - unsigned int len; + size_t len; u8 spectral_count; mutex_lock(&ar->conf_mutex); @@ -422,7 +422,8 @@ static ssize_t read_file_spectral_bins(struct file *file, { struct ath10k *ar = file->private_data; char buf[32]; - unsigned int len, bins, fft_size, bin_scale; + unsigned int bins, fft_size, bin_scale; + size_t len; mutex_lock(&ar->conf_mutex); diff --git a/drivers/net/wireless/ath/ath10k/testmode.c b/drivers/net/wireless/ath/ath10k/testmode.c index ed85f938e3c0..8bb36c18a749 100644 --- a/drivers/net/wireless/ath/ath10k/testmode.c +++ b/drivers/net/wireless/ath/ath10k/testmode.c @@ -150,7 +150,10 @@ static int ath10k_tm_fetch_utf_firmware_api_1(struct ath10k *ar, ar->hw_params.fw.dir, ATH10K_FW_UTF_FILE); /* load utf firmware image */ - ret = request_firmware(&fw_file->firmware, filename, ar->dev); + ret = request_firmware_direct(&fw_file->firmware, filename, ar->dev); + ath10k_dbg(ar, ATH10K_DBG_TESTMODE, "testmode fw request '%s': %d\n", + filename, ret); + if (ret) { ath10k_warn(ar, "failed to retrieve utf firmware '%s': %d\n", filename, ret); diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 1f6bb9e8bb01..f9188027a6f6 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -3637,6 +3637,7 @@ static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = { .vht = WMI_TLV_PEER_VHT, .bw80 = WMI_TLV_PEER_80MHZ, .pmf = WMI_TLV_PEER_PMF, + .bw160 = WMI_TLV_PEER_160MHZ, }; /************/ diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h index b8aa6000573c..22cf011e839a 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h @@ -543,6 +543,7 @@ enum wmi_tlv_peer_flags { WMI_TLV_PEER_VHT = 0x02000000, WMI_TLV_PEER_80MHZ = 0x04000000, WMI_TLV_PEER_PMF = 0x08000000, + WMI_TLV_PEER_160MHZ = 0x20000000, }; enum wmi_tlv_tag { diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 50d6ee6afe26..2f1743e60fa1 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -28,6 +28,7 @@ #include "wmi-ops.h" #include "p2p.h" #include "hw.h" +#include "hif.h" #define ATH10K_WMI_BARRIER_ECHO_ID 0xBA991E9 #define ATH10K_WMI_BARRIER_TIMEOUT_HZ (3 * HZ) @@ -1574,6 +1575,7 @@ static const struct wmi_peer_flags_map wmi_peer_flags_map = { .bw80 = WMI_PEER_80MHZ, .vht_2g = WMI_PEER_VHT_2G, .pmf = WMI_PEER_PMF, + .bw160 = WMI_PEER_160MHZ, }; static const struct wmi_peer_flags_map wmi_10x_peer_flags_map = { @@ -1591,6 +1593,7 @@ static const struct wmi_peer_flags_map wmi_10x_peer_flags_map = { .spatial_mux = WMI_10X_PEER_SPATIAL_MUX, .vht = WMI_10X_PEER_VHT, .bw80 = WMI_10X_PEER_80MHZ, + .bw160 = WMI_10X_PEER_160MHZ, }; static const struct wmi_peer_flags_map wmi_10_2_peer_flags_map = { @@ -1610,6 +1613,7 @@ static const struct wmi_peer_flags_map wmi_10_2_peer_flags_map = { .bw80 = WMI_10_2_PEER_80MHZ, .vht_2g = WMI_10_2_PEER_VHT_2G, .pmf = WMI_10_2_PEER_PMF, + .bw160 = WMI_10_2_PEER_160MHZ, }; void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch, @@ -1634,7 +1638,10 @@ void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch, ch->mhz = __cpu_to_le32(arg->freq); ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1); - ch->band_center_freq2 = 0; + if (arg->mode == MODE_11AC_VHT80_80) + ch->band_center_freq2 = __cpu_to_le32(arg->band_center_freq2); + else + ch->band_center_freq2 = 0; ch->min_power = arg->min_power; ch->max_power = arg->max_power; ch->reg_power = arg->max_reg_power; @@ -1772,7 +1779,7 @@ unlock: static void ath10k_wmi_tx_beacons_iter(void *data, u8 *mac, struct ieee80211_vif *vif) { - struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); + struct ath10k_vif *arvif = (void *)vif->drv_priv; ath10k_wmi_tx_beacon_nowait(arvif); } @@ -2319,7 +2326,7 @@ int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) */ if (channel >= 1 && channel <= 14) { status->band = NL80211_BAND_2GHZ; - } else if (channel >= 36 && channel <= 165) { + } else if (channel >= 36 && channel <= 169) { status->band = NL80211_BAND_5GHZ; } else { /* Shouldn't happen unless list of advertised channels to diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 5d3dff95b2e5..386aa51435f1 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -75,7 +75,7 @@ struct wmi_cmd_hdr { /* * There is no signed version of __le32, so for a temporary solution come - * up with our own version. The idea is from fs/ntfs/types.h. + * up with our own version. The idea is from fs/ntfs/endian.h. * * Use a_ prefix so that it doesn't conflict if we get proper support to * linux/types.h. @@ -1728,8 +1728,10 @@ enum wmi_phy_mode { MODE_11AC_VHT20_2G = 11, MODE_11AC_VHT40_2G = 12, MODE_11AC_VHT80_2G = 13, - MODE_UNKNOWN = 14, - MODE_MAX = 14 + MODE_11AC_VHT80_80 = 14, + MODE_11AC_VHT160 = 15, + MODE_UNKNOWN = 16, + MODE_MAX = 16 }; static inline const char *ath10k_wmi_phymode_str(enum wmi_phy_mode mode) @@ -1757,6 +1759,10 @@ static inline const char *ath10k_wmi_phymode_str(enum wmi_phy_mode mode) return "11ac-vht40"; case MODE_11AC_VHT80: return "11ac-vht80"; + case MODE_11AC_VHT160: + return "11ac-vht160"; + case MODE_11AC_VHT80_80: + return "11ac-vht80+80"; case MODE_11AC_VHT20_2G: return "11ac-vht20-2g"; case MODE_11AC_VHT40_2G: @@ -1811,6 +1817,7 @@ struct wmi_channel { struct wmi_channel_arg { u32 freq; u32 band_center_freq1; + u32 band_center_freq2; bool passive; bool allow_ibss; bool allow_ht; @@ -1875,9 +1882,18 @@ enum wmi_channel_change_cause { #define WMI_VHT_CAP_MAX_MPDU_LEN_MASK 0x00000003 #define WMI_VHT_CAP_RX_LDPC 0x00000010 #define WMI_VHT_CAP_SGI_80MHZ 0x00000020 +#define WMI_VHT_CAP_SGI_160MHZ 0x00000040 #define WMI_VHT_CAP_TX_STBC 0x00000080 #define WMI_VHT_CAP_RX_STBC_MASK 0x00000300 #define WMI_VHT_CAP_RX_STBC_MASK_SHIFT 8 +#define WMI_VHT_CAP_SU_BFER 0x00000800 +#define WMI_VHT_CAP_SU_BFEE 0x00001000 +#define WMI_VHT_CAP_MAX_CS_ANT_MASK 0x0000E000 +#define WMI_VHT_CAP_MAX_CS_ANT_MASK_SHIFT 13 +#define WMI_VHT_CAP_MAX_SND_DIM_MASK 0x00070000 +#define WMI_VHT_CAP_MAX_SND_DIM_MASK_SHIFT 16 +#define WMI_VHT_CAP_MU_BFER 0x00080000 +#define WMI_VHT_CAP_MU_BFEE 0x00100000 #define WMI_VHT_CAP_MAX_AMPDU_LEN_EXP 0x03800000 #define WMI_VHT_CAP_MAX_AMPDU_LEN_EXP_SHIFT 23 #define WMI_VHT_CAP_RX_FIXED_ANT 0x10000000 @@ -1926,6 +1942,8 @@ enum { REGDMN_MODE_11AC_VHT40PLUS = 0x40000, /* 5Ghz, VHT40 + channels */ REGDMN_MODE_11AC_VHT40MINUS = 0x80000, /* 5Ghz VHT40 - channels */ REGDMN_MODE_11AC_VHT80 = 0x100000, /* 5Ghz, VHT80 channels */ + REGDMN_MODE_11AC_VHT160 = 0x200000, /* 5Ghz, VHT160 channels */ + REGDMN_MODE_11AC_VHT80_80 = 0x400000, /* 5Ghz, VHT80+80 channels */ REGDMN_MODE_ALL = 0xffffffff }; @@ -5783,6 +5801,7 @@ enum wmi_peer_chwidth { WMI_PEER_CHWIDTH_20MHZ = 0, WMI_PEER_CHWIDTH_40MHZ = 1, WMI_PEER_CHWIDTH_80MHZ = 2, + WMI_PEER_CHWIDTH_160MHZ = 3, }; enum wmi_peer_param { @@ -5792,6 +5811,7 @@ enum wmi_peer_param { WMI_PEER_CHAN_WIDTH = 0x4, WMI_PEER_NSS = 0x5, WMI_PEER_USE_4ADDR = 0x6, + WMI_PEER_DEBUG = 0xa, WMI_PEER_DUMMY_VAR = 0xff, /* dummy parameter for STA PS workaround */ }; @@ -5873,6 +5893,7 @@ struct wmi_peer_flags_map { u32 bw80; u32 vht_2g; u32 pmf; + u32 bw160; }; enum wmi_peer_flags { @@ -5892,6 +5913,7 @@ enum wmi_peer_flags { WMI_PEER_80MHZ = 0x04000000, WMI_PEER_VHT_2G = 0x08000000, WMI_PEER_PMF = 0x10000000, + WMI_PEER_160MHZ = 0x20000000 }; enum wmi_10x_peer_flags { @@ -5909,6 +5931,7 @@ enum wmi_10x_peer_flags { WMI_10X_PEER_SPATIAL_MUX = 0x00200000, WMI_10X_PEER_VHT = 0x02000000, WMI_10X_PEER_80MHZ = 0x04000000, + WMI_10X_PEER_160MHZ = 0x20000000 }; enum wmi_10_2_peer_flags { @@ -5928,6 +5951,7 @@ enum wmi_10_2_peer_flags { WMI_10_2_PEER_80MHZ = 0x04000000, WMI_10_2_PEER_VHT_2G = 0x08000000, WMI_10_2_PEER_PMF = 0x10000000, + WMI_10_2_PEER_160MHZ = 0x20000000 }; /* @@ -6581,7 +6605,7 @@ 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_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); -void ath10k_wmi_start_scan_init(struct ath10k *ar, struct wmi_start_scan_arg *); +void ath10k_wmi_start_scan_init(struct ath10k *ar, struct wmi_start_scan_arg *arg); void ath10k_wmi_pull_pdev_stats_base(const struct wmi_pdev_stats_base *src, struct ath10k_fw_stats_pdev *dst); diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c index 2ca88b593e4c..c0794f5988b3 100644 --- a/drivers/net/wireless/ath/ath5k/ahb.c +++ b/drivers/net/wireless/ath/ath5k/ahb.c @@ -16,10 +16,10 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include <linux/module.h> #include <linux/nl80211.h> #include <linux/platform_device.h> #include <linux/etherdevice.h> -#include <linux/export.h> #include <ath25_platform.h> #include "ath5k.h" #include "debug.h" diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index dc44cfef7517..16e052d02c94 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -502,8 +502,7 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, break; return -EOPNOTSUPP; default: - WARN_ON(1); - return -EINVAL; + return -EOPNOTSUPP; } mutex_lock(&ah->lock); diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index ac25f1781b42..87e99c12d4ba 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h @@ -641,7 +641,6 @@ struct ath6kl_vif { u32 txe_intvl; u16 bg_scan_period; u8 assoc_bss_dtim_period; - struct net_device_stats net_stats; struct target_stats target_stats; struct wmi_connect_cmd profile; u16 rsn_capab; diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 1af3fed5a72c..91ee542de3d7 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c @@ -1113,13 +1113,6 @@ static int ath6kl_close(struct net_device *dev) return 0; } -static struct net_device_stats *ath6kl_get_stats(struct net_device *dev) -{ - struct ath6kl_vif *vif = netdev_priv(dev); - - return &vif->net_stats; -} - static int ath6kl_set_features(struct net_device *dev, netdev_features_t features) { @@ -1285,7 +1278,6 @@ static const struct net_device_ops ath6kl_netdev_ops = { .ndo_open = ath6kl_open, .ndo_stop = ath6kl_close, .ndo_start_xmit = ath6kl_data_tx, - .ndo_get_stats = ath6kl_get_stats, .ndo_set_features = ath6kl_set_features, .ndo_set_rx_mode = ath6kl_set_multicast_list, }; diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 8ec66e74d06d..2195b1b7a8a6 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c @@ -713,7 +713,7 @@ static void ath6kl_sdio_cleanup_scatter(struct ath6kl *ar) * that the packet is properly freed? */ if (s_req->busrequest) { - s_req->busrequest->scat_req = 0; + s_req->busrequest->scat_req = NULL; ath6kl_sdio_free_bus_req(ar_sdio, s_req->busrequest); } kfree(s_req->virt_dma_buf); diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 9df41d5e3249..a531e0c5c1e2 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c @@ -405,7 +405,7 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) skb = skb_realloc_headroom(skb, dev->needed_headroom); kfree_skb(tmp_skb); if (skb == NULL) { - vif->net_stats.tx_dropped++; + dev->stats.tx_dropped++; return 0; } } @@ -520,8 +520,8 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) fail_tx: dev_kfree_skb(skb); - vif->net_stats.tx_dropped++; - vif->net_stats.tx_aborted_errors++; + dev->stats.tx_dropped++; + dev->stats.tx_aborted_errors++; return 0; } @@ -767,7 +767,7 @@ void ath6kl_tx_complete(struct htc_target *target, /* a packet was flushed */ flushing[if_idx] = true; - vif->net_stats.tx_errors++; + vif->ndev->stats.tx_errors++; if (status != -ENOSPC && status != -ECANCELED) ath6kl_warn("tx complete error: %d\n", status); @@ -783,8 +783,8 @@ void ath6kl_tx_complete(struct htc_target *target, eid, "OK"); flushing[if_idx] = false; - vif->net_stats.tx_packets++; - vif->net_stats.tx_bytes += skb->len; + vif->ndev->stats.tx_packets++; + vif->ndev->stats.tx_bytes += skb->len; } ath6kl_tx_clear_node_map(vif, eid, map_no); @@ -1365,8 +1365,8 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) */ spin_lock_bh(&vif->if_lock); - vif->net_stats.rx_packets++; - vif->net_stats.rx_bytes += packet->act_len; + vif->ndev->stats.rx_packets++; + vif->ndev->stats.rx_bytes += packet->act_len; spin_unlock_bh(&vif->if_lock); @@ -1395,8 +1395,8 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) ((packet->act_len < min_hdr_len) || (packet->act_len > WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH))) { ath6kl_info("frame len is too short or too long\n"); - vif->net_stats.rx_errors++; - vif->net_stats.rx_length_errors++; + vif->ndev->stats.rx_errors++; + vif->ndev->stats.rx_length_errors++; dev_kfree_skb(skb); return; } @@ -1619,7 +1619,7 @@ void ath6kl_rx(struct htc_target *target, struct htc_packet *packet) return; } } else if (!is_broadcast_ether_addr(datap->h_dest)) { - vif->net_stats.multicast++; + vif->ndev->stats.multicast++; } ath6kl_deliver_frames_to_nw_stack(vif->ndev, skb); diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 8f231c67dd51..783a38f1a626 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -3,8 +3,8 @@ config ATH9K_HW config ATH9K_COMMON tristate select ATH_COMMON - select DEBUG_FS - select RELAY +config ATH9K_COMMON_DEBUG + bool config ATH9K_DFS_DEBUGFS def_bool y depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED @@ -60,12 +60,14 @@ config ATH9K_DEBUGFS bool "Atheros ath9k debugging" depends on ATH9K && DEBUG_FS select MAC80211_DEBUGFS + select ATH9K_COMMON_DEBUG select RELAY ---help--- Say Y, if you need access to ath9k's statistics for interrupts, rate control, etc. Also required for changing debug message flags at run time. + As well as access to the FFT/spectral data and TX99. config ATH9K_STATION_STATISTICS bool "Detailed station statistics" @@ -174,8 +176,11 @@ config ATH9K_HTC config ATH9K_HTC_DEBUGFS bool "Atheros ath9k_htc debugging" depends on ATH9K_HTC && DEBUG_FS + select ATH9K_COMMON_DEBUG + select RELAY ---help--- Say Y, if you need access to ath9k_htc's statistics. + As well as access to the FFT/spectral data. config ATH9K_HWRNG bool "Random number generator support" diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 76f9dc37500b..36a40ffdce15 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -60,8 +60,9 @@ obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o ath9k_common-y:= common.o \ common-init.o \ common-beacon.o \ - common-debug.o \ - common-spectral.o + +ath9k_common-$(CONFIG_ATH9K_COMMON_DEBUG) += common-debug.o \ + common-spectral.o ath9k_htc-y += htc_hst.o \ hif_usb.o \ diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index f816909d9474..4b3c9b108197 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -220,8 +220,8 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) ads->ds_txstatus6 = ads->ds_txstatus7 = 0; ads->ds_txstatus8 = ads->ds_txstatus9 = 0; - ACCESS_ONCE(ads->ds_link) = i->link; - ACCESS_ONCE(ads->ds_data) = i->buf_addr[0]; + WRITE_ONCE(ads->ds_link, i->link); + WRITE_ONCE(ads->ds_data, i->buf_addr[0]); ctl1 = i->buf_len[0] | (i->is_last ? 0 : AR_TxMore); ctl6 = SM(i->keytype, AR_EncrType); @@ -235,26 +235,26 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) if ((i->is_first || i->is_last) && i->aggr != AGGR_BUF_MIDDLE && i->aggr != AGGR_BUF_LAST) { - ACCESS_ONCE(ads->ds_ctl2) = set11nTries(i->rates, 0) + WRITE_ONCE(ads->ds_ctl2, set11nTries(i->rates, 0) | set11nTries(i->rates, 1) | set11nTries(i->rates, 2) | set11nTries(i->rates, 3) | (i->dur_update ? AR_DurUpdateEna : 0) - | SM(0, AR_BurstDur); + | SM(0, AR_BurstDur)); - ACCESS_ONCE(ads->ds_ctl3) = set11nRate(i->rates, 0) + WRITE_ONCE(ads->ds_ctl3, set11nRate(i->rates, 0) | set11nRate(i->rates, 1) | set11nRate(i->rates, 2) - | set11nRate(i->rates, 3); + | set11nRate(i->rates, 3)); } else { - ACCESS_ONCE(ads->ds_ctl2) = 0; - ACCESS_ONCE(ads->ds_ctl3) = 0; + WRITE_ONCE(ads->ds_ctl2, 0); + WRITE_ONCE(ads->ds_ctl3, 0); } if (!i->is_first) { - ACCESS_ONCE(ads->ds_ctl0) = 0; - ACCESS_ONCE(ads->ds_ctl1) = ctl1; - ACCESS_ONCE(ads->ds_ctl6) = ctl6; + WRITE_ONCE(ads->ds_ctl0, 0); + WRITE_ONCE(ads->ds_ctl1, ctl1); + WRITE_ONCE(ads->ds_ctl6, ctl6); return; } @@ -279,7 +279,7 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) break; } - ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen) + WRITE_ONCE(ads->ds_ctl0, (i->pkt_len & AR_FrameLen) | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | SM(i->txpower[0], AR_XmitPower0) | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) @@ -287,29 +287,29 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable : - (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0)); + (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0))); - ACCESS_ONCE(ads->ds_ctl1) = ctl1; - ACCESS_ONCE(ads->ds_ctl6) = ctl6; + WRITE_ONCE(ads->ds_ctl1, ctl1); + WRITE_ONCE(ads->ds_ctl6, ctl6); if (i->aggr == AGGR_BUF_MIDDLE || i->aggr == AGGR_BUF_LAST) return; - ACCESS_ONCE(ads->ds_ctl4) = set11nPktDurRTSCTS(i->rates, 0) - | set11nPktDurRTSCTS(i->rates, 1); + WRITE_ONCE(ads->ds_ctl4, set11nPktDurRTSCTS(i->rates, 0) + | set11nPktDurRTSCTS(i->rates, 1)); - ACCESS_ONCE(ads->ds_ctl5) = set11nPktDurRTSCTS(i->rates, 2) - | set11nPktDurRTSCTS(i->rates, 3); + WRITE_ONCE(ads->ds_ctl5, set11nPktDurRTSCTS(i->rates, 2) + | set11nPktDurRTSCTS(i->rates, 3)); - ACCESS_ONCE(ads->ds_ctl7) = set11nRateFlags(i->rates, 0) + WRITE_ONCE(ads->ds_ctl7, set11nRateFlags(i->rates, 0) | set11nRateFlags(i->rates, 1) | set11nRateFlags(i->rates, 2) | set11nRateFlags(i->rates, 3) - | SM(i->rtscts_rate, AR_RTSCTSRate); + | SM(i->rtscts_rate, AR_RTSCTSRate)); - ACCESS_ONCE(ads->ds_ctl9) = SM(i->txpower[1], AR_XmitPower1); - ACCESS_ONCE(ads->ds_ctl10) = SM(i->txpower[2], AR_XmitPower2); - ACCESS_ONCE(ads->ds_ctl11) = SM(i->txpower[3], AR_XmitPower3); + WRITE_ONCE(ads->ds_ctl9, SM(i->txpower[1], AR_XmitPower1)); + WRITE_ONCE(ads->ds_ctl10, SM(i->txpower[2], AR_XmitPower2)); + WRITE_ONCE(ads->ds_ctl11, SM(i->txpower[3], AR_XmitPower3)); } static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, @@ -318,7 +318,7 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, struct ar5416_desc *ads = AR5416DESC(ds); u32 status; - status = ACCESS_ONCE(ads->ds_txstatus9); + status = READ_ONCE(ads->ds_txstatus9); if ((status & AR_TxDone) == 0) return -EINPROGRESS; @@ -332,7 +332,7 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, ts->ts_rateindex = MS(status, AR_FinalTxIdx); ts->ts_seqnum = MS(status, AR_SeqNum); - status = ACCESS_ONCE(ads->ds_txstatus0); + status = READ_ONCE(ads->ds_txstatus0); ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00); ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01); ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02); @@ -342,7 +342,7 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, ts->ba_high = ads->AR_BaBitmapHigh; } - status = ACCESS_ONCE(ads->ds_txstatus1); + status = READ_ONCE(ads->ds_txstatus1); if (status & AR_FrmXmitOK) ts->ts_status |= ATH9K_TX_ACKED; else { @@ -371,7 +371,7 @@ static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds, ts->ts_longretry = MS(status, AR_DataFailCnt); ts->ts_virtcol = MS(status, AR_VirtRetryCnt); - status = ACCESS_ONCE(ads->ds_txstatus5); + status = READ_ONCE(ads->ds_txstatus5); ts->ts_rssi = MS(status, AR_TxRSSICombined); ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10); ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); @@ -390,13 +390,13 @@ static int ar9002_hw_get_duration(struct ath_hw *ah, const void *ds, int index) switch (index) { case 0: - return MS(ACCESS_ONCE(ads->ds_ctl4), AR_PacketDur0); + return MS(READ_ONCE(ads->ds_ctl4), AR_PacketDur0); case 1: - return MS(ACCESS_ONCE(ads->ds_ctl4), AR_PacketDur1); + return MS(READ_ONCE(ads->ds_ctl4), AR_PacketDur1); case 2: - return MS(ACCESS_ONCE(ads->ds_ctl5), AR_PacketDur2); + return MS(READ_ONCE(ads->ds_ctl5), AR_PacketDur2); case 3: - return MS(ACCESS_ONCE(ads->ds_ctl5), AR_PacketDur3); + return MS(READ_ONCE(ads->ds_ctl5), AR_PacketDur3); default: return -1; } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index 7dc7205dc877..bd2269c7de6b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -75,13 +75,13 @@ #define AR9300_OTP_BASE \ ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30000 : 0x14000) #define AR9300_OTP_STATUS \ - ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x30018 : 0x15f18) + ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x31018 : 0x15f18) #define AR9300_OTP_STATUS_TYPE 0x7 #define AR9300_OTP_STATUS_VALID 0x4 #define AR9300_OTP_STATUS_ACCESS_BUSY 0x2 #define AR9300_OTP_STATUS_SM_BUSY 0x1 #define AR9300_OTP_READ_DATA \ - ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x3001c : 0x15f1c) + ((AR_SREV_9340(ah) || AR_SREV_9550(ah)) ? 0x3101c : 0x15f1c) enum targetPowerHTRates { HT_TARGET_RATE_0_8_16, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index da84b705cbcd..cc5bb0a76baf 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -39,47 +39,47 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) (i->qcu << AR_TxQcuNum_S) | desc_len; checksum += val; - ACCESS_ONCE(ads->info) = val; + WRITE_ONCE(ads->info, val); checksum += i->link; - ACCESS_ONCE(ads->link) = i->link; + WRITE_ONCE(ads->link, i->link); checksum += i->buf_addr[0]; - ACCESS_ONCE(ads->data0) = i->buf_addr[0]; + WRITE_ONCE(ads->data0, i->buf_addr[0]); checksum += i->buf_addr[1]; - ACCESS_ONCE(ads->data1) = i->buf_addr[1]; + WRITE_ONCE(ads->data1, i->buf_addr[1]); checksum += i->buf_addr[2]; - ACCESS_ONCE(ads->data2) = i->buf_addr[2]; + WRITE_ONCE(ads->data2, i->buf_addr[2]); checksum += i->buf_addr[3]; - ACCESS_ONCE(ads->data3) = i->buf_addr[3]; + WRITE_ONCE(ads->data3, i->buf_addr[3]); checksum += (val = (i->buf_len[0] << AR_BufLen_S) & AR_BufLen); - ACCESS_ONCE(ads->ctl3) = val; + WRITE_ONCE(ads->ctl3, val); checksum += (val = (i->buf_len[1] << AR_BufLen_S) & AR_BufLen); - ACCESS_ONCE(ads->ctl5) = val; + WRITE_ONCE(ads->ctl5, val); checksum += (val = (i->buf_len[2] << AR_BufLen_S) & AR_BufLen); - ACCESS_ONCE(ads->ctl7) = val; + WRITE_ONCE(ads->ctl7, val); checksum += (val = (i->buf_len[3] << AR_BufLen_S) & AR_BufLen); - ACCESS_ONCE(ads->ctl9) = val; + WRITE_ONCE(ads->ctl9, val); checksum = (u16) (((checksum & 0xffff) + (checksum >> 16)) & 0xffff); - ACCESS_ONCE(ads->ctl10) = checksum; + WRITE_ONCE(ads->ctl10, checksum); if (i->is_first || i->is_last) { - ACCESS_ONCE(ads->ctl13) = set11nTries(i->rates, 0) + WRITE_ONCE(ads->ctl13, set11nTries(i->rates, 0) | set11nTries(i->rates, 1) | set11nTries(i->rates, 2) | set11nTries(i->rates, 3) | (i->dur_update ? AR_DurUpdateEna : 0) - | SM(0, AR_BurstDur); + | SM(0, AR_BurstDur)); - ACCESS_ONCE(ads->ctl14) = set11nRate(i->rates, 0) + WRITE_ONCE(ads->ctl14, set11nRate(i->rates, 0) | set11nRate(i->rates, 1) | set11nRate(i->rates, 2) - | set11nRate(i->rates, 3); + | set11nRate(i->rates, 3)); } else { - ACCESS_ONCE(ads->ctl13) = 0; - ACCESS_ONCE(ads->ctl14) = 0; + WRITE_ONCE(ads->ctl13, 0); + WRITE_ONCE(ads->ctl14, 0); } ads->ctl20 = 0; @@ -89,17 +89,17 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) ctl17 = SM(i->keytype, AR_EncrType); if (!i->is_first) { - ACCESS_ONCE(ads->ctl11) = 0; - ACCESS_ONCE(ads->ctl12) = i->is_last ? 0 : AR_TxMore; - ACCESS_ONCE(ads->ctl15) = 0; - ACCESS_ONCE(ads->ctl16) = 0; - ACCESS_ONCE(ads->ctl17) = ctl17; - ACCESS_ONCE(ads->ctl18) = 0; - ACCESS_ONCE(ads->ctl19) = 0; + WRITE_ONCE(ads->ctl11, 0); + WRITE_ONCE(ads->ctl12, i->is_last ? 0 : AR_TxMore); + WRITE_ONCE(ads->ctl15, 0); + WRITE_ONCE(ads->ctl16, 0); + WRITE_ONCE(ads->ctl17, ctl17); + WRITE_ONCE(ads->ctl18, 0); + WRITE_ONCE(ads->ctl19, 0); return; } - ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen) + WRITE_ONCE(ads->ctl11, (i->pkt_len & AR_FrameLen) | (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | SM(i->txpower[0], AR_XmitPower0) | (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) @@ -107,7 +107,7 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) | (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0) | (i->flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) | (i->flags & ATH9K_TXDESC_RTSENA ? AR_RTSEnable : - (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0)); + (i->flags & ATH9K_TXDESC_CTSENA ? AR_CTSEnable : 0))); ctl12 = (i->keyix != ATH9K_TXKEYIX_INVALID ? SM(i->keyix, AR_DestIdx) : 0) @@ -135,26 +135,26 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) val = (i->flags & ATH9K_TXDESC_PAPRD) >> ATH9K_TXDESC_PAPRD_S; ctl12 |= SM(val, AR_PAPRDChainMask); - ACCESS_ONCE(ads->ctl12) = ctl12; - ACCESS_ONCE(ads->ctl17) = ctl17; + WRITE_ONCE(ads->ctl12, ctl12); + WRITE_ONCE(ads->ctl17, ctl17); - ACCESS_ONCE(ads->ctl15) = set11nPktDurRTSCTS(i->rates, 0) - | set11nPktDurRTSCTS(i->rates, 1); + WRITE_ONCE(ads->ctl15, set11nPktDurRTSCTS(i->rates, 0) + | set11nPktDurRTSCTS(i->rates, 1)); - ACCESS_ONCE(ads->ctl16) = set11nPktDurRTSCTS(i->rates, 2) - | set11nPktDurRTSCTS(i->rates, 3); + WRITE_ONCE(ads->ctl16, set11nPktDurRTSCTS(i->rates, 2) + | set11nPktDurRTSCTS(i->rates, 3)); - ACCESS_ONCE(ads->ctl18) = set11nRateFlags(i->rates, 0) + WRITE_ONCE(ads->ctl18, set11nRateFlags(i->rates, 0) | set11nRateFlags(i->rates, 1) | set11nRateFlags(i->rates, 2) | set11nRateFlags(i->rates, 3) - | SM(i->rtscts_rate, AR_RTSCTSRate); + | SM(i->rtscts_rate, AR_RTSCTSRate)); - ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding; + WRITE_ONCE(ads->ctl19, AR_Not_Sounding); - ACCESS_ONCE(ads->ctl20) = SM(i->txpower[1], AR_XmitPower1); - ACCESS_ONCE(ads->ctl21) = SM(i->txpower[2], AR_XmitPower2); - ACCESS_ONCE(ads->ctl22) = SM(i->txpower[3], AR_XmitPower3); + WRITE_ONCE(ads->ctl20, SM(i->txpower[1], AR_XmitPower1)); + WRITE_ONCE(ads->ctl21, SM(i->txpower[2], AR_XmitPower2)); + WRITE_ONCE(ads->ctl22, SM(i->txpower[3], AR_XmitPower3)); } static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads) @@ -359,7 +359,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, ads = &ah->ts_ring[ah->ts_tail]; - status = ACCESS_ONCE(ads->status8); + status = READ_ONCE(ads->status8); if ((status & AR_TxDone) == 0) return -EINPROGRESS; @@ -385,7 +385,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, if (status & AR_TxOpExceeded) ts->ts_status |= ATH9K_TXERR_XTXOP; - status = ACCESS_ONCE(ads->status2); + status = READ_ONCE(ads->status2); ts->ts_rssi_ctl0 = MS(status, AR_TxRSSIAnt00); ts->ts_rssi_ctl1 = MS(status, AR_TxRSSIAnt01); ts->ts_rssi_ctl2 = MS(status, AR_TxRSSIAnt02); @@ -395,7 +395,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, ts->ba_high = ads->status6; } - status = ACCESS_ONCE(ads->status3); + status = READ_ONCE(ads->status3); if (status & AR_ExcessiveRetries) ts->ts_status |= ATH9K_TXERR_XRETRY; if (status & AR_Filtered) @@ -420,7 +420,7 @@ static int ar9003_hw_proc_txdesc(struct ath_hw *ah, void *ds, ts->ts_longretry = MS(status, AR_DataFailCnt); ts->ts_virtcol = MS(status, AR_VirtRetryCnt); - status = ACCESS_ONCE(ads->status7); + status = READ_ONCE(ads->status7); ts->ts_rssi = MS(status, AR_TxRSSICombined); ts->ts_rssi_ext0 = MS(status, AR_TxRSSIAnt10); ts->ts_rssi_ext1 = MS(status, AR_TxRSSIAnt11); @@ -437,13 +437,13 @@ static int ar9003_hw_get_duration(struct ath_hw *ah, const void *ds, int index) switch (index) { case 0: - return MS(ACCESS_ONCE(adc->ctl15), AR_PacketDur0); + return MS(READ_ONCE(adc->ctl15), AR_PacketDur0); case 1: - return MS(ACCESS_ONCE(adc->ctl15), AR_PacketDur1); + return MS(READ_ONCE(adc->ctl15), AR_PacketDur1); case 2: - return MS(ACCESS_ONCE(adc->ctl16), AR_PacketDur2); + return MS(READ_ONCE(adc->ctl16), AR_PacketDur2); case 3: - return MS(ACCESS_ONCE(adc->ctl16), AR_PacketDur3); + return MS(READ_ONCE(adc->ctl16), AR_PacketDur3); default: return 0; } diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 331947b6a667..cf076719c27e 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -108,7 +108,7 @@ int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, #define ATH_AGGR_MIN_QDEPTH 2 /* minimum h/w qdepth for non-aggregated traffic */ #define ATH_NON_AGGR_MIN_QDEPTH 8 -#define ATH_TX_COMPLETE_POLL_INT 1000 +#define ATH_HW_CHECK_POLL_INT 1000 #define ATH_TXFIFO_DEPTH 8 #define ATH_TX_ERROR 0x01 @@ -745,7 +745,7 @@ void ath9k_csa_update(struct ath_softc *sc); #define ATH_PAPRD_TIMEOUT 100 /* msecs */ #define ATH_PLL_WORK_INTERVAL 100 -void ath_tx_complete_poll_work(struct work_struct *work); +void ath_hw_check_work(struct work_struct *work); void ath_reset_work(struct work_struct *work); bool ath_hw_check(struct ath_softc *sc); void ath_hw_pll_work(struct work_struct *work); @@ -998,6 +998,7 @@ struct ath_softc { struct survey_info *cur_survey; struct survey_info survey[ATH9K_NUM_CHANNELS]; + spinlock_t intr_lock; struct tasklet_struct intr_tq; struct tasklet_struct bcon_tasklet; struct ath_hw *sc_ah; @@ -1053,7 +1054,7 @@ struct ath_softc { #ifdef CONFIG_ATH9K_DEBUGFS struct ath9k_debug debug; #endif - struct delayed_work tx_complete_work; + struct delayed_work hw_check_work; struct delayed_work hw_pll_work; struct timer_list sleep_timer; diff --git a/drivers/net/wireless/ath/ath9k/common-debug.h b/drivers/net/wireless/ath/ath9k/common-debug.h index 7c9788490f7f..3376990d3a24 100644 --- a/drivers/net/wireless/ath/ath9k/common-debug.h +++ b/drivers/net/wireless/ath/ath9k/common-debug.h @@ -60,6 +60,7 @@ struct ath_rx_stats { u32 rx_spectral; }; +#ifdef CONFIG_ATH9K_COMMON_DEBUG void ath9k_cmn_debug_modal_eeprom(struct dentry *debugfs_phy, struct ath_hw *ah); void ath9k_cmn_debug_base_eeprom(struct dentry *debugfs_phy, @@ -70,3 +71,29 @@ void ath9k_cmn_debug_recv(struct dentry *debugfs_phy, struct ath_rx_stats *rxstats); void ath9k_cmn_debug_phy_err(struct dentry *debugfs_phy, struct ath_rx_stats *rxstats); +#else +static inline void ath9k_cmn_debug_modal_eeprom(struct dentry *debugfs_phy, + struct ath_hw *ah) +{ +} + +static inline void ath9k_cmn_debug_base_eeprom(struct dentry *debugfs_phy, + struct ath_hw *ah) +{ +} + +static inline void ath9k_cmn_debug_stat_rx(struct ath_rx_stats *rxstats, + struct ath_rx_status *rs) +{ +} + +static inline void ath9k_cmn_debug_recv(struct dentry *debugfs_phy, + struct ath_rx_stats *rxstats) +{ +} + +static inline void ath9k_cmn_debug_phy_err(struct dentry *debugfs_phy, + struct ath_rx_stats *rxstats) +{ +} +#endif /* CONFIG_ATH9K_COMMON_DEBUG */ diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c index eedf86b67cf5..0ffa23a61568 100644 --- a/drivers/net/wireless/ath/ath9k/common-spectral.c +++ b/drivers/net/wireless/ath/ath9k/common-spectral.c @@ -482,7 +482,7 @@ ath_cmn_is_fft_buf_full(struct ath_spec_scan_priv *spec_priv) struct rchan *rc = spec_priv->rfs_chan_spec_scan; for_each_online_cpu(i) - ret += relay_buf_full(rc->buf[i]); + ret += relay_buf_full(*per_cpu_ptr(rc->buf, i)); i = num_online_cpus(); @@ -1075,7 +1075,7 @@ static struct rchan_callbacks rfs_spec_scan_cb = { void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) { - if (IS_ENABLED(CONFIG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) { + if (spec_priv->rfs_chan_spec_scan) { relay_close(spec_priv->rfs_chan_spec_scan); spec_priv->rfs_chan_spec_scan = NULL; } diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.h b/drivers/net/wireless/ath/ath9k/common-spectral.h index 998743be9c67..5d1a51d83aa6 100644 --- a/drivers/net/wireless/ath/ath9k/common-spectral.h +++ b/drivers/net/wireless/ath/ath9k/common-spectral.h @@ -151,6 +151,7 @@ static inline u8 spectral_bitmap_weight(u8 *bins) return bins[0] & 0x3f; } +#ifdef CONFIG_ATH9K_COMMON_DEBUG void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy); void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv); @@ -161,5 +162,27 @@ int ath9k_cmn_spectral_scan_config(struct ath_common *common, enum spectral_mode spectral_mode); int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr, struct ath_rx_status *rs, u64 tsf); +#else +static inline void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, + struct dentry *debugfs_phy) +{ +} + +static inline void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) +{ +} + +static inline void ath9k_cmn_spectral_scan_trigger(struct ath_common *common, + struct ath_spec_scan_priv *spec_priv) +{ +} + +static inline int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, + struct ieee80211_hdr *hdr, + struct ath_rx_status *rs, u64 tsf) +{ + return 0; +} +#endif /* CONFIG_ATH9K_COMMON_DEBUG */ #endif /* SPECTRAL_H */ diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 4a01ebe53053..b8c0a08066a0 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c @@ -72,7 +72,7 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) return __ath9k_hw_4k_fill_eeprom(ah); } -#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS) +#ifdef CONFIG_ATH9K_COMMON_DEBUG static u32 ath9k_dump_4k_modal_eeprom(char *buf, u32 len, u32 size, struct modal_eep_4k_header *modal_hdr) { diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 9611f020f7c0..3caa149b1013 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c @@ -75,7 +75,7 @@ static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah) return __ath9k_hw_ar9287_fill_eeprom(ah); } -#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS) +#ifdef CONFIG_ATH9K_COMMON_DEBUG static u32 ar9287_dump_modal_eeprom(char *buf, u32 len, u32 size, struct modal_eep_ar9287_header *modal_hdr) { diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 7d5223451ce9..56b44fc7a8e6 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c @@ -131,7 +131,7 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) return __ath9k_hw_def_fill_eeprom(ah); } -#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS) +#ifdef CONFIG_ATH9K_COMMON_DEBUG static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size, struct modal_eep_header *modal_hdr) { diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index a35f78be8dec..8c5c2dd8fa7f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -731,7 +731,7 @@ u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) udelay(100); if (WARN_ON_ONCE(i >= 100)) { - ath_err(common, "PLL4 meaurement not done\n"); + ath_err(common, "PLL4 measurement not done\n"); break; } @@ -1603,6 +1603,10 @@ bool ath9k_hw_check_alive(struct ath_hw *ah) int count = 50; u32 reg, last_val; + /* Check if chip failed to wake up */ + if (REG_READ(ah, AR_CFG) == 0xdeadbeef) + return false; + if (AR_SREV_9300(ah)) return !ath9k_hw_detect_mac_hang(ah); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 084ad1bd495f..fa4b3cc1ba22 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -669,6 +669,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, common->bt_ant_diversity = 1; spin_lock_init(&common->cc_lock); + spin_lock_init(&sc->intr_lock); spin_lock_init(&sc->sc_serial_rw); spin_lock_init(&sc->sc_pm_lock); spin_lock_init(&sc->chan_lock); @@ -681,6 +682,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, INIT_WORK(&sc->hw_reset_work, ath_reset_work); INIT_WORK(&sc->paprd_work, ath_paprd_calibrate); INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work); + INIT_DELAYED_WORK(&sc->hw_check_work, ath_hw_check_work); ath9k_init_channel_context(sc); diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index 5ad0feeebc86..27c50562dc47 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c @@ -20,20 +20,13 @@ * TX polling - checks if the TX engine is stuck somewhere * and issues a chip reset if so. */ -void ath_tx_complete_poll_work(struct work_struct *work) +static bool ath_tx_complete_check(struct ath_softc *sc) { - struct ath_softc *sc = container_of(work, struct ath_softc, - tx_complete_work.work); struct ath_txq *txq; int i; - bool needreset = false; - - if (sc->tx99_state) { - ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, - "skip tx hung detection on tx99\n"); - return; - } + if (sc->tx99_state) + return true; for (i = 0; i < IEEE80211_NUM_ACS; i++) { txq = sc->tx.txq_map[i]; @@ -41,25 +34,36 @@ void ath_tx_complete_poll_work(struct work_struct *work) ath_txq_lock(sc, txq); if (txq->axq_depth) { if (txq->axq_tx_inprogress) { - needreset = true; ath_txq_unlock(sc, txq); - break; - } else { - txq->axq_tx_inprogress = true; + goto reset; } + + txq->axq_tx_inprogress = true; } ath_txq_unlock(sc, txq); } - if (needreset) { - ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, - "tx hung, resetting the chip\n"); - ath9k_queue_reset(sc, RESET_TYPE_TX_HANG); + return true; + +reset: + ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, + "tx hung, resetting the chip\n"); + ath9k_queue_reset(sc, RESET_TYPE_TX_HANG); + return false; + +} + +void ath_hw_check_work(struct work_struct *work) +{ + struct ath_softc *sc = container_of(work, struct ath_softc, + hw_check_work.work); + + if (!ath_hw_check(sc) || + !ath_tx_complete_check(sc)) return; - } - ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, - msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT)); + ieee80211_queue_delayed_work(sc->hw, &sc->hw_check_work, + msecs_to_jiffies(ATH_HW_CHECK_POLL_INT)); } /* diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index bba85d1a6cd1..d937c39b3a0b 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -805,21 +805,12 @@ void ath9k_hw_disable_interrupts(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_disable_interrupts); -void ath9k_hw_enable_interrupts(struct ath_hw *ah) +static void __ath9k_hw_enable_interrupts(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); u32 sync_default = AR_INTR_SYNC_DEFAULT; u32 async_mask; - if (!(ah->imask & ATH9K_INT_GLOBAL)) - return; - - if (!atomic_inc_and_test(&ah->intr_ref_cnt)) { - ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n", - atomic_read(&ah->intr_ref_cnt)); - return; - } - if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) || AR_SREV_9561(ah)) sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; @@ -841,6 +832,39 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah) ath_dbg(common, INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); } + +void ath9k_hw_resume_interrupts(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + + if (!(ah->imask & ATH9K_INT_GLOBAL)) + return; + + if (atomic_read(&ah->intr_ref_cnt) != 0) { + ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n", + atomic_read(&ah->intr_ref_cnt)); + return; + } + + __ath9k_hw_enable_interrupts(ah); +} +EXPORT_SYMBOL(ath9k_hw_resume_interrupts); + +void ath9k_hw_enable_interrupts(struct ath_hw *ah) +{ + struct ath_common *common = ath9k_hw_common(ah); + + if (!(ah->imask & ATH9K_INT_GLOBAL)) + return; + + if (!atomic_inc_and_test(&ah->intr_ref_cnt)) { + ath_dbg(common, INTERRUPT, "Do not enable IER ref count %d\n", + atomic_read(&ah->intr_ref_cnt)); + return; + } + + __ath9k_hw_enable_interrupts(ah); +} EXPORT_SYMBOL(ath9k_hw_enable_interrupts); void ath9k_hw_set_interrupts(struct ath_hw *ah) diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index 3bab01435a86..770fc11b41d1 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -744,6 +744,7 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah); void ath9k_hw_enable_interrupts(struct ath_hw *ah); void ath9k_hw_disable_interrupts(struct ath_hw *ah); void ath9k_hw_kill_interrupts(struct ath_hw *ah); +void ath9k_hw_resume_interrupts(struct ath_hw *ah); void ar9002_hw_attach_mac_ops(struct ath_hw *ah); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 58f06ce9a4cf..9e65d14e7b1e 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -181,7 +181,7 @@ void ath9k_ps_restore(struct ath_softc *sc) static void __ath_cancel_work(struct ath_softc *sc) { cancel_work_sync(&sc->paprd_work); - cancel_delayed_work_sync(&sc->tx_complete_work); + cancel_delayed_work_sync(&sc->hw_check_work); cancel_delayed_work_sync(&sc->hw_pll_work); #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT @@ -198,7 +198,8 @@ void ath_cancel_work(struct ath_softc *sc) void ath_restart_work(struct ath_softc *sc) { - ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); + ieee80211_queue_delayed_work(sc->hw, &sc->hw_check_work, + ATH_HW_CHECK_POLL_INT); if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9330(sc->sc_ah)) ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, @@ -373,21 +374,20 @@ void ath9k_tasklet(unsigned long data) struct ath_common *common = ath9k_hw_common(ah); enum ath_reset_type type; unsigned long flags; - u32 status = sc->intrstatus; + u32 status; u32 rxmask; + spin_lock_irqsave(&sc->intr_lock, flags); + status = sc->intrstatus; + sc->intrstatus = 0; + spin_unlock_irqrestore(&sc->intr_lock, flags); + ath9k_ps_wakeup(sc); spin_lock(&sc->sc_pcu_lock); if (status & ATH9K_INT_FATAL) { type = RESET_TYPE_FATAL_INT; ath9k_queue_reset(sc, type); - - /* - * Increment the ref. counter here so that - * interrupts are enabled in the reset routine. - */ - atomic_inc(&ah->intr_ref_cnt); ath_dbg(common, RESET, "FATAL: Skipping interrupts\n"); goto out; } @@ -403,11 +403,6 @@ void ath9k_tasklet(unsigned long data) type = RESET_TYPE_BB_WATCHDOG; ath9k_queue_reset(sc, type); - /* - * Increment the ref. counter here so that - * interrupts are enabled in the reset routine. - */ - atomic_inc(&ah->intr_ref_cnt); ath_dbg(common, RESET, "BB_WATCHDOG: Skipping interrupts\n"); goto out; @@ -420,7 +415,6 @@ void ath9k_tasklet(unsigned long data) if ((sc->gtt_cnt >= MAX_GTT_CNT) && !ath9k_hw_check_alive(ah)) { type = RESET_TYPE_TX_GTT; ath9k_queue_reset(sc, type); - atomic_inc(&ah->intr_ref_cnt); ath_dbg(common, RESET, "GTT: Skipping interrupts\n"); goto out; @@ -477,7 +471,7 @@ void ath9k_tasklet(unsigned long data) ath9k_btcoex_handle_interrupt(sc, status); /* re-enable hardware interrupt */ - ath9k_hw_enable_interrupts(ah); + ath9k_hw_resume_interrupts(ah); out: spin_unlock(&sc->sc_pcu_lock); ath9k_ps_restore(sc); @@ -541,7 +535,9 @@ irqreturn_t ath_isr(int irq, void *dev) return IRQ_NONE; /* Cache the status */ - sc->intrstatus = status; + spin_lock(&sc->intr_lock); + sc->intrstatus |= status; + spin_unlock(&sc->intr_lock); if (status & SCHED_INTR) sched = true; @@ -587,7 +583,7 @@ chip_reset: if (sched) { /* turn off every interrupt */ - ath9k_hw_disable_interrupts(ah); + ath9k_hw_kill_interrupts(ah); tasklet_schedule(&sc->intr_tq); } @@ -2091,7 +2087,7 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop, int timeout; bool drain_txq; - cancel_delayed_work_sync(&sc->tx_complete_work); + cancel_delayed_work_sync(&sc->hw_check_work); if (ah->ah_flags & AH_UNPLUGGED) { ath_dbg(common, ANY, "Device has been unplugged!\n"); @@ -2129,7 +2125,8 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop, ath9k_ps_restore(sc); } - ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0); + ieee80211_queue_delayed_work(hw, &sc->hw_check_work, + ATH_HW_CHECK_POLL_INT); } static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index c35a192861ab..396bf05c6bf6 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -699,51 +699,31 @@ static bool bf_is_ampdu_not_probing(struct ath_buf *bf) return bf_isampdu(bf) && !(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); } -static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf, struct ath_tx_status *ts) +static void ath_tx_count_airtime(struct ath_softc *sc, struct ath_node *an, + struct ath_atx_tid *tid, struct ath_buf *bf, + struct ath_tx_status *ts) { - struct ath_node *an; - struct ath_acq *acq = &sc->cur_chan->acq[txq->mac80211_qnum]; - struct sk_buff *skb; - struct ieee80211_hdr *hdr; - struct ieee80211_hw *hw = sc->hw; - struct ieee80211_tx_rate rates[4]; - struct ieee80211_sta *sta; - int i; + struct ath_txq *txq = tid->txq; u32 airtime = 0; - - skb = bf->bf_mpdu; - if(!skb) - return; - - hdr = (struct ieee80211_hdr *)skb->data; - memcpy(rates, bf->rates, sizeof(rates)); - - rcu_read_lock(); - - sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2); - if(!sta) - goto exit; - - - an = (struct ath_node *) sta->drv_priv; + int i; airtime += ts->duration * (ts->ts_longretry + 1); + for(i = 0; i < ts->ts_rateindex; i++) { + int rate_dur = ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc, i); + airtime += rate_dur * bf->rates[i].count; + } - for(i=0; i < ts->ts_rateindex; i++) - airtime += ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc, i) * rates[i].count; + if (sc->airtime_flags & AIRTIME_USE_TX) { + int q = txq->mac80211_qnum; + struct ath_acq *acq = &sc->cur_chan->acq[q]; - if (!!(sc->airtime_flags & AIRTIME_USE_TX)) { spin_lock_bh(&acq->lock); - an->airtime_deficit[txq->mac80211_qnum] -= airtime; - if (an->airtime_deficit[txq->mac80211_qnum] <= 0) - __ath_tx_queue_tid(sc, ath_get_skb_tid(sc, an, skb)); + an->airtime_deficit[q] -= airtime; + if (an->airtime_deficit[q] <= 0) + __ath_tx_queue_tid(sc, tid); spin_unlock_bh(&acq->lock); } ath_debug_airtime(sc, an, 0, airtime); - -exit: - rcu_read_unlock(); } static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, @@ -767,13 +747,13 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, ts->duration = ath9k_hw_get_duration(sc->sc_ah, bf->bf_desc, ts->ts_rateindex); - ath_tx_count_airtime(sc, txq, bf, ts); hdr = (struct ieee80211_hdr *) bf->bf_mpdu->data; sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr1, hdr->addr2); if (sta) { struct ath_node *an = (struct ath_node *)sta->drv_priv; tid = ath_get_skb_tid(sc, an, bf->bf_mpdu); + ath_tx_count_airtime(sc, an, tid, bf, ts); if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY)) tid->clear_ps_filter = true; } @@ -2872,8 +2852,6 @@ int ath_tx_init(struct ath_softc *sc, int nbufs) return error; } - INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work); - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) error = ath_tx_edma_init(sc); diff --git a/drivers/net/wireless/ath/wcn36xx/Kconfig b/drivers/net/wireless/ath/wcn36xx/Kconfig index 591ebaea8265..4b83e87f0b94 100644 --- a/drivers/net/wireless/ath/wcn36xx/Kconfig +++ b/drivers/net/wireless/ath/wcn36xx/Kconfig @@ -1,6 +1,8 @@ config WCN36XX tristate "Qualcomm Atheros WCN3660/3680 support" depends on MAC80211 && HAS_DMA + depends on QCOM_WCNSS_CTRL || QCOM_WCNSS_CTRL=n + depends on QCOM_SMD || QCOM_SMD=n ---help--- This module adds support for wireless adapters based on Qualcomm Atheros WCN3660 and WCN3680 mobile chipsets. diff --git a/drivers/net/wireless/ath/wcn36xx/dxe.c b/drivers/net/wireless/ath/wcn36xx/dxe.c index 231fd022f0f5..87dfdaf9044c 100644 --- a/drivers/net/wireless/ath/wcn36xx/dxe.c +++ b/drivers/net/wireless/ath/wcn36xx/dxe.c @@ -23,6 +23,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/interrupt.h> +#include <linux/soc/qcom/smem_state.h> #include "wcn36xx.h" #include "txrx.h" @@ -151,9 +152,12 @@ int wcn36xx_dxe_alloc_ctl_blks(struct wcn36xx *wcn) goto out_err; /* Initialize SMSM state Clear TX Enable RING EMPTY STATE */ - ret = wcn->ctrl_ops->smsm_change_state( - WCN36XX_SMSM_WLAN_TX_ENABLE, - WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY); + ret = qcom_smem_state_update_bits(wcn->tx_enable_state, + WCN36XX_SMSM_WLAN_TX_ENABLE | + WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY, + WCN36XX_SMSM_WLAN_TX_RINGS_EMPTY); + if (ret) + goto out_err; return 0; @@ -678,9 +682,9 @@ int wcn36xx_dxe_tx_frame(struct wcn36xx *wcn, * notify chip about new frame through SMSM bus. */ if (is_low && vif_priv->pw_state == WCN36XX_BMPS) { - wcn->ctrl_ops->smsm_change_state( - 0, - WCN36XX_SMSM_WLAN_TX_ENABLE); + qcom_smem_state_update_bits(wcn->tx_rings_empty_state, + WCN36XX_SMSM_WLAN_TX_ENABLE, + WCN36XX_SMSM_WLAN_TX_ENABLE); } else { /* indicate End Of Packet and generate interrupt on descriptor * done. diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index 4f87ef1e1eb8..b765c647319d 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -350,6 +350,8 @@ enum wcn36xx_hal_host_msg_type { WCN36XX_HAL_AVOID_FREQ_RANGE_IND = 233, + WCN36XX_HAL_PRINT_REG_INFO_IND = 259, + WCN36XX_HAL_MSG_MAX = WCN36XX_HAL_MSG_TYPE_MAX_ENUM_SIZE }; @@ -4703,4 +4705,18 @@ struct stats_class_b_ind { u32 rx_time_total; }; +/* WCN36XX_HAL_PRINT_REG_INFO_IND */ +struct wcn36xx_hal_print_reg_info_ind { + struct wcn36xx_hal_msg_header header; + + u32 count; + u32 scenario; + u32 reason; + + struct { + u32 addr; + u32 value; + } regs[]; +} __packed; + #endif /* _HAL_H_ */ diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index e1d59da2ad20..7a0c2e7da7f6 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -21,6 +21,10 @@ #include <linux/platform_device.h> #include <linux/of_address.h> #include <linux/of_device.h> +#include <linux/of_irq.h> +#include <linux/soc/qcom/smd.h> +#include <linux/soc/qcom/smem_state.h> +#include <linux/soc/qcom/wcnss_ctrl.h> #include "wcn36xx.h" unsigned int wcn36xx_dbg_mask; @@ -564,23 +568,81 @@ out: return ret; } -static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - const u8 *mac_addr) +static void wcn36xx_hw_scan_worker(struct work_struct *work) { - struct wcn36xx *wcn = hw->priv; + struct wcn36xx *wcn = container_of(work, struct wcn36xx, scan_work); + struct cfg80211_scan_request *req = wcn->scan_req; + u8 channels[WCN36XX_HAL_PNO_MAX_NETW_CHANNELS_EX]; + struct cfg80211_scan_info scan_info = {}; + bool aborted = false; + int i; + + wcn36xx_dbg(WCN36XX_DBG_MAC, "mac80211 scan %d channels worker\n", req->n_channels); + + for (i = 0; i < req->n_channels; i++) + channels[i] = req->channels[i]->hw_value; + + wcn36xx_smd_update_scan_params(wcn, channels, req->n_channels); wcn36xx_smd_init_scan(wcn, HAL_SYS_MODE_SCAN); - wcn36xx_smd_start_scan(wcn); + for (i = 0; i < req->n_channels; i++) { + mutex_lock(&wcn->scan_lock); + aborted = wcn->scan_aborted; + mutex_unlock(&wcn->scan_lock); + + if (aborted) + break; + + wcn->scan_freq = req->channels[i]->center_freq; + wcn->scan_band = req->channels[i]->band; + + wcn36xx_smd_start_scan(wcn, req->channels[i]->hw_value); + msleep(30); + wcn36xx_smd_end_scan(wcn, req->channels[i]->hw_value); + + wcn->scan_freq = 0; + } + wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN); + + scan_info.aborted = aborted; + ieee80211_scan_completed(wcn->hw, &scan_info); + + mutex_lock(&wcn->scan_lock); + wcn->scan_req = NULL; + mutex_unlock(&wcn->scan_lock); } -static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) +static int wcn36xx_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_scan_request *hw_req) { struct wcn36xx *wcn = hw->priv; - wcn36xx_smd_end_scan(wcn); - wcn36xx_smd_finish_scan(wcn, HAL_SYS_MODE_SCAN); + mutex_lock(&wcn->scan_lock); + if (wcn->scan_req) { + mutex_unlock(&wcn->scan_lock); + return -EBUSY; + } + + wcn->scan_aborted = false; + wcn->scan_req = &hw_req->req; + mutex_unlock(&wcn->scan_lock); + + schedule_work(&wcn->scan_work); + + return 0; +} + +static void wcn36xx_cancel_hw_scan(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct wcn36xx *wcn = hw->priv; + + mutex_lock(&wcn->scan_lock); + wcn->scan_aborted = true; + mutex_unlock(&wcn->scan_lock); + + cancel_work_sync(&wcn->scan_work); } static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta, @@ -993,8 +1055,8 @@ static const struct ieee80211_ops wcn36xx_ops = { .configure_filter = wcn36xx_configure_filter, .tx = wcn36xx_tx, .set_key = wcn36xx_set_key, - .sw_scan_start = wcn36xx_sw_scan_start, - .sw_scan_complete = wcn36xx_sw_scan_complete, + .hw_scan = wcn36xx_hw_scan, + .cancel_hw_scan = wcn36xx_cancel_hw_scan, .bss_info_changed = wcn36xx_bss_info_changed, .set_rts_threshold = wcn36xx_set_rts_threshold, .sta_add = wcn36xx_sta_add, @@ -1019,6 +1081,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) ieee80211_hw_set(wcn->hw, SUPPORTS_PS); ieee80211_hw_set(wcn->hw, SIGNAL_DBM); ieee80211_hw_set(wcn->hw, HAS_RATE_CONTROL); + ieee80211_hw_set(wcn->hw, SINGLE_SCAN_ON_ALL_BANDS); wcn->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP) | @@ -1028,6 +1091,9 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn) wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = &wcn_band_2ghz; wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz; + wcn->hw->wiphy->max_scan_ssids = WCN36XX_MAX_SCAN_SSIDS; + wcn->hw->wiphy->max_scan_ie_len = WCN36XX_MAX_SCAN_IE_LEN; + wcn->hw->wiphy->cipher_suites = cipher_suites; wcn->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); @@ -1058,8 +1124,7 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn, int ret; /* Set TX IRQ */ - res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, - "wcnss_wlantx_irq"); + res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tx"); if (!res) { wcn36xx_err("failed to get tx_irq\n"); return -ENOENT; @@ -1067,14 +1132,29 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn, wcn->tx_irq = res->start; /* Set RX IRQ */ - res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, - "wcnss_wlanrx_irq"); + res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "rx"); if (!res) { wcn36xx_err("failed to get rx_irq\n"); return -ENOENT; } wcn->rx_irq = res->start; + /* Acquire SMSM tx enable handle */ + wcn->tx_enable_state = qcom_smem_state_get(&pdev->dev, + "tx-enable", &wcn->tx_enable_state_bit); + if (IS_ERR(wcn->tx_enable_state)) { + wcn36xx_err("failed to get tx-enable state\n"); + return PTR_ERR(wcn->tx_enable_state); + } + + /* Acquire SMSM tx rings empty handle */ + wcn->tx_rings_empty_state = qcom_smem_state_get(&pdev->dev, + "tx-rings-empty", &wcn->tx_rings_empty_state_bit); + if (IS_ERR(wcn->tx_rings_empty_state)) { + wcn36xx_err("failed to get tx-rings-empty state\n"); + return PTR_ERR(wcn->tx_rings_empty_state); + } + mmio_node = of_parse_phandle(pdev->dev.parent->of_node, "qcom,mmio", 0); if (!mmio_node) { wcn36xx_err("failed to acquire qcom,mmio reference\n"); @@ -1115,11 +1195,14 @@ static int wcn36xx_probe(struct platform_device *pdev) { struct ieee80211_hw *hw; struct wcn36xx *wcn; + void *wcnss; int ret; - u8 addr[ETH_ALEN]; + const u8 *addr; wcn36xx_dbg(WCN36XX_DBG_MAC, "platform probe\n"); + wcnss = dev_get_drvdata(pdev->dev.parent); + hw = ieee80211_alloc_hw(sizeof(struct wcn36xx), &wcn36xx_ops); if (!hw) { wcn36xx_err("failed to alloc hw\n"); @@ -1130,11 +1213,26 @@ static int wcn36xx_probe(struct platform_device *pdev) wcn = hw->priv; wcn->hw = hw; wcn->dev = &pdev->dev; - wcn->ctrl_ops = pdev->dev.platform_data; - mutex_init(&wcn->hal_mutex); + mutex_init(&wcn->scan_lock); - if (!wcn->ctrl_ops->get_hw_mac(addr)) { + INIT_WORK(&wcn->scan_work, wcn36xx_hw_scan_worker); + + wcn->smd_channel = qcom_wcnss_open_channel(wcnss, "WLAN_CTRL", wcn36xx_smd_rsp_process); + if (IS_ERR(wcn->smd_channel)) { + wcn36xx_err("failed to open WLAN_CTRL channel\n"); + ret = PTR_ERR(wcn->smd_channel); + goto out_wq; + } + + qcom_smd_set_drvdata(wcn->smd_channel, hw); + + addr = of_get_property(pdev->dev.of_node, "local-mac-address", &ret); + if (addr && ret != ETH_ALEN) { + wcn36xx_err("invalid local-mac-address\n"); + ret = -EINVAL; + goto out_wq; + } else if (addr) { wcn36xx_info("mac address: %pM\n", addr); SET_IEEE80211_PERM_ADDR(wcn->hw, addr); } @@ -1158,6 +1256,7 @@ out_wq: out_err: return ret; } + static int wcn36xx_remove(struct platform_device *pdev) { struct ieee80211_hw *hw = platform_get_drvdata(pdev); @@ -1165,45 +1264,37 @@ static int wcn36xx_remove(struct platform_device *pdev) wcn36xx_dbg(WCN36XX_DBG_MAC, "platform remove\n"); release_firmware(wcn->nv); - mutex_destroy(&wcn->hal_mutex); ieee80211_unregister_hw(hw); + + qcom_smem_state_put(wcn->tx_enable_state); + qcom_smem_state_put(wcn->tx_rings_empty_state); + iounmap(wcn->dxe_base); iounmap(wcn->ccu_base); + + mutex_destroy(&wcn->hal_mutex); ieee80211_free_hw(hw); return 0; } -static const struct platform_device_id wcn36xx_platform_id_table[] = { - { - .name = "wcn36xx", - .driver_data = 0 - }, + +static const struct of_device_id wcn36xx_of_match[] = { + { .compatible = "qcom,wcnss-wlan" }, {} }; -MODULE_DEVICE_TABLE(platform, wcn36xx_platform_id_table); +MODULE_DEVICE_TABLE(of, wcn36xx_of_match); static struct platform_driver wcn36xx_driver = { .probe = wcn36xx_probe, .remove = wcn36xx_remove, .driver = { .name = "wcn36xx", + .of_match_table = wcn36xx_of_match, }, - .id_table = wcn36xx_platform_id_table, }; -static int __init wcn36xx_init(void) -{ - platform_driver_register(&wcn36xx_driver); - return 0; -} -module_init(wcn36xx_init); - -static void __exit wcn36xx_exit(void) -{ - platform_driver_unregister(&wcn36xx_driver); -} -module_exit(wcn36xx_exit); +module_platform_driver(wcn36xx_driver); MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Eugene Krasnikov k.eugene.e@gmail.com"); diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index a443992320f2..1c2966f7db7a 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -19,6 +19,7 @@ #include <linux/etherdevice.h> #include <linux/firmware.h> #include <linux/bitops.h> +#include <linux/soc/qcom/smd.h> #include "smd.h" struct wcn36xx_cfg_val { @@ -253,7 +254,7 @@ static int wcn36xx_smd_send_and_wait(struct wcn36xx *wcn, size_t len) init_completion(&wcn->hal_rsp_compl); start = jiffies; - ret = wcn->ctrl_ops->tx(wcn->hal_buf, len); + ret = qcom_smd_send(wcn->smd_channel, wcn->hal_buf, len); if (ret) { wcn36xx_err("HAL TX failed\n"); goto out; @@ -521,7 +522,7 @@ out: return ret; } -int wcn36xx_smd_start_scan(struct wcn36xx *wcn) +int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel) { struct wcn36xx_hal_start_scan_req_msg msg_body; int ret = 0; @@ -529,7 +530,7 @@ int wcn36xx_smd_start_scan(struct wcn36xx *wcn) mutex_lock(&wcn->hal_mutex); INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_SCAN_REQ); - msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn); + msg_body.scan_channel = scan_channel; PREPARE_HAL_BUF(wcn->hal_buf, msg_body); @@ -551,7 +552,7 @@ out: return ret; } -int wcn36xx_smd_end_scan(struct wcn36xx *wcn) +int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel) { struct wcn36xx_hal_end_scan_req_msg msg_body; int ret = 0; @@ -559,7 +560,7 @@ int wcn36xx_smd_end_scan(struct wcn36xx *wcn) mutex_lock(&wcn->hal_mutex); INIT_HAL_MSG(msg_body, WCN36XX_HAL_END_SCAN_REQ); - msg_body.scan_channel = WCN36XX_HW_CHANNEL(wcn); + msg_body.scan_channel = scan_channel; PREPARE_HAL_BUF(wcn->hal_buf, msg_body); @@ -2108,6 +2109,30 @@ static int wcn36xx_smd_delete_sta_context_ind(struct wcn36xx *wcn, return -ENOENT; } +static int wcn36xx_smd_print_reg_info_ind(struct wcn36xx *wcn, + void *buf, + size_t len) +{ + struct wcn36xx_hal_print_reg_info_ind *rsp = buf; + int i; + + if (len < sizeof(*rsp)) { + wcn36xx_warn("Corrupted print reg info indication\n"); + return -EIO; + } + + wcn36xx_dbg(WCN36XX_DBG_HAL, + "reginfo indication, scenario: 0x%x reason: 0x%x\n", + rsp->scenario, rsp->reason); + + for (i = 0; i < rsp->count; i++) { + wcn36xx_dbg(WCN36XX_DBG_HAL, "\t0x%x: 0x%x\n", + rsp->regs[i].addr, rsp->regs[i].value); + } + + return 0; +} + int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value) { struct wcn36xx_hal_update_cfg_req_msg msg_body, *body; @@ -2180,9 +2205,12 @@ out: return ret; } -static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) +int wcn36xx_smd_rsp_process(struct qcom_smd_channel *channel, + const void *buf, size_t len) { - struct wcn36xx_hal_msg_header *msg_header = buf; + const struct wcn36xx_hal_msg_header *msg_header = buf; + struct ieee80211_hw *hw = qcom_smd_get_drvdata(channel); + struct wcn36xx *wcn = hw->priv; struct wcn36xx_hal_ind_msg *msg_ind; wcn36xx_dbg_dump(WCN36XX_DBG_SMD_DUMP, "SMD <<< ", buf, len); @@ -2233,15 +2261,12 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) case WCN36XX_HAL_OTA_TX_COMPL_IND: case WCN36XX_HAL_MISSED_BEACON_IND: case WCN36XX_HAL_DELETE_STA_CONTEXT_IND: - msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_KERNEL); + case WCN36XX_HAL_PRINT_REG_INFO_IND: + msg_ind = kmalloc(sizeof(*msg_ind) + len, GFP_ATOMIC); if (!msg_ind) { - /* - * FIXME: Do something smarter then just - * printing an error. - */ wcn36xx_err("Run out of memory while handling SMD_EVENT (%d)\n", msg_header->msg_type); - break; + return -ENOMEM; } msg_ind->msg_len = len; @@ -2257,6 +2282,8 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len) wcn36xx_err("SMD_EVENT (%d) not supported\n", msg_header->msg_type); } + + return 0; } static void wcn36xx_ind_smd_work(struct work_struct *work) { @@ -2294,6 +2321,11 @@ static void wcn36xx_ind_smd_work(struct work_struct *work) hal_ind_msg->msg, hal_ind_msg->msg_len); break; + case WCN36XX_HAL_PRINT_REG_INFO_IND: + wcn36xx_smd_print_reg_info_ind(wcn, + hal_ind_msg->msg, + hal_ind_msg->msg_len); + break; default: wcn36xx_err("SMD_EVENT (%d) not supported\n", msg_header->msg_type); @@ -2315,22 +2347,13 @@ int wcn36xx_smd_open(struct wcn36xx *wcn) INIT_LIST_HEAD(&wcn->hal_ind_queue); spin_lock_init(&wcn->hal_ind_lock); - ret = wcn->ctrl_ops->open(wcn, wcn36xx_smd_rsp_process); - if (ret) { - wcn36xx_err("failed to open control channel\n"); - goto free_wq; - } - - return ret; + return 0; -free_wq: - destroy_workqueue(wcn->hal_ind_wq); out: return ret; } void wcn36xx_smd_close(struct wcn36xx *wcn) { - wcn->ctrl_ops->close(); destroy_workqueue(wcn->hal_ind_wq); } diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h index df80cbbd9d1b..8892ccd67b14 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.h +++ b/drivers/net/wireless/ath/wcn36xx/smd.h @@ -51,6 +51,7 @@ struct wcn36xx_hal_ind_msg { }; struct wcn36xx; +struct qcom_smd_channel; int wcn36xx_smd_open(struct wcn36xx *wcn); void wcn36xx_smd_close(struct wcn36xx *wcn); @@ -59,8 +60,8 @@ int wcn36xx_smd_load_nv(struct wcn36xx *wcn); int wcn36xx_smd_start(struct wcn36xx *wcn); int wcn36xx_smd_stop(struct wcn36xx *wcn); int wcn36xx_smd_init_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode); -int wcn36xx_smd_start_scan(struct wcn36xx *wcn); -int wcn36xx_smd_end_scan(struct wcn36xx *wcn); +int wcn36xx_smd_start_scan(struct wcn36xx *wcn, u8 scan_channel); +int wcn36xx_smd_end_scan(struct wcn36xx *wcn, u8 scan_channel); int wcn36xx_smd_finish_scan(struct wcn36xx *wcn, enum wcn36xx_hal_sys_mode mode); int wcn36xx_smd_update_scan_params(struct wcn36xx *wcn, u8 *channels, size_t channel_count); @@ -127,6 +128,10 @@ int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 sta_index); int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index); int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value); + +int wcn36xx_smd_rsp_process(struct qcom_smd_channel *channel, + const void *buf, size_t len); + int wcn36xx_smd_set_mc_list(struct wcn36xx *wcn, struct ieee80211_vif *vif, struct wcn36xx_hal_rcv_flt_mc_addr_list_type *fp); diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c index 1f34c2e912d7..8c387a0a3c09 100644 --- a/drivers/net/wireless/ath/wcn36xx/txrx.c +++ b/drivers/net/wireless/ath/wcn36xx/txrx.c @@ -45,9 +45,20 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) skb_put(skb, bd->pdu.mpdu_header_off + bd->pdu.mpdu_len); skb_pull(skb, bd->pdu.mpdu_header_off); + hdr = (struct ieee80211_hdr *) skb->data; + fc = __le16_to_cpu(hdr->frame_control); + sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)); + + /* When scanning associate beacons to this */ + if (ieee80211_is_beacon(hdr->frame_control) && wcn->scan_freq) { + status.freq = wcn->scan_freq; + status.band = wcn->scan_band; + } else { + status.freq = WCN36XX_CENTER_FREQ(wcn); + status.band = WCN36XX_BAND(wcn); + } + status.mactime = 10; - status.freq = WCN36XX_CENTER_FREQ(wcn); - status.band = WCN36XX_BAND(wcn); status.signal = -get_rssi0(bd); status.antenna = 1; status.rate_idx = 1; @@ -61,10 +72,6 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb) memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); - hdr = (struct ieee80211_hdr *) skb->data; - fc = __le16_to_cpu(hdr->frame_control); - sn = IEEE80211_SEQ_TO_SN(__le16_to_cpu(hdr->seq_ctrl)); - if (ieee80211_is_beacon(hdr->frame_control)) { wcn36xx_dbg(WCN36XX_DBG_BEACON, "beacon skb %p len %d fc %04x sn %d\n", skb, skb->len, fc, sn); diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h index 22242d18e1fe..7423998ddeb4 100644 --- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h +++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h @@ -35,6 +35,9 @@ /* How many frames until we start a-mpdu TX session */ #define WCN36XX_AMPDU_START_THRESH 20 +#define WCN36XX_MAX_SCAN_SSIDS 9 +#define WCN36XX_MAX_SCAN_IE_LEN 500 + extern unsigned int wcn36xx_dbg_mask; enum wcn36xx_debug_mask { @@ -103,19 +106,6 @@ struct nv_data { u8 table; }; -/* Interface for platform control path - * - * @open: hook must be called when wcn36xx wants to open control channel. - * @tx: sends a buffer. - */ -struct wcn36xx_platform_ctrl_ops { - int (*open)(void *drv_priv, void *rsp_cb); - void (*close)(void); - int (*tx)(char *buf, size_t len); - int (*get_hw_mac)(u8 *addr); - int (*smsm_change_state)(u32 clear_mask, u32 set_mask); -}; - /** * struct wcn36xx_vif - holds VIF related fields * @@ -205,7 +195,13 @@ struct wcn36xx { void __iomem *ccu_base; void __iomem *dxe_base; - struct wcn36xx_platform_ctrl_ops *ctrl_ops; + struct qcom_smd_channel *smd_channel; + + struct qcom_smem_state *tx_enable_state; + unsigned tx_enable_state_bit; + struct qcom_smem_state *tx_rings_empty_state; + unsigned tx_rings_empty_state_bit; + /* * smd_buf must be protected with smd_mutex to garantee * that all messages are sent one after another @@ -219,6 +215,13 @@ struct wcn36xx { spinlock_t hal_ind_lock; struct list_head hal_ind_queue; + struct work_struct scan_work; + struct cfg80211_scan_request *scan_req; + int scan_freq; + int scan_band; + struct mutex scan_lock; + bool scan_aborted; + /* DXE channels */ struct wcn36xx_dxe_ch dxe_tx_l_ch; /* TX low */ struct wcn36xx_dxe_ch dxe_tx_h_ch; /* TX high */ diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index 6aa3ff4240a9..83155b5ddbfb 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -15,11 +15,16 @@ */ #include <linux/etherdevice.h> +#include <linux/moduleparam.h> #include "wil6210.h" #include "wmi.h" #define WIL_MAX_ROC_DURATION_MS 5000 +bool disable_ap_sme; +module_param(disable_ap_sme, bool, 0444); +MODULE_PARM_DESC(disable_ap_sme, " let user space handle AP mode SME"); + #define CHAN60G(_channel, _flags) { \ .band = NL80211_BAND_60GHZ, \ .center_freq = 56160 + (2160 * (_channel)), \ @@ -62,9 +67,16 @@ wil_mgmt_stypes[NUM_NL80211_IFTYPES] = { }, [NL80211_IFTYPE_AP] = { .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), + BIT(IEEE80211_STYPE_PROBE_RESP >> 4) | + BIT(IEEE80211_STYPE_ASSOC_RESP >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4), .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4) + BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | + BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) | + BIT(IEEE80211_STYPE_DISASSOC >> 4) | + BIT(IEEE80211_STYPE_AUTH >> 4) | + BIT(IEEE80211_STYPE_DEAUTH >> 4) | + BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) }, [NL80211_IFTYPE_P2P_CLIENT] = { .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | @@ -194,7 +206,7 @@ static int wil_cfg80211_get_station(struct wiphy *wiphy, int cid = wil_find_cid(wil, mac); - wil_dbg_misc(wil, "%s(%pM) CID %d\n", __func__, mac, cid); + wil_dbg_misc(wil, "get_station: %pM CID %d\n", mac, cid); if (cid < 0) return cid; @@ -233,7 +245,7 @@ static int wil_cfg80211_dump_station(struct wiphy *wiphy, return -ENOENT; ether_addr_copy(mac, wil->sta[cid].addr); - wil_dbg_misc(wil, "%s(%pM) CID %d\n", __func__, mac, cid); + wil_dbg_misc(wil, "dump_station: %pM CID %d\n", mac, cid); rc = wil_cid_fill_sinfo(wil, cid, sinfo); @@ -250,16 +262,15 @@ wil_cfg80211_add_iface(struct wiphy *wiphy, const char *name, struct net_device *ndev = wil_to_ndev(wil); struct wireless_dev *p2p_wdev; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "add_iface\n"); if (type != NL80211_IFTYPE_P2P_DEVICE) { - wil_err(wil, "%s: unsupported iftype %d\n", __func__, type); + wil_err(wil, "unsupported iftype %d\n", type); return ERR_PTR(-EINVAL); } if (wil->p2p_wdev) { - wil_err(wil, "%s: P2P_DEVICE interface already created\n", - __func__); + wil_err(wil, "P2P_DEVICE interface already created\n"); return ERR_PTR(-EINVAL); } @@ -282,11 +293,10 @@ static int wil_cfg80211_del_iface(struct wiphy *wiphy, { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "del_iface\n"); if (wdev != wil->p2p_wdev) { - wil_err(wil, "%s: delete of incorrect interface 0x%p\n", - __func__, wdev); + wil_err(wil, "delete of incorrect interface 0x%p\n", wdev); return -EINVAL; } @@ -304,7 +314,7 @@ static int wil_cfg80211_change_iface(struct wiphy *wiphy, struct wireless_dev *wdev = wil_to_wdev(wil); int rc; - wil_dbg_misc(wil, "%s() type=%d\n", __func__, type); + wil_dbg_misc(wil, "change_iface: type=%d\n", type); if (netif_running(wil_to_ndev(wil)) && !wil_is_recovery_blocked(wil)) { wil_dbg_misc(wil, "interface is up. resetting...\n"); @@ -351,8 +361,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy, uint i, n; int rc; - wil_dbg_misc(wil, "%s(), wdev=0x%p iftype=%d\n", - __func__, wdev, wdev->iftype); + wil_dbg_misc(wil, "scan: wdev=0x%p iftype=%d\n", wdev, wdev->iftype); /* check we are client side */ switch (wdev->iftype) { @@ -557,7 +566,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, int rc = 0; enum ieee80211_bss_type bss_type = IEEE80211_BSS_TYPE_ESS; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "connect\n"); wil_print_connect_params(wil, sme); if (test_bit(wil_status_fwconnecting, wil->status) || @@ -593,6 +602,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy, goto out; } wil->privacy = sme->privacy; + wil->pbss = sme->pbss; if (wil->privacy) { /* For secure assoc, remove old keys */ @@ -689,12 +699,11 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy, int rc; struct wil6210_priv *wil = wiphy_to_wil(wiphy); - wil_dbg_misc(wil, "%s(reason=%d)\n", __func__, reason_code); + wil_dbg_misc(wil, "disconnect: reason=%d\n", reason_code); if (!(test_bit(wil_status_fwconnecting, wil->status) || test_bit(wil_status_fwconnected, wil->status))) { - wil_err(wil, "%s: Disconnect was called while disconnected\n", - __func__); + wil_err(wil, "Disconnect was called while disconnected\n"); return 0; } @@ -702,7 +711,7 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy, WMI_DISCONNECT_EVENTID, NULL, 0, WIL6210_DISCONNECT_TO_MS); if (rc) - wil_err(wil, "%s: disconnect error %d\n", __func__, rc); + wil_err(wil, "disconnect error %d\n", rc); return rc; } @@ -750,7 +759,7 @@ int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, * different from currently "listened" channel and fail if it is. */ - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "mgmt_tx\n"); print_hex_dump_bytes("mgmt tx frame ", DUMP_PREFIX_OFFSET, buf, len); cmd = kmalloc(sizeof(*cmd) + len, GFP_KERNEL); @@ -811,7 +820,7 @@ static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil, break; } } - wil_dbg_misc(wil, "%s() -> %s\n", __func__, key_usage_str[rc]); + wil_dbg_misc(wil, "detect_key_usage: -> %s\n", key_usage_str[rc]); return rc; } @@ -916,13 +925,13 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy, return -EINVAL; } - wil_dbg_misc(wil, "%s(%pM %s[%d] PN %*phN)\n", __func__, + wil_dbg_misc(wil, "add_key: %pM %s[%d] PN %*phN\n", mac_addr, key_usage_str[key_usage], key_index, params->seq_len, params->seq); if (IS_ERR(cs)) { - wil_err(wil, "Not connected, %s(%pM %s[%d] PN %*phN)\n", - __func__, mac_addr, key_usage_str[key_usage], key_index, + wil_err(wil, "Not connected, %pM %s[%d] PN %*phN\n", + mac_addr, key_usage_str[key_usage], key_index, params->seq_len, params->seq); return -EINVAL; } @@ -931,8 +940,8 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy, if (params->seq && params->seq_len != IEEE80211_GCMP_PN_LEN) { wil_err(wil, - "Wrong PN len %d, %s(%pM %s[%d] PN %*phN)\n", - params->seq_len, __func__, mac_addr, + "Wrong PN len %d, %pM %s[%d] PN %*phN\n", + params->seq_len, mac_addr, key_usage_str[key_usage], key_index, params->seq_len, params->seq); return -EINVAL; @@ -956,11 +965,11 @@ static int wil_cfg80211_del_key(struct wiphy *wiphy, struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage, mac_addr); - wil_dbg_misc(wil, "%s(%pM %s[%d])\n", __func__, mac_addr, + wil_dbg_misc(wil, "del_key: %pM %s[%d]\n", mac_addr, key_usage_str[key_usage], key_index); if (IS_ERR(cs)) - wil_info(wil, "Not connected, %s(%pM %s[%d])\n", __func__, + wil_info(wil, "Not connected, %pM %s[%d]\n", mac_addr, key_usage_str[key_usage], key_index); if (!IS_ERR_OR_NULL(cs)) @@ -977,7 +986,7 @@ static int wil_cfg80211_set_default_key(struct wiphy *wiphy, { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - wil_dbg_misc(wil, "%s: entered\n", __func__); + wil_dbg_misc(wil, "set_default_key: entered\n"); return 0; } @@ -990,8 +999,9 @@ static int wil_remain_on_channel(struct wiphy *wiphy, struct wil6210_priv *wil = wiphy_to_wil(wiphy); int rc; - wil_dbg_misc(wil, "%s() center_freq=%d, duration=%d iftype=%d\n", - __func__, chan->center_freq, duration, wdev->iftype); + wil_dbg_misc(wil, + "remain_on_channel: center_freq=%d, duration=%d iftype=%d\n", + chan->center_freq, duration, wdev->iftype); rc = wil_p2p_listen(wil, wdev, duration, chan, cookie); return rc; @@ -1003,7 +1013,7 @@ static int wil_cancel_remain_on_channel(struct wiphy *wiphy, { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "cancel_remain_on_channel\n"); return wil_p2p_cancel_listen(wil, cookie); } @@ -1159,9 +1169,9 @@ static int _wil_cfg80211_start_ap(struct wiphy *wiphy, if (pbss) wmi_nettype = WMI_NETTYPE_P2P; - wil_dbg_misc(wil, "%s: is_go=%d\n", __func__, is_go); + wil_dbg_misc(wil, "start_ap: is_go=%d\n", is_go); if (is_go && !pbss) { - wil_err(wil, "%s: P2P GO must be in PBSS\n", __func__); + wil_err(wil, "P2P GO must be in PBSS\n"); return -ENOTSUPP; } @@ -1216,7 +1226,7 @@ static int wil_cfg80211_change_beacon(struct wiphy *wiphy, int rc; u32 privacy = 0; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "change_beacon\n"); wil_print_bcon_data(bcon); if (bcon->tail && @@ -1255,7 +1265,7 @@ static int wil_cfg80211_start_ap(struct wiphy *wiphy, struct cfg80211_crypto_settings *crypto = &info->crypto; u8 hidden_ssid; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "start_ap\n"); if (!channel) { wil_err(wil, "AP: No channel???\n"); @@ -1306,7 +1316,7 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy, { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "stop_ap\n"); netif_carrier_off(ndev); wil_set_recovery_state(wil, fw_recovery_idle); @@ -1322,13 +1332,35 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy, return 0; } +static int wil_cfg80211_add_station(struct wiphy *wiphy, + struct net_device *dev, + const u8 *mac, + struct station_parameters *params) +{ + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + + wil_dbg_misc(wil, "add station %pM aid %d\n", mac, params->aid); + + if (!disable_ap_sme) { + wil_err(wil, "not supported with AP SME enabled\n"); + return -EOPNOTSUPP; + } + + if (params->aid > WIL_MAX_DMG_AID) { + wil_err(wil, "invalid aid\n"); + return -EINVAL; + } + + return wmi_new_sta(wil, mac, params->aid); +} + static int wil_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, struct station_del_parameters *params) { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - wil_dbg_misc(wil, "%s(%pM, reason=%d)\n", __func__, params->mac, + wil_dbg_misc(wil, "del_station: %pM, reason=%d\n", params->mac, params->reason_code); mutex_lock(&wil->mutex); @@ -1338,6 +1370,52 @@ static int wil_cfg80211_del_station(struct wiphy *wiphy, return 0; } +static int wil_cfg80211_change_station(struct wiphy *wiphy, + struct net_device *dev, + const u8 *mac, + struct station_parameters *params) +{ + struct wil6210_priv *wil = wiphy_to_wil(wiphy); + int authorize; + int cid, i; + struct vring_tx_data *txdata = NULL; + + wil_dbg_misc(wil, "change station %pM mask 0x%x set 0x%x\n", mac, + params->sta_flags_mask, params->sta_flags_set); + + if (!disable_ap_sme) { + wil_dbg_misc(wil, "not supported with AP SME enabled\n"); + return -EOPNOTSUPP; + } + + if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) + return 0; + + cid = wil_find_cid(wil, mac); + if (cid < 0) { + wil_err(wil, "station not found\n"); + return -ENOLINK; + } + + for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) + if (wil->vring2cid_tid[i][0] == cid) { + txdata = &wil->vring_tx_data[i]; + break; + } + + if (!txdata) { + wil_err(wil, "vring data not found\n"); + return -ENOLINK; + } + + authorize = params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED); + txdata->dot1x_open = authorize ? 1 : 0; + wil_dbg_misc(wil, "cid %d vring %d authorize %d\n", cid, i, + txdata->dot1x_open); + + return 0; +} + /* probe_client handling */ static void wil_probe_client_handle(struct wil6210_priv *wil, struct wil_probe_client_req *req) @@ -1387,7 +1465,7 @@ void wil_probe_client_flush(struct wil6210_priv *wil) { struct wil_probe_client_req *req, *t; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "probe_client_flush\n"); mutex_lock(&wil->probe_client_mutex); @@ -1407,7 +1485,7 @@ static int wil_cfg80211_probe_client(struct wiphy *wiphy, struct wil_probe_client_req *req; int cid = wil_find_cid(wil, peer); - wil_dbg_misc(wil, "%s(%pM => CID %d)\n", __func__, peer, cid); + wil_dbg_misc(wil, "probe_client: %pM => CID %d\n", peer, cid); if (cid < 0) return -ENOLINK; @@ -1435,7 +1513,7 @@ static int wil_cfg80211_change_bss(struct wiphy *wiphy, struct wil6210_priv *wil = wiphy_to_wil(wiphy); if (params->ap_isolate >= 0) { - wil_dbg_misc(wil, "%s(ap_isolate %d => %d)\n", __func__, + wil_dbg_misc(wil, "change_bss: ap_isolate %d => %d\n", wil->ap_isolate, params->ap_isolate); wil->ap_isolate = params->ap_isolate; } @@ -1448,7 +1526,7 @@ static int wil_cfg80211_start_p2p_device(struct wiphy *wiphy, { struct wil6210_priv *wil = wiphy_to_wil(wiphy); - wil_dbg_misc(wil, "%s: entered\n", __func__); + wil_dbg_misc(wil, "start_p2p_device: entered\n"); wil->p2p.p2p_dev_started = 1; return 0; } @@ -1462,7 +1540,7 @@ static void wil_cfg80211_stop_p2p_device(struct wiphy *wiphy, if (!p2p->p2p_dev_started) return; - wil_dbg_misc(wil, "%s: entered\n", __func__); + wil_dbg_misc(wil, "stop_p2p_device: entered\n"); mutex_lock(&wil->mutex); mutex_lock(&wil->p2p_wdev_mutex); wil_p2p_stop_radio_operations(wil); @@ -1499,7 +1577,7 @@ static int wil_cfg80211_set_power_mgmt(struct wiphy *wiphy, return rc; } -static struct cfg80211_ops wil_cfg80211_ops = { +static const struct cfg80211_ops wil_cfg80211_ops = { .add_virtual_intf = wil_cfg80211_add_iface, .del_virtual_intf = wil_cfg80211_del_iface, .scan = wil_cfg80211_scan, @@ -1521,7 +1599,9 @@ static struct cfg80211_ops wil_cfg80211_ops = { .change_beacon = wil_cfg80211_change_beacon, .start_ap = wil_cfg80211_start_ap, .stop_ap = wil_cfg80211_stop_ap, + .add_station = wil_cfg80211_add_station, .del_station = wil_cfg80211_del_station, + .change_station = wil_cfg80211_change_station, .probe_client = wil_cfg80211_probe_client, .change_bss = wil_cfg80211_change_bss, /* P2P device */ @@ -1542,10 +1622,11 @@ static void wil_wiphy_init(struct wiphy *wiphy) BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_DEVICE) | BIT(NL80211_IFTYPE_MONITOR); - wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | - WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | + wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | WIPHY_FLAG_PS_ON_BY_DEFAULT; + if (!disable_ap_sme) + wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME; dev_dbg(wiphy_dev(wiphy), "%s : flags = 0x%08x\n", __func__, wiphy->flags); wiphy->probe_resp_offload = diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c index 5e4058a4037b..3e8cdf12feda 100644 --- a/drivers/net/wireless/ath/wil6210/debugfs.c +++ b/drivers/net/wireless/ath/wil6210/debugfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -364,13 +364,13 @@ static void wil6210_debugfs_init_offset(struct wil6210_priv *wil, } static const struct dbg_off isr_off[] = { - {"ICC", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, ICC), doff_io32}, - {"ICR", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, ICR), doff_io32}, - {"ICM", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, ICM), doff_io32}, - {"ICS", S_IWUSR, offsetof(struct RGF_ICR, ICS), doff_io32}, - {"IMV", S_IRUGO | S_IWUSR, offsetof(struct RGF_ICR, IMV), doff_io32}, - {"IMS", S_IWUSR, offsetof(struct RGF_ICR, IMS), doff_io32}, - {"IMC", S_IWUSR, offsetof(struct RGF_ICR, IMC), doff_io32}, + {"ICC", 0644, offsetof(struct RGF_ICR, ICC), doff_io32}, + {"ICR", 0644, offsetof(struct RGF_ICR, ICR), doff_io32}, + {"ICM", 0644, offsetof(struct RGF_ICR, ICM), doff_io32}, + {"ICS", 0244, offsetof(struct RGF_ICR, ICS), doff_io32}, + {"IMV", 0644, offsetof(struct RGF_ICR, IMV), doff_io32}, + {"IMS", 0244, offsetof(struct RGF_ICR, IMS), doff_io32}, + {"IMC", 0244, offsetof(struct RGF_ICR, IMC), doff_io32}, {}, }; @@ -390,9 +390,9 @@ static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil, } static const struct dbg_off pseudo_isr_off[] = { - {"CAUSE", S_IRUGO, HOSTADDR(RGF_DMA_PSEUDO_CAUSE), doff_io32}, - {"MASK_SW", S_IRUGO, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW), doff_io32}, - {"MASK_FW", S_IRUGO, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW), doff_io32}, + {"CAUSE", 0444, HOSTADDR(RGF_DMA_PSEUDO_CAUSE), doff_io32}, + {"MASK_SW", 0444, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW), doff_io32}, + {"MASK_FW", 0444, HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW), doff_io32}, {}, }; @@ -411,40 +411,40 @@ static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil, } static const struct dbg_off lgc_itr_cnt_off[] = { - {"TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_TRSH), doff_io32}, - {"DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_DATA), doff_io32}, - {"CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_CNT_CRL), doff_io32}, + {"TRSH", 0644, HOSTADDR(RGF_DMA_ITR_CNT_TRSH), doff_io32}, + {"DATA", 0644, HOSTADDR(RGF_DMA_ITR_CNT_DATA), doff_io32}, + {"CTL", 0644, HOSTADDR(RGF_DMA_ITR_CNT_CRL), doff_io32}, {}, }; static const struct dbg_off tx_itr_cnt_off[] = { - {"TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_CNT_TRSH), + {"TRSH", 0644, HOSTADDR(RGF_DMA_ITR_TX_CNT_TRSH), doff_io32}, - {"DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_CNT_DATA), + {"DATA", 0644, HOSTADDR(RGF_DMA_ITR_TX_CNT_DATA), doff_io32}, - {"CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_CNT_CTL), + {"CTL", 0644, HOSTADDR(RGF_DMA_ITR_TX_CNT_CTL), doff_io32}, - {"IDL_TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_TRSH), + {"IDL_TRSH", 0644, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_TRSH), doff_io32}, - {"IDL_DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_DATA), + {"IDL_DATA", 0644, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_DATA), doff_io32}, - {"IDL_CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_CTL), + {"IDL_CTL", 0644, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_CTL), doff_io32}, {}, }; static const struct dbg_off rx_itr_cnt_off[] = { - {"TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_CNT_TRSH), + {"TRSH", 0644, HOSTADDR(RGF_DMA_ITR_RX_CNT_TRSH), doff_io32}, - {"DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_CNT_DATA), + {"DATA", 0644, HOSTADDR(RGF_DMA_ITR_RX_CNT_DATA), doff_io32}, - {"CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_CNT_CTL), + {"CTL", 0644, HOSTADDR(RGF_DMA_ITR_RX_CNT_CTL), doff_io32}, - {"IDL_TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_TRSH), + {"IDL_TRSH", 0644, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_TRSH), doff_io32}, - {"IDL_DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_DATA), + {"IDL_DATA", 0644, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_DATA), doff_io32}, - {"IDL_CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_CTL), + {"IDL_CTL", 0644, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_CTL), doff_io32}, {}, }; @@ -813,7 +813,7 @@ static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf, rc = wil_cfg80211_mgmt_tx(wiphy, wdev, ¶ms, NULL); kfree(frame); - wil_info(wil, "%s() -> %d\n", __func__, rc); + wil_info(wil, "-> %d\n", rc); return len; } @@ -855,7 +855,7 @@ static ssize_t wil_write_file_wmi(struct file *file, const char __user *buf, rc1 = wmi_send(wil, cmdid, cmd, cmdlen); kfree(wmi); - wil_info(wil, "%s(0x%04x[%d]) -> %d\n", __func__, cmdid, cmdlen, rc1); + wil_info(wil, "0x%04x[%d] -> %d\n", cmdid, cmdlen, rc1); return rc; } @@ -1379,6 +1379,7 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) for (i = 0; i < ARRAY_SIZE(wil->sta); i++) { struct wil_sta_info *p = &wil->sta[i]; char *status = "unknown"; + u8 aid = 0; switch (p->status) { case wil_sta_unused: @@ -1389,9 +1390,10 @@ __acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock) break; case wil_sta_connected: status = "connected"; + aid = p->aid; break; } - seq_printf(s, "[%d] %pM %s\n", i, p->addr, status); + seq_printf(s, "[%d] %pM %s AID %d\n", i, p->addr, status, aid); if (p->status == wil_sta_connected) { spin_lock_bh(&p->tid_rx_lock); @@ -1622,7 +1624,7 @@ static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil, blob->data = (void * __force)wil->csr + HOSTADDR(map->host); blob->size = map->to - map->from; snprintf(name, sizeof(name), "blob_%s", map->name); - wil_debugfs_create_ioblob(name, S_IRUGO, dbg, wil_blob); + wil_debugfs_create_ioblob(name, 0444, dbg, wil_blob); } } @@ -1632,29 +1634,29 @@ static const struct { umode_t mode; const struct file_operations *fops; } dbg_files[] = { - {"mbox", S_IRUGO, &fops_mbox}, - {"vrings", S_IRUGO, &fops_vring}, - {"stations", S_IRUGO, &fops_sta}, - {"desc", S_IRUGO, &fops_txdesc}, - {"bf", S_IRUGO, &fops_bf}, - {"ssid", S_IRUGO | S_IWUSR, &fops_ssid}, - {"mem_val", S_IRUGO, &fops_memread}, - {"reset", S_IWUSR, &fops_reset}, - {"rxon", S_IWUSR, &fops_rxon}, - {"tx_mgmt", S_IWUSR, &fops_txmgmt}, - {"wmi_send", S_IWUSR, &fops_wmi}, - {"back", S_IRUGO | S_IWUSR, &fops_back}, - {"pmccfg", S_IRUGO | S_IWUSR, &fops_pmccfg}, - {"pmcdata", S_IRUGO, &fops_pmcdata}, - {"temp", S_IRUGO, &fops_temp}, - {"freq", S_IRUGO, &fops_freq}, - {"link", S_IRUGO, &fops_link}, - {"info", S_IRUGO, &fops_info}, - {"recovery", S_IRUGO | S_IWUSR, &fops_recovery}, - {"led_cfg", S_IRUGO | S_IWUSR, &fops_led_cfg}, - {"led_blink_time", S_IRUGO | S_IWUSR, &fops_led_blink_time}, - {"fw_capabilities", S_IRUGO, &fops_fw_capabilities}, - {"fw_version", S_IRUGO, &fops_fw_version}, + {"mbox", 0444, &fops_mbox}, + {"vrings", 0444, &fops_vring}, + {"stations", 0444, &fops_sta}, + {"desc", 0444, &fops_txdesc}, + {"bf", 0444, &fops_bf}, + {"ssid", 0644, &fops_ssid}, + {"mem_val", 0644, &fops_memread}, + {"reset", 0244, &fops_reset}, + {"rxon", 0244, &fops_rxon}, + {"tx_mgmt", 0244, &fops_txmgmt}, + {"wmi_send", 0244, &fops_wmi}, + {"back", 0644, &fops_back}, + {"pmccfg", 0644, &fops_pmccfg}, + {"pmcdata", 0444, &fops_pmcdata}, + {"temp", 0444, &fops_temp}, + {"freq", 0444, &fops_freq}, + {"link", 0444, &fops_link}, + {"info", 0444, &fops_info}, + {"recovery", 0644, &fops_recovery}, + {"led_cfg", 0644, &fops_led_cfg}, + {"led_blink_time", 0644, &fops_led_blink_time}, + {"fw_capabilities", 0444, &fops_fw_capabilities}, + {"fw_version", 0444, &fops_fw_version}, }; static void wil6210_debugfs_init_files(struct wil6210_priv *wil, @@ -1693,30 +1695,32 @@ static void wil6210_debugfs_init_isr(struct wil6210_priv *wil, /* fields in struct wil6210_priv */ static const struct dbg_off dbg_wil_off[] = { - WIL_FIELD(privacy, S_IRUGO, doff_u32), - WIL_FIELD(status[0], S_IRUGO | S_IWUSR, doff_ulong), - WIL_FIELD(hw_version, S_IRUGO, doff_x32), - WIL_FIELD(recovery_count, S_IRUGO, doff_u32), - WIL_FIELD(ap_isolate, S_IRUGO, doff_u32), - WIL_FIELD(discovery_mode, S_IRUGO | S_IWUSR, doff_u8), + WIL_FIELD(privacy, 0444, doff_u32), + WIL_FIELD(status[0], 0644, doff_ulong), + WIL_FIELD(hw_version, 0444, doff_x32), + WIL_FIELD(recovery_count, 0444, doff_u32), + WIL_FIELD(ap_isolate, 0444, doff_u32), + WIL_FIELD(discovery_mode, 0644, doff_u8), + WIL_FIELD(chip_revision, 0444, doff_u8), + WIL_FIELD(abft_len, 0644, doff_u8), {}, }; static const struct dbg_off dbg_wil_regs[] = { - {"RGF_MAC_MTRL_COUNTER_0", S_IRUGO, HOSTADDR(RGF_MAC_MTRL_COUNTER_0), + {"RGF_MAC_MTRL_COUNTER_0", 0444, HOSTADDR(RGF_MAC_MTRL_COUNTER_0), doff_io32}, - {"RGF_USER_USAGE_1", S_IRUGO, HOSTADDR(RGF_USER_USAGE_1), doff_io32}, + {"RGF_USER_USAGE_1", 0444, HOSTADDR(RGF_USER_USAGE_1), doff_io32}, {}, }; /* static parameters */ static const struct dbg_off dbg_statics[] = { - {"desc_index", S_IRUGO | S_IWUSR, (ulong)&dbg_txdesc_index, doff_u32}, - {"vring_index", S_IRUGO | S_IWUSR, (ulong)&dbg_vring_index, doff_u32}, - {"mem_addr", S_IRUGO | S_IWUSR, (ulong)&mem_addr, doff_u32}, - {"vring_idle_trsh", S_IRUGO | S_IWUSR, (ulong)&vring_idle_trsh, + {"desc_index", 0644, (ulong)&dbg_txdesc_index, doff_u32}, + {"vring_index", 0644, (ulong)&dbg_vring_index, doff_u32}, + {"mem_addr", 0644, (ulong)&mem_addr, doff_u32}, + {"vring_idle_trsh", 0644, (ulong)&vring_idle_trsh, doff_u32}, - {"led_polarity", S_IRUGO | S_IWUSR, (ulong)&led_polarity, doff_u8}, + {"led_polarity", 0644, (ulong)&led_polarity, doff_u8}, {}, }; diff --git a/drivers/net/wireless/ath/wil6210/ethtool.c b/drivers/net/wireless/ath/wil6210/ethtool.c index 7053b62ca8d3..adcfef4dabf7 100644 --- a/drivers/net/wireless/ath/wil6210/ethtool.c +++ b/drivers/net/wireless/ath/wil6210/ethtool.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Qualcomm Atheros, Inc. + * Copyright (c) 2014,2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -27,7 +27,7 @@ static int wil_ethtoolops_begin(struct net_device *ndev) mutex_lock(&wil->mutex); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "ethtoolops_begin\n"); return 0; } @@ -36,7 +36,7 @@ static void wil_ethtoolops_complete(struct net_device *ndev) { struct wil6210_priv *wil = ndev_to_wil(ndev); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "ethtoolops_complete\n"); mutex_unlock(&wil->mutex); } @@ -48,7 +48,7 @@ static int wil_ethtoolops_get_coalesce(struct net_device *ndev, u32 tx_itr_en, tx_itr_val = 0; u32 rx_itr_en, rx_itr_val = 0; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "ethtoolops_get_coalesce\n"); tx_itr_en = wil_r(wil, RGF_DMA_ITR_TX_CNT_CTL); if (tx_itr_en & BIT_DMA_ITR_TX_CNT_CTL_EN) @@ -68,7 +68,7 @@ static int wil_ethtoolops_set_coalesce(struct net_device *ndev, { struct wil6210_priv *wil = ndev_to_wil(ndev); - wil_dbg_misc(wil, "%s(rx %d usec, tx %d usec)\n", __func__, + wil_dbg_misc(wil, "ethtoolops_set_coalesce: rx %d usec, tx %d usec\n", cp->rx_coalesce_usecs, cp->tx_coalesce_usecs); if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { diff --git a/drivers/net/wireless/ath/wil6210/fw.c b/drivers/net/wireless/ath/wil6210/fw.c index 82aae2d705b4..540fc20984d8 100644 --- a/drivers/net/wireless/ath/wil6210/fw.c +++ b/drivers/net/wireless/ath/wil6210/fw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015 Qualcomm Atheros, Inc. + * Copyright (c) 2014-2015,2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,8 +19,9 @@ #include "wil6210.h" #include "fw.h" -MODULE_FIRMWARE(WIL_FW_NAME); -MODULE_FIRMWARE(WIL_FW2_NAME); +MODULE_FIRMWARE(WIL_FW_NAME_DEFAULT); +MODULE_FIRMWARE(WIL_FW_NAME_SPARROW_PLUS); +MODULE_FIRMWARE(WIL_BOARD_FILE_NAME); static void wil_memset_toio_32(volatile void __iomem *dst, u32 val, diff --git a/drivers/net/wireless/ath/wil6210/fw_inc.c b/drivers/net/wireless/ath/wil6210/fw_inc.c index 8f40eb301924..f4901587c005 100644 --- a/drivers/net/wireless/ath/wil6210/fw_inc.c +++ b/drivers/net/wireless/ath/wil6210/fw_inc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -537,3 +537,22 @@ out: release_firmware(fw); return rc; } + +/** + * wil_fw_verify_file_exists - checks if firmware file exist + * + * @wil: driver context + * @name: firmware file name + * + * return value - boolean, true for success, false for failure + */ +bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name) +{ + const struct firmware *fw; + int rc; + + rc = request_firmware(&fw, name, wil_to_dev(wil)); + if (!rc) + release_firmware(fw); + return rc != -ENOENT; +} diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c index 64046e0bd0a2..cab1e5c0e374 100644 --- a/drivers/net/wireless/ath/wil6210/interrupt.c +++ b/drivers/net/wireless/ath/wil6210/interrupt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -94,7 +94,7 @@ static void wil6210_mask_irq_rx(struct wil6210_priv *wil) static void wil6210_mask_irq_misc(struct wil6210_priv *wil, bool mask_halp) { - wil_dbg_irq(wil, "%s: mask_halp(%s)\n", __func__, + wil_dbg_irq(wil, "mask_irq_misc: mask_halp(%s)\n", mask_halp ? "true" : "false"); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMS), @@ -103,7 +103,7 @@ static void wil6210_mask_irq_misc(struct wil6210_priv *wil, bool mask_halp) void wil6210_mask_halp(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "mask_halp\n"); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMS), BIT_DMA_EP_MISC_ICR_HALP); @@ -111,7 +111,7 @@ void wil6210_mask_halp(struct wil6210_priv *wil) static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "mask_irq_pseudo\n"); wil_w(wil, RGF_DMA_PSEUDO_CAUSE_MASK_SW, WIL6210_IRQ_DISABLE); @@ -134,7 +134,7 @@ void wil6210_unmask_irq_rx(struct wil6210_priv *wil) static void wil6210_unmask_irq_misc(struct wil6210_priv *wil, bool unmask_halp) { - wil_dbg_irq(wil, "%s: unmask_halp(%s)\n", __func__, + wil_dbg_irq(wil, "unmask_irq_misc: unmask_halp(%s)\n", unmask_halp ? "true" : "false"); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMC), @@ -143,7 +143,7 @@ static void wil6210_unmask_irq_misc(struct wil6210_priv *wil, bool unmask_halp) static void wil6210_unmask_halp(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "unmask_halp\n"); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, IMC), BIT_DMA_EP_MISC_ICR_HALP); @@ -151,7 +151,7 @@ static void wil6210_unmask_halp(struct wil6210_priv *wil) static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "unmask_irq_pseudo\n"); set_bit(wil_status_irqen, wil->status); @@ -160,7 +160,7 @@ static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil) void wil_mask_irq(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "mask_irq\n"); wil6210_mask_irq_tx(wil); wil6210_mask_irq_rx(wil); @@ -170,7 +170,7 @@ void wil_mask_irq(struct wil6210_priv *wil) void wil_unmask_irq(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "unmask_irq\n"); wil_w(wil, RGF_DMA_EP_RX_ICR + offsetof(struct RGF_ICR, ICC), WIL_ICR_ICC_VALUE); @@ -187,7 +187,7 @@ void wil_unmask_irq(struct wil6210_priv *wil) void wil_configure_interrupt_moderation(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "configure_interrupt_moderation\n"); /* disable interrupt moderation for monitor * to get better timestamp precision @@ -400,7 +400,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie) } if (isr & BIT_DMA_EP_MISC_ICR_HALP) { - wil_dbg_irq(wil, "%s: HALP IRQ invoked\n", __func__); + wil_dbg_irq(wil, "irq_misc: HALP IRQ invoked\n"); wil6210_mask_halp(wil); isr &= ~BIT_DMA_EP_MISC_ICR_HALP; complete(&wil->halp.comp); @@ -599,7 +599,7 @@ void wil6210_clear_irq(struct wil6210_priv *wil) void wil6210_set_halp(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "set_halp\n"); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICS), BIT_DMA_EP_MISC_ICR_HALP); @@ -607,7 +607,7 @@ void wil6210_set_halp(struct wil6210_priv *wil) void wil6210_clear_halp(struct wil6210_priv *wil) { - wil_dbg_irq(wil, "%s()\n", __func__); + wil_dbg_irq(wil, "clear_halp\n"); wil_w(wil, RGF_DMA_EP_MISC_ICR + offsetof(struct RGF_ICR, ICR), BIT_DMA_EP_MISC_ICR_HALP); @@ -618,7 +618,7 @@ int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi) { int rc; - wil_dbg_misc(wil, "%s(%s)\n", __func__, use_msi ? "MSI" : "INTx"); + wil_dbg_misc(wil, "init_irq: %s\n", use_msi ? "MSI" : "INTx"); rc = request_threaded_irq(irq, wil6210_hardirq, wil6210_thread_irq, @@ -629,7 +629,7 @@ int wil6210_init_irq(struct wil6210_priv *wil, int irq, bool use_msi) void wil6210_fini_irq(struct wil6210_priv *wil, int irq) { - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "fini_irq:\n"); wil_mask_irq(wil); free_irq(irq, wil); diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index e2e021bcaa03..efb1f59aafd9 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -27,23 +27,23 @@ #define WAIT_FOR_SCAN_ABORT_MS 1000 bool debug_fw; /* = false; */ -module_param(debug_fw, bool, S_IRUGO); +module_param(debug_fw, bool, 0444); MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug"); static bool oob_mode; -module_param(oob_mode, bool, S_IRUGO); +module_param(oob_mode, bool, 0444); MODULE_PARM_DESC(oob_mode, " enable out of the box (OOB) mode in FW, for diagnostics and certification"); bool no_fw_recovery; -module_param(no_fw_recovery, bool, S_IRUGO | S_IWUSR); +module_param(no_fw_recovery, bool, 0644); MODULE_PARM_DESC(no_fw_recovery, " disable automatic FW error recovery"); /* if not set via modparam, will be set to default value of 1/8 of * rx ring size during init flow */ unsigned short rx_ring_overflow_thrsh = WIL6210_RX_HIGH_TRSH_INIT; -module_param(rx_ring_overflow_thrsh, ushort, S_IRUGO); +module_param(rx_ring_overflow_thrsh, ushort, 0444); MODULE_PARM_DESC(rx_ring_overflow_thrsh, " RX ring overflow threshold in descriptors."); @@ -73,7 +73,7 @@ static const struct kernel_param_ops mtu_max_ops = { .get = param_get_uint, }; -module_param_cb(mtu_max, &mtu_max_ops, &mtu_max, S_IRUGO); +module_param_cb(mtu_max, &mtu_max_ops, &mtu_max, 0444); MODULE_PARM_DESC(mtu_max, " Max MTU value."); static uint rx_ring_order = WIL_RX_RING_SIZE_ORDER_DEFAULT; @@ -102,11 +102,11 @@ static const struct kernel_param_ops ring_order_ops = { .get = param_get_uint, }; -module_param_cb(rx_ring_order, &ring_order_ops, &rx_ring_order, S_IRUGO); +module_param_cb(rx_ring_order, &ring_order_ops, &rx_ring_order, 0444); MODULE_PARM_DESC(rx_ring_order, " Rx ring order; size = 1 << order"); -module_param_cb(tx_ring_order, &ring_order_ops, &tx_ring_order, S_IRUGO); +module_param_cb(tx_ring_order, &ring_order_ops, &tx_ring_order, 0444); MODULE_PARM_DESC(tx_ring_order, " Tx ring order; size = 1 << order"); -module_param_cb(bcast_ring_order, &ring_order_ops, &bcast_ring_order, S_IRUGO); +module_param_cb(bcast_ring_order, &ring_order_ops, &bcast_ring_order, 0444); MODULE_PARM_DESC(bcast_ring_order, " Bcast ring order; size = 1 << order"); #define RST_DELAY (20) /* msec, for loop in @wil_target_reset */ @@ -172,12 +172,16 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) struct wil_sta_info *sta = &wil->sta[cid]; might_sleep(); - wil_dbg_misc(wil, "%s(CID %d, status %d)\n", __func__, cid, - sta->status); + wil_dbg_misc(wil, "disconnect_cid: CID %d, status %d\n", + cid, sta->status); /* inform upper/lower layers */ if (sta->status != wil_sta_unused) { - if (!from_event) - wmi_disconnect_sta(wil, sta->addr, reason_code, true); + if (!from_event) { + bool del_sta = (wdev->iftype == NL80211_IFTYPE_AP) ? + disable_ap_sme : false; + wmi_disconnect_sta(wil, sta->addr, reason_code, + true, del_sta); + } switch (wdev->iftype) { case NL80211_IFTYPE_AP: @@ -237,7 +241,7 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, return; might_sleep(); - wil_info(wil, "%s(bssid=%pM, reason=%d, ev%s)\n", __func__, bssid, + wil_info(wil, "bssid=%pM, reason=%d, ev%s\n", bssid, reason_code, from_event ? "+" : "-"); /* Cases are: @@ -347,7 +351,7 @@ static int wil_wait_for_recovery(struct wil6210_priv *wil) void wil_set_recovery_state(struct wil6210_priv *wil, int state) { - wil_dbg_misc(wil, "%s(%d -> %d)\n", __func__, + wil_dbg_misc(wil, "set_recovery_state: %d -> %d\n", wil->recovery_state, state); wil->recovery_state = state; @@ -489,7 +493,7 @@ int wil_priv_init(struct wil6210_priv *wil) { uint i; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "priv_init\n"); memset(wil->sta, 0, sizeof(wil->sta)); for (i = 0; i < WIL6210_MAX_CID; i++) @@ -564,7 +568,7 @@ out_wmi_wq: void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, u16 reason_code, bool from_event) { - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "disconnect\n"); del_timer_sync(&wil->connect_timer); _wil6210_disconnect(wil, bssid, reason_code, from_event); @@ -572,7 +576,7 @@ void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, void wil_priv_deinit(struct wil6210_priv *wil) { - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "priv_deinit\n"); wil_set_recovery_state(wil, fw_recovery_idle); del_timer_sync(&wil->scan_timer); @@ -605,7 +609,7 @@ static inline void wil_release_cpu(struct wil6210_priv *wil) static void wil_set_oob_mode(struct wil6210_priv *wil, bool enable) { - wil_info(wil, "%s: enable=%d\n", __func__, enable); + wil_info(wil, "enable=%d\n", enable); if (enable) wil_s(wil, RGF_USER_USAGE_6, BIT_USER_OOB_MODE); else @@ -861,7 +865,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) { int rc; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "reset\n"); WARN_ON(!mutex_is_locked(&wil->mutex)); WARN_ON(test_bit(wil_status_napi_en, wil->status)); @@ -884,9 +888,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) rc = wil->platform_ops.notify(wil->platform_handle, WIL_PLATFORM_EVT_PRE_RESET); if (rc) - wil_err(wil, - "%s: PRE_RESET platform notify failed, rc %d\n", - __func__, rc); + wil_err(wil, "PRE_RESET platform notify failed, rc %d\n", + rc); } set_bit(wil_status_resetting, wil->status); @@ -915,7 +918,10 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) flush_workqueue(wil->wmi_wq); wil_bl_crash_info(wil, false); + wil_disable_irq(wil); rc = wil_target_reset(wil); + wil6210_clear_irq(wil); + wil_enable_irq(wil); wil_rx_fini(wil); if (rc) { wil_bl_crash_info(wil, true); @@ -930,16 +936,16 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) wil_set_oob_mode(wil, oob_mode); if (load_fw) { - wil_info(wil, "Use firmware <%s> + board <%s>\n", WIL_FW_NAME, - WIL_FW2_NAME); + wil_info(wil, "Use firmware <%s> + board <%s>\n", + wil->wil_fw_name, WIL_BOARD_FILE_NAME); wil_halt_cpu(wil); memset(wil->fw_version, 0, sizeof(wil->fw_version)); /* Loading f/w from the file */ - rc = wil_request_firmware(wil, WIL_FW_NAME, true); + rc = wil_request_firmware(wil, wil->wil_fw_name, true); if (rc) return rc; - rc = wil_request_firmware(wil, WIL_FW2_NAME, true); + rc = wil_request_firmware(wil, WIL_BOARD_FILE_NAME, true); if (rc) return rc; @@ -976,8 +982,7 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) /* check FW is responsive */ rc = wmi_echo(wil); if (rc) { - wil_err(wil, "%s: wmi_echo failed, rc %d\n", - __func__, rc); + wil_err(wil, "wmi_echo failed, rc %d\n", rc); return rc; } @@ -987,9 +992,8 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) rc = wil->platform_ops.notify(wil->platform_handle, WIL_PLATFORM_EVT_FW_RDY); if (rc) { - wil_err(wil, - "%s: FW_RDY notify failed, rc %d\n", - __func__, rc); + wil_err(wil, "FW_RDY notify failed, rc %d\n", + rc); rc = 0; } } @@ -1073,7 +1077,7 @@ int wil_up(struct wil6210_priv *wil) { int rc; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "up\n"); mutex_lock(&wil->mutex); rc = __wil_up(wil); @@ -1113,7 +1117,7 @@ int wil_down(struct wil6210_priv *wil) { int rc; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "down\n"); wil_set_recovery_state(wil, fw_recovery_idle); mutex_lock(&wil->mutex); @@ -1146,25 +1150,24 @@ void wil_halp_vote(struct wil6210_priv *wil) mutex_lock(&wil->halp.lock); - wil_dbg_irq(wil, "%s: start, HALP ref_cnt (%d)\n", __func__, + wil_dbg_irq(wil, "halp_vote: start, HALP ref_cnt (%d)\n", wil->halp.ref_cnt); if (++wil->halp.ref_cnt == 1) { wil6210_set_halp(wil); rc = wait_for_completion_timeout(&wil->halp.comp, to_jiffies); if (!rc) { - wil_err(wil, "%s: HALP vote timed out\n", __func__); + wil_err(wil, "HALP vote timed out\n"); /* Mask HALP as done in case the interrupt is raised */ wil6210_mask_halp(wil); } else { wil_dbg_irq(wil, - "%s: HALP vote completed after %d ms\n", - __func__, + "halp_vote: HALP vote completed after %d ms\n", jiffies_to_msecs(to_jiffies - rc)); } } - wil_dbg_irq(wil, "%s: end, HALP ref_cnt (%d)\n", __func__, + wil_dbg_irq(wil, "halp_vote: end, HALP ref_cnt (%d)\n", wil->halp.ref_cnt); mutex_unlock(&wil->halp.lock); @@ -1176,15 +1179,15 @@ void wil_halp_unvote(struct wil6210_priv *wil) mutex_lock(&wil->halp.lock); - wil_dbg_irq(wil, "%s: start, HALP ref_cnt (%d)\n", __func__, + wil_dbg_irq(wil, "halp_unvote: start, HALP ref_cnt (%d)\n", wil->halp.ref_cnt); if (--wil->halp.ref_cnt == 0) { wil6210_clear_halp(wil); - wil_dbg_irq(wil, "%s: HALP unvote\n", __func__); + wil_dbg_irq(wil, "HALP unvote\n"); } - wil_dbg_irq(wil, "%s: end, HALP ref_cnt (%d)\n", __func__, + wil_dbg_irq(wil, "halp_unvote:end, HALP ref_cnt (%d)\n", wil->halp.ref_cnt); mutex_unlock(&wil->halp.lock); diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 6676001dcbca..708facd5f667 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -22,10 +22,11 @@ static int wil_open(struct net_device *ndev) { struct wil6210_priv *wil = ndev_to_wil(ndev); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "open\n"); - if (debug_fw) { - wil_err(wil, "%s() while in debug_fw mode\n", __func__); + if (debug_fw || + test_bit(WMI_FW_CAPABILITY_WMI_ONLY, wil->fw_capabilities)) { + wil_err(wil, "while in debug_fw or wmi_only mode\n"); return -EINVAL; } @@ -36,7 +37,7 @@ static int wil_stop(struct net_device *ndev) { struct wil6210_priv *wil = ndev_to_wil(ndev); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "stop\n"); return wil_down(wil); } @@ -68,7 +69,7 @@ static int wil6210_netdev_poll_rx(struct napi_struct *napi, int budget) done = budget - quota; if (done < budget) { - napi_complete(napi); + napi_complete_done(napi, done); wil6210_unmask_irq_rx(wil); wil_dbg_txrx(wil, "NAPI RX complete\n"); } @@ -132,7 +133,7 @@ void *wil_if_alloc(struct device *dev) wil->wdev = wdev; wil->radio_wdev = wdev; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "if_alloc\n"); rc = wil_priv_init(wil); if (rc) { @@ -179,7 +180,7 @@ void wil_if_free(struct wil6210_priv *wil) { struct net_device *ndev = wil_to_ndev(wil); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "if_free\n"); if (!ndev) return; @@ -234,7 +235,7 @@ void wil_if_remove(struct wil6210_priv *wil) struct net_device *ndev = wil_to_ndev(wil); struct wireless_dev *wdev = wil_to_wdev(wil); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "if_remove\n"); unregister_netdev(ndev); wiphy_unregister(wdev->wiphy); diff --git a/drivers/net/wireless/ath/wil6210/p2p.c b/drivers/net/wireless/ath/wil6210/p2p.c index fbae99525e01..792484756654 100644 --- a/drivers/net/wireless/ath/wil6210/p2p.c +++ b/drivers/net/wireless/ath/wil6210/p2p.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -69,7 +69,7 @@ void wil_p2p_discovery_timer_fn(ulong x) { struct wil6210_priv *wil = (void *)x; - wil_dbg_misc(wil, "%s\n", __func__); + wil_dbg_misc(wil, "p2p_discovery_timer_fn\n"); schedule_work(&wil->p2p.discovery_expired_work); } @@ -80,27 +80,25 @@ int wil_p2p_search(struct wil6210_priv *wil, int rc; struct wil_p2p_info *p2p = &wil->p2p; - wil_dbg_misc(wil, "%s: channel %d\n", - __func__, P2P_DMG_SOCIAL_CHANNEL); + wil_dbg_misc(wil, "p2p_search: channel %d\n", P2P_DMG_SOCIAL_CHANNEL); lockdep_assert_held(&wil->mutex); if (p2p->discovery_started) { - wil_err(wil, "%s: search failed. discovery already ongoing\n", - __func__); + wil_err(wil, "search failed. discovery already ongoing\n"); rc = -EBUSY; goto out; } rc = wmi_p2p_cfg(wil, P2P_DMG_SOCIAL_CHANNEL, P2P_DEFAULT_BI); if (rc) { - wil_err(wil, "%s: wmi_p2p_cfg failed\n", __func__); + wil_err(wil, "wmi_p2p_cfg failed\n"); goto out; } rc = wmi_set_ssid(wil, strlen(P2P_WILDCARD_SSID), P2P_WILDCARD_SSID); if (rc) { - wil_err(wil, "%s: wmi_set_ssid failed\n", __func__); + wil_err(wil, "wmi_set_ssid failed\n"); goto out_stop; } @@ -108,8 +106,7 @@ int wil_p2p_search(struct wil6210_priv *wil, rc = wmi_set_ie(wil, WMI_FRAME_PROBE_REQ, request->ie_len, request->ie); if (rc) { - wil_err(wil, "%s: wmi_set_ie(WMI_FRAME_PROBE_REQ) failed\n", - __func__); + wil_err(wil, "wmi_set_ie(WMI_FRAME_PROBE_REQ) failed\n"); goto out_stop; } @@ -119,14 +116,13 @@ int wil_p2p_search(struct wil6210_priv *wil, rc = wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, request->ie_len, request->ie); if (rc) { - wil_err(wil, "%s: wmi_set_ie(WMI_FRAME_PROBE_RESP) failed\n", - __func__); + wil_err(wil, "wmi_set_ie(WMI_FRAME_PROBE_RESP) failed\n"); goto out_stop; } rc = wmi_start_search(wil); if (rc) { - wil_err(wil, "%s: wmi_start_search failed\n", __func__); + wil_err(wil, "wmi_start_search failed\n"); goto out_stop; } @@ -153,12 +149,12 @@ int wil_p2p_listen(struct wil6210_priv *wil, struct wireless_dev *wdev, if (!chan) return -EINVAL; - wil_dbg_misc(wil, "%s: duration %d\n", __func__, duration); + wil_dbg_misc(wil, "p2p_listen: duration %d\n", duration); mutex_lock(&wil->mutex); if (p2p->discovery_started) { - wil_err(wil, "%s: discovery already ongoing\n", __func__); + wil_err(wil, "discovery already ongoing\n"); rc = -EBUSY; goto out; } @@ -220,8 +216,8 @@ int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie) mutex_lock(&wil->mutex); if (cookie != p2p->cookie) { - wil_info(wil, "%s: Cookie mismatch: 0x%016llx vs. 0x%016llx\n", - __func__, p2p->cookie, cookie); + wil_info(wil, "Cookie mismatch: 0x%016llx vs. 0x%016llx\n", + p2p->cookie, cookie); mutex_unlock(&wil->mutex); return -ENOENT; } @@ -231,7 +227,7 @@ int wil_p2p_cancel_listen(struct wil6210_priv *wil, u64 cookie) mutex_unlock(&wil->mutex); if (!started) { - wil_err(wil, "%s: listen not started\n", __func__); + wil_err(wil, "listen not started\n"); return -ENOENT; } @@ -253,7 +249,7 @@ void wil_p2p_listen_expired(struct work_struct *work) struct wil6210_priv, p2p); u8 started; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "p2p_listen_expired\n"); mutex_lock(&wil->mutex); started = wil_p2p_stop_discovery(wil); @@ -279,7 +275,7 @@ void wil_p2p_search_expired(struct work_struct *work) struct wil6210_priv, p2p); u8 started; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "p2p_search_expired\n"); mutex_lock(&wil->mutex); started = wil_p2p_stop_discovery(wil); diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c index 44746ca0d2e6..874c787727fe 100644 --- a/drivers/net/wireless/ath/wil6210/pcie_bus.c +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c @@ -23,7 +23,7 @@ #include <linux/rtnetlink.h> static bool use_msi = true; -module_param(use_msi, bool, S_IRUGO); +module_param(use_msi, bool, 0444); MODULE_PARM_DESC(use_msi, " Use MSI interrupt, default - true"); #ifdef CONFIG_PM @@ -36,18 +36,38 @@ static int wil6210_pm_notify(struct notifier_block *notify_block, static void wil_set_capabilities(struct wil6210_priv *wil) { - u32 rev_id = wil_r(wil, RGF_USER_JTAG_DEV_ID); + u32 jtag_id = wil_r(wil, RGF_USER_JTAG_DEV_ID); + u8 chip_revision = (wil_r(wil, RGF_USER_REVISION_ID) & + RGF_USER_REVISION_ID_MASK); bitmap_zero(wil->hw_capabilities, hw_capability_last); bitmap_zero(wil->fw_capabilities, WMI_FW_CAPABILITY_MAX); - - switch (rev_id) { - case JTAG_DEV_ID_SPARROW_B0: - wil->hw_name = "Sparrow B0"; - wil->hw_version = HW_VER_SPARROW_B0; + wil->wil_fw_name = WIL_FW_NAME_DEFAULT; + wil->chip_revision = chip_revision; + + switch (jtag_id) { + case JTAG_DEV_ID_SPARROW: + switch (chip_revision) { + case REVISION_ID_SPARROW_D0: + wil->hw_name = "Sparrow D0"; + wil->hw_version = HW_VER_SPARROW_D0; + if (wil_fw_verify_file_exists(wil, + WIL_FW_NAME_SPARROW_PLUS)) + wil->wil_fw_name = WIL_FW_NAME_SPARROW_PLUS; + break; + case REVISION_ID_SPARROW_B0: + wil->hw_name = "Sparrow B0"; + wil->hw_version = HW_VER_SPARROW_B0; + break; + default: + wil->hw_name = "Unknown"; + wil->hw_version = HW_VER_UNKNOWN; + break; + } break; default: - wil_err(wil, "Unknown board hardware 0x%08x\n", rev_id); + wil_err(wil, "Unknown board hardware, chip_id 0x%08x, chip_revision 0x%08x\n", + jtag_id, chip_revision); wil->hw_name = "Unknown"; wil->hw_version = HW_VER_UNKNOWN; } @@ -55,7 +75,7 @@ void wil_set_capabilities(struct wil6210_priv *wil) wil_info(wil, "Board hardware is %s\n", wil->hw_name); /* extract FW capabilities from file without loading the FW */ - wil_request_firmware(wil, WIL_FW_NAME, false); + wil_request_firmware(wil, wil->wil_fw_name, false); } void wil_disable_irq(struct wil6210_priv *wil) @@ -79,8 +99,10 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil) */ int msi_only = pdev->msi_enabled; bool _use_msi = use_msi; + bool wmi_only = test_bit(WMI_FW_CAPABILITY_WMI_ONLY, + wil->fw_capabilities); - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "if_pcie_enable, wmi_only %d\n", wmi_only); pdev->msi_enabled = 0; @@ -103,9 +125,11 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil) if (rc) goto stop_master; - /* need reset here to obtain MAC */ + /* need reset here to obtain MAC or in case of WMI-only FW, full reset + * and fw loading takes place + */ mutex_lock(&wil->mutex); - rc = wil_reset(wil, false); + rc = wil_reset(wil, wmi_only); mutex_unlock(&wil->mutex); if (rc) goto release_irq; @@ -125,7 +149,7 @@ static int wil_if_pcie_disable(struct wil6210_priv *wil) { struct pci_dev *pdev = wil->pdev; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "if_pcie_disable\n"); pci_clear_master(pdev); /* disable and release IRQ */ @@ -289,7 +313,7 @@ static void wil_pcie_remove(struct pci_dev *pdev) struct wil6210_priv *wil = pci_get_drvdata(pdev); void __iomem *csr = wil->csr; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "pcie_remove\n"); #ifdef CONFIG_PM #ifdef CONFIG_PM_SLEEP @@ -327,8 +351,7 @@ static int wil6210_suspend(struct device *dev, bool is_runtime) struct pci_dev *pdev = to_pci_dev(dev); struct wil6210_priv *wil = pci_get_drvdata(pdev); - wil_dbg_pm(wil, "%s(%s)\n", __func__, - is_runtime ? "runtime" : "system"); + wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system"); rc = wil_can_suspend(wil, is_runtime); if (rc) @@ -354,8 +377,7 @@ static int wil6210_resume(struct device *dev, bool is_runtime) struct pci_dev *pdev = to_pci_dev(dev); struct wil6210_priv *wil = pci_get_drvdata(pdev); - wil_dbg_pm(wil, "%s(%s)\n", __func__, - is_runtime ? "runtime" : "system"); + wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system"); /* allow master */ pci_set_master(pdev); @@ -375,7 +397,7 @@ static int wil6210_pm_notify(struct notifier_block *notify_block, int rc = 0; enum wil_platform_event evt; - wil_dbg_pm(wil, "%s: mode (%ld)\n", __func__, mode); + wil_dbg_pm(wil, "pm_notify: mode (%ld)\n", mode); switch (mode) { case PM_HIBERNATION_PREPARE: diff --git a/drivers/net/wireless/ath/wil6210/pm.c b/drivers/net/wireless/ath/wil6210/pm.c index 11ee24d509e5..a0acb2d0cb79 100644 --- a/drivers/net/wireless/ath/wil6210/pm.c +++ b/drivers/net/wireless/ath/wil6210/pm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014,2016 Qualcomm Atheros, Inc. + * Copyright (c) 2014,2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -21,8 +21,7 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime) int rc = 0; struct wireless_dev *wdev = wil->wdev; - wil_dbg_pm(wil, "%s(%s)\n", __func__, - is_runtime ? "runtime" : "system"); + wil_dbg_pm(wil, "can_suspend: %s\n", is_runtime ? "runtime" : "system"); if (!netif_running(wil_to_ndev(wil))) { /* can always sleep when down */ @@ -59,7 +58,7 @@ int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime) } out: - wil_dbg_pm(wil, "%s(%s) => %s (%d)\n", __func__, + wil_dbg_pm(wil, "can_suspend: %s => %s (%d)\n", is_runtime ? "runtime" : "system", rc ? "No" : "Yes", rc); return rc; @@ -70,8 +69,7 @@ int wil_suspend(struct wil6210_priv *wil, bool is_runtime) int rc = 0; struct net_device *ndev = wil_to_ndev(wil); - wil_dbg_pm(wil, "%s(%s)\n", __func__, - is_runtime ? "runtime" : "system"); + wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system"); /* if netif up, hardware is alive, shut it down */ if (ndev->flags & IFF_UP) { @@ -86,7 +84,7 @@ int wil_suspend(struct wil6210_priv *wil, bool is_runtime) rc = wil->platform_ops.suspend(wil->platform_handle); out: - wil_dbg_pm(wil, "%s(%s) => %d\n", __func__, + wil_dbg_pm(wil, "suspend: %s => %d\n", is_runtime ? "runtime" : "system", rc); return rc; } @@ -96,8 +94,7 @@ int wil_resume(struct wil6210_priv *wil, bool is_runtime) int rc = 0; struct net_device *ndev = wil_to_ndev(wil); - wil_dbg_pm(wil, "%s(%s)\n", __func__, - is_runtime ? "runtime" : "system"); + wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system"); if (wil->platform_ops.resume) { rc = wil->platform_ops.resume(wil->platform_handle); @@ -115,7 +112,7 @@ int wil_resume(struct wil6210_priv *wil, bool is_runtime) rc = wil_up(wil); out: - wil_dbg_pm(wil, "%s(%s) => %d\n", __func__, + wil_dbg_pm(wil, "resume: %s => %d\n", is_runtime ? "runtime" : "system", rc); return rc; } diff --git a/drivers/net/wireless/ath/wil6210/pmc.c b/drivers/net/wireless/ath/wil6210/pmc.c index b9faae0278c9..3ff4f4ce9fef 100644 --- a/drivers/net/wireless/ath/wil6210/pmc.c +++ b/drivers/net/wireless/ath/wil6210/pmc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2015 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2015,2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -60,7 +60,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil, if (wil_is_pmc_allocated(pmc)) { /* sanity check */ - wil_err(wil, "%s: ERROR pmc is already allocated\n", __func__); + wil_err(wil, "ERROR pmc is already allocated\n"); goto no_release_err; } if ((num_descriptors <= 0) || (descriptor_size <= 0)) { @@ -90,21 +90,20 @@ void wil_pmc_alloc(struct wil6210_priv *wil, pmc->num_descriptors = num_descriptors; pmc->descriptor_size = descriptor_size; - wil_dbg_misc(wil, "%s: %d descriptors x %d bytes each\n", - __func__, num_descriptors, descriptor_size); + wil_dbg_misc(wil, "pmc_alloc: %d descriptors x %d bytes each\n", + num_descriptors, descriptor_size); /* allocate descriptors info list in pmc context*/ pmc->descriptors = kcalloc(num_descriptors, sizeof(struct desc_alloc_info), GFP_KERNEL); if (!pmc->descriptors) { - wil_err(wil, "%s: ERROR allocating pmc skb list\n", __func__); + wil_err(wil, "ERROR allocating pmc skb list\n"); goto no_release_err; } - wil_dbg_misc(wil, - "%s: allocated descriptors info list %p\n", - __func__, pmc->descriptors); + wil_dbg_misc(wil, "pmc_alloc: allocated descriptors info list %p\n", + pmc->descriptors); /* Allocate pring buffer and descriptors. * vring->va should be aligned on its size rounded up to power of 2 @@ -116,15 +115,14 @@ void wil_pmc_alloc(struct wil6210_priv *wil, GFP_KERNEL); wil_dbg_misc(wil, - "%s: allocated pring %p => %pad. %zd x %d = total %zd bytes\n", - __func__, + "pmc_alloc: allocated pring %p => %pad. %zd x %d = total %zd bytes\n", pmc->pring_va, &pmc->pring_pa, sizeof(struct vring_tx_desc), num_descriptors, sizeof(struct vring_tx_desc) * num_descriptors); if (!pmc->pring_va) { - wil_err(wil, "%s: ERROR allocating pmc pring\n", __func__); + wil_err(wil, "ERROR allocating pmc pring\n"); goto release_pmc_skb_list; } @@ -143,9 +141,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil, GFP_KERNEL); if (unlikely(!pmc->descriptors[i].va)) { - wil_err(wil, - "%s: ERROR allocating pmc descriptor %d", - __func__, i); + wil_err(wil, "ERROR allocating pmc descriptor %d", i); goto release_pmc_skbs; } @@ -165,21 +161,21 @@ void wil_pmc_alloc(struct wil6210_priv *wil, *_d = *d; } - wil_dbg_misc(wil, "%s: allocated successfully\n", __func__); + wil_dbg_misc(wil, "pmc_alloc: allocated successfully\n"); pmc_cmd.op = WMI_PMC_ALLOCATE; pmc_cmd.ring_size = cpu_to_le16(pmc->num_descriptors); pmc_cmd.mem_base = cpu_to_le64(pmc->pring_pa); - wil_dbg_misc(wil, "%s: send WMI_PMC_CMD with ALLOCATE op\n", __func__); + wil_dbg_misc(wil, "pmc_alloc: send WMI_PMC_CMD with ALLOCATE op\n"); pmc->last_cmd_status = wmi_send(wil, WMI_PMC_CMDID, &pmc_cmd, sizeof(pmc_cmd)); if (pmc->last_cmd_status) { wil_err(wil, - "%s: WMI_PMC_CMD with ALLOCATE op failed with status %d", - __func__, pmc->last_cmd_status); + "WMI_PMC_CMD with ALLOCATE op failed with status %d", + pmc->last_cmd_status); goto release_pmc_skbs; } @@ -188,7 +184,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil, return; release_pmc_skbs: - wil_err(wil, "%s: exit on error: Releasing skbs...\n", __func__); + wil_err(wil, "exit on error: Releasing skbs...\n"); for (i = 0; pmc->descriptors[i].va && i < num_descriptors; i++) { dma_free_coherent(dev, descriptor_size, @@ -197,7 +193,7 @@ release_pmc_skbs: pmc->descriptors[i].va = NULL; } - wil_err(wil, "%s: exit on error: Releasing pring...\n", __func__); + wil_err(wil, "exit on error: Releasing pring...\n"); dma_free_coherent(dev, sizeof(struct vring_tx_desc) * num_descriptors, @@ -207,8 +203,7 @@ release_pmc_skbs: pmc->pring_va = NULL; release_pmc_skb_list: - wil_err(wil, "%s: exit on error: Releasing descriptors info list...\n", - __func__); + wil_err(wil, "exit on error: Releasing descriptors info list...\n"); kfree(pmc->descriptors); pmc->descriptors = NULL; @@ -232,24 +227,23 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd) pmc->last_cmd_status = 0; if (!wil_is_pmc_allocated(pmc)) { - wil_dbg_misc(wil, "%s: Error, can't free - not allocated\n", - __func__); + wil_dbg_misc(wil, + "pmc_free: Error, can't free - not allocated\n"); pmc->last_cmd_status = -EPERM; mutex_unlock(&pmc->lock); return; } if (send_pmc_cmd) { - wil_dbg_misc(wil, "%s: send WMI_PMC_CMD with RELEASE op\n", - __func__); + wil_dbg_misc(wil, "send WMI_PMC_CMD with RELEASE op\n"); pmc_cmd.op = WMI_PMC_RELEASE; pmc->last_cmd_status = wmi_send(wil, WMI_PMC_CMDID, &pmc_cmd, sizeof(pmc_cmd)); if (pmc->last_cmd_status) { wil_err(wil, - "%s WMI_PMC_CMD with RELEASE op failed, status %d", - __func__, pmc->last_cmd_status); + "WMI_PMC_CMD with RELEASE op failed, status %d", + pmc->last_cmd_status); /* There's nothing we can do with this error. * Normally, it should never occur. * Continue to freeing all memory allocated for pmc. @@ -261,8 +255,8 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd) size_t buf_size = sizeof(struct vring_tx_desc) * pmc->num_descriptors; - wil_dbg_misc(wil, "%s: free pring va %p\n", - __func__, pmc->pring_va); + wil_dbg_misc(wil, "pmc_free: free pring va %p\n", + pmc->pring_va); dma_free_coherent(dev, buf_size, pmc->pring_va, pmc->pring_pa); pmc->pring_va = NULL; @@ -281,11 +275,11 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd) pmc->descriptors[i].pa); pmc->descriptors[i].va = NULL; } - wil_dbg_misc(wil, "%s: free descriptor info %d/%d\n", - __func__, i, pmc->num_descriptors); + wil_dbg_misc(wil, "pmc_free: free descriptor info %d/%d\n", i, + pmc->num_descriptors); wil_dbg_misc(wil, - "%s: free pmc descriptors info list %p\n", - __func__, pmc->descriptors); + "pmc_free: free pmc descriptors info list %p\n", + pmc->descriptors); kfree(pmc->descriptors); pmc->descriptors = NULL; } else { @@ -301,7 +295,7 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd) */ int wil_pmc_last_cmd_status(struct wil6210_priv *wil) { - wil_dbg_misc(wil, "%s: status %d\n", __func__, + wil_dbg_misc(wil, "pmc_last_cmd_status: status %d\n", wil->pmc.last_cmd_status); return wil->pmc.last_cmd_status; @@ -324,7 +318,7 @@ ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count, mutex_lock(&pmc->lock); if (!wil_is_pmc_allocated(pmc)) { - wil_err(wil, "%s: error, pmc is not allocated!\n", __func__); + wil_err(wil, "error, pmc is not allocated!\n"); pmc->last_cmd_status = -EPERM; mutex_unlock(&pmc->lock); return -EPERM; @@ -333,8 +327,8 @@ ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count, pmc_size = pmc->descriptor_size * pmc->num_descriptors; wil_dbg_misc(wil, - "%s: size %u, pos %lld\n", - __func__, (unsigned)count, *f_pos); + "pmc_read: size %u, pos %lld\n", + (u32)count, *f_pos); pmc->last_cmd_status = 0; @@ -343,15 +337,16 @@ ssize_t wil_pmc_read(struct file *filp, char __user *buf, size_t count, offset = *f_pos - (idx * pmc->descriptor_size); if (*f_pos >= pmc_size) { - wil_dbg_misc(wil, "%s: reached end of pmc buf: %lld >= %u\n", - __func__, *f_pos, (unsigned)pmc_size); + wil_dbg_misc(wil, + "pmc_read: reached end of pmc buf: %lld >= %u\n", + *f_pos, (u32)pmc_size); pmc->last_cmd_status = -ERANGE; goto out; } wil_dbg_misc(wil, - "%s: read from pos %lld (descriptor %llu, offset %llu) %zu bytes\n", - __func__, *f_pos, idx, offset, count); + "pmc_read: read from pos %lld (descriptor %llu, offset %llu) %zu bytes\n", + *f_pos, idx, offset, count); /* if no errors, return the copied byte count */ retval = simple_read_from_buffer(buf, diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c index 19ed127d4d05..7404b6f39c6a 100644 --- a/drivers/net/wireless/ath/wil6210/rx_reorder.c +++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2014-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -349,8 +349,8 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock) rc = wmi_addba_rx_resp(wil, cid, tid, dialog_token, status, agg_amsdu, agg_wsize, agg_timeout); if (rc || (status != WLAN_STATUS_SUCCESS)) { - wil_err(wil, "%s: do not apply ba, rc(%d), status(%d)\n", - __func__, rc, status); + wil_err(wil, "do not apply ba, rc(%d), status(%d)\n", rc, + status); goto out; } @@ -387,7 +387,7 @@ int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize) txdata->addba_in_progress = true; rc = wmi_addba(wil, ringid, agg_wsize, agg_timeout); if (rc) { - wil_err(wil, "%s: wmi_addba failed, rc (%d)", __func__, rc); + wil_err(wil, "wmi_addba failed, rc (%d)", rc); txdata->addba_in_progress = false; } diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index c1b4bb03e997..072182e527e6 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -29,12 +29,12 @@ #include "trace.h" static bool rtap_include_phy_info; -module_param(rtap_include_phy_info, bool, S_IRUGO); +module_param(rtap_include_phy_info, bool, 0444); MODULE_PARM_DESC(rtap_include_phy_info, " Include PHY info in the radiotap header, default - no"); bool rx_align_2; -module_param(rx_align_2, bool, S_IRUGO); +module_param(rx_align_2, bool, 0444); MODULE_PARM_DESC(rx_align_2, " align Rx buffers on 4*n+2, default - no"); static inline uint wil_rx_snaplen(void) @@ -112,7 +112,7 @@ static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring) size_t sz = vring->size * sizeof(vring->va[0]); uint i; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "vring_alloc:\n"); BUILD_BUG_ON(sizeof(vring->va[0]) != 32); @@ -745,7 +745,7 @@ void wil_rx_handle(struct wil6210_priv *wil, int *quota) wil_err(wil, "Rx IRQ while Rx not yet initialized\n"); return; } - wil_dbg_txrx(wil, "%s()\n", __func__); + wil_dbg_txrx(wil, "rx_handle\n"); while ((*quota > 0) && (NULL != (skb = wil_vring_reap_rx(wil, v)))) { (*quota)--; @@ -768,7 +768,7 @@ int wil_rx_init(struct wil6210_priv *wil, u16 size) struct vring *vring = &wil->vring_rx; int rc; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "rx_init\n"); if (vring->va) { wil_err(wil, "Rx ring already allocated\n"); @@ -799,7 +799,7 @@ void wil_rx_fini(struct wil6210_priv *wil) { struct vring *vring = &wil->vring_rx; - wil_dbg_misc(wil, "%s()\n", __func__); + wil_dbg_misc(wil, "rx_fini\n"); if (vring->va) wil_vring_free(wil, vring, 0); @@ -851,7 +851,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, struct vring *vring = &wil->vring_tx[id]; struct vring_tx_data *txdata = &wil->vring_tx_data[id]; - wil_dbg_misc(wil, "%s() max_mpdu_size %d\n", __func__, + wil_dbg_misc(wil, "vring_init_tx: max_mpdu_size %d\n", cmd.vring_cfg.tx_sw_ring.max_mpdu_size); lockdep_assert_held(&wil->mutex); @@ -931,7 +931,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size) struct vring *vring = &wil->vring_tx[id]; struct vring_tx_data *txdata = &wil->vring_tx_data[id]; - wil_dbg_misc(wil, "%s() max_mpdu_size %d\n", __func__, + wil_dbg_misc(wil, "vring_init_bcast: max_mpdu_size %d\n", cmd.vring_cfg.tx_sw_ring.max_mpdu_size); lockdep_assert_held(&wil->mutex); @@ -993,7 +993,7 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id) if (!vring->va) return; - wil_dbg_misc(wil, "%s() id=%d\n", __func__, id); + wil_dbg_misc(wil, "vring_fini_tx: id=%d\n", id); spin_lock_bh(&txdata->lock); txdata->dot1x_open = false; @@ -1032,12 +1032,14 @@ static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil, struct vring *v = &wil->vring_tx[i]; struct vring_tx_data *txdata = &wil->vring_tx_data[i]; - wil_dbg_txrx(wil, "%s(%pM) -> [%d]\n", - __func__, eth->h_dest, i); + wil_dbg_txrx(wil, "find_tx_ucast: (%pM) -> [%d]\n", + eth->h_dest, i); if (v->va && txdata->enabled) { return v; } else { - wil_dbg_txrx(wil, "vring[%d] not valid\n", i); + wil_dbg_txrx(wil, + "find_tx_ucast: vring[%d] not valid\n", + i); return NULL; } } @@ -1193,17 +1195,6 @@ found: return v; } -static struct vring *wil_find_tx_bcast(struct wil6210_priv *wil, - struct sk_buff *skb) -{ - struct wireless_dev *wdev = wil->wdev; - - if (wdev->iftype != NL80211_IFTYPE_AP) - return wil_find_tx_bcast_2(wil, skb); - - return wil_find_tx_bcast_1(wil, skb); -} - static int wil_tx_desc_map(struct vring_tx_desc *d, dma_addr_t pa, u32 len, int vring_index) { @@ -1373,8 +1364,8 @@ static int __wil_tx_vring_tso(struct wil6210_priv *wil, struct vring *vring, int gso_type; int rc = -EINVAL; - wil_dbg_txrx(wil, "%s() %d bytes to vring %d\n", - __func__, skb->len, vring_index); + wil_dbg_txrx(wil, "tx_vring_tso: %d bytes to vring %d\n", skb->len, + vring_index); if (unlikely(!txdata->enabled)) return -EINVAL; @@ -1643,8 +1634,8 @@ static int __wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, bool mcast = (vring_index == wil->bcast_vring); uint len = skb_headlen(skb); - wil_dbg_txrx(wil, "%s() %d bytes to vring %d\n", - __func__, skb->len, vring_index); + wil_dbg_txrx(wil, "tx_vring: %d bytes to vring %d\n", skb->len, + vring_index); if (unlikely(!txdata->enabled)) return -EINVAL; @@ -1884,7 +1875,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) static bool pr_once_fw; int rc; - wil_dbg_txrx(wil, "%s()\n", __func__); + wil_dbg_txrx(wil, "start_xmit\n"); if (unlikely(!test_bit(wil_status_fwready, wil->status))) { if (!pr_once_fw) { wil_err(wil, "FW not ready\n"); @@ -1903,12 +1894,26 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) pr_once_fw = false; /* find vring */ - if (wil->wdev->iftype == NL80211_IFTYPE_STATION) { - /* in STA mode (ESS), all to same VRING */ + if (wil->wdev->iftype == NL80211_IFTYPE_STATION && !wil->pbss) { + /* in STA mode (ESS), all to same VRING (to AP) */ vring = wil_find_tx_vring_sta(wil, skb); - } else { /* direct communication, find matching VRING */ - vring = bcast ? wil_find_tx_bcast(wil, skb) : - wil_find_tx_ucast(wil, skb); + } else if (bcast) { + if (wil->pbss) + /* in pbss, no bcast VRING - duplicate skb in + * all stations VRINGs + */ + vring = wil_find_tx_bcast_2(wil, skb); + else if (wil->wdev->iftype == NL80211_IFTYPE_AP) + /* AP has a dedicated bcast VRING */ + vring = wil_find_tx_bcast_1(wil, skb); + else + /* unexpected combination, fallback to duplicating + * the skb in all stations VRINGs + */ + vring = wil_find_tx_bcast_2(wil, skb); + } else { + /* unicast, find specific VRING by dest. address */ + vring = wil_find_tx_ucast(wil, skb); } if (unlikely(!vring)) { wil_dbg_txrx(wil, "No Tx VRING found for %pM\n", eth->h_dest); @@ -1982,7 +1987,7 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) return 0; } - wil_dbg_txrx(wil, "%s(%d)\n", __func__, ringid); + wil_dbg_txrx(wil, "tx_complete: (%d)\n", ringid); used_before_complete = wil_vring_used_tx(vring); diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index 237e1666df2d..085a2dbfa21d 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h @@ -33,10 +33,12 @@ extern int agg_wsize; extern u32 vring_idle_trsh; extern bool rx_align_2; extern bool debug_fw; +extern bool disable_ap_sme; #define WIL_NAME "wil6210" -#define WIL_FW_NAME "wil6210.fw" /* code */ -#define WIL_FW2_NAME "wil6210.brd" /* board & radio parameters */ +#define WIL_FW_NAME_DEFAULT "wil6210.fw" /* code Sparrow B0 */ +#define WIL_FW_NAME_SPARROW_PLUS "wil6210_sparrow_plus.fw" /* code Sparrow D0 */ +#define WIL_BOARD_FILE_NAME "wil6210.brd" /* board & radio parameters */ #define WIL_MAX_BUS_REQUEST_KBPS 800000 /* ~6.1Gbps */ @@ -98,6 +100,9 @@ static inline u32 wil_mtu2macbuf(u32 mtu) #define WIL6210_RX_HIGH_TRSH_INIT (0) #define WIL6210_RX_HIGH_TRSH_DEFAULT \ (1 << (WIL_RX_RING_SIZE_ORDER_DEFAULT - 3)) +#define WIL_MAX_DMG_AID 254 /* for DMG only 1-254 allowed (see + * 802.11REVmc/D5.0, section 9.4.1.8) + */ /* Hardware definitions begin */ /* @@ -249,7 +254,12 @@ struct RGF_ICR { #define BIT_CAF_OSC_DIG_XTAL_STABLE BIT(0) #define RGF_USER_JTAG_DEV_ID (0x880b34) /* device ID */ - #define JTAG_DEV_ID_SPARROW_B0 (0x2632072f) + #define JTAG_DEV_ID_SPARROW (0x2632072f) + +#define RGF_USER_REVISION_ID (0x88afe4) +#define RGF_USER_REVISION_ID_MASK (3) + #define REVISION_ID_SPARROW_B0 (0x0) + #define REVISION_ID_SPARROW_D0 (0x3) /* crash codes for FW/Ucode stored here */ #define RGF_FW_ASSERT_CODE (0x91f020) @@ -257,7 +267,8 @@ struct RGF_ICR { enum { HW_VER_UNKNOWN, - HW_VER_SPARROW_B0, /* JTAG_DEV_ID_SPARROW_B0 */ + HW_VER_SPARROW_B0, /* REVISION_ID_SPARROW_B0 */ + HW_VER_SPARROW_D0, /* REVISION_ID_SPARROW_D0 */ }; /* popular locations */ @@ -512,6 +523,7 @@ struct wil_sta_info { unsigned long tid_rx_stop_requested[BITS_TO_LONGS(WIL_STA_TID_NUM)]; struct wil_tid_crypto_rx tid_crypto_rx[WIL_STA_TID_NUM]; struct wil_tid_crypto_rx group_crypto_rx; + u8 aid; /* 1-254; 0 if unknown/not reported */ }; enum { @@ -583,7 +595,9 @@ struct wil6210_priv { DECLARE_BITMAP(status, wil_status_last); u8 fw_version[ETHTOOL_FWVERS_LEN]; u32 hw_version; + u8 chip_revision; const char *hw_name; + const char *wil_fw_name; DECLARE_BITMAP(hw_capabilities, hw_capability_last); DECLARE_BITMAP(fw_capabilities, WMI_FW_CAPABILITY_MAX); u8 n_mids; /* number of additional MIDs as reported by FW */ @@ -653,6 +667,7 @@ struct wil6210_priv { struct dentry *debug; struct wil_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)]; u8 discovery_mode; + u8 abft_len; void *platform_handle; struct wil_platform_ops platform_ops; @@ -816,8 +831,8 @@ int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie); int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring); int wmi_rxon(struct wil6210_priv *wil, bool on); int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_m, u32 *t_r); -int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason, - bool full_disconnect); +int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, + u16 reason, bool full_disconnect, bool del_sta); int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout); int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason); int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason); @@ -827,6 +842,7 @@ int wmi_ps_dev_profile_cfg(struct wil6210_priv *wil, enum wmi_ps_profile_type ps_profile); int wmi_set_mgmt_retry(struct wil6210_priv *wil, u8 retry_short); int wmi_get_mgmt_retry(struct wil6210_priv *wil, u8 *retry_short); +int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid); int wil_addba_rx_request(struct wil6210_priv *wil, u8 cidxtid, u8 dialog_token, __le16 ba_param_set, __le16 ba_timeout, __le16 ba_seq_ctrl); @@ -918,6 +934,7 @@ int wil_iftype_nl2wmi(enum nl80211_iftype type); int wil_ioctl(struct wil6210_priv *wil, void __user *data, int cmd); int wil_request_firmware(struct wil6210_priv *wil, const char *name, bool load); +bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name); int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime); int wil_suspend(struct wil6210_priv *wil, bool is_runtime); diff --git a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c index d051eea47a54..e53cf0cf7031 100644 --- a/drivers/net/wireless/ath/wil6210/wil_crash_dump.c +++ b/drivers/net/wireless/ath/wil6210/wil_crash_dump.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Qualcomm Atheros, Inc. + * Copyright (c) 2015,2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -62,13 +62,13 @@ int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size) u32 host_min, dump_size, offset, len; if (wil_fw_get_crash_dump_bounds(wil, &dump_size, &host_min)) { - wil_err(wil, "%s: fail to obtain crash dump size\n", __func__); + wil_err(wil, "fail to obtain crash dump size\n"); return -EINVAL; } if (dump_size > size) { - wil_err(wil, "%s: not enough space for dump. Need %d have %d\n", - __func__, dump_size, size); + wil_err(wil, "not enough space for dump. Need %d have %d\n", + dump_size, size); return -EINVAL; } @@ -83,8 +83,9 @@ int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size) len = map->to - map->from; offset = map->host - host_min; - wil_dbg_misc(wil, "%s() - dump %s, size %d, offset %d\n", - __func__, fw_mapping[i].name, len, offset); + wil_dbg_misc(wil, + "fw_copy_crash_dump: - dump %s, size %d, offset %d\n", + fw_mapping[i].name, len, offset); wil_memcpy_fromio_32((void * __force)(dest + offset), (const void __iomem * __force)data, len); @@ -99,7 +100,7 @@ void wil_fw_core_dump(struct wil6210_priv *wil) u32 fw_dump_size; if (wil_fw_get_crash_dump_bounds(wil, &fw_dump_size, NULL)) { - wil_err(wil, "%s: fail to get fw dump size\n", __func__); + wil_err(wil, "fail to get fw dump size\n"); return; } @@ -115,6 +116,5 @@ void wil_fw_core_dump(struct wil6210_priv *wil) * after 5 min */ dev_coredumpv(wil_to_dev(wil), fw_dump_data, fw_dump_size, GFP_KERNEL); - wil_info(wil, "%s: fw core dumped, size %d bytes\n", __func__, - fw_dump_size); + wil_info(wil, "fw core dumped, size %d bytes\n", fw_dump_size); } diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 7585003bef67..1f22c19696b1 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -24,16 +24,16 @@ #include "trace.h" static uint max_assoc_sta = WIL6210_MAX_CID; -module_param(max_assoc_sta, uint, S_IRUGO | S_IWUSR); +module_param(max_assoc_sta, uint, 0644); MODULE_PARM_DESC(max_assoc_sta, " Max number of stations associated to the AP"); int agg_wsize; /* = 0; */ -module_param(agg_wsize, int, S_IRUGO | S_IWUSR); +module_param(agg_wsize, int, 0644); MODULE_PARM_DESC(agg_wsize, " Window size for Tx Block Ack after connect;" " 0 - use default; < 0 - don't auto-establish"); u8 led_id = WIL_LED_INVALID_ID; -module_param(led_id, byte, S_IRUGO); +module_param(led_id, byte, 0444); MODULE_PARM_DESC(led_id, " 60G device led enablement. Set the led ID (0-2) to enable"); @@ -495,8 +495,8 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) } ch = evt->channel + 1; - wil_info(wil, "Connect %pM channel [%d] cid %d\n", - evt->bssid, ch, evt->cid); + wil_info(wil, "Connect %pM channel [%d] cid %d aid %d\n", + evt->bssid, ch, evt->cid, evt->aid); wil_hex_dump_wmi("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1, evt->assoc_info, len - sizeof(*evt), true); @@ -539,8 +539,8 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) } else if ((wdev->iftype == NL80211_IFTYPE_AP) || (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { if (wil->sta[evt->cid].status != wil_sta_unused) { - wil_err(wil, "%s: AP: Invalid status %d for CID %d\n", - __func__, wil->sta[evt->cid].status, evt->cid); + wil_err(wil, "AP: Invalid status %d for CID %d\n", + wil->sta[evt->cid].status, evt->cid); mutex_unlock(&wil->mutex); return; } @@ -553,22 +553,19 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) rc = wil_tx_init(wil, evt->cid); if (rc) { - wil_err(wil, "%s: config tx vring failed for CID %d, rc (%d)\n", - __func__, evt->cid, rc); + wil_err(wil, "config tx vring failed for CID %d, rc (%d)\n", + evt->cid, rc); wmi_disconnect_sta(wil, wil->sta[evt->cid].addr, - WLAN_REASON_UNSPECIFIED, false); + WLAN_REASON_UNSPECIFIED, false, false); } else { - wil_info(wil, "%s: successful connection to CID %d\n", - __func__, evt->cid); + wil_info(wil, "successful connection to CID %d\n", evt->cid); } if ((wdev->iftype == NL80211_IFTYPE_STATION) || (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { if (rc) { netif_carrier_off(ndev); - wil_err(wil, - "%s: cfg80211_connect_result with failure\n", - __func__); + wil_err(wil, "cfg80211_connect_result with failure\n"); cfg80211_connect_result(ndev, evt->bssid, NULL, 0, NULL, 0, WLAN_STATUS_UNSPECIFIED_FAILURE, @@ -583,8 +580,12 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) } } else if ((wdev->iftype == NL80211_IFTYPE_AP) || (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { - if (rc) + if (rc) { + if (disable_ap_sme) + /* notify new_sta has failed */ + cfg80211_del_sta(ndev, evt->bssid, GFP_KERNEL); goto out; + } memset(&sinfo, 0, sizeof(sinfo)); @@ -597,12 +598,13 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL); } else { - wil_err(wil, "%s: unhandled iftype %d for CID %d\n", - __func__, wdev->iftype, evt->cid); + wil_err(wil, "unhandled iftype %d for CID %d\n", wdev->iftype, + evt->cid); goto out; } wil->sta[evt->cid].status = wil_sta_connected; + wil->sta[evt->cid].aid = evt->aid; set_bit(wil_status_fwconnected, wil->status); wil_update_net_queues_bh(wil, NULL, false); @@ -687,6 +689,7 @@ static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len) { struct wmi_vring_en_event *evt = d; u8 vri = evt->vring_index; + struct wireless_dev *wdev = wil_to_wdev(wil); wil_dbg_wmi(wil, "Enable vring %d\n", vri); @@ -694,7 +697,12 @@ static void wmi_evt_vring_en(struct wil6210_priv *wil, int id, void *d, int len) wil_err(wil, "Enable for invalid vring %d\n", vri); return; } - wil->vring_tx_data[vri].dot1x_open = true; + + if (wdev->iftype != NL80211_IFTYPE_AP || !disable_ap_sme) + /* in AP mode with disable_ap_sme, this is done by + * wil_cfg80211_change_station() + */ + wil->vring_tx_data[vri].dot1x_open = true; if (vri == wil->bcast_vring) /* no BA for bcast */ return; if (agg_wsize >= 0) @@ -919,8 +927,8 @@ void wmi_recv_cmd(struct wil6210_priv *wil) offsetof(struct wil6210_mbox_ctl, rx.tail), r->tail); if (immed_reply) { - wil_dbg_wmi(wil, "%s: Complete WMI 0x%04x\n", - __func__, wil->reply_id); + wil_dbg_wmi(wil, "recv_cmd: Complete WMI 0x%04x\n", + wil->reply_id); kfree(evt); num_immed_reply++; complete(&wil->wmi_call); @@ -934,7 +942,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil) } } /* normally, 1 event per IRQ should be processed */ - wil_dbg_wmi(wil, "%s -> %d events queued, %d completed\n", __func__, + wil_dbg_wmi(wil, "recv_cmd: -> %d events queued, %d completed\n", n - num_immed_reply, num_immed_reply); } @@ -950,6 +958,7 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, wil->reply_id = reply_id; wil->reply_buf = reply; wil->reply_size = reply_size; + reinit_completion(&wil->wmi_call); spin_unlock(&wil->wmi_ev_lock); rc = __wmi_send(wil, cmdid, buf, len); @@ -1069,6 +1078,8 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, .pcp_max_assoc_sta = max_assoc_sta, .hidden_ssid = hidden_ssid, .is_go = is_go, + .disable_ap_sme = disable_ap_sme, + .abft_len = wil->abft_len, }; struct { struct wmi_cmd_hdr wmi; @@ -1086,6 +1097,13 @@ int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, cmd.pcp_max_assoc_sta = WIL6210_MAX_CID; } + if (disable_ap_sme && + !test_bit(WMI_FW_CAPABILITY_DISABLE_AP_SME, + wil->fw_capabilities)) { + wil_err(wil, "disable_ap_sme not supported by FW\n"); + return -EOPNOTSUPP; + } + /* * Processing time may be huge, in case of secure AP it takes about * 3500ms for FW to start AP @@ -1352,7 +1370,7 @@ int wmi_rxon(struct wil6210_priv *wil, bool on) struct wmi_listen_started_event evt; } __packed reply; - wil_info(wil, "%s(%s)\n", __func__, on ? "on" : "off"); + wil_info(wil, "(%s)\n", on ? "on" : "off"); if (on) { rc = wmi_call(wil, WMI_START_LISTEN_CMDID, NULL, 0, @@ -1456,12 +1474,15 @@ int wmi_get_temperature(struct wil6210_priv *wil, u32 *t_bb, u32 *t_rf) return 0; } -int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason, - bool full_disconnect) +int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, + u16 reason, bool full_disconnect, bool del_sta) { int rc; u16 reason_code; - struct wmi_disconnect_sta_cmd cmd = { + struct wmi_disconnect_sta_cmd disc_sta_cmd = { + .disconnect_reason = cpu_to_le16(reason), + }; + struct wmi_del_sta_cmd del_sta_cmd = { .disconnect_reason = cpu_to_le16(reason), }; struct { @@ -1469,12 +1490,19 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason, struct wmi_disconnect_event evt; } __packed reply; - ether_addr_copy(cmd.dst_mac, mac); - - wil_dbg_wmi(wil, "%s(%pM, reason %d)\n", __func__, mac, reason); + wil_dbg_wmi(wil, "disconnect_sta: (%pM, reason %d)\n", mac, reason); - rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, &cmd, sizeof(cmd), - WMI_DISCONNECT_EVENTID, &reply, sizeof(reply), 1000); + if (del_sta) { + ether_addr_copy(del_sta_cmd.dst_mac, mac); + rc = wmi_call(wil, WMI_DEL_STA_CMDID, &del_sta_cmd, + sizeof(del_sta_cmd), WMI_DISCONNECT_EVENTID, + &reply, sizeof(reply), 1000); + } else { + ether_addr_copy(disc_sta_cmd.dst_mac, mac); + rc = wmi_call(wil, WMI_DISCONNECT_STA_CMDID, &disc_sta_cmd, + sizeof(disc_sta_cmd), WMI_DISCONNECT_EVENTID, + &reply, sizeof(reply), 1000); + } /* failure to disconnect in reasonable time treated as FW error */ if (rc) { wil_fw_error_recovery(wil); @@ -1507,8 +1535,8 @@ int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout) .amsdu = 0, }; - wil_dbg_wmi(wil, "%s(ring %d size %d timeout %d)\n", __func__, - ringid, size, timeout); + wil_dbg_wmi(wil, "addba: (ring %d size %d timeout %d)\n", ringid, size, + timeout); return wmi_send(wil, WMI_VRING_BA_EN_CMDID, &cmd, sizeof(cmd)); } @@ -1520,8 +1548,7 @@ int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason) .reason = cpu_to_le16(reason), }; - wil_dbg_wmi(wil, "%s(ring %d reason %d)\n", __func__, - ringid, reason); + wil_dbg_wmi(wil, "delba_tx: (ring %d reason %d)\n", ringid, reason); return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, &cmd, sizeof(cmd)); } @@ -1533,8 +1560,8 @@ int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason) .reason = cpu_to_le16(reason), }; - wil_dbg_wmi(wil, "%s(CID %d TID %d reason %d)\n", __func__, - cidxtid & 0xf, (cidxtid >> 4) & 0xf, reason); + wil_dbg_wmi(wil, "delba_rx: (CID %d TID %d reason %d)\n", cidxtid & 0xf, + (cidxtid >> 4) & 0xf, reason); return wmi_send(wil, WMI_RCP_DELBA_CMDID, &cmd, sizeof(cmd)); } @@ -1686,11 +1713,29 @@ int wmi_abort_scan(struct wil6210_priv *wil) return rc; } +int wmi_new_sta(struct wil6210_priv *wil, const u8 *mac, u8 aid) +{ + int rc; + struct wmi_new_sta_cmd cmd = { + .aid = aid, + }; + + wil_dbg_wmi(wil, "new sta %pM, aid %d\n", mac, aid); + + ether_addr_copy(cmd.dst_mac, mac); + + rc = wmi_send(wil, WMI_NEW_STA_CMDID, &cmd, sizeof(cmd)); + if (rc) + wil_err(wil, "Failed to send new sta (%d)\n", rc); + + return rc; +} + void wmi_event_flush(struct wil6210_priv *wil) { struct pending_wmi_event *evt, *t; - wil_dbg_wmi(wil, "%s()\n", __func__); + wil_dbg_wmi(wil, "event_flush\n"); list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) { list_del(&evt->list); @@ -1731,8 +1776,8 @@ static void wmi_event_handle(struct wil6210_priv *wil, WARN_ON(wil->reply_buf); wmi_evt_call_handler(wil, id, evt_data, len - sizeof(*wmi)); - wil_dbg_wmi(wil, "%s: Complete WMI 0x%04x\n", - __func__, id); + wil_dbg_wmi(wil, "event_handle: Complete WMI 0x%04x\n", + id); complete(&wil->wmi_call); return; } @@ -1779,11 +1824,11 @@ void wmi_event_worker(struct work_struct *work) struct pending_wmi_event *evt; struct list_head *lh; - wil_dbg_wmi(wil, "Start %s\n", __func__); + wil_dbg_wmi(wil, "event_worker: Start\n"); while ((lh = next_wmi_ev(wil)) != NULL) { evt = list_entry(lh, struct pending_wmi_event, list); wmi_event_handle(wil, &evt->event.hdr); kfree(evt); } - wil_dbg_wmi(wil, "Finished %s\n", __func__); + wil_dbg_wmi(wil, "event_worker: Finished\n"); } diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h index d93a4d490d24..7c9fee57aa91 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.h +++ b/drivers/net/wireless/ath/wil6210/wmi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Qualcomm Atheros, Inc. + * Copyright (c) 2012-2017 Qualcomm Atheros, Inc. * Copyright (c) 2006-2012 Wilocity * * Permission to use, copy, modify, and/or distribute this software for any @@ -56,6 +56,8 @@ enum wmi_fw_capability { WMI_FW_CAPABILITY_PS_CONFIG = 1, WMI_FW_CAPABILITY_RF_SECTORS = 2, WMI_FW_CAPABILITY_MGMT_RETRY_LIMIT = 3, + WMI_FW_CAPABILITY_DISABLE_AP_SME = 4, + WMI_FW_CAPABILITY_WMI_ONLY = 5, WMI_FW_CAPABILITY_MAX, }; @@ -185,8 +187,11 @@ enum wmi_command_id { WMI_RS_CFG_CMDID = 0x921, WMI_GET_DETAILED_RS_RES_CMDID = 0x922, WMI_AOA_MEAS_CMDID = 0x923, + WMI_BRP_SET_ANT_LIMIT_CMDID = 0x924, WMI_SET_MGMT_RETRY_LIMIT_CMDID = 0x930, WMI_GET_MGMT_RETRY_LIMIT_CMDID = 0x931, + WMI_NEW_STA_CMDID = 0x935, + WMI_DEL_STA_CMDID = 0x936, WMI_TOF_SESSION_START_CMDID = 0x991, WMI_TOF_GET_CAPABILITIES_CMDID = 0x992, WMI_TOF_SET_LCR_CMDID = 0x993, @@ -543,7 +548,10 @@ struct wmi_pcp_start_cmd { u8 pcp_max_assoc_sta; u8 hidden_ssid; u8 is_go; - u8 reserved0[7]; + u8 reserved0[5]; + /* abft_len override if non-0 */ + u8 abft_len; + u8 disable_ap_sme; u8 network_type; u8 channel; u8 disable_sec_offload; @@ -902,6 +910,18 @@ struct wmi_set_mgmt_retry_limit_cmd { u8 reserved[3]; } __packed; +/* WMI_NEW_STA_CMDID */ +struct wmi_new_sta_cmd { + u8 dst_mac[WMI_MAC_LEN]; + u8 aid; +} __packed; + +/* WMI_DEL_STA_CMDID */ +struct wmi_del_sta_cmd { + u8 dst_mac[WMI_MAC_LEN]; + __le16 disconnect_reason; +} __packed; + enum wmi_tof_burst_duration { WMI_TOF_BURST_DURATION_250_USEC = 2, WMI_TOF_BURST_DURATION_500_USEC = 3, @@ -1067,6 +1087,7 @@ enum wmi_event_id { WMI_RS_CFG_DONE_EVENTID = 0x1921, WMI_GET_DETAILED_RS_RES_EVENTID = 0x1922, WMI_AOA_MEAS_EVENTID = 0x1923, + WMI_BRP_SET_ANT_LIMIT_EVENTID = 0x1924, WMI_SET_MGMT_RETRY_LIMIT_EVENTID = 0x1930, WMI_GET_MGMT_RETRY_LIMIT_EVENTID = 0x1931, WMI_TOF_SESSION_END_EVENTID = 0x1991, @@ -1287,12 +1308,13 @@ struct wmi_connect_event { u8 assoc_req_len; u8 assoc_resp_len; u8 cid; - u8 reserved2[3]; + u8 aid; + u8 reserved2[2]; /* not in use */ u8 assoc_info[0]; } __packed; -/* WMI_DISCONNECT_EVENTID */ +/* disconnect_reason */ enum wmi_disconnect_reason { WMI_DIS_REASON_NO_NETWORK_AVAIL = 0x01, /* bmiss */ @@ -1310,6 +1332,7 @@ enum wmi_disconnect_reason { WMI_DIS_REASON_IBSS_MERGE = 0x0E, }; +/* WMI_DISCONNECT_EVENTID */ struct wmi_disconnect_event { /* reason code, see 802.11 spec. */ __le16 protocol_reason_status; @@ -1759,6 +1782,42 @@ struct wmi_get_detailed_rs_res_event { u8 reserved[3]; } __packed; +/* BRP antenna limit mode */ +enum wmi_brp_ant_limit_mode { + /* Disable BRP force antenna limit */ + WMI_BRP_ANT_LIMIT_MODE_DISABLE = 0x00, + /* Define maximal antennas limit. Only effective antennas will be + * actually used + */ + WMI_BRP_ANT_LIMIT_MODE_EFFECTIVE = 0x01, + /* Force a specific number of antennas */ + WMI_BRP_ANT_LIMIT_MODE_FORCE = 0x02, + /* number of BRP antenna limit modes */ + WMI_BRP_ANT_LIMIT_MODES_NUM = 0x03, +}; + +/* WMI_BRP_SET_ANT_LIMIT_CMDID */ +struct wmi_brp_set_ant_limit_cmd { + /* connection id */ + u8 cid; + /* enum wmi_brp_ant_limit_mode */ + u8 limit_mode; + /* antenna limit count, 1-27 + * disable_mode - ignored + * effective_mode - upper limit to number of antennas to be used + * force_mode - exact number of antennas to be used + */ + u8 ant_limit; + u8 reserved; +} __packed; + +/* WMI_BRP_SET_ANT_LIMIT_EVENTID */ +struct wmi_brp_set_ant_limit_event { + /* wmi_fw_status */ + u8 status; + u8 reserved[3]; +} __packed; + /* broadcast connection ID */ #define WMI_LINK_MAINTAIN_CFG_CID_BROADCAST (0xFFFFFFFF) |