1
0
Fork 0

wireless-drivers-next patches for 4.11

It's nice to see rt2x00 development has becoming active, for example
 adding support for a new chip version. Also wcn36xx has been converted
 to use the recently merged QCOM_SMD subsystem. Otherwise new features
 and fixes it lots of drivers.
 
 Major changes:
 
 iwlwifi
 
 * some more work in preparation for A000 family support
 * add support for radiotap timestamps
 * some work on our firmware debugging capabilities
 
 wcn36xx
 
 * convert to a proper QCOM_SMD driver (from the platform_driver interface)
 
 ath10k
 
 * VHT160 support
 * dump Copy Engine registers during firmware crash
 * search board file extension from SMBIOS
 
 wil6210
 
 * add disable_ap_sme module parameter
 
 rt2x00
 
 * support RT3352 with external PA
 * support for RT3352 with 20MHz crystal
 * add support for RT5350 WiSoC
 
 brcmfmac
 
 * add support for BCM43455 sdio device
 
 rtl8xxxu
 
 * add support for D-Link DWA-131 rev E1, TP-Link TL-WN822N v4 and others
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQEcBAABAgAGBQJYkafBAAoJEG4XJFUm622b0EAH/3mFY0WDfdR/Ych29HX1M/Ao
 Bd5gQfKzHS8ANR56qqmxEbpLdBnBa8iNC0IS4RFsWVv6qMoEEOHDLeY5W9XsomWK
 i45fQN2XIdjBUOyDXUjsyz006cMe79VzRvFf9gfSekP8i8BCWQzyYC8VKt/F+6Sh
 yo9yA4Yv3zA3mA3yRKtxSjLm/6xUXCFVNshKGT0rXc/oEfIN6OnIC1k0p0xw2hhl
 GyLN6PSGOqcJc91+IoGOg4TaHzPdWJcWatuxGdQn8gKSDg0+gXaNh9Gtf4H/ojqp
 Fwt2Ckk5mgJYk/2TAuFRpRXNMTJznUhp4Tjp2AE7EVM0f5JujUbQuPblOVfLIYk=
 =vKKN
 -----END PGP SIGNATURE-----

Merge tag 'wireless-drivers-next-for-davem-2017-02-01' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next

Kalle Valo says:

====================
wireless-drivers-next patches for 4.11

It's nice to see rt2x00 development has becoming active, for example
adding support for a new chip version. Also wcn36xx has been converted
to use the recently merged QCOM_SMD subsystem. Otherwise new features
and fixes it lots of drivers.

Major changes:

iwlwifi

* some more work in preparation for A000 family support
* add support for radiotap timestamps
* some work on our firmware debugging capabilities

wcn36xx

* convert to a proper QCOM_SMD driver (from the platform_driver interface)

ath10k

* VHT160 support
* dump Copy Engine registers during firmware crash
* search board file extension from SMBIOS

wil6210

* add disable_ap_sme module parameter

rt2x00

* support RT3352 with external PA
* support for RT3352 with 20MHz crystal
* add support for RT5350 WiSoC

brcmfmac

* add support for BCM43455 sdio device

rtl8xxxu

* add support for D-Link DWA-131 rev E1, TP-Link TL-WN822N v4 and others
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
hifive-unleashed-5.1
David S. Miller 2017-02-01 12:46:17 -05:00
commit 889711a03e
156 changed files with 2852 additions and 2531 deletions

View File

@ -10607,7 +10607,7 @@ F: drivers/net/wireless/realtek/rtlwifi/
F: drivers/net/wireless/realtek/rtlwifi/rtl8192ce/
RTL8XXXU WIRELESS DRIVER (rtl8xxxu)
M: Jes Sorensen <Jes.Sorensen@redhat.com>
M: Jes Sorensen <Jes.Sorensen@gmail.com>
L: linux-wireless@vger.kernel.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jes/linux.git rtl8xxxu-devel
S: Maintained

View File

@ -136,17 +136,17 @@ static bool bcma_is_core_needed_early(u16 core_id)
return false;
}
static struct device_node *bcma_of_find_child_device(struct platform_device *parent,
static struct device_node *bcma_of_find_child_device(struct device *parent,
struct bcma_device *core)
{
struct device_node *node;
u64 size;
const __be32 *reg;
if (!parent || !parent->dev.of_node)
if (!parent->of_node)
return NULL;
for_each_child_of_node(parent->dev.of_node, node) {
for_each_child_of_node(parent->of_node, node) {
reg = of_get_address(node, 0, &size, NULL);
if (!reg)
continue;
@ -156,7 +156,7 @@ static struct device_node *bcma_of_find_child_device(struct platform_device *par
return NULL;
}
static int bcma_of_irq_parse(struct platform_device *parent,
static int bcma_of_irq_parse(struct device *parent,
struct bcma_device *core,
struct of_phandle_args *out_irq, int num)
{
@ -169,7 +169,7 @@ static int bcma_of_irq_parse(struct platform_device *parent,
return rc;
}
out_irq->np = parent->dev.of_node;
out_irq->np = parent->of_node;
out_irq->args_count = 1;
out_irq->args[0] = num;
@ -177,13 +177,13 @@ static int bcma_of_irq_parse(struct platform_device *parent,
return of_irq_parse_raw(laddr, out_irq);
}
static unsigned int bcma_of_get_irq(struct platform_device *parent,
static unsigned int bcma_of_get_irq(struct device *parent,
struct bcma_device *core, int num)
{
struct of_phandle_args out_irq;
int ret;
if (!IS_ENABLED(CONFIG_OF_IRQ) || !parent || !parent->dev.of_node)
if (!IS_ENABLED(CONFIG_OF_IRQ) || !parent->of_node)
return 0;
ret = bcma_of_irq_parse(parent, core, &out_irq, num);
@ -196,7 +196,7 @@ static unsigned int bcma_of_get_irq(struct platform_device *parent,
return irq_create_of_mapping(&out_irq);
}
static void bcma_of_fill_device(struct platform_device *parent,
static void bcma_of_fill_device(struct device *parent,
struct bcma_device *core)
{
struct device_node *node;
@ -227,7 +227,7 @@ unsigned int bcma_core_irq(struct bcma_device *core, int num)
return mips_irq <= 4 ? mips_irq + 2 : 0;
}
if (bus->host_pdev)
return bcma_of_get_irq(bus->host_pdev, core, num);
return bcma_of_get_irq(&bus->host_pdev->dev, core, num);
return 0;
case BCMA_HOSTTYPE_SDIO:
return 0;
@ -253,7 +253,8 @@ void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core)
if (IS_ENABLED(CONFIG_OF) && bus->host_pdev) {
core->dma_dev = &bus->host_pdev->dev;
core->dev.parent = &bus->host_pdev->dev;
bcma_of_fill_device(bus->host_pdev, core);
if (core->dev.parent)
bcma_of_fill_device(core->dev.parent, core);
} else {
core->dev.dma_mask = &core->dev.coherent_dma_mask;
core->dma_dev = &core->dev;
@ -633,8 +634,11 @@ static int bcma_device_probe(struct device *dev)
drv);
int err = 0;
get_device(dev);
if (adrv->probe)
err = adrv->probe(core);
if (err)
put_device(dev);
return err;
}
@ -647,6 +651,7 @@ static int bcma_device_remove(struct device *dev)
if (adrv->remove)
adrv->remove(core);
put_device(dev);
return 0;
}

View File

@ -958,7 +958,7 @@ 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,
dma_zalloc_coherent(ar->dev,
(nentries * sizeof(struct ce_desc) +
CE_DESC_RING_ALIGN),
&base_addr, GFP_KERNEL);
@ -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);
}

View File

@ -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? */

View File

@ -18,6 +18,8 @@
#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/of.h>
#include <linux/dmi.h>
#include <linux/ctype.h>
#include <asm/byteorder.h>
#include "core.h"
@ -707,6 +709,72 @@ static int ath10k_core_get_board_id_from_otp(struct ath10k *ar)
return 0;
}
static void ath10k_core_check_bdfext(const struct dmi_header *hdr, void *data)
{
struct ath10k *ar = data;
const char *bdf_ext;
const char *magic = ATH10K_SMBIOS_BDF_EXT_MAGIC;
u8 bdf_enabled;
int i;
if (hdr->type != ATH10K_SMBIOS_BDF_EXT_TYPE)
return;
if (hdr->length != ATH10K_SMBIOS_BDF_EXT_LENGTH) {
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"wrong smbios bdf ext type length (%d).\n",
hdr->length);
return;
}
bdf_enabled = *((u8 *)hdr + ATH10K_SMBIOS_BDF_EXT_OFFSET);
if (!bdf_enabled) {
ath10k_dbg(ar, ATH10K_DBG_BOOT, "bdf variant name not found.\n");
return;
}
/* Only one string exists (per spec) */
bdf_ext = (char *)hdr + hdr->length;
if (memcmp(bdf_ext, magic, strlen(magic)) != 0) {
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"bdf variant magic does not match.\n");
return;
}
for (i = 0; i < strlen(bdf_ext); i++) {
if (!isascii(bdf_ext[i]) || !isprint(bdf_ext[i])) {
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"bdf variant name contains non ascii chars.\n");
return;
}
}
/* Copy extension name without magic suffix */
if (strscpy(ar->id.bdf_ext, bdf_ext + strlen(magic),
sizeof(ar->id.bdf_ext)) < 0) {
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"bdf variant string is longer than the buffer can accommodate (variant: %s)\n",
bdf_ext);
return;
}
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"found and validated bdf variant smbios_type 0x%x bdf %s\n",
ATH10K_SMBIOS_BDF_EXT_TYPE, bdf_ext);
}
static int ath10k_core_check_smbios(struct ath10k *ar)
{
ar->id.bdf_ext[0] = '\0';
dmi_walk(ath10k_core_check_bdfext, ar);
if (ar->id.bdf_ext[0] == '\0')
return -ENODATA;
return 0;
}
static int ath10k_download_and_run_otp(struct ath10k *ar)
{
u32 result, address = ar->hw_params.patch_load_addr;
@ -1053,6 +1121,9 @@ err:
static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
size_t name_len)
{
/* strlen(',variant=') + strlen(ar->id.bdf_ext) */
char variant[9 + ATH10K_SMBIOS_BDF_EXT_STR_LENGTH];
if (ar->id.bmi_ids_valid) {
scnprintf(name, name_len,
"bus=%s,bmi-chip-id=%d,bmi-board-id=%d",
@ -1062,12 +1133,15 @@ static int ath10k_core_create_board_name(struct ath10k *ar, char *name,
goto out;
}
if (ar->id.bdf_ext[0] != '\0')
scnprintf(variant, sizeof(variant), ",variant=%s",
ar->id.bdf_ext);
scnprintf(name, name_len,
"bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x",
"bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,subsystem-device=%04x%s",
ath10k_bus_str(ar->hif.bus),
ar->id.vendor, ar->id.device,
ar->id.subsystem_vendor, ar->id.subsystem_device);
ar->id.subsystem_vendor, ar->id.subsystem_device, variant);
out:
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using board name '%s'\n", name);
@ -2128,6 +2202,10 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
goto err_free_firmware_files;
}
ret = ath10k_core_check_smbios(ar);
if (ret)
ath10k_dbg(ar, ATH10K_DBG_BOOT, "bdf variant name not set.\n");
ret = ath10k_core_fetch_board_file(ar);
if (ret) {
ath10k_err(ar, "failed to fetch board file: %d\n", ret);

View File

@ -69,6 +69,23 @@
#define ATH10K_NAPI_BUDGET 64
#define ATH10K_NAPI_QUOTA_LIMIT 60
/* SMBIOS type containing Board Data File Name Extension */
#define ATH10K_SMBIOS_BDF_EXT_TYPE 0xF8
/* SMBIOS type structure length (excluding strings-set) */
#define ATH10K_SMBIOS_BDF_EXT_LENGTH 0x9
/* Offset pointing to Board Data File Name Extension */
#define ATH10K_SMBIOS_BDF_EXT_OFFSET 0x8
/* Board Data File Name Extension string length.
* String format: BDF_<Customer ID>_<Extension>\0
*/
#define ATH10K_SMBIOS_BDF_EXT_STR_LENGTH 0x20
/* The magic used by QCA spec */
#define ATH10K_SMBIOS_BDF_EXT_MAGIC "BDF_"
struct ath10k;
enum ath10k_bus {
@ -314,6 +331,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 +437,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 +459,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 {
@ -781,6 +815,8 @@ struct ath10k {
bool bmi_ids_valid;
u8 bmi_board_id;
u8 bmi_chip_id;
char bdf_ext[ATH10K_SMBIOS_BDF_EXT_STR_LENGTH];
} id;
int fw_api;

View File

@ -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,
};
@ -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);
@ -726,6 +730,7 @@ 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);
@ -734,6 +739,8 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar,
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 +799,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);

View File

@ -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;

View File

@ -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;
};

View File

@ -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;

View File

@ -578,6 +578,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

View File

@ -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;
@ -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 =
@ -2533,6 +2542,33 @@ 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,
@ -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)
@ -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)))
@ -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;
@ -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)

View File

@ -896,7 +896,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 +905,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 +1473,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);
@ -1937,7 +1937,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);

View File

@ -24,11 +24,6 @@
#include "ce.h"
#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

View File

@ -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,
};
/************/

View File

@ -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 {

View File

@ -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;
@ -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

View File

@ -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 {
@ -5873,6 +5892,7 @@ struct wmi_peer_flags_map {
u32 bw80;
u32 vht_2g;
u32 pmf;
u32 bw160;
};
enum wmi_peer_flags {
@ -5892,6 +5912,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 +5930,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 +5950,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
};
/*

View File

@ -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);

View File

@ -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);

View File

@ -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"

View File

@ -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 \

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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 */

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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;
}

View File

@ -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.

View File

@ -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.

View File

@ -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_ */

View File

@ -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,59 @@ 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 = {};
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++) {
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 = false;
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_req = &hw_req->req;
mutex_unlock(&wcn->scan_lock);
schedule_work(&wcn->scan_work);
return 0;
}
static void wcn36xx_update_allowed_rates(struct ieee80211_sta *sta,
@ -993,8 +1033,7 @@ 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,
.bss_info_changed = wcn36xx_bss_info_changed,
.set_rts_threshold = wcn36xx_set_rts_threshold,
.sta_add = wcn36xx_sta_add,
@ -1019,6 +1058,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 +1068,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 +1101,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 +1109,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 +1172,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 +1190,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 +1233,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 +1241,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");

View File

@ -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 0;
return ret;
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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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,12 @@ 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;
/* DXE channels */
struct wcn36xx_dxe_ch dxe_tx_l_ch; /* TX low */
struct wcn36xx_dxe_ch dxe_tx_h_ch; /* TX high */

View File

@ -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
@ -20,6 +20,10 @@
#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 +66,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 +205,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 +244,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 +261,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 +292,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 +313,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 +360,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 +565,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 +601,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 +698,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 +710,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 +758,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 +819,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 +924,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 +939,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 +964,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 +985,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 +998,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 +1012,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 +1168,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 +1225,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 +1264,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 +1315,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 +1331,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 +1369,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 +1464,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 +1484,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 +1512,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 +1525,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 +1539,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 +1576,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 +1598,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 +1621,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 =

View File

@ -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, &params, 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},
{},
};

View File

@ -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) {

View File

@ -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,

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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);
}
@ -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);

View File

@ -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);

View File

@ -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);
wil->wil_fw_name = WIL_FW_NAME_DEFAULT;
wil->chip_revision = chip_revision;
switch (rev_id) {
case JTAG_DEV_ID_SPARROW_B0:
wil->hw_name = "Sparrow B0";
wil->hw_version = HW_VER_SPARROW_B0;
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:

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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, "disconnect_sta: (%pM, reason %d)\n", mac, reason);
wil_dbg_wmi(wil, "%s(%pM, reason %d)\n", __func__, 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");
}

View File

@ -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)

View File

@ -1104,6 +1104,7 @@ static const struct sdio_device_id brcmf_sdmmc_ids[] = {
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4339),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43430),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4345),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43455),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4356),
{ /* end: all zeroes */ }

View File

@ -218,9 +218,6 @@ int brcmf_bus_get_memdump(struct brcmf_bus *bus, void *data, size_t len)
* interface functions from common layer
*/
bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, struct sk_buff *pkt,
int prec);
/* Receive frame for delivery to OS. Callee disposes of rxp. */
void brcmf_rx_frame(struct device *dev, struct sk_buff *rxp, bool handle_event);
/* Receive async event packet from firmware. Callee disposes of rxp. */
@ -241,13 +238,12 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success);
/* Configure the "global" bus state used by upper layers */
void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state);
int brcmf_bus_start(struct device *dev);
int brcmf_bus_started(struct device *dev);
s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len);
void brcmf_bus_add_txhdrlen(struct device *dev, uint len);
#ifdef CONFIG_BRCMFMAC_SDIO
void brcmf_sdio_exit(void);
void brcmf_sdio_init(void);
void brcmf_sdio_register(void);
#endif
#ifdef CONFIG_BRCMFMAC_USB

View File

@ -138,7 +138,6 @@ static struct ieee80211_rate __wl_rates[] = {
.band = NL80211_BAND_2GHZ, \
.center_freq = (_freq), \
.hw_value = (_channel), \
.flags = IEEE80211_CHAN_DISABLED, \
.max_antenna_gain = 0, \
.max_power = 30, \
}
@ -147,7 +146,6 @@ static struct ieee80211_rate __wl_rates[] = {
.band = NL80211_BAND_5GHZ, \
.center_freq = 5000 + (5 * (_channel)), \
.hw_value = (_channel), \
.flags = IEEE80211_CHAN_DISABLED, \
.max_antenna_gain = 0, \
.max_power = 30, \
}
@ -328,7 +326,7 @@ u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
* triples, returning a pointer to the substring whose first element
* matches tag
*/
const struct brcmf_tlv *
static const struct brcmf_tlv *
brcmf_parse_tlvs(const void *buf, int buflen, uint key)
{
const struct brcmf_tlv *elt = buf;
@ -3332,7 +3330,6 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp,
goto out_err;
}
data += sizeof(struct brcmf_pno_scanresults_le);
netinfo_start = brcmf_get_netinfo_array(pfn_result);
for (i = 0; i < result_count; i++) {
@ -3480,8 +3477,7 @@ brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e,
return -EINVAL;
}
data += sizeof(struct brcmf_pno_scanresults_le);
netinfo = (struct brcmf_pno_net_info_le *)data;
netinfo = brcmf_get_netinfo_array(pfn_result);
memcpy(cfg->wowl.nd->ssid.ssid, netinfo->SSID, netinfo->SSID_len);
cfg->wowl.nd->ssid.ssid_len = netinfo->SSID_len;
cfg->wowl.nd->n_channels = 1;
@ -5071,6 +5067,29 @@ static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy,
return ret;
}
static int
brcmf_cfg80211_update_conn_params(struct wiphy *wiphy,
struct net_device *ndev,
struct cfg80211_connect_params *sme,
u32 changed)
{
struct brcmf_if *ifp;
int err;
if (!(changed & UPDATE_ASSOC_IES))
return 0;
ifp = netdev_priv(ndev);
err = brcmf_vif_set_mgmt_ie(ifp->vif, BRCMF_VNDR_IE_ASSOCREQ_FLAG,
sme->ie, sme->ie_len);
if (err)
brcmf_err("Set Assoc REQ IE Failed\n");
else
brcmf_dbg(TRACE, "Applied Vndr IEs for Assoc request\n");
return err;
}
#ifdef CONFIG_PM
static int
brcmf_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *ndev,
@ -5138,6 +5157,7 @@ static struct cfg80211_ops brcmf_cfg80211_ops = {
.crit_proto_start = brcmf_cfg80211_crit_proto_start,
.crit_proto_stop = brcmf_cfg80211_crit_proto_stop,
.tdls_oper = brcmf_cfg80211_tdls_oper,
.update_connect_params = brcmf_cfg80211_update_conn_params,
};
struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg,
@ -5825,7 +5845,6 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
u32 i, j;
u32 total;
u32 chaninfo;
u32 index;
pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
@ -5873,33 +5892,36 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
ch.bw == BRCMU_CHAN_BW_80)
continue;
channel = band->channels;
index = band->n_channels;
channel = NULL;
for (j = 0; j < band->n_channels; j++) {
if (channel[j].hw_value == ch.control_ch_num) {
index = j;
if (band->channels[j].hw_value == ch.control_ch_num) {
channel = &band->channels[j];
break;
}
}
channel[index].center_freq =
ieee80211_channel_to_frequency(ch.control_ch_num,
band->band);
channel[index].hw_value = ch.control_ch_num;
if (!channel) {
/* It seems firmware supports some channel we never
* considered. Something new in IEEE standard?
*/
brcmf_err("Ignoring unexpected firmware channel %d\n",
ch.control_ch_num);
continue;
}
/* assuming the chanspecs order is HT20,
* HT40 upper, HT40 lower, and VHT80.
*/
if (ch.bw == BRCMU_CHAN_BW_80) {
channel[index].flags &= ~IEEE80211_CHAN_NO_80MHZ;
channel->flags &= ~IEEE80211_CHAN_NO_80MHZ;
} else if (ch.bw == BRCMU_CHAN_BW_40) {
brcmf_update_bw40_channel_flag(&channel[index], &ch);
brcmf_update_bw40_channel_flag(channel, &ch);
} else {
/* enable the channel and disable other bandwidths
* for now as mentioned order assure they are enabled
* for subsequent chanspecs.
*/
channel[index].flags = IEEE80211_CHAN_NO_HT40 |
IEEE80211_CHAN_NO_80MHZ;
channel->flags = IEEE80211_CHAN_NO_HT40 |
IEEE80211_CHAN_NO_80MHZ;
ch.bw = BRCMU_CHAN_BW_20;
cfg->d11inf.encchspec(&ch);
chaninfo = ch.chspec;
@ -5907,11 +5929,11 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,
&chaninfo);
if (!err) {
if (chaninfo & WL_CHAN_RADAR)
channel[index].flags |=
channel->flags |=
(IEEE80211_CHAN_RADAR |
IEEE80211_CHAN_NO_IR);
if (chaninfo & WL_CHAN_PASSIVE)
channel[index].flags |=
channel->flags |=
IEEE80211_CHAN_NO_IR;
}
}
@ -6341,7 +6363,7 @@ static void brcmf_wiphy_pno_params(struct wiphy *wiphy)
}
#ifdef CONFIG_PM
static struct wiphy_wowlan_support brcmf_wowlan_support = {
static const struct wiphy_wowlan_support brcmf_wowlan_support = {
.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
.n_patterns = BRCMF_WOWL_MAXPATTERNS,
.pattern_max_len = BRCMF_WOWL_MAXPATTERNSIZE,
@ -6354,19 +6376,29 @@ static void brcmf_wiphy_wowl_params(struct wiphy *wiphy, struct brcmf_if *ifp)
{
#ifdef CONFIG_PM
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct wiphy_wowlan_support *wowl;
wowl = kmemdup(&brcmf_wowlan_support, sizeof(brcmf_wowlan_support),
GFP_KERNEL);
if (!wowl) {
brcmf_err("only support basic wowlan features\n");
wiphy->wowlan = &brcmf_wowlan_support;
return;
}
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PNO)) {
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_ND)) {
brcmf_wowlan_support.flags |= WIPHY_WOWLAN_NET_DETECT;
wowl->flags |= WIPHY_WOWLAN_NET_DETECT;
wowl->max_nd_match_sets = BRCMF_PNO_MAX_PFN_COUNT;
init_waitqueue_head(&cfg->wowl.nd_data_wait);
}
}
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_WOWL_GTK)) {
brcmf_wowlan_support.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY;
brcmf_wowlan_support.flags |= WIPHY_WOWLAN_GTK_REKEY_FAILURE;
wowl->flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY;
wowl->flags |= WIPHY_WOWLAN_GTK_REKEY_FAILURE;
}
wiphy->wowlan = &brcmf_wowlan_support;
wiphy->wowlan = wowl;
#endif
}
@ -6477,8 +6509,7 @@ static int brcmf_setup_wiphy(struct wiphy *wiphy, struct brcmf_if *ifp)
wiphy->bands[NL80211_BAND_5GHZ] = band;
}
}
err = brcmf_setup_wiphybands(wiphy);
return err;
return 0;
}
static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg)
@ -6748,6 +6779,10 @@ static void brcmf_free_wiphy(struct wiphy *wiphy)
kfree(wiphy->bands[NL80211_BAND_5GHZ]->channels);
kfree(wiphy->bands[NL80211_BAND_5GHZ]);
}
#if IS_ENABLED(CONFIG_PM)
if (wiphy->wowlan != &brcmf_wowlan_support)
kfree(wiphy->wowlan);
#endif
wiphy_free(wiphy);
}
@ -6843,6 +6878,12 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
goto priv_out;
}
err = brcmf_setup_wiphybands(wiphy);
if (err) {
brcmf_err("Setting wiphy bands failed (%d)\n", err);
goto wiphy_unreg_out;
}
/* If cfg80211 didn't disable 40MHz HT CAP in wiphy_register(),
* setup 40MHz in 2GHz band and enable OBSS scanning.
*/

View File

@ -396,8 +396,6 @@ void brcmf_free_vif(struct brcmf_cfg80211_vif *vif);
s32 brcmf_vif_set_mgmt_ie(struct brcmf_cfg80211_vif *vif, s32 pktflag,
const u8 *vndr_ie_buf, u32 vndr_ie_len);
s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif);
const struct brcmf_tlv *
brcmf_parse_tlvs(const void *buf, int buflen, uint key);
u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
struct ieee80211_channel *ch);
bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg,

View File

@ -74,7 +74,7 @@ module_param_named(roamoff, brcmf_roamoff, int, S_IRUSR);
MODULE_PARM_DESC(roamoff, "Do not use internal roaming engine");
#ifdef DEBUG
/* always succeed brcmf_bus_start() */
/* always succeed brcmf_bus_started() */
static int brcmf_ignore_probe_fail;
module_param_named(ignore_probe_fail, brcmf_ignore_probe_fail, int, 0);
MODULE_PARM_DESC(ignore_probe_fail, "always succeed probe for debugging");
@ -299,11 +299,9 @@ struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
}
}
}
if ((bus_type == BRCMF_BUSTYPE_SDIO) && (!found)) {
/* No platform data for this device. In case of SDIO try OF
* (Open Firwmare) Device Tree.
*/
brcmf_of_probe(dev, &settings->bus.sdio);
if (!found) {
/* No platform data for this device, try OF (Open Firwmare) */
brcmf_of_probe(dev, bus_type, settings);
}
return settings;
}

View File

@ -65,6 +65,8 @@ struct brcmf_mp_device {
} bus;
};
void brcmf_c_set_joinpref_default(struct brcmf_if *ifp);
struct brcmf_mp_device *brcmf_get_module_param(struct device *dev,
enum brcmf_bus_type bus_type,
u32 chip, u32 chiprev);

View File

@ -966,7 +966,7 @@ static int brcmf_revinfo_read(struct seq_file *s, void *data)
return 0;
}
int brcmf_bus_start(struct device *dev)
int brcmf_bus_started(struct device *dev)
{
int ret = -1;
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
@ -1075,16 +1075,6 @@ void brcmf_bus_add_txhdrlen(struct device *dev, uint len)
}
}
static void brcmf_bus_detach(struct brcmf_pub *drvr)
{
brcmf_dbg(TRACE, "Enter\n");
if (drvr) {
/* Stop the bus module */
brcmf_bus_stop(drvr->bus_if);
}
}
void brcmf_dev_reset(struct device *dev)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
@ -1131,7 +1121,7 @@ void brcmf_detach(struct device *dev)
brcmf_fws_deinit(drvr);
brcmf_bus_detach(drvr);
brcmf_bus_stop(drvr->bus_if);
brcmf_proto_detach(drvr);

View File

@ -216,7 +216,6 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp,
void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
void brcmf_c_set_joinpref_default(struct brcmf_if *ifp);
int __init brcmf_core_init(void);
void __exit brcmf_core_exit(void);

View File

@ -23,14 +23,17 @@
#include "common.h"
#include "of.h"
void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio)
void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
struct brcmf_mp_device *settings)
{
struct brcmfmac_sdio_pd *sdio = &settings->bus.sdio;
struct device_node *np = dev->of_node;
int irq;
u32 irqf;
u32 val;
if (!np || !of_device_is_compatible(np, "brcm,bcm4329-fmac"))
if (!np || bus_type != BRCMF_BUSTYPE_SDIO ||
!of_device_is_compatible(np, "brcm,bcm4329-fmac"))
return;
if (of_property_read_u32(np, "brcm,drive-strength", &val) == 0)

View File

@ -14,9 +14,11 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef CONFIG_OF
void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio);
void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
struct brcmf_mp_device *settings);
#else
static void brcmf_of_probe(struct device *dev, struct brcmfmac_sdio_pd *sdio)
static void brcmf_of_probe(struct device *dev, enum brcmf_bus_type bus_type,
struct brcmf_mp_device *settings)
{
}
#endif /* CONFIG_OF */

View File

@ -601,7 +601,6 @@ static void brcmf_pcie_attach(struct brcmf_pciedev_info *devinfo)
{
u32 config;
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
/* BAR1 window may not be sized properly */
brcmf_pcie_select_core(devinfo, BCMA_CORE_PCIE2);
brcmf_pcie_write_reg32(devinfo, BRCMF_PCIE_PCIE2REG_CONFIGADDR, 0x4e0);
@ -1572,7 +1571,7 @@ static int brcmf_pcie_attach_bus(struct brcmf_pciedev_info *devinfo)
if (ret) {
brcmf_err("brcmf_attach failed\n");
} else {
ret = brcmf_bus_start(&devinfo->pdev->dev);
ret = brcmf_bus_started(&devinfo->pdev->dev);
if (ret)
brcmf_err("dongle is not responding\n");
}

View File

@ -1661,7 +1661,7 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq)
pfirst->len, pfirst->next,
pfirst->prev);
skb_unlink(pfirst, &bus->glom);
if (brcmf_sdio_fromevntchan(pfirst->data))
if (brcmf_sdio_fromevntchan(&dptr[SDPCM_HWHDR_LEN]))
brcmf_rx_event(bus->sdiodev->dev, pfirst);
else
brcmf_rx_frame(bus->sdiodev->dev, pfirst,
@ -4065,7 +4065,7 @@ static void brcmf_sdio_firmware_callback(struct device *dev,
sdio_release_host(sdiodev->func[1]);
err = brcmf_bus_start(dev);
err = brcmf_bus_started(dev);
if (err != 0) {
brcmf_err("dongle is not responding\n");
goto fail;

View File

@ -1148,7 +1148,7 @@ static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo)
if (ret)
goto fail;
ret = brcmf_bus_start(devinfo->dev);
ret = brcmf_bus_started(devinfo->dev);
if (ret)
goto fail;

View File

@ -2310,7 +2310,7 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
{
struct iwl_priv *priv = file->private_data;
bool restart_fw = iwlwifi_mod_params.restart_fw;
int ret;
int __maybe_unused ret;
iwlwifi_mod_params.restart_fw = true;

View File

@ -163,7 +163,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv,
REGULATORY_DISABLE_BEACON_HINTS;
#ifdef CONFIG_PM_SLEEP
if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
if (priv->fw->img[IWL_UCODE_WOWLAN].num_sec &&
priv->trans->ops->d3_suspend &&
priv->trans->ops->d3_resume &&
device_can_wakeup(priv->trans->dev)) {

View File

@ -364,7 +364,7 @@ static void rs_program_fix_rate(struct iwl_priv *priv,
/*
get the traffic load value for tid
*/
static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid)
static void rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid)
{
u32 curr_time = jiffies_to_msecs(jiffies);
u32 time_diff;
@ -372,14 +372,14 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid)
struct iwl_traffic_load *tl = NULL;
if (tid >= IWL_MAX_TID_COUNT)
return 0;
return;
tl = &(lq_data->load[tid]);
curr_time -= curr_time % TID_ROUND_VALUE;
if (!(tl->queue_count))
return 0;
return;
time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
index = time_diff / TID_QUEUE_CELL_SPACING;
@ -388,8 +388,6 @@ static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid)
/* TID_MAX_TIME_DIFF */
if (index >= TID_QUEUE_MAX_SIZE)
rs_tl_rm_old_stats(tl, curr_time);
return tl->total;
}
static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
@ -397,7 +395,6 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
struct ieee80211_sta *sta)
{
int ret = -EAGAIN;
u32 load;
/*
* Don't create TX aggregation sessions when in high
@ -410,7 +407,7 @@ static int rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
return ret;
}
load = rs_tl_get_load(lq_data, tid);
rs_tl_get_load(lq_data, tid);
IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
sta->addr, tid);

View File

@ -407,7 +407,7 @@ int iwl_run_init_ucode(struct iwl_priv *priv)
lockdep_assert_held(&priv->mutex);
/* No init ucode required? Curious, but maybe ok */
if (!priv->fw->img[IWL_UCODE_INIT].sec[0].len)
if (!priv->fw->img[IWL_UCODE_INIT].num_sec)
return 0;
iwl_init_notification_wait(&priv->notif_wait, &calib_wait,

View File

@ -371,4 +371,4 @@ const struct iwl_cfg iwl6000_3agn_cfg = {
MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX));
MODULE_FIRMWARE(IWL6005_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));
MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2B_UCODE_API_MAX));
MODULE_FIRMWARE(IWL6030_MODULE_FIRMWARE(IWL6000G2_UCODE_API_MAX));

View File

@ -73,8 +73,8 @@
/* Highest firmware API version supported */
#define IWL7260_UCODE_API_MAX 17
#define IWL7265_UCODE_API_MAX 17
#define IWL7265D_UCODE_API_MAX 26
#define IWL3168_UCODE_API_MAX 26
#define IWL7265D_UCODE_API_MAX 28
#define IWL3168_UCODE_API_MAX 28
/* Lowest firmware API version supported */
#define IWL7260_UCODE_API_MIN 17

View File

@ -70,8 +70,8 @@
#include "iwl-agn-hw.h"
/* Highest firmware API version supported */
#define IWL8000_UCODE_API_MAX 26
#define IWL8265_UCODE_API_MAX 26
#define IWL8000_UCODE_API_MAX 28
#define IWL8265_UCODE_API_MAX 28
/* Lowest firmware API version supported */
#define IWL8000_UCODE_API_MIN 17

View File

@ -55,7 +55,7 @@
#include "iwl-agn-hw.h"
/* Highest firmware API version supported */
#define IWL9000_UCODE_API_MAX 26
#define IWL9000_UCODE_API_MAX 28
/* Lowest firmware API version supported */
#define IWL9000_UCODE_API_MIN 17

View File

@ -55,7 +55,7 @@
#include "iwl-agn-hw.h"
/* Highest firmware API version supported */
#define IWL_A000_UCODE_API_MAX 26
#define IWL_A000_UCODE_API_MAX 28
/* Lowest firmware API version supported */
#define IWL_A000_UCODE_API_MIN 24

View File

@ -166,8 +166,9 @@ static void iwl_free_fw_desc(struct iwl_drv *drv, struct fw_desc *desc)
static void iwl_free_fw_img(struct iwl_drv *drv, struct fw_img *img)
{
int i;
for (i = 0; i < IWL_UCODE_SECTION_MAX; i++)
for (i = 0; i < img->num_sec; i++)
iwl_free_fw_desc(drv, &img->sec[i]);
kfree(img->sec);
}
static void iwl_dealloc_ucode(struct iwl_drv *drv)
@ -179,8 +180,7 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)
kfree(drv->fw.dbg_conf_tlv[i]);
for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_trigger_tlv); i++)
kfree(drv->fw.dbg_trigger_tlv[i]);
for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_mem_tlv); i++)
kfree(drv->fw.dbg_mem_tlv[i]);
kfree(drv->fw.dbg_mem_tlv);
for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
iwl_free_fw_img(drv, drv->fw.img + i);
@ -241,7 +241,7 @@ static int iwl_request_firmware(struct iwl_drv *drv, bool first)
}
struct fw_img_parsing {
struct fw_sec sec[IWL_UCODE_SECTION_MAX];
struct fw_sec *sec;
int sec_counter;
};
@ -276,7 +276,8 @@ struct iwl_firmware_pieces {
size_t dbg_conf_tlv_len[FW_DBG_CONF_MAX];
struct iwl_fw_dbg_trigger_tlv *dbg_trigger_tlv[FW_DBG_TRIGGER_MAX];
size_t dbg_trigger_tlv_len[FW_DBG_TRIGGER_MAX];
struct iwl_fw_dbg_mem_seg_tlv *dbg_mem_tlv[FW_DBG_MEM_MAX];
struct iwl_fw_dbg_mem_seg_tlv *dbg_mem_tlv;
size_t n_dbg_mem_tlv;
};
/*
@ -290,11 +291,33 @@ static struct fw_sec *get_sec(struct iwl_firmware_pieces *pieces,
return &pieces->img[type].sec[sec];
}
static void alloc_sec_data(struct iwl_firmware_pieces *pieces,
enum iwl_ucode_type type,
int sec)
{
struct fw_img_parsing *img = &pieces->img[type];
struct fw_sec *sec_memory;
int size = sec + 1;
size_t alloc_size = sizeof(*img->sec) * size;
if (img->sec && img->sec_counter >= size)
return;
sec_memory = krealloc(img->sec, alloc_size, GFP_KERNEL);
if (!sec_memory)
return;
img->sec = sec_memory;
img->sec_counter = size;
}
static void set_sec_data(struct iwl_firmware_pieces *pieces,
enum iwl_ucode_type type,
int sec,
const void *data)
{
alloc_sec_data(pieces, type, sec);
pieces->img[type].sec[sec].data = data;
}
@ -303,6 +326,8 @@ static void set_sec_size(struct iwl_firmware_pieces *pieces,
int sec,
size_t size)
{
alloc_sec_data(pieces, type, sec);
pieces->img[type].sec[sec].size = size;
}
@ -318,6 +343,8 @@ static void set_sec_offset(struct iwl_firmware_pieces *pieces,
int sec,
u32 offset)
{
alloc_sec_data(pieces, type, sec);
pieces->img[type].sec[sec].offset = offset;
}
@ -383,6 +410,7 @@ static int iwl_store_ucode_sec(struct iwl_firmware_pieces *pieces,
struct fw_img_parsing *img;
struct fw_sec *sec;
struct fw_sec_parsing *sec_parse;
size_t alloc_size;
if (WARN_ON(!pieces || !data || type >= IWL_UCODE_TYPE_MAX))
return -1;
@ -390,6 +418,13 @@ static int iwl_store_ucode_sec(struct iwl_firmware_pieces *pieces,
sec_parse = (struct fw_sec_parsing *)data;
img = &pieces->img[type];
alloc_size = sizeof(*img->sec) * (img->sec_counter + 1);
sec = krealloc(img->sec, alloc_size, GFP_KERNEL);
if (!sec)
return -ENOMEM;
img->sec = sec;
sec = &img->sec[img->sec_counter];
sec->offset = le32_to_cpu(sec_parse->offset);
@ -1009,31 +1044,37 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv,
struct iwl_fw_dbg_mem_seg_tlv *dbg_mem =
(void *)tlv_data;
u32 type;
size_t size;
struct iwl_fw_dbg_mem_seg_tlv *n;
if (tlv_len != (sizeof(*dbg_mem)))
goto invalid_tlv_len;
type = le32_to_cpu(dbg_mem->data_type);
drv->fw.dbg_dynamic_mem = true;
if (type >= ARRAY_SIZE(drv->fw.dbg_mem_tlv)) {
IWL_ERR(drv,
"Skip unknown dbg mem segment: %u\n",
dbg_mem->data_type);
break;
}
if (pieces->dbg_mem_tlv[type]) {
IWL_ERR(drv,
"Ignore duplicate mem segment: %u\n",
dbg_mem->data_type);
break;
}
IWL_DEBUG_INFO(drv, "Found debug memory segment: %u\n",
dbg_mem->data_type);
pieces->dbg_mem_tlv[type] = dbg_mem;
switch (type & FW_DBG_MEM_TYPE_MASK) {
case FW_DBG_MEM_TYPE_REGULAR:
case FW_DBG_MEM_TYPE_PRPH:
/* we know how to handle these */
break;
default:
IWL_ERR(drv,
"Found debug memory segment with invalid type: 0x%x\n",
type);
return -EINVAL;
}
size = sizeof(*pieces->dbg_mem_tlv) *
(pieces->n_dbg_mem_tlv + 1);
n = krealloc(pieces->dbg_mem_tlv, size, GFP_KERNEL);
if (!n)
return -ENOMEM;
pieces->dbg_mem_tlv = n;
pieces->dbg_mem_tlv[pieces->n_dbg_mem_tlv] = *dbg_mem;
pieces->n_dbg_mem_tlv++;
break;
}
default:
@ -1083,12 +1124,18 @@ static int iwl_alloc_ucode(struct iwl_drv *drv,
enum iwl_ucode_type type)
{
int i;
for (i = 0;
i < IWL_UCODE_SECTION_MAX && get_sec_size(pieces, type, i);
i++)
if (iwl_alloc_fw_desc(drv, &(drv->fw.img[type].sec[i]),
get_sec(pieces, type, i)))
struct fw_desc *sec;
sec = kcalloc(pieces->img[type].sec_counter, sizeof(*sec), GFP_KERNEL);
if (!sec)
return -ENOMEM;
drv->fw.img[type].sec = sec;
drv->fw.img[type].num_sec = pieces->img[type].sec_counter;
for (i = 0; i < pieces->img[type].sec_counter; i++)
if (iwl_alloc_fw_desc(drv, &sec[i], get_sec(pieces, type, i)))
return -ENOMEM;
return 0;
}
@ -1345,19 +1392,12 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
}
}
for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_mem_tlv); i++) {
if (pieces->dbg_mem_tlv[i]) {
drv->fw.dbg_mem_tlv[i] =
kmemdup(pieces->dbg_mem_tlv[i],
sizeof(*drv->fw.dbg_mem_tlv[i]),
GFP_KERNEL);
if (!drv->fw.dbg_mem_tlv[i])
goto out_free_fw;
}
}
/* Now that we can no longer fail, copy information */
drv->fw.dbg_mem_tlv = pieces->dbg_mem_tlv;
pieces->dbg_mem_tlv = NULL;
drv->fw.n_dbg_mem_tlv = pieces->n_dbg_mem_tlv;
/*
* The (size - 16) / 12 formula is based on the information recorded
* for each event, which is of mode 1 (including timestamp) for all
@ -1441,25 +1481,27 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
op->name, err);
#endif
}
kfree(pieces);
return;
goto free;
try_again:
/* try next, if any */
release_firmware(ucode_raw);
if (iwl_request_firmware(drv, false))
goto out_unbind;
kfree(pieces);
return;
goto free;
out_free_fw:
IWL_ERR(drv, "failed to allocate pci memory\n");
iwl_dealloc_ucode(drv);
release_firmware(ucode_raw);
out_unbind:
kfree(pieces);
complete(&drv->request_firmware_complete);
device_release_driver(drv->trans->dev);
free:
for (i = 0; i < ARRAY_SIZE(pieces->img); i++)
kfree(pieces->img[i].sec);
kfree(pieces->dbg_mem_tlv);
kfree(pieces);
}
struct iwl_drv *iwl_drv_start(struct iwl_trans *trans,

View File

@ -379,7 +379,6 @@ enum iwl_ucode_tlv_capa {
* For 16.0 uCode and above, there is no differentiation between sections,
* just an offset to the HW address.
*/
#define IWL_UCODE_SECTION_MAX 16
#define CPU1_CPU2_SEPARATOR_SECTION 0xFFFFCCCC
#define PAGING_SEPARATOR_SECTION 0xAAAABBBB
@ -489,25 +488,22 @@ enum iwl_fw_dbg_monitor_mode {
};
/**
* enum iwl_fw_mem_seg_type - data types for dumping on error
*
* @FW_DBG_MEM_SMEM: the data type is SMEM
* @FW_DBG_MEM_DCCM_LMAC: the data type is DCCM_LMAC
* @FW_DBG_MEM_DCCM_UMAC: the data type is DCCM_UMAC
* enum iwl_fw_mem_seg_type - memory segment type
* @FW_DBG_MEM_TYPE_MASK: mask for the type indication
* @FW_DBG_MEM_TYPE_REGULAR: regular memory
* @FW_DBG_MEM_TYPE_PRPH: periphery memory (requires special reading)
*/
enum iwl_fw_dbg_mem_seg_type {
FW_DBG_MEM_DCCM_LMAC = 0,
FW_DBG_MEM_DCCM_UMAC,
FW_DBG_MEM_SMEM,
/* Must be last */
FW_DBG_MEM_MAX,
enum iwl_fw_mem_seg_type {
FW_DBG_MEM_TYPE_MASK = 0xff000000,
FW_DBG_MEM_TYPE_REGULAR = 0x00000000,
FW_DBG_MEM_TYPE_PRPH = 0x01000000,
};
/**
* struct iwl_fw_dbg_mem_seg_tlv - configures the debug data memory segments
*
* @data_type: enum %iwl_fw_mem_seg_type
* @data_type: the memory segment type to record, see &enum iwl_fw_mem_seg_type
* for what we care about
* @ofs: the memory segment offset
* @len: the memory segment length, in bytes
*

View File

@ -132,7 +132,8 @@ struct fw_desc {
};
struct fw_img {
struct fw_desc sec[IWL_UCODE_SECTION_MAX];
struct fw_desc *sec;
int num_sec;
bool is_dual_cpus;
u32 paging_mem_size;
};
@ -295,8 +296,8 @@ struct iwl_fw {
struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_CONF_MAX];
size_t dbg_conf_tlv_len[FW_DBG_CONF_MAX];
struct iwl_fw_dbg_trigger_tlv *dbg_trigger_tlv[FW_DBG_TRIGGER_MAX];
struct iwl_fw_dbg_mem_seg_tlv *dbg_mem_tlv[FW_DBG_MEM_MAX];
bool dbg_dynamic_mem;
struct iwl_fw_dbg_mem_seg_tlv *dbg_mem_tlv;
size_t n_dbg_mem_tlv;
size_t dbg_trigger_tlv_len[FW_DBG_TRIGGER_MAX];
u8 dbg_dest_reg_num;
struct iwl_gscan_capabilities gscan_capa;

View File

@ -1262,12 +1262,15 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
iwl_trans_d3_suspend(mvm->trans, test, !unified_image);
out:
if (ret < 0) {
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
if (mvm->restart_fw > 0) {
mvm->restart_fw--;
ieee80211_restart_hw(mvm->hw);
}
iwl_mvm_free_nd(mvm);
if (!unified_image) {
iwl_mvm_ref(mvm, IWL_MVM_REF_UCODE_DOWN);
if (mvm->restart_fw > 0) {
mvm->restart_fw--;
ieee80211_restart_hw(mvm->hw);
}
}
}
out_noreset:
mutex_unlock(&mvm->mutex);

View File

@ -798,7 +798,7 @@ static ssize_t iwl_dbgfs_drv_rx_stats_read(struct file *file,
static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos)
{
int ret;
int __maybe_unused ret;
mutex_lock(&mvm->mutex);

View File

@ -2075,7 +2075,7 @@ struct iwl_mu_group_mgmt_notif {
* @system_time: system time on air rise
* @tsf: TSF on air rise
* @beacon_timestamp: beacon on air rise
* @phy_flags: general phy flags: band, modulation, etc.
* @band: band, matches &RX_RES_PHY_FLAGS_BAND_24 definition
* @channel: channel this beacon was received on
* @rates: rate in ucode internal format
* @byte_count: frame's byte count
@ -2084,12 +2084,12 @@ struct iwl_stored_beacon_notif {
__le32 system_time;
__le64 tsf;
__le32 beacon_timestamp;
__le16 phy_flags;
__le16 band;
__le16 channel;
__le32 rates;
__le32 byte_count;
u8 data[MAX_STORED_BEACON_SIZE];
} __packed; /* WOWLAN_STROED_BEACON_INFO_S_VER_1 */
} __packed; /* WOWLAN_STROED_BEACON_INFO_S_VER_2 */
#define LQM_NUMBER_OF_STATIONS_IN_REPORT 16

View File

@ -406,46 +406,63 @@ static const struct iwl_prph_range iwl_prph_dump_addr_9000[] = {
{ .start = 0x00a02400, .end = 0x00a02758 },
};
static u32 iwl_dump_prph(struct iwl_trans *trans,
struct iwl_fw_error_dump_data **data,
const struct iwl_prph_range *iwl_prph_dump_addr,
u32 range_len)
static void _iwl_read_prph_block(struct iwl_trans *trans, u32 start,
u32 len_bytes, __le32 *data)
{
u32 i;
for (i = 0; i < len_bytes; i += 4)
*data++ = cpu_to_le32(iwl_read_prph_no_grab(trans, start + i));
}
static bool iwl_read_prph_block(struct iwl_trans *trans, u32 start,
u32 len_bytes, __le32 *data)
{
unsigned long flags;
bool success = false;
if (iwl_trans_grab_nic_access(trans, &flags)) {
success = true;
_iwl_read_prph_block(trans, start, len_bytes, data);
iwl_trans_release_nic_access(trans, &flags);
}
return success;
}
static void iwl_dump_prph(struct iwl_trans *trans,
struct iwl_fw_error_dump_data **data,
const struct iwl_prph_range *iwl_prph_dump_addr,
u32 range_len)
{
struct iwl_fw_error_dump_prph *prph;
unsigned long flags;
u32 prph_len = 0, i;
u32 i;
if (!iwl_trans_grab_nic_access(trans, &flags))
return 0;
return;
for (i = 0; i < range_len; i++) {
/* The range includes both boundaries */
int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
iwl_prph_dump_addr[i].start + 4;
int reg;
__le32 *val;
prph_len += sizeof(**data) + sizeof(*prph) + num_bytes_in_chunk;
(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
(*data)->len = cpu_to_le32(sizeof(*prph) +
num_bytes_in_chunk);
prph = (void *)(*data)->data;
prph->prph_start = cpu_to_le32(iwl_prph_dump_addr[i].start);
val = (void *)prph->data;
for (reg = iwl_prph_dump_addr[i].start;
reg <= iwl_prph_dump_addr[i].end;
reg += 4)
*val++ = cpu_to_le32(iwl_read_prph_no_grab(trans,
reg));
_iwl_read_prph_block(trans, iwl_prph_dump_addr[i].start,
/* our range is inclusive, hence + 4 */
iwl_prph_dump_addr[i].end -
iwl_prph_dump_addr[i].start + 4,
(void *)prph->data);
*data = iwl_fw_error_next_data(*data);
}
iwl_trans_release_nic_access(trans, &flags);
return prph_len;
}
/*
@ -495,11 +512,10 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
struct iwl_mvm_dump_ptrs *fw_error_dump;
struct scatterlist *sg_dump_data;
u32 sram_len, sram_ofs;
struct iwl_fw_dbg_mem_seg_tlv * const *fw_dbg_mem =
mvm->fw->dbg_mem_tlv;
const struct iwl_fw_dbg_mem_seg_tlv *fw_dbg_mem = mvm->fw->dbg_mem_tlv;
u32 file_len, fifo_data_len = 0, prph_len = 0, radio_len = 0;
u32 smem_len = mvm->fw->dbg_dynamic_mem ? 0 : mvm->cfg->smem_len;
u32 sram2_len = mvm->fw->dbg_dynamic_mem ? 0 : mvm->cfg->dccm2_len;
u32 smem_len = mvm->fw->n_dbg_mem_tlv ? 0 : mvm->cfg->smem_len;
u32 sram2_len = mvm->fw->n_dbg_mem_tlv ? 0 : mvm->cfg->dccm2_len;
bool monitor_dump_only = false;
int i;
@ -624,10 +640,9 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
file_len += sizeof(*dump_data) + sizeof(*dump_mem) + sram2_len;
/* Make room for MEM segments */
for (i = 0; i < ARRAY_SIZE(mvm->fw->dbg_mem_tlv); i++) {
if (fw_dbg_mem[i])
file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
le32_to_cpu(fw_dbg_mem[i]->len);
for (i = 0; i < mvm->fw->n_dbg_mem_tlv; i++) {
file_len += sizeof(*dump_data) + sizeof(*dump_mem) +
le32_to_cpu(fw_dbg_mem[i].len);
}
/* Make room for fw's virtual image pages, if it exists */
@ -656,7 +671,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
file_len += sizeof(*dump_data) + sizeof(*dump_trig) +
mvm->fw_dump_desc->len;
if (!mvm->fw->dbg_dynamic_mem)
if (!mvm->fw->n_dbg_mem_tlv)
file_len += sram_len + sizeof(*dump_mem);
dump_file = vzalloc(file_len);
@ -708,7 +723,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
if (monitor_dump_only)
goto dump_trans_data;
if (!mvm->fw->dbg_dynamic_mem) {
if (!mvm->fw->n_dbg_mem_tlv) {
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
dump_data->len = cpu_to_le32(sram_len + sizeof(*dump_mem));
dump_mem = (void *)dump_data->data;
@ -719,22 +734,39 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
dump_data = iwl_fw_error_next_data(dump_data);
}
for (i = 0; i < ARRAY_SIZE(mvm->fw->dbg_mem_tlv); i++) {
if (fw_dbg_mem[i]) {
u32 len = le32_to_cpu(fw_dbg_mem[i]->len);
u32 ofs = le32_to_cpu(fw_dbg_mem[i]->ofs);
for (i = 0; i < mvm->fw->n_dbg_mem_tlv; i++) {
u32 len = le32_to_cpu(fw_dbg_mem[i].len);
u32 ofs = le32_to_cpu(fw_dbg_mem[i].ofs);
bool success;
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
dump_data->len = cpu_to_le32(len +
sizeof(*dump_mem));
dump_mem = (void *)dump_data->data;
dump_mem->type = fw_dbg_mem[i]->data_type;
dump_mem->offset = cpu_to_le32(ofs);
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_MEM);
dump_data->len = cpu_to_le32(len + sizeof(*dump_mem));
dump_mem = (void *)dump_data->data;
dump_mem->type = fw_dbg_mem[i].data_type;
dump_mem->offset = cpu_to_le32(ofs);
switch (dump_mem->type & cpu_to_le32(FW_DBG_MEM_TYPE_MASK)) {
case cpu_to_le32(FW_DBG_MEM_TYPE_REGULAR):
iwl_trans_read_mem_bytes(mvm->trans, ofs,
dump_mem->data,
len);
dump_data = iwl_fw_error_next_data(dump_data);
success = true;
break;
case cpu_to_le32(FW_DBG_MEM_TYPE_PRPH):
success = iwl_read_prph_block(mvm->trans, ofs, len,
(void *)dump_mem->data);
break;
default:
/*
* shouldn't get here, we ignored this kind
* of TLV earlier during the TLV parsing?!
*/
WARN_ON(1);
success = false;
}
if (success)
dump_data = iwl_fw_error_next_data(dump_data);
}
if (smem_len) {
@ -816,11 +848,12 @@ dump_trans_data:
sg_nents(sg_dump_data),
fw_error_dump->op_mode_ptr,
fw_error_dump->op_mode_len, 0);
sg_pcopy_from_buffer(sg_dump_data,
sg_nents(sg_dump_data),
fw_error_dump->trans_ptr->data,
fw_error_dump->trans_ptr->len,
fw_error_dump->op_mode_len);
if (fw_error_dump->trans_ptr)
sg_pcopy_from_buffer(sg_dump_data,
sg_nents(sg_dump_data),
fw_error_dump->trans_ptr->data,
fw_error_dump->trans_ptr->len,
fw_error_dump->op_mode_len);
dev_coredumpsg(mvm->trans->dev, sg_dump_data, file_len,
GFP_KERNEL);
}

View File

@ -190,7 +190,7 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image)
* CPU2 paging CSS
* CPU2 paging image (including instruction and data)
*/
for (sec_idx = 0; sec_idx < IWL_UCODE_SECTION_MAX; sec_idx++) {
for (sec_idx = 0; sec_idx < image->num_sec; sec_idx++) {
if (image->sec[sec_idx].offset == PAGING_SEPARATOR_SECTION) {
sec_idx++;
break;
@ -201,7 +201,7 @@ static int iwl_fill_paging_mem(struct iwl_mvm *mvm, const struct fw_img *image)
* If paging is enabled there should be at least 2 more sections left
* (one for CSS and one for Paging data)
*/
if (sec_idx >= ARRAY_SIZE(image->sec) - 1) {
if (sec_idx >= image->num_sec - 1) {
IWL_ERR(mvm, "Paging: Missing CSS and/or paging sections\n");
iwl_free_fw_paging(mvm);
return -EINVAL;
@ -259,9 +259,7 @@ static int iwl_alloc_fw_paging_mem(struct iwl_mvm *mvm,
{
struct page *block;
dma_addr_t phys = 0;
int blk_idx = 0;
int order, num_of_pages;
int dma_enabled;
int blk_idx, order, num_of_pages, size, dma_enabled;
if (mvm->fw_paging_db[0].fw_paging_block)
return 0;
@ -272,9 +270,8 @@ static int iwl_alloc_fw_paging_mem(struct iwl_mvm *mvm,
BUILD_BUG_ON(BIT(BLOCK_2_EXP_SIZE) != PAGING_BLOCK_SIZE);
num_of_pages = image->paging_mem_size / FW_PAGING_SIZE;
mvm->num_of_paging_blk = ((num_of_pages - 1) /
NUM_OF_PAGE_PER_GROUP) + 1;
mvm->num_of_paging_blk =
DIV_ROUND_UP(num_of_pages, NUM_OF_PAGE_PER_GROUP);
mvm->num_of_pages_in_last_blk =
num_of_pages -
NUM_OF_PAGE_PER_GROUP * (mvm->num_of_paging_blk - 1);
@ -284,46 +281,13 @@ static int iwl_alloc_fw_paging_mem(struct iwl_mvm *mvm,
mvm->num_of_paging_blk,
mvm->num_of_pages_in_last_blk);
/* allocate block of 4Kbytes for paging CSS */
order = get_order(FW_PAGING_SIZE);
block = alloc_pages(GFP_KERNEL, order);
if (!block) {
/* free all the previous pages since we failed */
iwl_free_fw_paging(mvm);
return -ENOMEM;
}
mvm->fw_paging_db[blk_idx].fw_paging_block = block;
mvm->fw_paging_db[blk_idx].fw_paging_size = FW_PAGING_SIZE;
if (dma_enabled) {
phys = dma_map_page(mvm->trans->dev, block, 0,
PAGE_SIZE << order, DMA_BIDIRECTIONAL);
if (dma_mapping_error(mvm->trans->dev, phys)) {
/*
* free the previous pages and the current one since
* we failed to map_page.
*/
iwl_free_fw_paging(mvm);
return -ENOMEM;
}
mvm->fw_paging_db[blk_idx].fw_paging_phys = phys;
} else {
mvm->fw_paging_db[blk_idx].fw_paging_phys = PAGING_ADDR_SIG |
blk_idx << BLOCK_2_EXP_SIZE;
}
IWL_DEBUG_FW(mvm,
"Paging: allocated 4K(CSS) bytes (order %d) for firmware paging.\n",
order);
/*
* allocate blocks in dram.
* since that CSS allocated in fw_paging_db[0] loop start from index 1
* Allocate CSS and paging blocks in dram.
*/
for (blk_idx = 1; blk_idx < mvm->num_of_paging_blk + 1; blk_idx++) {
/* allocate block of PAGING_BLOCK_SIZE (32K) */
order = get_order(PAGING_BLOCK_SIZE);
for (blk_idx = 0; blk_idx < mvm->num_of_paging_blk + 1; blk_idx++) {
/* For CSS allocate 4KB, for others PAGING_BLOCK_SIZE (32K) */
size = blk_idx ? PAGING_BLOCK_SIZE : FW_PAGING_SIZE;
order = get_order(size);
block = alloc_pages(GFP_KERNEL, order);
if (!block) {
/* free all the previous pages since we failed */
@ -332,7 +296,7 @@ static int iwl_alloc_fw_paging_mem(struct iwl_mvm *mvm,
}
mvm->fw_paging_db[blk_idx].fw_paging_block = block;
mvm->fw_paging_db[blk_idx].fw_paging_size = PAGING_BLOCK_SIZE;
mvm->fw_paging_db[blk_idx].fw_paging_size = size;
if (dma_enabled) {
phys = dma_map_page(mvm->trans->dev, block, 0,
@ -353,9 +317,14 @@ static int iwl_alloc_fw_paging_mem(struct iwl_mvm *mvm,
blk_idx << BLOCK_2_EXP_SIZE;
}
IWL_DEBUG_FW(mvm,
"Paging: allocated 32K bytes (order %d) for firmware paging.\n",
order);
if (!blk_idx)
IWL_DEBUG_FW(mvm,
"Paging: allocated 4K(CSS) bytes (order %d) for firmware paging.\n",
order);
else
IWL_DEBUG_FW(mvm,
"Paging: allocated 32K bytes (order %d) for firmware paging.\n",
order);
}
return 0;

View File

@ -1565,7 +1565,7 @@ void iwl_mvm_rx_stored_beacon_notif(struct iwl_mvm *mvm,
rx_status.flag |= RX_FLAG_MACTIME_PLCP_START;
rx_status.device_timestamp = le32_to_cpu(sb->system_time);
rx_status.band =
(sb->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ?
(sb->band & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ?
NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
rx_status.freq =
ieee80211_channel_to_frequency(le16_to_cpu(sb->channel),

View File

@ -463,6 +463,13 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
IEEE80211_RADIOTAP_MCS_HAVE_STBC;
hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC |
IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED;
hw->radiotap_timestamp.units_pos =
IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US |
IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ;
/* this is the case for CCK frames, it's better (only 8) for OFDM */
hw->radiotap_timestamp.accuracy = 22;
hw->rate_control_algorithm = "iwl-mvm-rs";
hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES;
hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
@ -670,7 +677,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->wiphy->wowlan = &mvm->wowlan;
}
if (mvm->fw->img[IWL_UCODE_WOWLAN].sec[0].len &&
if (mvm->fw->img[IWL_UCODE_WOWLAN].num_sec &&
mvm->trans->ops->d3_suspend &&
mvm->trans->ops->d3_resume &&
device_can_wakeup(mvm->trans->dev)) {

View File

@ -1657,8 +1657,8 @@ void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
* Disable a TXQ.
* Note that in non-DQA mode the %mac80211_queue and %tid params are ignored.
*/
void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
u8 tid, u8 flags);
int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
u8 tid, u8 flags);
int iwl_mvm_find_free_queue(struct iwl_mvm *mvm, u8 sta_id, u8 minq, u8 maxq);
/* Return a bitmask with all the hw supported queues, except for the

View File

@ -161,9 +161,6 @@ static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct rs_rate *rate,
const struct rs_tx_column *next_col)
{
struct iwl_mvm_sta *mvmsta;
struct iwl_mvm_vif *mvmvif;
if (!sta->ht_cap.ht_supported)
return false;
@ -176,9 +173,6 @@ static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta))
return false;
mvmsta = iwl_mvm_sta_from_mac80211(sta);
mvmvif = iwl_mvm_vif_from_mac80211(mvmsta->vif);
if (mvm->nvm_data->sku_cap_mimo_disabled)
return false;
@ -3071,7 +3065,7 @@ static void iwl_mvm_reset_frame_stats(struct iwl_mvm *mvm)
void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg)
{
u8 nss = 0, mcs = 0;
u8 nss = 0;
spin_lock(&mvm->drv_stats_lock);
@ -3099,11 +3093,9 @@ void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg)
if (rate & RATE_MCS_HT_MSK) {
mvm->drv_rx_stats.ht_frames++;
mcs = rate & RATE_HT_MCS_RATE_CODE_MSK;
nss = ((rate & RATE_HT_MCS_NSS_MSK) >> RATE_HT_MCS_NSS_POS) + 1;
} else if (rate & RATE_MCS_VHT_MSK) {
mvm->drv_rx_stats.vht_frames++;
mcs = rate & RATE_VHT_MCS_RATE_CODE_MSK;
nss = ((rate & RATE_VHT_MCS_NSS_MSK) >>
RATE_VHT_MCS_NSS_POS) + 1;
} else {

View File

@ -621,12 +621,10 @@ void iwl_mvm_handle_rx_statistics(struct iwl_mvm *mvm,
};
int expected_size = iwl_mvm_has_new_rx_api(mvm) ? sizeof(*stats) :
sizeof(struct iwl_notif_statistics_v10);
u32 temperature;
if (iwl_rx_packet_payload_len(pkt) != expected_size)
goto invalid;
temperature = le32_to_cpu(stats->general.radio_temperature);
data.mac_id = stats->rx.general.mac_id;
data.beacon_filter_average_energy =
stats->general.beacon_filter_average_energy;

View File

@ -454,13 +454,6 @@ static int iwl_mvm_remove_sta_queue_marking(struct iwl_mvm *mvm, int queue)
rcu_read_unlock();
spin_lock_bh(&mvm->queue_info_lock);
/* Unmap MAC queues and TIDs from this queue */
mvm->queue_info[queue].hw_queue_to_mac80211 = 0;
mvm->queue_info[queue].hw_queue_refcount = 0;
mvm->queue_info[queue].tid_bitmap = 0;
spin_unlock_bh(&mvm->queue_info_lock);
return disable_agg_tids;
}
@ -755,28 +748,22 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
* first
*/
if (using_inactive_queue) {
struct iwl_scd_txq_cfg_cmd cmd = {
.scd_queue = queue,
.action = SCD_CFG_DISABLE_QUEUE,
};
u8 txq_curr_ac;
disable_agg_tids = iwl_mvm_remove_sta_queue_marking(mvm, queue);
u8 txq_curr_ac, sta_id;
spin_lock_bh(&mvm->queue_info_lock);
txq_curr_ac = mvm->queue_info[queue].mac80211_ac;
cmd.sta_id = mvm->queue_info[queue].ra_sta_id;
cmd.tx_fifo = iwl_mvm_ac_to_tx_fifo[txq_curr_ac];
cmd.tid = mvm->queue_info[queue].txq_tid;
sta_id = mvm->queue_info[queue].ra_sta_id;
spin_unlock_bh(&mvm->queue_info_lock);
disable_agg_tids = iwl_mvm_remove_sta_queue_marking(mvm, queue);
/* Disable the queue */
if (disable_agg_tids)
iwl_mvm_invalidate_sta_queue(mvm, queue,
disable_agg_tids, false);
iwl_trans_txq_disable(mvm->trans, queue, false);
ret = iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd),
&cmd);
ret = iwl_mvm_disable_txq(mvm, queue,
mvmsta->vif->hw_queue[txq_curr_ac],
tid, 0);
if (ret) {
IWL_ERR(mvm,
"Failed to free inactive queue %d (ret=%d)\n",
@ -791,7 +778,7 @@ static int iwl_mvm_sta_alloc_queue(struct iwl_mvm *mvm,
}
/* If TXQ is allocated to another STA, update removal in FW */
if (cmd.sta_id != mvmsta->sta_id)
if (sta_id != mvmsta->sta_id)
iwl_mvm_invalidate_sta_queue(mvm, queue, 0, true);
}
@ -868,7 +855,6 @@ static void iwl_mvm_change_queue_owner(struct iwl_mvm *mvm, int queue)
.scd_queue = queue,
.action = SCD_CFG_UPDATE_QUEUE_TID,
};
s8 sta_id;
int tid;
unsigned long tid_bitmap;
int ret;
@ -876,7 +862,6 @@ static void iwl_mvm_change_queue_owner(struct iwl_mvm *mvm, int queue)
lockdep_assert_held(&mvm->mutex);
spin_lock_bh(&mvm->queue_info_lock);
sta_id = mvm->queue_info[queue].ra_sta_id;
tid_bitmap = mvm->queue_info[queue].tid_bitmap;
spin_unlock_bh(&mvm->queue_info_lock);

View File

@ -102,14 +102,13 @@ iwl_mvm_bar_check_trigger(struct iwl_mvm *mvm, const u8 *addr,
#define OPT_HDR(type, skb, off) \
(type *)(skb_network_header(skb) + (off))
static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *info,
struct iwl_tx_cmd *tx_cmd)
static u16 iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *info)
{
u16 offload_assist = 0;
#if IS_ENABLED(CONFIG_INET)
u16 mh_len = ieee80211_hdrlen(hdr->frame_control);
u16 offload_assist = le16_to_cpu(tx_cmd->offload_assist);
u8 protocol = 0;
/*
@ -117,7 +116,7 @@ static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
* compute it
*/
if (skb->ip_summed != CHECKSUM_PARTIAL || IWL_MVM_SW_TX_CSUM_OFFLOAD)
return;
goto out;
/* We do not expect to be requested to csum stuff we do not support */
if (WARN_ONCE(!(mvm->hw->netdev_features & IWL_TX_CSUM_NETIF_FLAGS) ||
@ -125,7 +124,7 @@ static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
skb->protocol != htons(ETH_P_IPV6)),
"No support for requested checksum\n")) {
skb_checksum_help(skb);
return;
goto out;
}
if (skb->protocol == htons(ETH_P_IP)) {
@ -145,7 +144,7 @@ static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
protocol != NEXTHDR_HOP &&
protocol != NEXTHDR_DEST) {
skb_checksum_help(skb);
return;
goto out;
}
hp = OPT_HDR(struct ipv6_opt_hdr, skb, off);
@ -159,7 +158,7 @@ static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
if (protocol != IPPROTO_TCP && protocol != IPPROTO_UDP) {
WARN_ON_ONCE(1);
skb_checksum_help(skb);
return;
goto out;
}
/* enable L4 csum */
@ -191,8 +190,9 @@ static void iwl_mvm_tx_csum(struct iwl_mvm *mvm, struct sk_buff *skb,
mh_len /= 2;
offload_assist |= mh_len << TX_CMD_OFFLD_MH_SIZE;
tx_cmd->offload_assist = cpu_to_le16(offload_assist);
out:
#endif
return offload_assist;
}
/*
@ -295,7 +295,52 @@ void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
!(tx_cmd->offload_assist & cpu_to_le16(BIT(TX_CMD_OFFLD_AMSDU))))
tx_cmd->offload_assist |= cpu_to_le16(BIT(TX_CMD_OFFLD_PAD));
iwl_mvm_tx_csum(mvm, skb, hdr, info, tx_cmd);
tx_cmd->offload_assist |=
cpu_to_le16(iwl_mvm_tx_csum(mvm, skb, hdr, info));
}
static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta)
{
int rate_idx;
u8 rate_plcp;
u32 rate_flags;
/* HT rate doesn't make sense for a non data frame */
WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS,
"Got an HT rate (flags:0x%x/mcs:%d) for a non data frame\n",
info->control.rates[0].flags,
info->control.rates[0].idx);
rate_idx = info->control.rates[0].idx;
/* if the rate isn't a well known legacy rate, take the lowest one */
if (rate_idx < 0 || rate_idx >= IWL_RATE_COUNT_LEGACY)
rate_idx = rate_lowest_index(
&mvm->nvm_data->bands[info->band], sta);
/* For 5 GHZ band, remap mac80211 rate indices into driver indices */
if (info->band == NL80211_BAND_5GHZ)
rate_idx += IWL_FIRST_OFDM_RATE;
/* For 2.4 GHZ band, check that there is no need to remap */
BUILD_BUG_ON(IWL_FIRST_CCK_RATE != 0);
/* Get PLCP rate for tx_cmd->rate_n_flags */
rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(rate_idx);
if (info->band == NL80211_BAND_2GHZ &&
!iwl_mvm_bt_coex_is_shared_ant_avail(mvm))
rate_flags = mvm->cfg->non_shared_ant << RATE_MCS_ANT_POS;
else
rate_flags =
BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS;
/* Set CCK flag as needed */
if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE))
rate_flags |= RATE_MCS_CCK_MSK;
return (u32)rate_plcp | rate_flags;
}
/*
@ -305,10 +350,6 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd,
struct ieee80211_tx_info *info,
struct ieee80211_sta *sta, __le16 fc)
{
u32 rate_flags;
int rate_idx;
u8 rate_plcp;
/* Set retry limit on RTS packets */
tx_cmd->rts_retry_limit = IWL_RTS_DFAULT_RETRY_LIMIT;
@ -337,46 +378,12 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd,
cpu_to_le32(TX_CMD_FLG_ACK | TX_CMD_FLG_BAR);
}
/* HT rate doesn't make sense for a non data frame */
WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS,
"Got an HT rate (flags:0x%x/mcs:%d) for a non data frame (fc:0x%x)\n",
info->control.rates[0].flags,
info->control.rates[0].idx,
le16_to_cpu(fc));
rate_idx = info->control.rates[0].idx;
/* if the rate isn't a well known legacy rate, take the lowest one */
if (rate_idx < 0 || rate_idx >= IWL_RATE_COUNT_LEGACY)
rate_idx = rate_lowest_index(
&mvm->nvm_data->bands[info->band], sta);
/* For 5 GHZ band, remap mac80211 rate indices into driver indices */
if (info->band == NL80211_BAND_5GHZ)
rate_idx += IWL_FIRST_OFDM_RATE;
/* For 2.4 GHZ band, check that there is no need to remap */
BUILD_BUG_ON(IWL_FIRST_CCK_RATE != 0);
/* Get PLCP rate for tx_cmd->rate_n_flags */
rate_plcp = iwl_mvm_mac80211_idx_to_hwrate(rate_idx);
mvm->mgmt_last_antenna_idx =
iwl_mvm_next_antenna(mvm, iwl_mvm_get_valid_tx_ant(mvm),
mvm->mgmt_last_antenna_idx);
if (info->band == NL80211_BAND_2GHZ &&
!iwl_mvm_bt_coex_is_shared_ant_avail(mvm))
rate_flags = mvm->cfg->non_shared_ant << RATE_MCS_ANT_POS;
else
rate_flags =
BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS;
/* Set CCK flag as needed */
if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE))
rate_flags |= RATE_MCS_CCK_MSK;
/* Set the rate in the TX cmd */
tx_cmd->rate_n_flags = cpu_to_le32((u32)rate_plcp | rate_flags);
tx_cmd->rate_n_flags = cpu_to_le32(iwl_mvm_get_tx_rate(mvm, info, sta));
}
static inline void iwl_mvm_set_tx_cmd_pn(struct ieee80211_tx_info *info,

View File

@ -693,10 +693,6 @@ void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
.tid = cfg->tid,
};
/* Set sta_id in the command, if it exists */
if (iwl_mvm_is_dqa_supported(mvm))
cmd.sta_id = cfg->sta_id;
iwl_trans_txq_enable_cfg(mvm->trans, queue, ssn, NULL,
wdg_timeout);
WARN(iwl_mvm_send_cmd_pdu(mvm, SCD_QUEUE_CFG, 0, sizeof(cmd),
@ -706,8 +702,8 @@ void iwl_mvm_enable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
}
}
void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
u8 tid, u8 flags)
int iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
u8 tid, u8 flags)
{
struct iwl_scd_txq_cfg_cmd cmd = {
.scd_queue = queue,
@ -720,7 +716,7 @@ void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
if (WARN_ON(mvm->queue_info[queue].hw_queue_refcount == 0)) {
spin_unlock_bh(&mvm->queue_info_lock);
return;
return 0;
}
mvm->queue_info[queue].tid_bitmap &= ~BIT(tid);
@ -760,7 +756,7 @@ void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
/* If the queue is still enabled - nothing left to do in this func */
if (cmd.action == SCD_CFG_ENABLE_QUEUE) {
spin_unlock_bh(&mvm->queue_info_lock);
return;
return 0;
}
cmd.sta_id = mvm->queue_info[queue].ra_sta_id;
@ -791,6 +787,8 @@ void iwl_mvm_disable_txq(struct iwl_mvm *mvm, int queue, int mac80211_queue,
if (ret)
IWL_ERR(mvm, "Failed to disable queue %d (ret=%d)\n",
queue, ret);
return ret;
}
/**

View File

@ -805,7 +805,7 @@ static int iwl_pcie_load_cpu_sections_8000(struct iwl_trans *trans,
(*first_ucode_section)++;
}
for (i = *first_ucode_section; i < IWL_UCODE_SECTION_MAX; i++) {
for (i = *first_ucode_section; i < image->num_sec; i++) {
last_read_idx = i;
/*
@ -868,19 +868,15 @@ static int iwl_pcie_load_cpu_sections(struct iwl_trans *trans,
int cpu,
int *first_ucode_section)
{
int shift_param;
int i, ret = 0;
u32 last_read_idx = 0;
if (cpu == 1) {
shift_param = 0;
if (cpu == 1)
*first_ucode_section = 0;
} else {
shift_param = 16;
else
(*first_ucode_section)++;
}
for (i = *first_ucode_section; i < IWL_UCODE_SECTION_MAX; i++) {
for (i = *first_ucode_section; i < image->num_sec; i++) {
last_read_idx = i;
/*
@ -1066,6 +1062,20 @@ static int iwl_pcie_load_given_ucode_8000(struct iwl_trans *trans,
&first_ucode_section);
}
static bool iwl_trans_check_hw_rf_kill(struct iwl_trans *trans)
{
bool hw_rfkill = iwl_is_rfkill_set(trans);
if (hw_rfkill)
set_bit(STATUS_RFKILL, &trans->status);
else
clear_bit(STATUS_RFKILL, &trans->status);
iwl_trans_pcie_rf_kill(trans, hw_rfkill);
return hw_rfkill;
}
static void _iwl_trans_pcie_stop_device(struct iwl_trans *trans, bool low_power)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@ -1208,12 +1218,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
mutex_lock(&trans_pcie->mutex);
/* If platform's RF_KILL switch is NOT set to KILL */
hw_rfkill = iwl_is_rfkill_set(trans);
if (hw_rfkill)
set_bit(STATUS_RFKILL, &trans->status);
else
clear_bit(STATUS_RFKILL, &trans->status);
iwl_trans_pcie_rf_kill(trans, hw_rfkill);
hw_rfkill = iwl_trans_check_hw_rf_kill(trans);
if (hw_rfkill && !run_in_rfkill) {
ret = -ERFKILL;
goto out;
@ -1261,13 +1266,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
ret = iwl_pcie_load_given_ucode(trans, fw);
/* re-check RF-Kill state since we may have missed the interrupt */
hw_rfkill = iwl_is_rfkill_set(trans);
if (hw_rfkill)
set_bit(STATUS_RFKILL, &trans->status);
else
clear_bit(STATUS_RFKILL, &trans->status);
iwl_trans_pcie_rf_kill(trans, hw_rfkill);
hw_rfkill = iwl_trans_check_hw_rf_kill(trans);
if (hw_rfkill && !run_in_rfkill)
ret = -ERFKILL;
@ -1659,7 +1658,6 @@ static int iwl_pcie_init_msix_handler(struct pci_dev *pdev,
static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
bool hw_rfkill;
int err;
lockdep_assert_held(&trans_pcie->mutex);
@ -1683,13 +1681,8 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power)
/* Set is_down to false here so that...*/
trans_pcie->is_down = false;
hw_rfkill = iwl_is_rfkill_set(trans);
if (hw_rfkill)
set_bit(STATUS_RFKILL, &trans->status);
else
clear_bit(STATUS_RFKILL, &trans->status);
/* ... rfkill can call stop_device and set it false if needed */
iwl_trans_pcie_rf_kill(trans, hw_rfkill);
/* ...rfkill can call stop_device and set it false if needed */
iwl_trans_check_hw_rf_kill(trans);
/* Make sure we sync here, because we'll need full access later */
if (low_power)

View File

@ -305,7 +305,7 @@ int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action,
}
lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret);
return 0;
return ret;
}
static int lbs_wait_for_ds_awake(struct lbs_private *priv)

View File

@ -101,13 +101,6 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv,
{
struct txpd *local_tx_pd;
struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb);
unsigned int pad;
int headroom = (priv->adapter->iface_type ==
MWIFIEX_USB) ? 0 : INTF_HEADER_LEN;
pad = ((void *)skb->data - sizeof(*local_tx_pd) -
headroom - NULL) & (MWIFIEX_DMA_ALIGN_SZ - 1);
skb_push(skb, pad);
skb_push(skb, sizeof(*local_tx_pd));
@ -121,12 +114,10 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv,
local_tx_pd->bss_num = priv->bss_num;
local_tx_pd->bss_type = priv->bss_type;
/* Always zero as the data is followed by struct txpd */
local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd) +
pad);
local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd));
local_tx_pd->tx_pkt_type = cpu_to_le16(PKT_TYPE_AMSDU);
local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len -
sizeof(*local_tx_pd) -
pad);
sizeof(*local_tx_pd));
if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT)
local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET;
@ -190,7 +181,11 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
ra_list_flags);
return -1;
}
skb_reserve(skb_aggr, MWIFIEX_MIN_DATA_HEADER_LEN);
/* skb_aggr->data already 64 byte align, just reserve bus interface
* header and txpd.
*/
skb_reserve(skb_aggr, headroom + sizeof(struct txpd));
tx_info_aggr = MWIFIEX_SKB_TXCB(skb_aggr);
memset(tx_info_aggr, 0, sizeof(*tx_info_aggr));

View File

@ -114,7 +114,8 @@ mwifiex_info_read(struct file *file, char __user *ubuf,
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) {
p += sprintf(p, "multicast_count=\"%d\"\n",
netdev_mc_count(netdev));
p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid);
p += sprintf(p, "essid=\"%.*s\"\n", info.ssid.ssid_len,
info.ssid.ssid);
p += sprintf(p, "bssid=\"%pM\"\n", info.bssid);
p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan);
p += sprintf(p, "country_code = \"%s\"\n", info.country_code);

View File

@ -550,6 +550,7 @@ enum mwifiex_channel_flags {
#define EVENT_TX_DATA_PAUSE 0x00000055
#define EVENT_EXT_SCAN_REPORT 0x00000058
#define EVENT_RXBA_SYNC 0x00000059
#define EVENT_UNKNOWN_DEBUG 0x00000063
#define EVENT_BG_SCAN_STOPPED 0x00000065
#define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f
#define EVENT_MULTI_CHAN_INFO 0x0000006a

Some files were not shown because too many files have changed in this diff Show More