Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next

Kalle Valo says:

====================
pull-request: wireless-drivers-next 2015-01-22

now a bigger pull request for net-next. Rafal found a UTF-8 bug in
patchwork[1] and because of that two commits (d0c102f70a and
d0f66df539) have his name corrupted:

    Acked-by: Rafa? Mi?ecki <zajec5@gmail.com>

Somehow I failed to spot that when I commited the patches. As rebasing
public git trees is bad, I thought we can live with these and decided
not to rebase. But I'll pay close attention to this in the future to
make sure that it won't happen again. Also we requested an update to
patchwork.kernel.org, the latest patchwork doesn't seem to have this
bug.

Also please note this pull request also adds one DT binding doc, but
this was reviewed in the device tree list:

 .../bindings/net/wireless/qcom,ath10k.txt          |   30 +

Please let me know if you have any issues.

[1] https://lists.ozlabs.org/pipermail/patchwork/2015-January/001261.html
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2015-01-26 16:09:45 -08:00
commit 9c5d94bc18
233 changed files with 13706 additions and 3327 deletions

View file

@ -0,0 +1,30 @@
* Qualcomm Atheros ath10k wireless devices
For ath10k devices the calibration data can be provided through Device
Tree. The node is a child node of the PCI controller.
Required properties:
-compatible : Should be "qcom,ath10k"
Optional properties:
- qcom,ath10k-calibration-data : calibration data as an array, the
length can vary between hw versions
Example:
pci {
pcie@0 {
reg = <0 0 0 0 0>;
#interrupt-cells = <1>;
#size-cells = <2>;
#address-cells = <3>;
device_type = "pci";
ath10k@0,0 {
reg = <0 0 0 0 0>;
device_type = "pci";
qcom,ath10k-calibration-data = [ 01 02 03 ... ];
};
};
};

View file

@ -1657,7 +1657,6 @@ M: Jiri Slaby <jirislaby@gmail.com>
M: Nick Kossifidis <mickflemm@gmail.com>
M: "Luis R. Rodriguez" <mcgrof@do-not-panic.com>
L: linux-wireless@vger.kernel.org
L: ath5k-devel@lists.ath5k.org
W: http://wireless.kernel.org/en/users/Drivers/ath5k
S: Maintained
F: drivers/net/wireless/ath/ath5k/

View file

@ -25,22 +25,18 @@ struct bcma_bus;
bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value,
int timeout);
void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core);
void bcma_init_bus(struct bcma_bus *bus);
int bcma_bus_register(struct bcma_bus *bus);
void bcma_bus_unregister(struct bcma_bus *bus);
int __init bcma_bus_early_register(struct bcma_bus *bus,
struct bcma_device *core_cc,
struct bcma_device *core_mips);
int __init bcma_bus_early_register(struct bcma_bus *bus);
#ifdef CONFIG_PM
int bcma_bus_suspend(struct bcma_bus *bus);
int bcma_bus_resume(struct bcma_bus *bus);
#endif
/* scan.c */
void bcma_detect_chip(struct bcma_bus *bus);
int bcma_bus_scan(struct bcma_bus *bus);
int __init bcma_bus_scan_early(struct bcma_bus *bus,
struct bcma_device_id *match,
struct bcma_device *core);
void bcma_init_bus(struct bcma_bus *bus);
/* sprom.c */
int bcma_sprom_get(struct bcma_bus *bus);

View file

@ -79,7 +79,9 @@ static int bcma_chipco_watchdog_ticks_per_ms(struct bcma_drv_cc *cc)
if (cc->capabilities & BCMA_CC_CAP_PMU) {
if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
/* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP clock */
/* 4706 CC and PMU watchdogs are clocked at 1/4 of ALP
* clock
*/
return bcma_chipco_get_alp_clock(cc) / 4000;
else
/* based on 32KHz ILP clock */
@ -97,7 +99,8 @@ int bcma_chipco_watchdog_register(struct bcma_drv_cc *cc)
wdt.driver_data = cc;
wdt.timer_set = bcma_chipco_watchdog_timer_set_wdt;
wdt.timer_set_ms = bcma_chipco_watchdog_timer_set_ms_wdt;
wdt.max_timer_ms = bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
wdt.max_timer_ms =
bcma_chipco_watchdog_get_max_timer(cc) / cc->ticks_per_ms;
pdev = platform_device_register_data(NULL, "bcm47xx-wdt",
cc->core->bus->num, &wdt,
@ -335,7 +338,8 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
| BCMA_CC_CORECTL_UARTCLKEN);
}
} else {
bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n", ccrev);
bcma_err(cc->core->bus, "serial not supported on this device ccrev: 0x%x\n",
ccrev);
return;
}

View file

@ -193,7 +193,7 @@ int __init bcma_host_soc_init(struct bcma_soc *soc)
int err;
/* Scan bus and initialize it */
err = bcma_bus_early_register(bus, &soc->core_cc, &soc->core_mips);
err = bcma_bus_early_register(bus);
if (err)
iounmap(bus->mmio);

View file

@ -268,6 +268,18 @@ void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core)
}
}
void bcma_init_bus(struct bcma_bus *bus)
{
mutex_lock(&bcma_buses_mutex);
bus->num = bcma_bus_next_num++;
mutex_unlock(&bcma_buses_mutex);
INIT_LIST_HEAD(&bus->cores);
bus->nr_cores = 0;
bcma_detect_chip(bus);
}
static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core)
{
int err;
@ -369,10 +381,6 @@ int bcma_bus_register(struct bcma_bus *bus)
int err;
struct bcma_device *core;
mutex_lock(&bcma_buses_mutex);
bus->num = bcma_bus_next_num++;
mutex_unlock(&bcma_buses_mutex);
/* Scan for devices (cores) */
err = bcma_bus_scan(bus);
if (err) {
@ -481,35 +489,20 @@ void bcma_bus_unregister(struct bcma_bus *bus)
kfree(cores[0]);
}
int __init bcma_bus_early_register(struct bcma_bus *bus,
struct bcma_device *core_cc,
struct bcma_device *core_mips)
/*
* This is a special version of bus registration function designed for SoCs.
* It scans bus and performs basic initialization of main cores only.
* Please note it requires memory allocation, however it won't try to sleep.
*/
int __init bcma_bus_early_register(struct bcma_bus *bus)
{
int err;
struct bcma_device *core;
struct bcma_device_id match;
match.manuf = BCMA_MANUF_BCM;
match.id = bcma_cc_core_id(bus);
match.class = BCMA_CL_SIM;
match.rev = BCMA_ANY_REV;
/* Scan for chip common core */
err = bcma_bus_scan_early(bus, &match, core_cc);
/* Scan for devices (cores) */
err = bcma_bus_scan(bus);
if (err) {
bcma_err(bus, "Failed to scan for common core: %d\n", err);
return -1;
}
match.manuf = BCMA_MANUF_MIPS;
match.id = BCMA_CORE_MIPS_74K;
match.class = BCMA_CL_SIM;
match.rev = BCMA_ANY_REV;
/* Scan for mips core */
err = bcma_bus_scan_early(bus, &match, core_mips);
if (err) {
bcma_err(bus, "Failed to scan for mips core: %d\n", err);
bcma_err(bus, "Failed to scan bus: %d\n", err);
return -1;
}

View file

@ -435,15 +435,12 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
return 0;
}
void bcma_init_bus(struct bcma_bus *bus)
void bcma_detect_chip(struct bcma_bus *bus)
{
s32 tmp;
struct bcma_chipinfo *chipinfo = &(bus->chipinfo);
char chip_id[8];
INIT_LIST_HEAD(&bus->cores);
bus->nr_cores = 0;
bcma_scan_switch_core(bus, BCMA_ADDR_BASE);
tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID);
@ -464,6 +461,10 @@ int bcma_bus_scan(struct bcma_bus *bus)
int err, core_num = 0;
/* Skip if bus was already scanned (e.g. during early register) */
if (bus->nr_cores)
return 0;
erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
@ -522,61 +523,3 @@ out:
return err;
}
int __init bcma_bus_scan_early(struct bcma_bus *bus,
struct bcma_device_id *match,
struct bcma_device *core)
{
u32 erombase;
u32 __iomem *eromptr, *eromend;
int err = -ENODEV;
int core_num = 0;
erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM);
if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
eromptr = ioremap_nocache(erombase, BCMA_CORE_SIZE);
if (!eromptr)
return -ENOMEM;
} else {
eromptr = bus->mmio;
}
eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32);
bcma_scan_switch_core(bus, erombase);
while (eromptr < eromend) {
memset(core, 0, sizeof(*core));
INIT_LIST_HEAD(&core->list);
core->bus = bus;
err = bcma_get_next_core(bus, &eromptr, match, core_num, core);
if (err == -ENODEV) {
core_num++;
continue;
} else if (err == -ENXIO)
continue;
else if (err == -ESPIPE)
break;
else if (err < 0)
goto out;
core->core_index = core_num++;
bus->nr_cores++;
bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
core->core_index, bcma_device_name(&core->id),
core->id.manuf, core->id.id, core->id.rev,
core->id.class);
list_add_tail(&core->list, &bus->cores);
err = 0;
break;
}
out:
if (bus->hosttype == BCMA_HOSTTYPE_SOC)
iounmap(eromptr);
return err;
}

View file

@ -1837,6 +1837,7 @@ static int adm8211_probe(struct pci_dev *pdev,
if (!priv->map) {
printk(KERN_ERR "%s (adm8211): Cannot map device memory\n",
pci_name(pdev));
err = -ENOMEM;
goto err_free_dev;
}

View file

@ -8,11 +8,13 @@ ath10k_core-y += mac.o \
htt_tx.o \
txrx.o \
wmi.o \
wmi-tlv.o \
bmi.o
ath10k_core-$(CONFIG_ATH10K_DEBUGFS) += spectral.o
ath10k_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o
ath10k_core-$(CONFIG_THERMAL) += thermal.o
obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o
ath10k_pci-y += pci.o \

View file

@ -1093,6 +1093,8 @@ int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC >
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
BUILD_BUG_ON(2*TARGET_TLV_NUM_MSDU_DESC >
(CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
ce_state->ar = ar;
ce_state->id = ce_id;

View file

@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/of.h>
#include "core.h"
#include "mac.h"
@ -27,20 +28,18 @@
#include "debug.h"
#include "htt.h"
#include "testmode.h"
#include "wmi-ops.h"
unsigned int ath10k_debug_mask;
static bool uart_print;
static unsigned int ath10k_p2p;
static bool skip_otp;
module_param_named(debug_mask, ath10k_debug_mask, uint, 0644);
module_param(uart_print, bool, 0644);
module_param_named(p2p, ath10k_p2p, uint, 0644);
module_param(skip_otp, bool, 0644);
MODULE_PARM_DESC(debug_mask, "Debugging mask");
MODULE_PARM_DESC(uart_print, "Uart target debugging");
MODULE_PARM_DESC(p2p, "Enable ath10k P2P support");
MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
static const struct ath10k_hw_params ath10k_hw_params_list[] = {
@ -48,11 +47,14 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.id = QCA988X_HW_2_0_VERSION,
.name = "qca988x hw2.0",
.patch_load_addr = QCA988X_HW_2_0_PATCH_LOAD_ADDR,
.uart_pin = 7,
.fw = {
.dir = QCA988X_HW_2_0_FW_DIR,
.fw = QCA988X_HW_2_0_FW_FILE,
.otp = QCA988X_HW_2_0_OTP_FILE,
.board = QCA988X_HW_2_0_BOARD_DATA_FILE,
.board_size = QCA988X_BOARD_DATA_SZ,
.board_ext_size = QCA988X_BOARD_EXT_DATA_SZ,
},
},
};
@ -146,8 +148,8 @@ static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar,
static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data,
size_t data_len)
{
u32 board_data_size = QCA988X_BOARD_DATA_SZ;
u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ;
u32 board_data_size = ar->hw_params.fw.board_size;
u32 board_ext_data_size = ar->hw_params.fw.board_ext_size;
u32 board_ext_data_addr;
int ret;
@ -193,7 +195,7 @@ static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data,
static int ath10k_download_board_data(struct ath10k *ar, const void *data,
size_t data_len)
{
u32 board_data_size = QCA988X_BOARD_DATA_SZ;
u32 board_data_size = ar->hw_params.fw.board_size;
u32 address;
int ret;
@ -249,6 +251,63 @@ static int ath10k_download_cal_file(struct ath10k *ar)
return 0;
}
static int ath10k_download_cal_dt(struct ath10k *ar)
{
struct device_node *node;
int data_len;
void *data;
int ret;
node = ar->dev->of_node;
if (!node)
/* Device Tree is optional, don't print any warnings if
* there's no node for ath10k.
*/
return -ENOENT;
if (!of_get_property(node, "qcom,ath10k-calibration-data",
&data_len)) {
/* The calibration data node is optional */
return -ENOENT;
}
if (data_len != QCA988X_CAL_DATA_LEN) {
ath10k_warn(ar, "invalid calibration data length in DT: %d\n",
data_len);
ret = -EMSGSIZE;
goto out;
}
data = kmalloc(data_len, GFP_KERNEL);
if (!data) {
ret = -ENOMEM;
goto out;
}
ret = of_property_read_u8_array(node, "qcom,ath10k-calibration-data",
data, data_len);
if (ret) {
ath10k_warn(ar, "failed to read calibration data from DT: %d\n",
ret);
goto out_free;
}
ret = ath10k_download_board_data(ar, data, data_len);
if (ret) {
ath10k_warn(ar, "failed to download calibration data from Device Tree: %d\n",
ret);
goto out_free;
}
ret = 0;
out_free:
kfree(data);
out:
return ret;
}
static int ath10k_download_and_run_otp(struct ath10k *ar)
{
u32 result, address = ar->hw_params.patch_load_addr;
@ -447,7 +506,7 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
int ie_id, i, index, bit, ret;
struct ath10k_fw_ie *hdr;
const u8 *data;
__le32 *timestamp;
__le32 *timestamp, *version;
/* first fetch the firmware file (firmware-*.bin) */
ar->firmware = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir, name);
@ -562,6 +621,17 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
ar->otp_len = ie_len;
break;
case ATH10K_FW_IE_WMI_OP_VERSION:
if (ie_len != sizeof(u32))
break;
version = (__le32 *)data;
ar->wmi.op_version = le32_to_cpup(version);
ath10k_dbg(ar, ATH10K_DBG_BOOT, "found fw ie wmi op version %d\n",
ar->wmi.op_version);
break;
default:
ath10k_warn(ar, "Unknown FW IE: %u\n",
le32_to_cpu(hdr->id));
@ -582,13 +652,6 @@ static int ath10k_core_fetch_firmware_api_n(struct ath10k *ar, const char *name)
goto err;
}
if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features) &&
!test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
ath10k_err(ar, "feature bits corrupted: 10.2 feature requires 10.x feature to be set as well");
ret = -EINVAL;
goto err;
}
/* now fetch the board file */
if (ar->hw_params.fw.board == NULL) {
ath10k_err(ar, "board data file not defined");
@ -624,6 +687,13 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
/* calibration file is optional, don't check for any errors */
ath10k_fetch_cal_file(ar);
ar->fw_api = 4;
ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
ret = ath10k_core_fetch_firmware_api_n(ar, ATH10K_FW_API4_FILE);
if (ret == 0)
goto success;
ar->fw_api = 3;
ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
@ -662,7 +732,17 @@ static int ath10k_download_cal_data(struct ath10k *ar)
}
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"boot did not find a calibration file, try OTP next: %d\n",
"boot did not find a calibration file, try DT next: %d\n",
ret);
ret = ath10k_download_cal_dt(ar);
if (ret == 0) {
ar->cal_mode = ATH10K_CAL_MODE_DT;
goto done;
}
ath10k_dbg(ar, ATH10K_DBG_BOOT,
"boot did not find DT entry, try OTP next: %d\n",
ret);
ret = ath10k_download_and_run_otp(ar);
@ -696,7 +776,7 @@ static int ath10k_init_uart(struct ath10k *ar)
if (!uart_print)
return 0;
ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, 7);
ret = ath10k_bmi_write32(ar, hi_dbg_uart_txpin, ar->hw_params.uart_pin);
if (ret) {
ath10k_warn(ar, "could not enable UART prints (%d)\n", ret);
return ret;
@ -764,6 +844,7 @@ static void ath10k_core_restart(struct work_struct *work)
complete_all(&ar->offchan_tx_completed);
complete_all(&ar->install_key_done);
complete_all(&ar->vdev_setup_done);
complete_all(&ar->thermal.wmi_sync);
wake_up(&ar->htt.empty_tx_wq);
wake_up(&ar->wmi.tx_credits_wq);
wake_up(&ar->peer_mapping_wq);
@ -799,15 +880,62 @@ static void ath10k_core_restart(struct work_struct *work)
mutex_unlock(&ar->conf_mutex);
}
static void ath10k_core_init_max_sta_count(struct ath10k *ar)
static int ath10k_core_init_firmware_features(struct ath10k *ar)
{
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
ar->max_num_peers = TARGET_10X_NUM_PEERS;
ar->max_num_stations = TARGET_10X_NUM_STATIONS;
} else {
if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features) &&
!test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
ath10k_err(ar, "feature bits corrupted: 10.2 feature requires 10.x feature to be set as well");
return -EINVAL;
}
if (ar->wmi.op_version >= ATH10K_FW_WMI_OP_VERSION_MAX) {
ath10k_err(ar, "unsupported WMI OP version (max %d): %d\n",
ATH10K_FW_WMI_OP_VERSION_MAX, ar->wmi.op_version);
return -EINVAL;
}
/* Backwards compatibility for firmwares without
* ATH10K_FW_IE_WMI_OP_VERSION.
*/
if (ar->wmi.op_version == ATH10K_FW_WMI_OP_VERSION_UNSET) {
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
if (test_bit(ATH10K_FW_FEATURE_WMI_10_2,
ar->fw_features))
ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_2;
else
ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
} else {
ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_MAIN;
}
}
switch (ar->wmi.op_version) {
case ATH10K_FW_WMI_OP_VERSION_MAIN:
ar->max_num_peers = TARGET_NUM_PEERS;
ar->max_num_stations = TARGET_NUM_STATIONS;
ar->max_num_vdevs = TARGET_NUM_VDEVS;
ar->htt.max_num_pending_tx = TARGET_NUM_MSDU_DESC;
break;
case ATH10K_FW_WMI_OP_VERSION_10_1:
case ATH10K_FW_WMI_OP_VERSION_10_2:
case ATH10K_FW_WMI_OP_VERSION_10_2_4:
ar->max_num_peers = TARGET_10X_NUM_PEERS;
ar->max_num_stations = TARGET_10X_NUM_STATIONS;
ar->max_num_vdevs = TARGET_10X_NUM_VDEVS;
ar->htt.max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC;
break;
case ATH10K_FW_WMI_OP_VERSION_TLV:
ar->max_num_peers = TARGET_TLV_NUM_PEERS;
ar->max_num_stations = TARGET_TLV_NUM_STATIONS;
ar->htt.max_num_pending_tx = TARGET_TLV_NUM_MSDU_DESC;
break;
case ATH10K_FW_WMI_OP_VERSION_UNSET:
case ATH10K_FW_WMI_OP_VERSION_MAX:
WARN_ON(1);
return -EINVAL;
}
return 0;
}
int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
@ -945,10 +1073,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
if (status)
goto err_hif_stop;
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS) - 1;
else
ar->free_vdev_map = (1LL << TARGET_NUM_VDEVS) - 1;
ar->free_vdev_map = (1LL << ar->max_num_vdevs) - 1;
INIT_LIST_HEAD(&ar->arvifs);
@ -1025,8 +1150,7 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
ret = ath10k_bmi_get_target_info(ar, &target_info);
if (ret) {
ath10k_err(ar, "could not get target info (%d)\n", ret);
ath10k_hif_power_down(ar);
return ret;
goto err_power_down;
}
ar->target_version = target_info.version;
@ -1035,28 +1159,28 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
ret = ath10k_init_hw_params(ar);
if (ret) {
ath10k_err(ar, "could not get hw params (%d)\n", ret);
ath10k_hif_power_down(ar);
return ret;
goto err_power_down;
}
ret = ath10k_core_fetch_firmware_files(ar);
if (ret) {
ath10k_err(ar, "could not fetch firmware files (%d)\n", ret);
ath10k_hif_power_down(ar);
return ret;
goto err_power_down;
}
ath10k_core_init_max_sta_count(ar);
ret = ath10k_core_init_firmware_features(ar);
if (ret) {
ath10k_err(ar, "fatal problem with firmware features: %d\n",
ret);
goto err_free_firmware_files;
}
mutex_lock(&ar->conf_mutex);
ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
if (ret) {
ath10k_err(ar, "could not init core (%d)\n", ret);
ath10k_core_free_firmware_files(ar);
ath10k_hif_power_down(ar);
mutex_unlock(&ar->conf_mutex);
return ret;
goto err_unlock;
}
ath10k_print_driver_info(ar);
@ -1066,34 +1190,17 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
ath10k_hif_power_down(ar);
return 0;
}
static int ath10k_core_check_chip_id(struct ath10k *ar)
{
u32 hw_revision = MS(ar->chip_id, SOC_CHIP_ID_REV);
err_unlock:
mutex_unlock(&ar->conf_mutex);
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip_id 0x%08x hw_revision 0x%x\n",
ar->chip_id, hw_revision);
err_free_firmware_files:
ath10k_core_free_firmware_files(ar);
/* Check that we are not using hw1.0 (some of them have same pci id
* as hw2.0) before doing anything else as ath10k crashes horribly
* due to missing hw1.0 workarounds. */
switch (hw_revision) {
case QCA988X_HW_1_0_CHIP_ID_REV:
ath10k_err(ar, "ERROR: qca988x hw1.0 is not supported\n");
return -EOPNOTSUPP;
err_power_down:
ath10k_hif_power_down(ar);
case QCA988X_HW_2_0_CHIP_ID_REV:
/* known hardware revision, continue normally */
return 0;
default:
ath10k_warn(ar, "Warning: hardware revision unknown (0x%x), expect problems\n",
ar->chip_id);
return 0;
}
return 0;
return ret;
}
static void ath10k_core_register_work(struct work_struct *work)
@ -1125,9 +1232,18 @@ static void ath10k_core_register_work(struct work_struct *work)
goto err_debug_destroy;
}
status = ath10k_thermal_register(ar);
if (status) {
ath10k_err(ar, "could not register thermal device: %d\n",
status);
goto err_spectral_destroy;
}
set_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags);
return;
err_spectral_destroy:
ath10k_spectral_destroy(ar);
err_debug_destroy:
ath10k_debug_destroy(ar);
err_unregister_mac:
@ -1143,16 +1259,7 @@ err:
int ath10k_core_register(struct ath10k *ar, u32 chip_id)
{
int status;
ar->chip_id = chip_id;
status = ath10k_core_check_chip_id(ar);
if (status) {
ath10k_err(ar, "Unsupported chip id 0x%08x\n", ar->chip_id);
return status;
}
queue_work(ar->workqueue, &ar->register_work);
return 0;
@ -1166,6 +1273,7 @@ void ath10k_core_unregister(struct ath10k *ar)
if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags))
return;
ath10k_thermal_unregister(ar);
/* Stop spectral before unregistering from mac80211 to remove the
* relayfs debugfs file cleanly. Otherwise the parent debugfs tree
* would be already be free'd recursively, leading to a double free.
@ -1198,10 +1306,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
ar->ath_common.priv = ar;
ar->ath_common.hw = ar->hw;
ar->p2p = !!ath10k_p2p;
ar->dev = dev;
ar->hif.ops = hif_ops;
ar->hif.bus = bus;
@ -1212,6 +1317,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
init_completion(&ar->install_key_done);
init_completion(&ar->vdev_setup_done);
init_completion(&ar->thermal.wmi_sync);
INIT_DELAYED_WORK(&ar->scan.timeout, ath10k_scan_timeout_work);

View file

@ -34,6 +34,7 @@
#include "../regd.h"
#include "../dfs_pattern_detector.h"
#include "spectral.h"
#include "thermal.h"
#define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
@ -120,6 +121,7 @@ struct ath10k_mem_chunk {
};
struct ath10k_wmi {
enum ath10k_fw_wmi_op_version op_version;
enum ath10k_htc_ep_id eid;
struct completion service_ready;
struct completion unified_ready;
@ -128,6 +130,7 @@ struct ath10k_wmi {
struct wmi_cmd_map *cmd;
struct wmi_vdev_param_map *vdev_param;
struct wmi_pdev_param_map *pdev_param;
const struct wmi_ops *ops;
u32 num_mem_chunks;
struct ath10k_mem_chunk mem_chunks[WMI_MAX_MEM_REQS];
@ -325,6 +328,7 @@ struct ath10k_debug {
u32 fw_dbglog_mask;
u32 pktlog_filter;
u32 reg_addr;
u32 nf_cal_period;
u8 htt_max_amsdu;
u8 htt_max_ampdu;
@ -369,7 +373,7 @@ enum ath10k_fw_features {
/* wmi_mgmt_rx_hdr contains extra RSSI information */
ATH10K_FW_FEATURE_EXT_WMI_MGMT_RX = 0,
/* firmware from 10X branch */
/* Firmware from 10X branch. Deprecated, don't use in new code. */
ATH10K_FW_FEATURE_WMI_10X = 1,
/* firmware support tx frame management over WMI, otherwise it's HTT */
@ -378,8 +382,9 @@ enum ath10k_fw_features {
/* Firmware does not support P2P */
ATH10K_FW_FEATURE_NO_P2P = 3,
/* Firmware 10.2 feature bit. The ATH10K_FW_FEATURE_WMI_10X feature bit
* is required to be set as well.
/* Firmware 10.2 feature bit. The ATH10K_FW_FEATURE_WMI_10X feature
* bit is required to be set as well. Deprecated, don't use in new
* code.
*/
ATH10K_FW_FEATURE_WMI_10_2 = 4,
@ -401,6 +406,7 @@ enum ath10k_dev_flags {
enum ath10k_cal_mode {
ATH10K_CAL_MODE_FILE,
ATH10K_CAL_MODE_OTP,
ATH10K_CAL_MODE_DT,
};
static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
@ -410,6 +416,8 @@ static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
return "file";
case ATH10K_CAL_MODE_OTP:
return "otp";
case ATH10K_CAL_MODE_DT:
return "dt";
}
return "unknown";
@ -480,12 +488,15 @@ struct ath10k {
u32 id;
const char *name;
u32 patch_load_addr;
int uart_pin;
struct ath10k_hw_params_fw {
const char *dir;
const char *fw;
const char *otp;
const char *board;
size_t board_size;
size_t board_ext_size;
} fw;
} hw_params;
@ -571,6 +582,7 @@ struct ath10k {
int max_num_peers;
int max_num_stations;
int max_num_vdevs;
struct work_struct offchan_tx_work;
struct sk_buff_head offchan_tx_queue;
@ -610,6 +622,7 @@ struct ath10k {
/* protected by conf_mutex */
const struct firmware *utf;
DECLARE_BITMAP(orig_fw_features, ATH10K_FW_FEATURE_COUNT);
enum ath10k_fw_wmi_op_version orig_wmi_op_version;
/* protected by data_lock */
bool utf_monitor;
@ -622,6 +635,8 @@ struct ath10k {
u32 fw_cold_reset_counter;
} stats;
struct ath10k_thermal thermal;
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};

View file

@ -23,6 +23,7 @@
#include "core.h"
#include "debug.h"
#include "hif.h"
#include "wmi-ops.h"
/* ms */
#define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
@ -123,7 +124,7 @@ EXPORT_SYMBOL(ath10k_info);
void ath10k_print_driver_info(struct ath10k *ar)
{
ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d.%d.%d.%d cal %s max_sta %d\n",
ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d cal %s max_sta %d\n",
ar->hw_params.name,
ar->target_version,
ar->chip_id,
@ -131,10 +132,7 @@ void ath10k_print_driver_info(struct ath10k *ar)
ar->fw_api,
ar->htt.target_version_major,
ar->htt.target_version_minor,
ar->fw_version_major,
ar->fw_version_minor,
ar->fw_version_release,
ar->fw_version_build,
ar->wmi.op_version,
ath10k_cal_mode_str(ar->cal_mode),
ar->max_num_stations);
ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
@ -1607,6 +1605,73 @@ static const struct file_operations fops_cal_data = {
.llseek = default_llseek,
};
static ssize_t ath10k_read_nf_cal_period(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
unsigned int len;
char buf[32];
len = scnprintf(buf, sizeof(buf), "%d\n",
ar->debug.nf_cal_period);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t ath10k_write_nf_cal_period(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
unsigned long period;
int ret;
ret = kstrtoul_from_user(user_buf, count, 0, &period);
if (ret)
return ret;
if (period > WMI_PDEV_PARAM_CAL_PERIOD_MAX)
return -EINVAL;
/* there's no way to switch back to the firmware default */
if (period == 0)
return -EINVAL;
mutex_lock(&ar->conf_mutex);
ar->debug.nf_cal_period = period;
if (ar->state != ATH10K_STATE_ON) {
/* firmware is not running, nothing else to do */
ret = count;
goto exit;
}
ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->cal_period,
ar->debug.nf_cal_period);
if (ret) {
ath10k_warn(ar, "cal period cfg failed from debugfs: %d\n",
ret);
goto exit;
}
ret = count;
exit:
mutex_unlock(&ar->conf_mutex);
return ret;
}
static const struct file_operations fops_nf_cal_period = {
.read = ath10k_read_nf_cal_period,
.write = ath10k_write_nf_cal_period,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
int ath10k_debug_start(struct ath10k *ar)
{
int ret;
@ -1642,6 +1707,16 @@ int ath10k_debug_start(struct ath10k *ar)
ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
}
if (ar->debug.nf_cal_period) {
ret = ath10k_wmi_pdev_set_param(ar,
ar->wmi.pdev_param->cal_period,
ar->debug.nf_cal_period);
if (ret)
/* not serious */
ath10k_warn(ar, "cal period cfg failed from debug start: %d\n",
ret);
}
return ret;
}
@ -1880,6 +1955,9 @@ int ath10k_debug_register(struct ath10k *ar)
debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_cal_data);
debugfs_create_file("nf_cal_period", S_IRUSR | S_IWUSR,
ar->debug.debugfs_phy, ar, &fops_nf_cal_period);
if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
debugfs_create_file("dfs_simulate_radar", S_IWUSR,
ar->debug.debugfs_phy, ar,

View file

@ -93,11 +93,6 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
spin_lock_init(&htt->tx_lock);
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, htt->ar->fw_features))
htt->max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC;
else
htt->max_num_pending_tx = TARGET_NUM_MSDU_DESC;
ath10k_dbg(ar, ATH10K_DBG_BOOT, "htt tx max num pending tx %d\n",
htt->max_num_pending_tx);

View file

@ -37,6 +37,9 @@
#define ATH10K_FW_API2_FILE "firmware-2.bin"
#define ATH10K_FW_API3_FILE "firmware-3.bin"
/* added support for ATH10K_FW_IE_WMI_OP_VERSION */
#define ATH10K_FW_API4_FILE "firmware-4.bin"
#define ATH10K_FW_UTF_FILE "utf.bin"
/* includes also the null byte */
@ -58,6 +61,24 @@ enum ath10k_fw_ie_type {
ATH10K_FW_IE_FEATURES = 2,
ATH10K_FW_IE_FW_IMAGE = 3,
ATH10K_FW_IE_OTP_IMAGE = 4,
/* WMI "operations" interface version, 32 bit value. Supported from
* FW API 4 and above.
*/
ATH10K_FW_IE_WMI_OP_VERSION = 5,
};
enum ath10k_fw_wmi_op_version {
ATH10K_FW_WMI_OP_VERSION_UNSET = 0,
ATH10K_FW_WMI_OP_VERSION_MAIN = 1,
ATH10K_FW_WMI_OP_VERSION_10_1 = 2,
ATH10K_FW_WMI_OP_VERSION_10_2 = 3,
ATH10K_FW_WMI_OP_VERSION_TLV = 4,
ATH10K_FW_WMI_OP_VERSION_10_2_4 = 5,
/* keep last */
ATH10K_FW_WMI_OP_VERSION_MAX,
};
/* Known pecularities:
@ -162,6 +183,15 @@ struct ath10k_pktlog_hdr {
#define TARGET_10X_NUM_MSDU_DESC (1024 + 400)
#define TARGET_10X_MAX_FRAG_ENTRIES 0
/* Target specific defines for WMI-TLV firmware */
#define TARGET_TLV_NUM_VDEVS 3
#define TARGET_TLV_NUM_STATIONS 32
#define TARGET_TLV_NUM_PEERS ((TARGET_TLV_NUM_STATIONS) + \
(TARGET_TLV_NUM_VDEVS) + \
2)
#define TARGET_TLV_NUM_TIDS ((TARGET_TLV_NUM_PEERS) * 2)
#define TARGET_TLV_NUM_MSDU_DESC (1024 + 32)
/* Number of Copy Engines supported */
#define CE_COUNT 8

View file

@ -27,6 +27,8 @@
#include "htt.h"
#include "txrx.h"
#include "testmode.h"
#include "wmi.h"
#include "wmi-ops.h"
/**********/
/* Crypto */
@ -267,7 +269,10 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef)
case IEEE80211_BAND_2GHZ:
switch (chandef->width) {
case NL80211_CHAN_WIDTH_20_NOHT:
phymode = MODE_11G;
if (chandef->chan->flags & IEEE80211_CHAN_NO_OFDM)
phymode = MODE_11B;
else
phymode = MODE_11G;
break;
case NL80211_CHAN_WIDTH_20:
phymode = MODE_11NG_HT20;
@ -1046,28 +1051,85 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif,
arvif->vdev_id, ret);
}
/*
* Review this when mac80211 gains per-interface powersave support.
*/
static int ath10k_mac_vif_recalc_ps_wake_threshold(struct ath10k_vif *arvif)
{
struct ath10k *ar = arvif->ar;
u32 param;
u32 value;
int ret;
lockdep_assert_held(&arvif->ar->conf_mutex);
if (arvif->u.sta.uapsd)
value = WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER;
else
value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param, value);
if (ret) {
ath10k_warn(ar, "failed to submit ps wake threshold %u on vdev %i: %d\n",
value, arvif->vdev_id, ret);
return ret;
}
return 0;
}
static int ath10k_mac_vif_recalc_ps_poll_count(struct ath10k_vif *arvif)
{
struct ath10k *ar = arvif->ar;
u32 param;
u32 value;
int ret;
lockdep_assert_held(&arvif->ar->conf_mutex);
if (arvif->u.sta.uapsd)
value = WMI_STA_PS_PSPOLL_COUNT_UAPSD;
else
value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
param = WMI_STA_PS_PARAM_PSPOLL_COUNT;
ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
param, value);
if (ret) {
ath10k_warn(ar, "failed to submit ps poll count %u on vdev %i: %d\n",
value, arvif->vdev_id, ret);
return ret;
}
return 0;
}
static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif)
{
struct ath10k *ar = arvif->ar;
struct ieee80211_vif *vif = arvif->vif;
struct ieee80211_conf *conf = &ar->hw->conf;
enum wmi_sta_powersave_param param;
enum wmi_sta_ps_mode psmode;
int ret;
int ps_timeout;
lockdep_assert_held(&arvif->ar->conf_mutex);
if (arvif->vif->type != NL80211_IFTYPE_STATION)
return 0;
if (conf->flags & IEEE80211_CONF_PS) {
if (vif->bss_conf.ps) {
psmode = WMI_STA_PS_MODE_ENABLED;
param = WMI_STA_PS_PARAM_INACTIVITY_TIME;
ps_timeout = conf->dynamic_ps_timeout;
if (ps_timeout == 0) {
/* Firmware doesn't like 0 */
ps_timeout = ieee80211_tu_to_usec(
vif->bss_conf.beacon_int) / 1000;
}
ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param,
conf->dynamic_ps_timeout);
ps_timeout);
if (ret) {
ath10k_warn(ar, "failed to set inactivity time for vdev %d: %i\n",
arvif->vdev_id, ret);
@ -1409,9 +1471,22 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
if (vif->bss_conf.qos)
arg->peer_flags |= WMI_PEER_QOS;
break;
case WMI_VDEV_TYPE_IBSS:
if (sta->wme)
arg->peer_flags |= WMI_PEER_QOS;
break;
default:
break;
}
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac peer %pM qos %d\n",
sta->addr, !!(arg->peer_flags & WMI_PEER_QOS));
}
static bool ath10k_mac_sta_has_11g_rates(struct ieee80211_sta *sta)
{
/* First 4 rates in ath10k_rates are CCK (11b) rates. */
return sta->supp_rates[IEEE80211_BAND_2GHZ] >> 4;
}
static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
@ -1428,8 +1503,10 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
phymode = MODE_11NG_HT40;
else
phymode = MODE_11NG_HT20;
} else {
} else if (ath10k_mac_sta_has_11g_rates(sta)) {
phymode = MODE_11G;
} else {
phymode = MODE_11B;
}
break;
@ -2896,10 +2973,11 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
arvif->vdev_id = bit;
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
if (ar->p2p)
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
switch (vif->type) {
case NL80211_IFTYPE_P2P_DEVICE:
arvif->vdev_type = WMI_VDEV_TYPE_STA;
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_P2P_DEVICE;
break;
case NL80211_IFTYPE_UNSPECIFIED:
case NL80211_IFTYPE_STATION:
arvif->vdev_type = WMI_VDEV_TYPE_STA;
@ -3028,22 +3106,16 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
goto err_peer_delete;
}
param = WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD;
value = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
param, value);
ret = ath10k_mac_vif_recalc_ps_wake_threshold(arvif);
if (ret) {
ath10k_warn(ar, "failed to set vdev %i TX wake thresh: %d\n",
ath10k_warn(ar, "failed to recalc ps wake threshold on vdev %i: %d\n",
arvif->vdev_id, ret);
goto err_peer_delete;
}
param = WMI_STA_PS_PARAM_PSPOLL_COUNT;
value = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
ret = ath10k_wmi_set_sta_ps_param(ar, arvif->vdev_id,
param, value);
ret = ath10k_mac_vif_recalc_ps_poll_count(arvif);
if (ret) {
ath10k_warn(ar, "failed to set vdev %i PSPOLL count: %d\n",
ath10k_warn(ar, "failed to recalc ps poll count on vdev %i: %d\n",
arvif->vdev_id, ret);
goto err_peer_delete;
}
@ -3316,6 +3388,13 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
ath10k_warn(ar, "failed to recalc tx power: %d\n", ret);
}
if (changed & BSS_CHANGED_PS) {
ret = ath10k_mac_vif_setup_ps(arvif);
if (ret)
ath10k_warn(ar, "failed to setup ps on vdev %i: %d\n",
arvif->vdev_id, ret);
}
mutex_unlock(&ar->conf_mutex);
}
@ -3585,8 +3664,9 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk)
sta->addr, smps, err);
}
if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates\n",
if (changed & IEEE80211_RC_SUPP_RATES_CHANGED ||
changed & IEEE80211_RC_NSS_CHANGED) {
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates/nss\n",
sta->addr);
err = ath10k_station_assoc(ar, arvif->vif, sta, true);
@ -3810,6 +3890,20 @@ static int ath10k_conf_tx_uapsd(struct ath10k *ar, struct ieee80211_vif *vif,
if (ret)
ath10k_warn(ar, "failed to set rx wake param: %d\n", ret);
ret = ath10k_mac_vif_recalc_ps_wake_threshold(arvif);
if (ret) {
ath10k_warn(ar, "failed to recalc ps wake threshold on vdev %i: %d\n",
arvif->vdev_id, ret);
return ret;
}
ret = ath10k_mac_vif_recalc_ps_poll_count(arvif);
if (ret) {
ath10k_warn(ar, "failed to recalc ps poll count on vdev %i: %d\n",
arvif->vdev_id, ret);
return ret;
}
exit:
return ret;
}
@ -3991,29 +4085,6 @@ static int ath10k_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
return ret;
}
static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
{
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif;
int ret = 0;
mutex_lock(&ar->conf_mutex);
list_for_each_entry(arvif, &ar->arvifs, list) {
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d fragmentation threshold %d\n",
arvif->vdev_id, value);
ret = ath10k_mac_set_frag(arvif, value);
if (ret) {
ath10k_warn(ar, "failed to set fragmentation threshold for vdev %d: %d\n",
arvif->vdev_id, ret);
break;
}
}
mutex_unlock(&ar->conf_mutex);
return ret;
}
static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop)
{
@ -4657,7 +4728,6 @@ static const struct ieee80211_ops ath10k_ops = {
.remain_on_channel = ath10k_remain_on_channel,
.cancel_remain_on_channel = ath10k_cancel_remain_on_channel,
.set_rts_threshold = ath10k_set_rts_threshold,
.set_frag_threshold = ath10k_set_frag_threshold,
.flush = ath10k_flush,
.tx_last_beacon = ath10k_tx_last_beacon,
.set_antenna = ath10k_set_antenna,
@ -4748,6 +4818,9 @@ static const struct ieee80211_channel ath10k_5ghz_channels[] = {
CHAN5G(165, 5825, 0),
};
/* Note: Be careful if you re-order these. There is code which depends on this
* ordering.
*/
static struct ieee80211_rate ath10k_rates[] = {
/* CCK */
RATETAB_ENT(10, 0x82, 0),
@ -4801,6 +4874,10 @@ static const struct ieee80211_iface_limit ath10k_if_limits[] = {
.types = BIT(NL80211_IFTYPE_P2P_GO)
},
{
.max = 1,
.types = BIT(NL80211_IFTYPE_P2P_DEVICE)
},
{
.max = 7,
.types = BIT(NL80211_IFTYPE_AP)
},
@ -5020,6 +5097,7 @@ int ath10k_mac_register(struct ath10k *ar)
if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features))
ar->hw->wiphy->interface_modes |=
BIT(NL80211_IFTYPE_P2P_DEVICE) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO);
@ -5063,16 +5141,26 @@ int ath10k_mac_register(struct ath10k *ar)
*/
ar->hw->queues = 4;
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
ar->hw->wiphy->iface_combinations = ath10k_10x_if_comb;
ar->hw->wiphy->n_iface_combinations =
ARRAY_SIZE(ath10k_10x_if_comb);
} else {
switch (ar->wmi.op_version) {
case ATH10K_FW_WMI_OP_VERSION_MAIN:
case ATH10K_FW_WMI_OP_VERSION_TLV:
ar->hw->wiphy->iface_combinations = ath10k_if_comb;
ar->hw->wiphy->n_iface_combinations =
ARRAY_SIZE(ath10k_if_comb);
ar->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC);
break;
case ATH10K_FW_WMI_OP_VERSION_10_1:
case ATH10K_FW_WMI_OP_VERSION_10_2:
case ATH10K_FW_WMI_OP_VERSION_10_2_4:
ar->hw->wiphy->iface_combinations = ath10k_10x_if_comb;
ar->hw->wiphy->n_iface_combinations =
ARRAY_SIZE(ath10k_10x_if_comb);
break;
case ATH10K_FW_WMI_OP_VERSION_UNSET:
case ATH10K_FW_WMI_OP_VERSION_MAX:
WARN_ON(1);
ret = -EINVAL;
goto err_free;
}
ar->hw->netdev_features = NETIF_F_HW_CSUM;

View file

@ -64,6 +64,14 @@ static const struct pci_device_id ath10k_pci_id_table[] = {
{0}
};
static const struct ath10k_pci_supp_chip ath10k_pci_supp_chips[] = {
/* QCA988X pre 2.0 chips are not supported because they need some nasty
* hacks. ath10k doesn't have them and these devices crash horribly
* because of that.
*/
{ QCA988X_2_0_DEVICE_ID, QCA988X_HW_2_0_CHIP_ID_REV },
};
static void ath10k_pci_buffer_cleanup(struct ath10k *ar);
static int ath10k_pci_cold_reset(struct ath10k *ar);
static int ath10k_pci_warm_reset(struct ath10k *ar);
@ -2476,6 +2484,23 @@ static void ath10k_pci_release(struct ath10k *ar)
pci_disable_device(pdev);
}
static bool ath10k_pci_chip_is_supported(u32 dev_id, u32 chip_id)
{
const struct ath10k_pci_supp_chip *supp_chip;
int i;
u32 rev_id = MS(chip_id, SOC_CHIP_ID_REV);
for (i = 0; i < ARRAY_SIZE(ath10k_pci_supp_chips); i++) {
supp_chip = &ath10k_pci_supp_chips[i];
if (supp_chip->dev_id == dev_id &&
supp_chip->rev_id == rev_id)
return true;
}
return false;
}
static int ath10k_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *pci_dev)
{
@ -2521,6 +2546,12 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
goto err_sleep;
}
if (!ath10k_pci_chip_is_supported(pdev->device, chip_id)) {
ath10k_err(ar, "device %04x with chip_id %08x isn't supported\n",
pdev->device, chip_id);
goto err_sleep;
}
ret = ath10k_pci_alloc_pipes(ar);
if (ret) {
ath10k_err(ar, "failed to allocate copy engine pipes: %d\n",

View file

@ -152,6 +152,11 @@ struct ath10k_pci_pipe {
struct tasklet_struct intr;
};
struct ath10k_pci_supp_chip {
u32 dev_id;
u32 rev_id;
};
struct ath10k_pci {
struct pci_dev *pdev;
struct device *dev;

View file

@ -17,6 +17,7 @@
#include <linux/relay.h>
#include "core.h"
#include "debug.h"
#include "wmi-ops.h"
static void send_fft_sample(struct ath10k *ar,
const struct fft_sample_tlv *fft_sample_tlv)

View file

@ -187,13 +187,14 @@ static int ath10k_tm_cmd_utf_start(struct ath10k *ar, struct nlattr *tb[])
memcpy(ar->testmode.orig_fw_features, ar->fw_features,
sizeof(ar->fw_features));
ar->testmode.orig_wmi_op_version = ar->wmi.op_version;
/* utf.bin firmware image does not advertise firmware features. Do
* an ugly hack where we force the firmware features so that wmi.c
* will use the correct WMI interface.
*/
memset(ar->fw_features, 0, sizeof(ar->fw_features));
__set_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features);
ar->wmi.op_version = ATH10K_FW_WMI_OP_VERSION_10_1;
ret = ath10k_hif_power_up(ar);
if (ret) {
@ -224,6 +225,7 @@ err_fw_features:
/* return the original firmware features */
memcpy(ar->fw_features, ar->testmode.orig_fw_features,
sizeof(ar->fw_features));
ar->wmi.op_version = ar->testmode.orig_wmi_op_version;
release_firmware(ar->testmode.utf);
ar->testmode.utf = NULL;
@ -250,6 +252,7 @@ static void __ath10k_tm_cmd_utf_stop(struct ath10k *ar)
/* return the original firmware features */
memcpy(ar->fw_features, ar->testmode.orig_fw_features,
sizeof(ar->fw_features));
ar->wmi.op_version = ar->testmode.orig_wmi_op_version;
release_firmware(ar->testmode.utf);
ar->testmode.utf = NULL;

View file

@ -0,0 +1,243 @@
/*
* Copyright (c) 2014 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
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/device.h>
#include <linux/sysfs.h>
#include <linux/thermal.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include "core.h"
#include "debug.h"
#include "wmi-ops.h"
static int ath10k_thermal_get_active_vifs(struct ath10k *ar,
enum wmi_vdev_type type)
{
struct ath10k_vif *arvif;
int count = 0;
lockdep_assert_held(&ar->conf_mutex);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (!arvif->is_started)
continue;
if (!arvif->is_up)
continue;
if (arvif->vdev_type != type)
continue;
count++;
}
return count;
}
static int ath10k_thermal_get_max_dutycycle(struct thermal_cooling_device *cdev,
unsigned long *state)
{
*state = ATH10K_QUIET_DUTY_CYCLE_MAX;
return 0;
}
static int ath10k_thermal_get_cur_dutycycle(struct thermal_cooling_device *cdev,
unsigned long *state)
{
struct ath10k *ar = cdev->devdata;
mutex_lock(&ar->conf_mutex);
*state = ar->thermal.duty_cycle;
mutex_unlock(&ar->conf_mutex);
return 0;
}
static int ath10k_thermal_set_cur_dutycycle(struct thermal_cooling_device *cdev,
unsigned long duty_cycle)
{
struct ath10k *ar = cdev->devdata;
u32 period, duration, enabled;
int num_bss, ret = 0;
mutex_lock(&ar->conf_mutex);
if (ar->state != ATH10K_STATE_ON) {
ret = -ENETDOWN;
goto out;
}
if (duty_cycle > ATH10K_QUIET_DUTY_CYCLE_MAX) {
ath10k_warn(ar, "duty cycle %ld is exceeding the limit %d\n",
duty_cycle, ATH10K_QUIET_DUTY_CYCLE_MAX);
ret = -EINVAL;
goto out;
}
/* TODO: Right now, thermal mitigation is handled only for single/multi
* vif AP mode. Since quiet param is not validated in STA mode, it needs
* to be investigated further to handle multi STA and multi-vif (AP+STA)
* mode properly.
*/
num_bss = ath10k_thermal_get_active_vifs(ar, WMI_VDEV_TYPE_AP);
if (!num_bss) {
ath10k_warn(ar, "no active AP interfaces\n");
ret = -ENETDOWN;
goto out;
}
period = max(ATH10K_QUIET_PERIOD_MIN,
(ATH10K_QUIET_PERIOD_DEFAULT / num_bss));
duration = period * (duty_cycle / 100);
enabled = duration ? 1 : 0;
ret = ath10k_wmi_pdev_set_quiet_mode(ar, period, duration,
ATH10K_QUIET_START_OFFSET,
enabled);
if (ret) {
ath10k_warn(ar, "failed to set quiet mode period %u duarion %u enabled %u ret %d\n",
period, duration, enabled, ret);
goto out;
}
ar->thermal.duty_cycle = duty_cycle;
out:
mutex_unlock(&ar->conf_mutex);
return ret;
}
static struct thermal_cooling_device_ops ath10k_thermal_ops = {
.get_max_state = ath10k_thermal_get_max_dutycycle,
.get_cur_state = ath10k_thermal_get_cur_dutycycle,
.set_cur_state = ath10k_thermal_set_cur_dutycycle,
};
static ssize_t ath10k_thermal_show_temp(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct ath10k *ar = dev_get_drvdata(dev);
int ret, temperature;
mutex_lock(&ar->conf_mutex);
/* Can't get temperature when the card is off */
if (ar->state != ATH10K_STATE_ON) {
ret = -ENETDOWN;
goto out;
}
reinit_completion(&ar->thermal.wmi_sync);
ret = ath10k_wmi_pdev_get_temperature(ar);
if (ret) {
ath10k_warn(ar, "failed to read temperature %d\n", ret);
goto out;
}
if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) {
ret = -ESHUTDOWN;
goto out;
}
ret = wait_for_completion_timeout(&ar->thermal.wmi_sync,
ATH10K_THERMAL_SYNC_TIMEOUT_HZ);
if (ret == 0) {
ath10k_warn(ar, "failed to synchronize thermal read\n");
ret = -ETIMEDOUT;
goto out;
}
spin_lock_bh(&ar->data_lock);
temperature = ar->thermal.temperature;
spin_unlock_bh(&ar->data_lock);
ret = snprintf(buf, PAGE_SIZE, "%d", temperature);
out:
mutex_unlock(&ar->conf_mutex);
return ret;
}
void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature)
{
spin_lock_bh(&ar->data_lock);
ar->thermal.temperature = temperature;
spin_unlock_bh(&ar->data_lock);
complete(&ar->thermal.wmi_sync);
}
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ath10k_thermal_show_temp,
NULL, 0);
static struct attribute *ath10k_hwmon_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(ath10k_hwmon);
int ath10k_thermal_register(struct ath10k *ar)
{
struct thermal_cooling_device *cdev;
struct device *hwmon_dev;
int ret;
cdev = thermal_cooling_device_register("ath10k_thermal", ar,
&ath10k_thermal_ops);
if (IS_ERR(cdev)) {
ath10k_err(ar, "failed to setup thermal device result: %ld\n",
PTR_ERR(cdev));
return -EINVAL;
}
ret = sysfs_create_link(&ar->dev->kobj, &cdev->device.kobj,
"cooling_device");
if (ret) {
ath10k_err(ar, "failed to create thermal symlink\n");
goto err_cooling_destroy;
}
ar->thermal.cdev = cdev;
/* Do not register hwmon device when temperature reading is not
* supported by firmware
*/
if (ar->wmi.op_version != ATH10K_FW_WMI_OP_VERSION_10_2_4)
return 0;
/* Avoid linking error on devm_hwmon_device_register_with_groups, I
* guess linux/hwmon.h is missing proper stubs. */
if (!config_enabled(HWMON))
return 0;
hwmon_dev = devm_hwmon_device_register_with_groups(ar->dev,
"ath10k_hwmon", ar,
ath10k_hwmon_groups);
if (IS_ERR(hwmon_dev)) {
ath10k_err(ar, "failed to register hwmon device: %ld\n",
PTR_ERR(hwmon_dev));
ret = -EINVAL;
goto err_remove_link;
}
return 0;
err_remove_link:
sysfs_remove_link(&ar->dev->kobj, "thermal_sensor");
err_cooling_destroy:
thermal_cooling_device_unregister(cdev);
return ret;
}
void ath10k_thermal_unregister(struct ath10k *ar)
{
thermal_cooling_device_unregister(ar->thermal.cdev);
sysfs_remove_link(&ar->dev->kobj, "cooling_device");
}

View file

@ -0,0 +1,58 @@
/*
* Copyright (c) 2014 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
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _THERMAL_
#define _THERMAL_
#define ATH10K_QUIET_PERIOD_DEFAULT 100
#define ATH10K_QUIET_PERIOD_MIN 25
#define ATH10K_QUIET_START_OFFSET 10
#define ATH10K_QUIET_DUTY_CYCLE_MAX 70
#define ATH10K_HWMON_NAME_LEN 15
#define ATH10K_THERMAL_SYNC_TIMEOUT_HZ (5*HZ)
struct ath10k_thermal {
struct thermal_cooling_device *cdev;
struct completion wmi_sync;
/* protected by conf_mutex */
u32 duty_cycle;
/* temperature value in Celcius degree
* protected by data_lock
*/
int temperature;
};
#ifdef CONFIG_THERMAL
int ath10k_thermal_register(struct ath10k *ar);
void ath10k_thermal_unregister(struct ath10k *ar);
void ath10k_thermal_event_temperature(struct ath10k *ar, int temperature);
#else
static inline int ath10k_thermal_register(struct ath10k *ar)
{
return 0;
}
static inline void ath10k_thermal_unregister(struct ath10k *ar)
{
}
static inline void ath10k_thermal_event_temperature(struct ath10k *ar,
int temperature)
{
}
#endif
#endif /* _THERMAL_ */

View file

@ -0,0 +1,860 @@
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2014 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
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _WMI_OPS_H_
#define _WMI_OPS_H_
struct ath10k;
struct sk_buff;
struct wmi_ops {
void (*rx)(struct ath10k *ar, struct sk_buff *skb);
void (*map_svc)(const __le32 *in, unsigned long *out, size_t len);
int (*pull_scan)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_scan_ev_arg *arg);
int (*pull_mgmt_rx)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_mgmt_rx_ev_arg *arg);
int (*pull_ch_info)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_ch_info_ev_arg *arg);
int (*pull_vdev_start)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_vdev_start_ev_arg *arg);
int (*pull_peer_kick)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_peer_kick_ev_arg *arg);
int (*pull_swba)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_swba_ev_arg *arg);
int (*pull_phyerr)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_phyerr_ev_arg *arg);
int (*pull_svc_rdy)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_svc_rdy_ev_arg *arg);
int (*pull_rdy)(struct ath10k *ar, struct sk_buff *skb,
struct wmi_rdy_ev_arg *arg);
int (*pull_fw_stats)(struct ath10k *ar, struct sk_buff *skb,
struct ath10k_fw_stats *stats);
struct sk_buff *(*gen_pdev_suspend)(struct ath10k *ar, u32 suspend_opt);
struct sk_buff *(*gen_pdev_resume)(struct ath10k *ar);
struct sk_buff *(*gen_pdev_set_rd)(struct ath10k *ar, u16 rd, u16 rd2g,
u16 rd5g, u16 ctl2g, u16 ctl5g,
enum wmi_dfs_region dfs_reg);
struct sk_buff *(*gen_pdev_set_param)(struct ath10k *ar, u32 id,
u32 value);
struct sk_buff *(*gen_init)(struct ath10k *ar);
struct sk_buff *(*gen_start_scan)(struct ath10k *ar,
const struct wmi_start_scan_arg *arg);
struct sk_buff *(*gen_stop_scan)(struct ath10k *ar,
const struct wmi_stop_scan_arg *arg);
struct sk_buff *(*gen_vdev_create)(struct ath10k *ar, u32 vdev_id,
enum wmi_vdev_type type,
enum wmi_vdev_subtype subtype,
const u8 macaddr[ETH_ALEN]);
struct sk_buff *(*gen_vdev_delete)(struct ath10k *ar, u32 vdev_id);
struct sk_buff *(*gen_vdev_start)(struct ath10k *ar,
const struct wmi_vdev_start_request_arg *arg,
bool restart);
struct sk_buff *(*gen_vdev_stop)(struct ath10k *ar, u32 vdev_id);
struct sk_buff *(*gen_vdev_up)(struct ath10k *ar, u32 vdev_id, u32 aid,
const u8 *bssid);
struct sk_buff *(*gen_vdev_down)(struct ath10k *ar, u32 vdev_id);
struct sk_buff *(*gen_vdev_set_param)(struct ath10k *ar, u32 vdev_id,
u32 param_id, u32 param_value);
struct sk_buff *(*gen_vdev_install_key)(struct ath10k *ar,
const struct wmi_vdev_install_key_arg *arg);
struct sk_buff *(*gen_vdev_spectral_conf)(struct ath10k *ar,
const struct wmi_vdev_spectral_conf_arg *arg);
struct sk_buff *(*gen_vdev_spectral_enable)(struct ath10k *ar, u32 vdev_id,
u32 trigger, u32 enable);
struct sk_buff *(*gen_peer_create)(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN]);
struct sk_buff *(*gen_peer_delete)(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN]);
struct sk_buff *(*gen_peer_flush)(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN],
u32 tid_bitmap);
struct sk_buff *(*gen_peer_set_param)(struct ath10k *ar, u32 vdev_id,
const u8 *peer_addr,
enum wmi_peer_param param_id,
u32 param_value);
struct sk_buff *(*gen_peer_assoc)(struct ath10k *ar,
const struct wmi_peer_assoc_complete_arg *arg);
struct sk_buff *(*gen_set_psmode)(struct ath10k *ar, u32 vdev_id,
enum wmi_sta_ps_mode psmode);
struct sk_buff *(*gen_set_sta_ps)(struct ath10k *ar, u32 vdev_id,
enum wmi_sta_powersave_param param_id,
u32 value);
struct sk_buff *(*gen_set_ap_ps)(struct ath10k *ar, u32 vdev_id,
const u8 *mac,
enum wmi_ap_ps_peer_param param_id,
u32 value);
struct sk_buff *(*gen_scan_chan_list)(struct ath10k *ar,
const struct wmi_scan_chan_list_arg *arg);
struct sk_buff *(*gen_beacon_dma)(struct ath10k_vif *arvif);
struct sk_buff *(*gen_pdev_set_wmm)(struct ath10k *ar,
const struct wmi_pdev_set_wmm_params_arg *arg);
struct sk_buff *(*gen_request_stats)(struct ath10k *ar,
enum wmi_stats_id stats_id);
struct sk_buff *(*gen_force_fw_hang)(struct ath10k *ar,
enum wmi_force_fw_hang_type type,
u32 delay_ms);
struct sk_buff *(*gen_mgmt_tx)(struct ath10k *ar, struct sk_buff *skb);
struct sk_buff *(*gen_dbglog_cfg)(struct ath10k *ar, u32 module_enable);
struct sk_buff *(*gen_pktlog_enable)(struct ath10k *ar, u32 filter);
struct sk_buff *(*gen_pktlog_disable)(struct ath10k *ar);
struct sk_buff *(*gen_pdev_set_quiet_mode)(struct ath10k *ar,
u32 period, u32 duration,
u32 next_offset,
u32 enabled);
struct sk_buff *(*gen_pdev_get_temperature)(struct ath10k *ar);
};
int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
static inline int
ath10k_wmi_rx(struct ath10k *ar, struct sk_buff *skb)
{
if (WARN_ON_ONCE(!ar->wmi.ops->rx))
return -EOPNOTSUPP;
ar->wmi.ops->rx(ar, skb);
return 0;
}
static inline int
ath10k_wmi_map_svc(struct ath10k *ar, const __le32 *in, unsigned long *out,
size_t len)
{
if (!ar->wmi.ops->map_svc)
return -EOPNOTSUPP;
ar->wmi.ops->map_svc(in, out, len);
return 0;
}
static inline int
ath10k_wmi_pull_scan(struct ath10k *ar, struct sk_buff *skb,
struct wmi_scan_ev_arg *arg)
{
if (!ar->wmi.ops->pull_scan)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_scan(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_mgmt_rx(struct ath10k *ar, struct sk_buff *skb,
struct wmi_mgmt_rx_ev_arg *arg)
{
if (!ar->wmi.ops->pull_mgmt_rx)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_mgmt_rx(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_ch_info(struct ath10k *ar, struct sk_buff *skb,
struct wmi_ch_info_ev_arg *arg)
{
if (!ar->wmi.ops->pull_ch_info)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_ch_info(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_vdev_start(struct ath10k *ar, struct sk_buff *skb,
struct wmi_vdev_start_ev_arg *arg)
{
if (!ar->wmi.ops->pull_vdev_start)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_vdev_start(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_peer_kick(struct ath10k *ar, struct sk_buff *skb,
struct wmi_peer_kick_ev_arg *arg)
{
if (!ar->wmi.ops->pull_peer_kick)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_peer_kick(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_swba(struct ath10k *ar, struct sk_buff *skb,
struct wmi_swba_ev_arg *arg)
{
if (!ar->wmi.ops->pull_swba)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_swba(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_phyerr(struct ath10k *ar, struct sk_buff *skb,
struct wmi_phyerr_ev_arg *arg)
{
if (!ar->wmi.ops->pull_phyerr)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_phyerr(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_svc_rdy(struct ath10k *ar, struct sk_buff *skb,
struct wmi_svc_rdy_ev_arg *arg)
{
if (!ar->wmi.ops->pull_svc_rdy)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_svc_rdy(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_rdy(struct ath10k *ar, struct sk_buff *skb,
struct wmi_rdy_ev_arg *arg)
{
if (!ar->wmi.ops->pull_rdy)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_rdy(ar, skb, arg);
}
static inline int
ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb,
struct ath10k_fw_stats *stats)
{
if (!ar->wmi.ops->pull_fw_stats)
return -EOPNOTSUPP;
return ar->wmi.ops->pull_fw_stats(ar, skb, stats);
}
static inline int
ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *msdu)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(msdu);
struct sk_buff *skb;
int ret;
if (!ar->wmi.ops->gen_mgmt_tx)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_mgmt_tx(ar, msdu);
if (IS_ERR(skb))
return PTR_ERR(skb);
ret = ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->mgmt_tx_cmdid);
if (ret)
return ret;
/* FIXME There's no ACK event for Management Tx. This probably
* shouldn't be called here either. */
info->flags |= IEEE80211_TX_STAT_ACK;
ieee80211_tx_status_irqsafe(ar->hw, msdu);
return 0;
}
static inline int
ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, u16 rd5g,
u16 ctl2g, u16 ctl5g,
enum wmi_dfs_region dfs_reg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pdev_set_rd)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pdev_set_rd(ar, rd, rd2g, rd5g, ctl2g, ctl5g,
dfs_reg);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->pdev_set_regdomain_cmdid);
}
static inline int
ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pdev_suspend)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pdev_suspend(ar, suspend_opt);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_suspend_cmdid);
}
static inline int
ath10k_wmi_pdev_resume_target(struct ath10k *ar)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pdev_resume)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pdev_resume(ar);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_resume_cmdid);
}
static inline int
ath10k_wmi_pdev_set_param(struct ath10k *ar, u32 id, u32 value)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pdev_set_param)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pdev_set_param(ar, id, value);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_set_param_cmdid);
}
static inline int
ath10k_wmi_cmd_init(struct ath10k *ar)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_init)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_init(ar);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->init_cmdid);
}
static inline int
ath10k_wmi_start_scan(struct ath10k *ar,
const struct wmi_start_scan_arg *arg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_start_scan)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_start_scan(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->start_scan_cmdid);
}
static inline int
ath10k_wmi_stop_scan(struct ath10k *ar, const struct wmi_stop_scan_arg *arg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_stop_scan)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_stop_scan(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->stop_scan_cmdid);
}
static inline int
ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id,
enum wmi_vdev_type type,
enum wmi_vdev_subtype subtype,
const u8 macaddr[ETH_ALEN])
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_create)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_create(ar, vdev_id, type, subtype, macaddr);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_create_cmdid);
}
static inline int
ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_delete)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_delete(ar, vdev_id);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_delete_cmdid);
}
static inline int
ath10k_wmi_vdev_start(struct ath10k *ar,
const struct wmi_vdev_start_request_arg *arg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_start)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_start(ar, arg, false);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->vdev_start_request_cmdid);
}
static inline int
ath10k_wmi_vdev_restart(struct ath10k *ar,
const struct wmi_vdev_start_request_arg *arg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_start)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_start(ar, arg, true);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->vdev_restart_request_cmdid);
}
static inline int
ath10k_wmi_vdev_stop(struct ath10k *ar, u32 vdev_id)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_stop)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_stop(ar, vdev_id);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_stop_cmdid);
}
static inline int
ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_up)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_up(ar, vdev_id, aid, bssid);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_up_cmdid);
}
static inline int
ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_down)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_down(ar, vdev_id);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_down_cmdid);
}
static inline int
ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id, u32 param_id,
u32 param_value)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_set_param)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_set_param(ar, vdev_id, param_id,
param_value);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->vdev_set_param_cmdid);
}
static inline int
ath10k_wmi_vdev_install_key(struct ath10k *ar,
const struct wmi_vdev_install_key_arg *arg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_vdev_install_key)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_vdev_install_key(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->vdev_install_key_cmdid);
}
static inline int
ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
const struct wmi_vdev_spectral_conf_arg *arg)
{
struct sk_buff *skb;
u32 cmd_id;
skb = ar->wmi.ops->gen_vdev_spectral_conf(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
cmd_id = ar->wmi.cmd->vdev_spectral_scan_configure_cmdid;
return ath10k_wmi_cmd_send(ar, skb, cmd_id);
}
static inline int
ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
u32 enable)
{
struct sk_buff *skb;
u32 cmd_id;
skb = ar->wmi.ops->gen_vdev_spectral_enable(ar, vdev_id, trigger,
enable);
if (IS_ERR(skb))
return PTR_ERR(skb);
cmd_id = ar->wmi.cmd->vdev_spectral_scan_enable_cmdid;
return ath10k_wmi_cmd_send(ar, skb, cmd_id);
}
static inline int
ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN])
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_peer_create)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_peer_create(ar, vdev_id, peer_addr);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_create_cmdid);
}
static inline int
ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN])
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_peer_delete)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_peer_delete(ar, vdev_id, peer_addr);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_delete_cmdid);
}
static inline int
ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN], u32 tid_bitmap)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_peer_flush)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_peer_flush(ar, vdev_id, peer_addr, tid_bitmap);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_flush_tids_cmdid);
}
static inline int
ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id, const u8 *peer_addr,
enum wmi_peer_param param_id, u32 param_value)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_peer_set_param)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_peer_set_param(ar, vdev_id, peer_addr, param_id,
param_value);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_set_param_cmdid);
}
static inline int
ath10k_wmi_set_psmode(struct ath10k *ar, u32 vdev_id,
enum wmi_sta_ps_mode psmode)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_set_psmode)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_set_psmode(ar, vdev_id, psmode);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->sta_powersave_mode_cmdid);
}
static inline int
ath10k_wmi_set_sta_ps_param(struct ath10k *ar, u32 vdev_id,
enum wmi_sta_powersave_param param_id, u32 value)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_set_sta_ps)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_set_sta_ps(ar, vdev_id, param_id, value);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->sta_powersave_param_cmdid);
}
static inline int
ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac,
enum wmi_ap_ps_peer_param param_id, u32 value)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_set_ap_ps)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_set_ap_ps(ar, vdev_id, mac, param_id, value);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->ap_ps_peer_param_cmdid);
}
static inline int
ath10k_wmi_scan_chan_list(struct ath10k *ar,
const struct wmi_scan_chan_list_arg *arg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_scan_chan_list)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_scan_chan_list(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid);
}
static inline int
ath10k_wmi_peer_assoc(struct ath10k *ar,
const struct wmi_peer_assoc_complete_arg *arg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_peer_assoc)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_peer_assoc(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->peer_assoc_cmdid);
}
static inline int
ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif)
{
struct ath10k *ar = arvif->ar;
struct sk_buff *skb;
int ret;
if (!ar->wmi.ops->gen_beacon_dma)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_beacon_dma(arvif);
if (IS_ERR(skb))
return PTR_ERR(skb);
ret = ath10k_wmi_cmd_send_nowait(ar, skb,
ar->wmi.cmd->pdev_send_bcn_cmdid);
if (ret) {
dev_kfree_skb(skb);
return ret;
}
return 0;
}
static inline int
ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
const struct wmi_pdev_set_wmm_params_arg *arg)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pdev_set_wmm)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pdev_set_wmm(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->pdev_set_wmm_params_cmdid);
}
static inline int
ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_request_stats)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_request_stats(ar, stats_id);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->request_stats_cmdid);
}
static inline int
ath10k_wmi_force_fw_hang(struct ath10k *ar,
enum wmi_force_fw_hang_type type, u32 delay_ms)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_force_fw_hang)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_force_fw_hang(ar, type, delay_ms);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->force_fw_hang_cmdid);
}
static inline int
ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_dbglog_cfg)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_dbglog_cfg(ar, module_enable);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->dbglog_cfg_cmdid);
}
static inline int
ath10k_wmi_pdev_pktlog_enable(struct ath10k *ar, u32 filter)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pktlog_enable)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pktlog_enable(ar, filter);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_pktlog_enable_cmdid);
}
static inline int
ath10k_wmi_pdev_pktlog_disable(struct ath10k *ar)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pktlog_disable)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pktlog_disable(ar);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->pdev_pktlog_disable_cmdid);
}
static inline int
ath10k_wmi_pdev_set_quiet_mode(struct ath10k *ar, u32 period, u32 duration,
u32 next_offset, u32 enabled)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pdev_set_quiet_mode)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pdev_set_quiet_mode(ar, period, duration,
next_offset, enabled);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->pdev_set_quiet_mode_cmdid);
}
static inline int
ath10k_wmi_pdev_get_temperature(struct ath10k *ar)
{
struct sk_buff *skb;
if (!ar->wmi.ops->gen_pdev_get_temperature)
return -EOPNOTSUPP;
skb = ar->wmi.ops->gen_pdev_get_temperature(ar);
if (IS_ERR(skb))
return PTR_ERR(skb);
return ath10k_wmi_cmd_send(ar, skb,
ar->wmi.cmd->pdev_get_temperature_cmdid);
}
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -109,6 +109,45 @@ enum wmi_service {
WMI_SERVICE_BURST,
WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT,
WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT,
WMI_SERVICE_ROAM_SCAN_OFFLOAD,
WMI_SERVICE_AP_PS_DETECT_OUT_OF_SYNC,
WMI_SERVICE_EARLY_RX,
WMI_SERVICE_STA_SMPS,
WMI_SERVICE_FWTEST,
WMI_SERVICE_STA_WMMAC,
WMI_SERVICE_TDLS,
WMI_SERVICE_MCC_BCN_INTERVAL_CHANGE,
WMI_SERVICE_ADAPTIVE_OCS,
WMI_SERVICE_BA_SSN_SUPPORT,
WMI_SERVICE_FILTER_IPSEC_NATKEEPALIVE,
WMI_SERVICE_WLAN_HB,
WMI_SERVICE_LTE_ANT_SHARE_SUPPORT,
WMI_SERVICE_BATCH_SCAN,
WMI_SERVICE_QPOWER,
WMI_SERVICE_PLMREQ,
WMI_SERVICE_THERMAL_MGMT,
WMI_SERVICE_RMC,
WMI_SERVICE_MHF_OFFLOAD,
WMI_SERVICE_COEX_SAR,
WMI_SERVICE_BCN_TXRATE_OVERRIDE,
WMI_SERVICE_NAN,
WMI_SERVICE_L1SS_STAT,
WMI_SERVICE_ESTIMATE_LINKSPEED,
WMI_SERVICE_OBSS_SCAN,
WMI_SERVICE_TDLS_OFFCHAN,
WMI_SERVICE_TDLS_UAPSD_BUFFER_STA,
WMI_SERVICE_TDLS_UAPSD_SLEEP_STA,
WMI_SERVICE_IBSS_PWRSAVE,
WMI_SERVICE_LPASS,
WMI_SERVICE_EXTSCAN,
WMI_SERVICE_D0WOW,
WMI_SERVICE_HSOFFLOAD,
WMI_SERVICE_ROAM_HO_OFFLOAD,
WMI_SERVICE_RX_FULL_REORDER,
WMI_SERVICE_DHCP_OFFLOAD,
WMI_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT,
WMI_SERVICE_MDNS_OFFLOAD,
WMI_SERVICE_SAP_AUTH_OFFLOAD,
/* keep last */
WMI_SERVICE_MAX,
@ -215,6 +254,45 @@ static inline char *wmi_service_name(int service_id)
SVCSTR(WMI_SERVICE_BURST);
SVCSTR(WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT);
SVCSTR(WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT);
SVCSTR(WMI_SERVICE_ROAM_SCAN_OFFLOAD);
SVCSTR(WMI_SERVICE_AP_PS_DETECT_OUT_OF_SYNC);
SVCSTR(WMI_SERVICE_EARLY_RX);
SVCSTR(WMI_SERVICE_STA_SMPS);
SVCSTR(WMI_SERVICE_FWTEST);
SVCSTR(WMI_SERVICE_STA_WMMAC);
SVCSTR(WMI_SERVICE_TDLS);
SVCSTR(WMI_SERVICE_MCC_BCN_INTERVAL_CHANGE);
SVCSTR(WMI_SERVICE_ADAPTIVE_OCS);
SVCSTR(WMI_SERVICE_BA_SSN_SUPPORT);
SVCSTR(WMI_SERVICE_FILTER_IPSEC_NATKEEPALIVE);
SVCSTR(WMI_SERVICE_WLAN_HB);
SVCSTR(WMI_SERVICE_LTE_ANT_SHARE_SUPPORT);
SVCSTR(WMI_SERVICE_BATCH_SCAN);
SVCSTR(WMI_SERVICE_QPOWER);
SVCSTR(WMI_SERVICE_PLMREQ);
SVCSTR(WMI_SERVICE_THERMAL_MGMT);
SVCSTR(WMI_SERVICE_RMC);
SVCSTR(WMI_SERVICE_MHF_OFFLOAD);
SVCSTR(WMI_SERVICE_COEX_SAR);
SVCSTR(WMI_SERVICE_BCN_TXRATE_OVERRIDE);
SVCSTR(WMI_SERVICE_NAN);
SVCSTR(WMI_SERVICE_L1SS_STAT);
SVCSTR(WMI_SERVICE_ESTIMATE_LINKSPEED);
SVCSTR(WMI_SERVICE_OBSS_SCAN);
SVCSTR(WMI_SERVICE_TDLS_OFFCHAN);
SVCSTR(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA);
SVCSTR(WMI_SERVICE_TDLS_UAPSD_SLEEP_STA);
SVCSTR(WMI_SERVICE_IBSS_PWRSAVE);
SVCSTR(WMI_SERVICE_LPASS);
SVCSTR(WMI_SERVICE_EXTSCAN);
SVCSTR(WMI_SERVICE_D0WOW);
SVCSTR(WMI_SERVICE_HSOFFLOAD);
SVCSTR(WMI_SERVICE_ROAM_HO_OFFLOAD);
SVCSTR(WMI_SERVICE_RX_FULL_REORDER);
SVCSTR(WMI_SERVICE_DHCP_OFFLOAD);
SVCSTR(WMI_SERVICE_STA_RX_IPA_OFFLOAD_SUPPORT);
SVCSTR(WMI_SERVICE_MDNS_OFFLOAD);
SVCSTR(WMI_SERVICE_SAP_AUTH_OFFLOAD);
default:
return NULL;
}
@ -472,6 +550,7 @@ struct wmi_cmd_map {
u32 force_fw_hang_cmdid;
u32 gpio_config_cmdid;
u32 gpio_output_cmdid;
u32 pdev_get_temperature_cmdid;
};
/*
@ -1076,6 +1155,11 @@ enum wmi_10_2_cmd_id {
WMI_10_2_PDEV_SET_MIMOGAIN_TABLE_CMDID,
WMI_10_2_PDEV_RATEPWR_TABLE_CMDID,
WMI_10_2_PDEV_RATEPWR_CHAINMSK_TABLE_CMDID,
WMI_10_2_PDEV_GET_INFO,
WMI_10_2_VDEV_GET_INFO,
WMI_10_2_VDEV_ATF_REQUEST_CMDID,
WMI_10_2_PEER_ATF_REQUEST_CMDID,
WMI_10_2_PDEV_GET_TEMPERATURE_CMDID,
WMI_10_2_PDEV_UTF_CMDID = WMI_10_2_END_CMDID - 1,
};
@ -1117,6 +1201,8 @@ enum wmi_10_2_event_id {
WMI_10_2_MCAST_BUF_RELEASE_EVENTID,
WMI_10_2_MCAST_LIST_AGEOUT_EVENTID,
WMI_10_2_WDS_PEER_EVENTID,
WMI_10_2_PEER_STA_PS_STATECHG_EVENTID,
WMI_10_2_PDEV_TEMPERATURE_EVENTID,
WMI_10_2_PDEV_UTF_EVENTID = WMI_10_2_END_EVENTID - 1,
};
@ -1862,6 +1948,11 @@ struct wmi_resource_config_10x {
__le32 max_frag_entries;
} __packed;
enum wmi_10_2_feature_mask {
WMI_10_2_RX_BATCH_MODE = BIT(0),
WMI_10_2_ATF_CONFIG = BIT(1),
};
struct wmi_resource_config_10_2 {
struct wmi_resource_config_10x common;
__le32 max_peer_ext_stats;
@ -1870,7 +1961,7 @@ struct wmi_resource_config_10_2 {
__le32 be_min_free;
__le32 vi_min_free;
__le32 vo_min_free;
__le32 rx_batchmode; /* 0-disable, 1-enable */
__le32 feature_mask;
} __packed;
#define NUM_UNITS_IS_NUM_VDEVS 0x1
@ -2505,6 +2596,7 @@ struct wmi_pdev_param_map {
u32 fast_channel_reset;
u32 burst_dur;
u32 burst_enable;
u32 cal_period;
};
#define WMI_PDEV_PARAM_UNSUPPORTED 0
@ -2715,6 +2807,9 @@ enum wmi_10x_pdev_param {
WMI_10X_PDEV_PARAM_SET_MCAST2UCAST_MODE,
WMI_10X_PDEV_PARAM_SET_MCAST2UCAST_BUFFER,
WMI_10X_PDEV_PARAM_REMOVE_MCAST2UCAST_BUFFER,
WMI_10X_PDEV_PARAM_PEER_STA_PS_STATECHG_ENABLE,
WMI_10X_PDEV_PARAM_RTS_FIXED_RATE,
WMI_10X_PDEV_PARAM_CAL_PERIOD
};
struct wmi_pdev_set_param_cmd {
@ -2722,6 +2817,9 @@ struct wmi_pdev_set_param_cmd {
__le32 param_value;
} __packed;
/* valid period is 1 ~ 60000ms, unit in millisecond */
#define WMI_PDEV_PARAM_CAL_PERIOD_MAX 60000
struct wmi_pdev_get_tpc_config_cmd {
/* parameter */
__le32 param;
@ -3930,6 +4028,13 @@ enum wmi_sta_ps_param_pspoll_count {
* Values greater than 0 indicate the maximum numer of PS-Poll frames
* FW will send before waking up.
*/
/* When u-APSD is enabled the firmware will be very reluctant to exit
* STA PS. This could result in very poor Rx performance with STA doing
* PS-Poll for each and every buffered frame. This value is a bit
* arbitrary.
*/
WMI_STA_PS_PSPOLL_COUNT_UAPSD = 3,
};
/*
@ -4120,7 +4225,7 @@ struct wmi_bcn_info {
struct wmi_host_swba_event {
__le32 vdev_map;
struct wmi_bcn_info bcn_info[1];
struct wmi_bcn_info bcn_info[0];
} __packed;
#define WMI_MAX_AP_VDEV 16
@ -4567,6 +4672,58 @@ struct wmi_dbglog_cfg_cmd {
#define WMI_MAX_MEM_REQS 16
struct wmi_scan_ev_arg {
__le32 event_type; /* %WMI_SCAN_EVENT_ */
__le32 reason; /* %WMI_SCAN_REASON_ */
__le32 channel_freq; /* only valid for WMI_SCAN_EVENT_FOREIGN_CHANNEL */
__le32 scan_req_id;
__le32 scan_id;
__le32 vdev_id;
};
struct wmi_mgmt_rx_ev_arg {
__le32 channel;
__le32 snr;
__le32 rate;
__le32 phy_mode;
__le32 buf_len;
__le32 status; /* %WMI_RX_STATUS_ */
};
struct wmi_ch_info_ev_arg {
__le32 err_code;
__le32 freq;
__le32 cmd_flags;
__le32 noise_floor;
__le32 rx_clear_count;
__le32 cycle_count;
};
struct wmi_vdev_start_ev_arg {
__le32 vdev_id;
__le32 req_id;
__le32 resp_type; /* %WMI_VDEV_RESP_ */
__le32 status;
};
struct wmi_peer_kick_ev_arg {
const u8 *mac_addr;
};
struct wmi_swba_ev_arg {
__le32 vdev_map;
const struct wmi_tim_info *tim_info[WMI_MAX_AP_VDEV];
const struct wmi_p2p_noa_info *noa_info[WMI_MAX_AP_VDEV];
};
struct wmi_phyerr_ev_arg {
__le32 num_phyerrs;
__le32 tsf_l32;
__le32 tsf_u32;
__le32 buf_len;
const struct wmi_phyerr *phyerrs;
};
struct wmi_svc_rdy_ev_arg {
__le32 min_tx_power;
__le32 max_tx_power;
@ -4574,6 +4731,7 @@ struct wmi_svc_rdy_ev_arg {
__le32 vht_cap;
__le32 sw_ver0;
__le32 sw_ver1;
__le32 fw_build;
__le32 phy_capab;
__le32 num_rf_chains;
__le32 eeprom_rd;
@ -4583,83 +4741,93 @@ struct wmi_svc_rdy_ev_arg {
const struct wlan_host_mem_req *mem_reqs[WMI_MAX_MEM_REQS];
};
struct wmi_rdy_ev_arg {
__le32 sw_version;
__le32 abi_version;
__le32 status;
const u8 *mac_addr;
};
struct wmi_pdev_temperature_event {
/* temperature value in Celcius degree */
__le32 temperature;
} __packed;
struct ath10k;
struct ath10k_vif;
struct ath10k_fw_stats;
struct ath10k_fw_stats_pdev;
struct ath10k_fw_stats_peer;
int ath10k_wmi_attach(struct ath10k *ar);
void ath10k_wmi_detach(struct ath10k *ar);
int ath10k_wmi_wait_for_service_ready(struct ath10k *ar);
int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar);
struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len);
int ath10k_wmi_connect(struct ath10k *ar);
struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len);
int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt);
int ath10k_wmi_pdev_resume_target(struct ath10k *ar);
int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g,
u16 rd5g, u16 ctl2g, u16 ctl5g,
enum wmi_dfs_region dfs_reg);
int ath10k_wmi_pdev_set_param(struct ath10k *ar, u32 id, u32 value);
int ath10k_wmi_cmd_init(struct ath10k *ar);
int ath10k_wmi_start_scan(struct ath10k *ar, const struct wmi_start_scan_arg *);
int ath10k_wmi_cmd_send_nowait(struct ath10k *ar, struct sk_buff *skb,
u32 cmd_id);
void ath10k_wmi_start_scan_init(struct ath10k *ar, struct wmi_start_scan_arg *);
int ath10k_wmi_stop_scan(struct ath10k *ar,
const struct wmi_stop_scan_arg *arg);
int ath10k_wmi_vdev_create(struct ath10k *ar, u32 vdev_id,
enum wmi_vdev_type type,
enum wmi_vdev_subtype subtype,
const u8 macaddr[ETH_ALEN]);
int ath10k_wmi_vdev_delete(struct ath10k *ar, u32 vdev_id);
int ath10k_wmi_vdev_start(struct ath10k *ar,
const struct wmi_vdev_start_request_arg *);
int ath10k_wmi_vdev_restart(struct ath10k *ar,
const struct wmi_vdev_start_request_arg *);
int ath10k_wmi_vdev_stop(struct ath10k *ar, u32 vdev_id);
int ath10k_wmi_vdev_up(struct ath10k *ar, u32 vdev_id, u32 aid,
const u8 *bssid);
int ath10k_wmi_vdev_down(struct ath10k *ar, u32 vdev_id);
int ath10k_wmi_vdev_set_param(struct ath10k *ar, u32 vdev_id,
u32 param_id, u32 param_value);
int ath10k_wmi_vdev_install_key(struct ath10k *ar,
const struct wmi_vdev_install_key_arg *arg);
int ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
const struct wmi_vdev_spectral_conf_arg *arg);
int ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
u32 enable);
int ath10k_wmi_peer_create(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN]);
int ath10k_wmi_peer_delete(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN]);
int ath10k_wmi_peer_flush(struct ath10k *ar, u32 vdev_id,
const u8 peer_addr[ETH_ALEN], u32 tid_bitmap);
int ath10k_wmi_peer_set_param(struct ath10k *ar, u32 vdev_id,
const u8 *peer_addr,
enum wmi_peer_param param_id, u32 param_value);
int ath10k_wmi_peer_assoc(struct ath10k *ar,
const struct wmi_peer_assoc_complete_arg *arg);
int ath10k_wmi_set_psmode(struct ath10k *ar, u32 vdev_id,
enum wmi_sta_ps_mode psmode);
int ath10k_wmi_set_sta_ps_param(struct ath10k *ar, u32 vdev_id,
enum wmi_sta_powersave_param param_id,
u32 value);
int ath10k_wmi_set_ap_ps_param(struct ath10k *ar, u32 vdev_id, const u8 *mac,
enum wmi_ap_ps_peer_param param_id, u32 value);
int ath10k_wmi_scan_chan_list(struct ath10k *ar,
const struct wmi_scan_chan_list_arg *arg);
int ath10k_wmi_beacon_send_ref_nowait(struct ath10k_vif *arvif);
int ath10k_wmi_pdev_set_wmm_params(struct ath10k *ar,
const struct wmi_pdev_set_wmm_params_arg *arg);
int ath10k_wmi_request_stats(struct ath10k *ar, enum wmi_stats_id stats_id);
int ath10k_wmi_force_fw_hang(struct ath10k *ar,
enum wmi_force_fw_hang_type type, u32 delay_ms);
int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb);
int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable);
int ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb,
struct ath10k_fw_stats *stats);
int ath10k_wmi_pdev_pktlog_enable(struct ath10k *ar, u32 ev_list);
int ath10k_wmi_pdev_pktlog_disable(struct ath10k *ar);
void ath10k_wmi_pull_pdev_stats(const struct wmi_pdev_stats *src,
struct ath10k_fw_stats_pdev *dst);
void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src,
struct ath10k_fw_stats_peer *dst);
void ath10k_wmi_put_host_mem_chunks(struct ath10k *ar,
struct wmi_host_mem_chunks *chunks);
void ath10k_wmi_put_start_scan_common(struct wmi_start_scan_common *cmn,
const struct wmi_start_scan_arg *arg);
void ath10k_wmi_pdev_set_wmm_param(struct wmi_wmm_params *params,
const struct wmi_wmm_params_arg *arg);
void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
const struct wmi_channel_arg *arg);
int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg);
int ath10k_wmi_event_scan(struct ath10k *ar, struct sk_buff *skb);
int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_chan_info(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_echo(struct ath10k *ar, struct sk_buff *skb);
int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_update_stats(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_vdev_stopped(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_peer_sta_kickout(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_dfs(struct ath10k *ar,
const struct wmi_phyerr *phyerr, u64 tsf);
void ath10k_wmi_event_spectral_scan(struct ath10k *ar,
const struct wmi_phyerr *phyerr,
u64 tsf);
void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_roam(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_profile_match(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_debug_print(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_pdev_qvit(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_wlan_profile_data(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_rtt_measurement_report(struct ath10k *ar,
struct sk_buff *skb);
void ath10k_wmi_event_tsf_measurement_report(struct ath10k *ar,
struct sk_buff *skb);
void ath10k_wmi_event_rtt_error_report(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_wow_wakeup_host(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_dcs_interference(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_pdev_ftm_intg(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_gtk_offload_status(struct ath10k *ar,
struct sk_buff *skb);
void ath10k_wmi_event_gtk_rekey_fail(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_delba_complete(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_addba_complete(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_vdev_install_key_complete(struct ath10k *ar,
struct sk_buff *skb);
void ath10k_wmi_event_inst_rssi_stats(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_vdev_standby_req(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar, struct sk_buff *skb);
void ath10k_wmi_event_service_ready(struct ath10k *ar, struct sk_buff *skb);
int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb);
#endif /* _WMI_H_ */

View file

@ -227,7 +227,6 @@ static struct platform_driver ath_ahb_driver = {
.remove = ath_ahb_remove,
.driver = {
.name = "ar231x-wmac",
.owner = THIS_MODULE,
},
};

View file

@ -912,6 +912,7 @@ ath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode)
pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
| (ah->ah_version == AR5K_AR5210 ?
AR5K_STA_ID1_PWR_SV : 0);
/* fall through */
case NL80211_IFTYPE_MONITOR:
pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE
| (ah->ah_version == AR5K_AR5210 ?

View file

@ -43,6 +43,10 @@ static const struct platform_device_id ath9k_platform_id_table[] = {
.name = "qca953x_wmac",
.driver_data = AR9300_DEVID_AR953X,
},
{
.name = "qca956x_wmac",
.driver_data = AR9300_DEVID_QCA956X,
},
{},
};

View file

@ -259,7 +259,8 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel,
entry_cck->fir_step_level);
/* Skip MRC CCK for pre AR9003 families */
if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah) || AR_SREV_9565(ah))
if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9485(ah) ||
AR_SREV_9565(ah) || AR_SREV_9561(ah))
return;
if (aniState->mrcCCK != entry_cck->mrc_cck_on)

View file

@ -22,6 +22,21 @@
/* All code below is for AR5008, AR9001, AR9002 */
#define AR5008_OFDM_RATES 8
#define AR5008_HT_SS_RATES 8
#define AR5008_HT_DS_RATES 8
#define AR5008_HT20_SHIFT 16
#define AR5008_HT40_SHIFT 24
#define AR5008_11NA_OFDM_SHIFT 0
#define AR5008_11NA_HT_SS_SHIFT 8
#define AR5008_11NA_HT_DS_SHIFT 16
#define AR5008_11NG_OFDM_SHIFT 4
#define AR5008_11NG_HT_SS_SHIFT 12
#define AR5008_11NG_HT_DS_SHIFT 20
static const int firstep_table[] =
/* level: 0 1 2 3 4 5 6 7 8 */
{ -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */
@ -1235,6 +1250,71 @@ static void ar5008_hw_set_radar_conf(struct ath_hw *ah)
conf->radar_inband = 8;
}
static void ar5008_hw_init_txpower_cck(struct ath_hw *ah, int16_t *rate_array)
{
#define CCK_DELTA(x) ((OLC_FOR_AR9280_20_LATER) ? max((x) - 2, 0) : (x))
ah->tx_power[0] = CCK_DELTA(rate_array[rate1l]);
ah->tx_power[1] = CCK_DELTA(min(rate_array[rate2l],
rate_array[rate2s]));
ah->tx_power[2] = CCK_DELTA(min(rate_array[rate5_5l],
rate_array[rate5_5s]));
ah->tx_power[3] = CCK_DELTA(min(rate_array[rate11l],
rate_array[rate11s]));
#undef CCK_DELTA
}
static void ar5008_hw_init_txpower_ofdm(struct ath_hw *ah, int16_t *rate_array,
int offset)
{
int i, idx = 0;
for (i = offset; i < offset + AR5008_OFDM_RATES; i++) {
ah->tx_power[i] = rate_array[idx];
idx++;
}
}
static void ar5008_hw_init_txpower_ht(struct ath_hw *ah, int16_t *rate_array,
int ss_offset, int ds_offset,
bool is_40, int ht40_delta)
{
int i, mcs_idx = (is_40) ? AR5008_HT40_SHIFT : AR5008_HT20_SHIFT;
for (i = ss_offset; i < ss_offset + AR5008_HT_SS_RATES; i++) {
ah->tx_power[i] = rate_array[mcs_idx] + ht40_delta;
mcs_idx++;
}
memcpy(&ah->tx_power[ds_offset], &ah->tx_power[ss_offset],
AR5008_HT_SS_RATES);
}
void ar5008_hw_init_rate_txpower(struct ath_hw *ah, int16_t *rate_array,
struct ath9k_channel *chan, int ht40_delta)
{
if (IS_CHAN_5GHZ(chan)) {
ar5008_hw_init_txpower_ofdm(ah, rate_array,
AR5008_11NA_OFDM_SHIFT);
if (IS_CHAN_HT20(chan) || IS_CHAN_HT40(chan)) {
ar5008_hw_init_txpower_ht(ah, rate_array,
AR5008_11NA_HT_SS_SHIFT,
AR5008_11NA_HT_DS_SHIFT,
IS_CHAN_HT40(chan),
ht40_delta);
}
} else {
ar5008_hw_init_txpower_cck(ah, rate_array);
ar5008_hw_init_txpower_ofdm(ah, rate_array,
AR5008_11NG_OFDM_SHIFT);
if (IS_CHAN_HT20(chan) || IS_CHAN_HT40(chan)) {
ar5008_hw_init_txpower_ht(ah, rate_array,
AR5008_11NG_HT_SS_SHIFT,
AR5008_11NG_HT_DS_SHIFT,
IS_CHAN_HT40(chan),
ht40_delta);
}
}
}
int ar5008_hw_attach_phy_ops(struct ath_hw *ah)
{
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);

View file

@ -3536,7 +3536,7 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz)
int bias = ar9003_modal_header(ah, is2ghz)->xpaBiasLvl;
if (AR_SREV_9485(ah) || AR_SREV_9330(ah) || AR_SREV_9340(ah) ||
AR_SREV_9531(ah))
AR_SREV_9531(ah) || AR_SREV_9561(ah))
REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias);
else if (AR_SREV_9462(ah) || AR_SREV_9550(ah) || AR_SREV_9565(ah))
REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias);
@ -3599,7 +3599,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
AR_SWITCH_TABLE_COM_AR9462_ALL, value);
} else if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) {
} else if (AR_SREV_9550(ah) || AR_SREV_9531(ah) || AR_SREV_9561(ah)) {
REG_RMW_FIELD(ah, AR_PHY_SWITCH_COM,
AR_SWITCH_TABLE_COM_AR9550_ALL, value);
} else
@ -3929,9 +3929,13 @@ void ar9003_hw_internal_regulator_apply(struct ath_hw *ah)
REG_WRITE(ah, AR_PHY_PMU2, reg_pmu_set);
if (!is_pmu_set(ah, AR_PHY_PMU2, reg_pmu_set))
return;
} else if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
} else if (AR_SREV_9462(ah) || AR_SREV_9565(ah) ||
AR_SREV_9561(ah)) {
reg_val = le32_to_cpu(pBase->swreg);
REG_WRITE(ah, AR_PHY_PMU1, reg_val);
if (AR_SREV_9561(ah))
REG_WRITE(ah, AR_PHY_PMU2, 0x10200000);
} else {
/* Internal regulator is ON. Write swreg register. */
reg_val = le32_to_cpu(pBase->swreg);
@ -4034,7 +4038,8 @@ static void ar9003_hw_xpa_timing_control_apply(struct ath_hw *ah, bool is2ghz)
if (!AR_SREV_9300(ah) &&
!AR_SREV_9340(ah) &&
!AR_SREV_9580(ah) &&
!AR_SREV_9531(ah))
!AR_SREV_9531(ah) &&
!AR_SREV_9561(ah))
return;
xpa_ctl = ar9003_modal_header(ah, is2ghz)->txFrameToXpaOn;
@ -4812,7 +4817,7 @@ static void ar9003_hw_power_control_override(struct ath_hw *ah,
}
tempslope:
if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) {
if (AR_SREV_9550(ah) || AR_SREV_9531(ah) || AR_SREV_9561(ah)) {
u8 txmask = (eep->baseEepHeader.txrxMask & 0xf0) >> 4;
/*

View file

@ -29,6 +29,7 @@
#include "ar9565_1p0_initvals.h"
#include "ar9565_1p1_initvals.h"
#include "ar953x_initvals.h"
#include "ar956x_initvals.h"
/* General hardware code for the AR9003 hadware family */
@ -358,6 +359,40 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
INIT_INI_ARRAY(&ah->iniModesFastClock,
qca953x_1p0_modes_fast_clock);
} else if (AR_SREV_9561(ah)) {
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
qca956x_1p0_mac_core);
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
qca956x_1p0_mac_postamble);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
qca956x_1p0_baseband_core);
INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
qca956x_1p0_baseband_postamble);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
qca956x_1p0_radio_core);
INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
qca956x_1p0_radio_postamble);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
qca956x_1p0_soc_preamble);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
qca956x_1p0_soc_postamble);
INIT_INI_ARRAY(&ah->iniModesRxGain,
qca956x_1p0_common_wo_xlna_rx_gain_table);
INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
qca956x_1p0_common_wo_xlna_rx_gain_bounds);
INIT_INI_ARRAY(&ah->iniModesTxGain,
qca956x_1p0_modes_no_xpa_tx_gain_table);
INIT_INI_ARRAY(&ah->ini_dfs,
qca956x_1p0_baseband_postamble_dfs_channel);
INIT_INI_ARRAY(&ah->iniCckfirJapan2484,
qca956x_1p0_baseband_core_txfir_coeff_japan_2484);
INIT_INI_ARRAY(&ah->iniModesFastClock,
qca956x_1p0_modes_fast_clock);
} else if (AR_SREV_9580(ah)) {
/* mac */
INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
@ -544,6 +579,9 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah)
else if (AR_SREV_9531_20(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
qca953x_2p0_modes_xpa_tx_gain_table);
else if (AR_SREV_9561(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
qca956x_1p0_modes_xpa_tx_gain_table);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_lowest_ob_db_tx_gain_table);
@ -594,7 +632,10 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah)
else
INIT_INI_ARRAY(&ah->iniModesTxGain,
qca953x_1p0_modes_no_xpa_tx_gain_table);
} else if (AR_SREV_9462_21(ah))
} else if (AR_SREV_9561(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
qca956x_1p0_modes_no_xpa_tx_gain_table);
else if (AR_SREV_9462_21(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9462_2p1_modes_high_ob_db_tx_gain);
else if (AR_SREV_9462_20(ah))
@ -628,6 +669,9 @@ static void ar9003_tx_gain_table_mode2(struct ath_hw *ah)
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_low_ob_db_tx_gain_table);
else if (AR_SREV_9561(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
qca956x_1p0_modes_no_xpa_low_ob_db_tx_gain_table);
else if (AR_SREV_9565_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9565_1p1_modes_low_ob_db_tx_gain_table);
@ -699,6 +743,9 @@ static void ar9003_tx_gain_table_mode5(struct ath_hw *ah)
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_type5_tx_gain_table);
else if (AR_SREV_9561(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
qca956x_1p0_modes_no_xpa_green_tx_gain_table);
else if (AR_SREV_9300_22(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9300Modes_type5_tx_gain_table_2p2);
@ -770,6 +817,13 @@ static void ar9003_rx_gain_table_mode0(struct ath_hw *ah)
qca953x_1p0_common_rx_gain_table);
INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
qca953x_1p0_common_rx_gain_bounds);
} else if (AR_SREV_9561(ah)) {
INIT_INI_ARRAY(&ah->iniModesRxGain,
qca956x_1p0_common_rx_gain_table);
INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
qca956x_1p0_common_rx_gain_bounds);
INIT_INI_ARRAY(&ah->ini_modes_rxgain_5g_xlna,
qca956x_1p0_xlna_only);
} else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9580_1p0_rx_gain_table);
@ -825,6 +879,11 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah)
qca953x_2p0_common_wo_xlna_rx_gain_table);
INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
qca953x_2p0_common_wo_xlna_rx_gain_bounds);
} else if (AR_SREV_9561(ah)) {
INIT_INI_ARRAY(&ah->iniModesRxGain,
qca956x_1p0_common_wo_xlna_rx_gain_table);
INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
qca956x_1p0_common_wo_xlna_rx_gain_bounds);
} else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9580_1p0_wo_xlna_rx_gain_table);

View file

@ -183,7 +183,8 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
} else {
channelSel = CHANSEL_2G(freq) >> 1;
}
} else if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) {
} else if (AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
AR_SREV_9561(ah)) {
if (ah->is_clk_25mhz)
div = 75;
else
@ -198,7 +199,8 @@ static int ar9003_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan)
/* Set to 2G mode */
bMode = 1;
} else {
if ((AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) &&
if ((AR_SREV_9340(ah) || AR_SREV_9550(ah) ||
AR_SREV_9531(ah) || AR_SREV_9561(ah)) &&
ah->is_clk_25mhz) {
channelSel = freq / 75;
chan_frac = ((freq % 75) * 0x20000) / 75;
@ -265,7 +267,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
*/
if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) ||
AR_SREV_9550(ah)) {
AR_SREV_9550(ah) || AR_SREV_9561(ah)) {
if (spur_fbin_ptr[0] == 0) /* No spur */
return;
max_spur_cnts = 5;
@ -292,7 +294,7 @@ static void ar9003_hw_spur_mitigate_mrc_cck(struct ath_hw *ah,
negative = 0;
if (AR_SREV_9485(ah) || AR_SREV_9340(ah) || AR_SREV_9330(ah) ||
AR_SREV_9550(ah))
AR_SREV_9550(ah) || AR_SREV_9561(ah))
cur_bb_spur = ath9k_hw_fbin2freq(spur_fbin_ptr[i],
IS_CHAN_2GHZ(chan));
else
@ -641,8 +643,10 @@ static void ar9003_hw_set_channel_regs(struct ath_hw *ah,
(REG_READ(ah, AR_PHY_GEN_CTRL) & AR_PHY_GC_ENABLE_DAC_FIFO);
/* Enable 11n HT, 20 MHz */
phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SINGLE_HT_LTF1 |
AR_PHY_GC_SHORT_GI_40 | enableDacFifo;
phymode = AR_PHY_GC_HT_EN | AR_PHY_GC_SHORT_GI_40 | enableDacFifo;
if (!AR_SREV_9561(ah))
phymode |= AR_PHY_GC_SINGLE_HT_LTF1;
/* Configure baseband for dynamic 20/40 operation */
if (IS_CHAN_HT40(chan)) {
@ -745,7 +749,8 @@ static void ar9003_hw_override_ini(struct ath_hw *ah)
else
ah->enabled_cals &= ~TX_CL_CAL;
if (AR_SREV_9340(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) {
if (AR_SREV_9340(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah) ||
AR_SREV_9561(ah)) {
if (ah->is_clk_25mhz) {
REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1);
REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7);
@ -812,6 +817,19 @@ static int ar9550_hw_get_modes_txgain_index(struct ath_hw *ah,
return ret;
}
static int ar9561_hw_get_modes_txgain_index(struct ath_hw *ah,
struct ath9k_channel *chan)
{
if (IS_CHAN_2GHZ(chan)) {
if (IS_CHAN_HT40(chan))
return 1;
else
return 2;
}
return 0;
}
static void ar9003_doubler_fix(struct ath_hw *ah)
{
if (AR_SREV_9300(ah) || AR_SREV_9580(ah) || AR_SREV_9550(ah)) {
@ -911,21 +929,29 @@ static int ar9003_hw_process_ini(struct ath_hw *ah,
REG_WRITE_ARRAY(&ah->ini_modes_rxgain_5g_xlna,
modesIndex, regWrites);
}
if (AR_SREV_9561(ah) && (ar9003_hw_get_rx_gain_idx(ah) == 0))
REG_WRITE_ARRAY(&ah->ini_modes_rxgain_5g_xlna,
modesIndex, regWrites);
}
if (AR_SREV_9550(ah))
if (AR_SREV_9550(ah) || AR_SREV_9561(ah))
REG_WRITE_ARRAY(&ah->ini_modes_rx_gain_bounds, modesIndex,
regWrites);
/*
* TXGAIN initvals.
*/
if (AR_SREV_9550(ah) || AR_SREV_9531(ah)) {
if (AR_SREV_9550(ah) || AR_SREV_9531(ah) || AR_SREV_9561(ah)) {
int modes_txgain_index = 1;
if (AR_SREV_9550(ah))
modes_txgain_index = ar9550_hw_get_modes_txgain_index(ah, chan);
if (AR_SREV_9561(ah))
modes_txgain_index =
ar9561_hw_get_modes_txgain_index(ah, chan);
if (modes_txgain_index < 0)
return -EINVAL;
@ -1989,7 +2015,8 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->rf_set_freq = ar9003_hw_set_channel;
priv_ops->spur_mitigate_freq = ar9003_hw_spur_mitigate;
if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah))
if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
AR_SREV_9561(ah))
priv_ops->compute_pll_control = ar9003_hw_compute_pll_control_soc;
else
priv_ops->compute_pll_control = ar9003_hw_compute_pll_control;

View file

@ -454,7 +454,7 @@
#define AR_PHY_GEN_CTRL (AR_SM_BASE + 0x4)
#define AR_PHY_MODE (AR_SM_BASE + 0x8)
#define AR_PHY_ACTIVE (AR_SM_BASE + 0xc)
#define AR_PHY_SPUR_MASK_A (AR_SM_BASE + 0x20)
#define AR_PHY_SPUR_MASK_A (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x18 : 0x20))
#define AR_PHY_SPUR_MASK_B (AR_SM_BASE + 0x24)
#define AR_PHY_SPECTRAL_SCAN (AR_SM_BASE + 0x28)
#define AR_PHY_RADAR_BW_FILTER (AR_SM_BASE + 0x2c)
@ -506,7 +506,7 @@
#define AR_PHY_TEST_CHAIN_SEL 0xC0000000
#define AR_PHY_TEST_CHAIN_SEL_S 30
#define AR_PHY_TEST_CTL_STATUS (AR_SM_BASE + 0x164)
#define AR_PHY_TEST_CTL_STATUS (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x160 : 0x164))
#define AR_PHY_TEST_CTL_TSTDAC_EN 0x1
#define AR_PHY_TEST_CTL_TSTDAC_EN_S 0
#define AR_PHY_TEST_CTL_TX_OBS_SEL 0x1C
@ -525,7 +525,7 @@
#define AR_PHY_CHAN_STATUS (AR_SM_BASE + 0x16c)
#define AR_PHY_CHAN_INFO_MEMORY (AR_SM_BASE + 0x170)
#define AR_PHY_CHAN_INFO_MEMORY (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x16c : 0x170))
#define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ 0x00000008
#define AR_PHY_CHAN_INFO_MEMORY_CHANINFOMEM_S2_READ_S 3
@ -536,7 +536,7 @@
#define AR_PHY_SCRAMBLER_SEED (AR_SM_BASE + 0x190)
#define AR_PHY_CCK_TX_CTRL (AR_SM_BASE + 0x194)
#define AR_PHY_HEAVYCLIP_CTL (AR_SM_BASE + 0x1a4)
#define AR_PHY_HEAVYCLIP_CTL (AR_SM_BASE + (AR_SREV_9561(ah) ? 0x198 : 0x1a4))
#define AR_PHY_HEAVYCLIP_20 (AR_SM_BASE + 0x1a8)
#define AR_PHY_HEAVYCLIP_40 (AR_SM_BASE + 0x1ac)
#define AR_PHY_ILLEGAL_TXRATE (AR_SM_BASE + 0x1b0)
@ -726,21 +726,24 @@
#define AR_CH0_TOP2 (AR_SREV_9300(ah) ? 0x1628c : \
(AR_SREV_9462(ah) ? 0x16290 : 0x16284))
#define AR_CH0_TOP2_XPABIASLVL 0xf000
#define AR_CH0_TOP2_XPABIASLVL (AR_SREV_9561(ah) ? 0x1e00 : 0xf000)
#define AR_CH0_TOP2_XPABIASLVL_S 12
#define AR_CH0_XTAL (AR_SREV_9300(ah) ? 0x16294 : \
((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16298 : 0x16290))
((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16298 : \
(AR_SREV_9561(ah) ? 0x162c0 : 0x16290)))
#define AR_CH0_XTAL_CAPINDAC 0x7f000000
#define AR_CH0_XTAL_CAPINDAC_S 24
#define AR_CH0_XTAL_CAPOUTDAC 0x00fe0000
#define AR_CH0_XTAL_CAPOUTDAC_S 17
#define AR_PHY_PMU1 ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16340 : 0x16c40)
#define AR_PHY_PMU1 ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16340 : \
(AR_SREV_9561(ah) ? 0x16cc0 : 0x16c40))
#define AR_PHY_PMU1_PWD 0x1
#define AR_PHY_PMU1_PWD_S 0
#define AR_PHY_PMU2 ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16344 : 0x16c44)
#define AR_PHY_PMU2 ((AR_SREV_9462(ah) || AR_SREV_9565(ah)) ? 0x16344 : \
(AR_SREV_9561(ah) ? 0x16cc4 : 0x16c44))
#define AR_PHY_PMU2_PGM 0x00200000
#define AR_PHY_PMU2_PGM_S 21

File diff suppressed because it is too large Load diff

View file

@ -403,7 +403,8 @@ static const struct file_operations fops_antenna_diversity = {
static int read_file_dma(struct seq_file *file, void *data)
{
struct ath_softc *sc = file->private;
struct ieee80211_hw *hw = dev_get_drvdata(file->private);
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
u32 val[ATH9K_NUM_DMA_DEBUG_REGS];
int i, qcuOffset = 0, dcuOffset = 0;
@ -470,20 +471,6 @@ static int read_file_dma(struct seq_file *file, void *data)
return 0;
}
static int open_file_dma(struct inode *inode, struct file *f)
{
return single_open(f, read_file_dma, inode->i_private);
}
static const struct file_operations fops_dma = {
.open = open_file_dma,
.read = seq_read,
.owner = THIS_MODULE,
.llseek = seq_lseek,
.release = single_release,
};
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
{
if (status)
@ -539,7 +526,8 @@ void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status)
static int read_file_interrupt(struct seq_file *file, void *data)
{
struct ath_softc *sc = file->private;
struct ieee80211_hw *hw = dev_get_drvdata(file->private);
struct ath_softc *sc = hw->priv;
#define PR_IS(a, s) \
do { \
@ -600,22 +588,10 @@ static int read_file_interrupt(struct seq_file *file, void *data)
return 0;
}
static int open_file_interrupt(struct inode *inode, struct file *f)
{
return single_open(f, read_file_interrupt, inode->i_private);
}
static const struct file_operations fops_interrupt = {
.read = seq_read,
.open = open_file_interrupt,
.owner = THIS_MODULE,
.llseek = seq_lseek,
.release = single_release,
};
static int read_file_xmit(struct seq_file *file, void *data)
{
struct ath_softc *sc = file->private;
struct ieee80211_hw *hw = dev_get_drvdata(file->private);
struct ath_softc *sc = hw->priv;
seq_printf(file, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO");
@ -661,7 +637,8 @@ static void print_queue(struct ath_softc *sc, struct ath_txq *txq,
static int read_file_queues(struct seq_file *file, void *data)
{
struct ath_softc *sc = file->private;
struct ieee80211_hw *hw = dev_get_drvdata(file->private);
struct ath_softc *sc = hw->priv;
struct ath_txq *txq;
int i;
static const char *qname[4] = {
@ -682,7 +659,8 @@ static int read_file_queues(struct seq_file *file, void *data)
static int read_file_misc(struct seq_file *file, void *data)
{
struct ath_softc *sc = file->private;
struct ieee80211_hw *hw = dev_get_drvdata(file->private);
struct ath_softc *sc = hw->priv;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath9k_vif_iter_data iter_data;
struct ath_chanctx *ctx;
@ -773,7 +751,8 @@ static int read_file_misc(struct seq_file *file, void *data)
static int read_file_reset(struct seq_file *file, void *data)
{
struct ath_softc *sc = file->private;
struct ieee80211_hw *hw = dev_get_drvdata(file->private);
struct ath_softc *sc = hw->priv;
static const char * const reset_cause[__RESET_TYPE_MAX] = {
[RESET_TYPE_BB_HANG] = "Baseband Hang",
[RESET_TYPE_BB_WATCHDOG] = "Baseband Watchdog",
@ -837,58 +816,6 @@ void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
TX_STAT_INC(qnum, delim_underrun);
}
static int open_file_xmit(struct inode *inode, struct file *f)
{
return single_open(f, read_file_xmit, inode->i_private);
}
static const struct file_operations fops_xmit = {
.read = seq_read,
.open = open_file_xmit,
.owner = THIS_MODULE,
.llseek = seq_lseek,
.release = single_release,
};
static int open_file_queues(struct inode *inode, struct file *f)
{
return single_open(f, read_file_queues, inode->i_private);
}
static const struct file_operations fops_queues = {
.read = seq_read,
.open = open_file_queues,
.owner = THIS_MODULE,
.llseek = seq_lseek,
.release = single_release,
};
static int open_file_misc(struct inode *inode, struct file *f)
{
return single_open(f, read_file_misc, inode->i_private);
}
static const struct file_operations fops_misc = {
.read = seq_read,
.open = open_file_misc,
.owner = THIS_MODULE,
.llseek = seq_lseek,
.release = single_release,
};
static int open_file_reset(struct inode *inode, struct file *f)
{
return single_open(f, read_file_reset, inode->i_private);
}
static const struct file_operations fops_reset = {
.read = seq_read,
.open = open_file_reset,
.owner = THIS_MODULE,
.llseek = seq_lseek,
.release = single_release,
};
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
{
ath9k_cmn_debug_stat_rx(&sc->debug.stats.rxstats, rs);
@ -1018,7 +945,8 @@ static const struct file_operations fops_regdump = {
static int read_file_dump_nfcal(struct seq_file *file, void *data)
{
struct ath_softc *sc = file->private;
struct ieee80211_hw *hw = dev_get_drvdata(file->private);
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath9k_nfcal_hist *h = sc->cur_chan->caldata.nfCalHist;
struct ath_common *common = ath9k_hw_common(ah);
@ -1150,11 +1078,6 @@ static ssize_t write_file_tpc(struct file *file, const char __user *user_buf,
ssize_t len;
bool tpc_enabled;
if (!AR_SREV_9300_20_OR_LATER(ah)) {
/* ar9002 does not support TPC for the moment */
return -EOPNOTSUPP;
}
len = min(count, sizeof(buf) - 1);
if (copy_from_user(buf, user_buf, len))
return -EFAULT;
@ -1329,14 +1252,14 @@ int ath9k_init_debug(struct ath_hw *ah)
ath9k_tx99_init_debug(sc);
ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy);
debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_dma);
debugfs_create_file("interrupt", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_interrupt);
debugfs_create_file("xmit", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_xmit);
debugfs_create_file("queues", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_queues);
debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy,
read_file_dma);
debugfs_create_devm_seqfile(sc->dev, "interrupt", sc->debug.debugfs_phy,
read_file_interrupt);
debugfs_create_devm_seqfile(sc->dev, "xmit", sc->debug.debugfs_phy,
read_file_xmit);
debugfs_create_devm_seqfile(sc->dev, "queues", sc->debug.debugfs_phy,
read_file_queues);
debugfs_create_u32("qlen_bk", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
&sc->tx.txq_max_pending[IEEE80211_AC_BK]);
debugfs_create_u32("qlen_be", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
@ -1345,10 +1268,10 @@ int ath9k_init_debug(struct ath_hw *ah)
&sc->tx.txq_max_pending[IEEE80211_AC_VI]);
debugfs_create_u32("qlen_vo", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
&sc->tx.txq_max_pending[IEEE80211_AC_VO]);
debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_misc);
debugfs_create_file("reset", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_reset);
debugfs_create_devm_seqfile(sc->dev, "misc", sc->debug.debugfs_phy,
read_file_misc);
debugfs_create_devm_seqfile(sc->dev, "reset", sc->debug.debugfs_phy,
read_file_reset);
ath9k_cmn_debug_recv(sc->debug.debugfs_phy, &sc->debug.stats.rxstats);
ath9k_cmn_debug_phy_err(sc->debug.debugfs_phy, &sc->debug.stats.rxstats);
@ -1370,8 +1293,9 @@ int ath9k_init_debug(struct ath_hw *ah)
&ah->config.cwm_ignore_extcca);
debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_regdump);
debugfs_create_file("dump_nfcal", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_dump_nfcal);
debugfs_create_devm_seqfile(sc->dev, "dump_nfcal",
sc->debug.debugfs_phy,
read_file_dump_nfcal);
ath9k_cmn_debug_base_eeprom(sc->debug.debugfs_phy, sc->sc_ah);
ath9k_cmn_debug_modal_eeprom(sc->debug.debugfs_phy, sc->sc_ah);

View file

@ -748,6 +748,20 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
| ATH9K_POW_SM(ratesArray[rateDupCck], 0));
}
/* TPC initializations */
if (ah->tpc_enabled) {
int ht40_delta;
ht40_delta = (IS_CHAN_HT40(chan)) ? ht40PowerIncForPdadc : 0;
ar5008_hw_init_rate_txpower(ah, ratesArray, chan, ht40_delta);
/* Enable TPC */
REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX,
MAX_RATE_POWER | AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE);
} else {
/* Disable TPC */
REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER);
}
REGWRITE_BUFFER_FLUSH(ah);
}

View file

@ -886,6 +886,21 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
| ATH9K_POW_SM(ratesArray[rateDupOfdm], 8)
| ATH9K_POW_SM(ratesArray[rateDupCck], 0));
}
/* TPC initializations */
if (ah->tpc_enabled) {
int ht40_delta;
ht40_delta = (IS_CHAN_HT40(chan)) ? ht40PowerIncForPdadc : 0;
ar5008_hw_init_rate_txpower(ah, ratesArray, chan, ht40_delta);
/* Enable TPC */
REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX,
MAX_RATE_POWER | AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE);
} else {
/* Disable TPC */
REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER);
}
REGWRITE_BUFFER_FLUSH(ah);
}

View file

@ -1332,6 +1332,20 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6)
| ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0));
/* TPC initializations */
if (ah->tpc_enabled) {
int ht40_delta;
ht40_delta = (IS_CHAN_HT40(chan)) ? ht40PowerIncForPdadc : 0;
ar5008_hw_init_rate_txpower(ah, ratesArray, chan, ht40_delta);
/* Enable TPC */
REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX,
MAX_RATE_POWER | AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE);
} else {
/* Disable TPC */
REG_WRITE(ah, AR_PHY_POWER_TX_RATE_MAX, MAX_RATE_POWER);
}
REGWRITE_BUFFER_FLUSH(ah);
}

View file

@ -44,6 +44,9 @@
extern struct ieee80211_ops ath9k_htc_ops;
extern int htc_modparam_nohwcrypt;
#ifdef CONFIG_MAC80211_LEDS
extern int led_blink;
#endif
enum htc_phymode {
HTC_MODE_11NA = 0,

View file

@ -279,6 +279,10 @@ void ath9k_init_leds(struct ath9k_htc_priv *priv)
else
priv->ah->led_pin = ATH_LED_PIN_DEF;
if (!led_blink)
priv->led_cdev.default_trigger =
ieee80211_get_radio_led_name(priv->hw);
ath9k_configure_leds(priv);
snprintf(priv->led_name, sizeof(priv->led_name),

View file

@ -39,6 +39,10 @@ module_param_named(ps_enable, ath9k_ps_enable, int, 0444);
MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave");
#ifdef CONFIG_MAC80211_LEDS
int led_blink = 1;
module_param_named(blink, led_blink, int, 0444);
MODULE_PARM_DESC(blink, "Enable LED blink on activity");
static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = {
{ .throughput = 0 * 1024, .blink_time = 334 },
{ .throughput = 1 * 1024, .blink_time = 260 },

View file

@ -351,11 +351,7 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle,
return;
ret:
/* HTC-generated packets are freed here. */
if (htc_hdr && htc_hdr->endpoint_id != ENDPOINT0)
dev_kfree_skb_any(skb);
else
kfree_skb(skb);
kfree_skb(skb);
}
static void ath9k_htc_fw_panic_report(struct htc_target *htc_handle,

View file

@ -246,6 +246,8 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
case AR9300_DEVID_AR953X:
ah->hw_version.macVersion = AR_SREV_VERSION_9531;
return;
case AR9300_DEVID_QCA956X:
ah->hw_version.macVersion = AR_SREV_VERSION_9561;
}
val = REG_READ(ah, AR_SREV) & AR_SREV_ID;
@ -422,8 +424,7 @@ static void ath9k_hw_init_defaults(struct ath_hw *ah)
ah->power_mode = ATH9K_PM_UNDEFINED;
ah->htc_reset_init = true;
/* ar9002 does not support TPC for the moment */
ah->tpc_enabled = !!AR_SREV_9300_20_OR_LATER(ah);
ah->tpc_enabled = true;
ah->ani_function = ATH9K_ANI_ALL;
if (!AR_SREV_9300_20_OR_LATER(ah))
@ -539,6 +540,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
case AR_SREV_VERSION_9550:
case AR_SREV_VERSION_9565:
case AR_SREV_VERSION_9531:
case AR_SREV_VERSION_9561:
break;
default:
ath_err(common,
@ -639,6 +641,7 @@ int ath9k_hw_init(struct ath_hw *ah)
case AR9485_DEVID_AR1111:
case AR9300_DEVID_AR9565:
case AR9300_DEVID_AR953X:
case AR9300_DEVID_QCA956X:
break;
default:
if (common->bus_ops->ath_bus_type == ATH_USB)
@ -779,7 +782,8 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
/* program BB PLL phase_shift */
REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
AR_CH0_BB_DPLL3_PHASE_SHIFT, 0x1);
} else if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah)) {
} else if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
AR_SREV_9561(ah)) {
u32 regval, pll2_divint, pll2_divfrac, refdiv;
REG_WRITE(ah, AR_RTC_PLL_CONTROL,
@ -790,7 +794,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
udelay(100);
if (ah->is_clk_25mhz) {
if (AR_SREV_9531(ah)) {
if (AR_SREV_9531(ah) || AR_SREV_9561(ah)) {
pll2_divint = 0x1c;
pll2_divfrac = 0xa3d2;
refdiv = 1;
@ -806,14 +810,15 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
refdiv = 5;
} else {
pll2_divint = 0x11;
pll2_divfrac =
AR_SREV_9531(ah) ? 0x26665 : 0x26666;
pll2_divfrac = (AR_SREV_9531(ah) ||
AR_SREV_9561(ah)) ?
0x26665 : 0x26666;
refdiv = 1;
}
}
regval = REG_READ(ah, AR_PHY_PLL_MODE);
if (AR_SREV_9531(ah))
if (AR_SREV_9531(ah) || AR_SREV_9561(ah))
regval |= (0x1 << 22);
else
regval |= (0x1 << 16);
@ -831,14 +836,16 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
(0x1 << 13) |
(0x4 << 26) |
(0x18 << 19);
else if (AR_SREV_9531(ah))
else if (AR_SREV_9531(ah) || AR_SREV_9561(ah)) {
regval = (regval & 0x01c00fff) |
(0x1 << 31) |
(0x2 << 29) |
(0xa << 25) |
(0x1 << 19) |
(0x6 << 12);
else
(0x1 << 19);
if (AR_SREV_9531(ah))
regval |= (0x6 << 12);
} else
regval = (regval & 0x80071fff) |
(0x3 << 30) |
(0x1 << 13) |
@ -846,7 +853,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
(0x60 << 19);
REG_WRITE(ah, AR_PHY_PLL_MODE, regval);
if (AR_SREV_9531(ah))
if (AR_SREV_9531(ah) || AR_SREV_9561(ah))
REG_WRITE(ah, AR_PHY_PLL_MODE,
REG_READ(ah, AR_PHY_PLL_MODE) & 0xffbfffff);
else
@ -885,7 +892,8 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
AR_IMR_RXORN |
AR_IMR_BCNMISC;
if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah))
if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
AR_SREV_9561(ah))
sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
if (AR_SREV_9300_20_OR_LATER(ah)) {
@ -1674,7 +1682,8 @@ static void ath9k_hw_init_desc(struct ath_hw *ah)
}
#ifdef __BIG_ENDIAN
else if (AR_SREV_9330(ah) || AR_SREV_9340(ah) ||
AR_SREV_9550(ah) || AR_SREV_9531(ah))
AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
AR_SREV_9561(ah))
REG_RMW(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB, 0);
else
REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD);
@ -2462,7 +2471,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
if (AR_SREV_9300_20_OR_LATER(ah)) {
pCap->hw_caps |= ATH9K_HW_CAP_EDMA | ATH9K_HW_CAP_FASTCLOCK;
if (!AR_SREV_9330(ah) && !AR_SREV_9485(ah) && !AR_SREV_9565(ah))
if (!AR_SREV_9330(ah) && !AR_SREV_9485(ah) &&
!AR_SREV_9561(ah) && !AR_SREV_9565(ah))
pCap->hw_caps |= ATH9K_HW_CAP_LDPC;
pCap->rx_hp_qdepth = ATH9K_HW_RX_HP_QDEPTH;
@ -2479,7 +2489,9 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
if (AR_SREV_9300_20_OR_LATER(ah))
pCap->hw_caps |= ATH9K_HW_CAP_RAC_SUPPORTED;
if (AR_SREV_9300_20_OR_LATER(ah))
if (AR_SREV_9561(ah))
ah->ent_mode = 0x3BDA000;
else if (AR_SREV_9300_20_OR_LATER(ah))
ah->ent_mode = REG_READ(ah, AR_ENT_OTP);
if (AR_SREV_9287_11_OR_LATER(ah) || AR_SREV_9271(ah))

View file

@ -54,6 +54,7 @@
#define AR9485_DEVID_AR1111 0x0037
#define AR9300_DEVID_AR9565 0x0036
#define AR9300_DEVID_AR953X 0x003d
#define AR9300_DEVID_QCA956X 0x003f
#define AR5416_AR9100_DEVID 0x000b
@ -1086,6 +1087,8 @@ bool ar9003_is_paprd_enabled(struct ath_hw *ah);
void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
void ar9003_hw_init_rate_txpower(struct ath_hw *ah, u8 *rate_array,
struct ath9k_channel *chan);
void ar5008_hw_init_rate_txpower(struct ath_hw *ah, int16_t *rate_array,
struct ath9k_channel *chan, int ht40_delta);
/* Hardware family op attach helpers */
int ar5008_hw_attach_phy_ops(struct ath_hw *ah);

View file

@ -820,7 +820,8 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah)
return;
}
if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah))
if (AR_SREV_9340(ah) || AR_SREV_9550(ah) || AR_SREV_9531(ah) ||
AR_SREV_9561(ah))
sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
async_mask = AR_INTR_MAC_IRQ;

View file

@ -424,6 +424,11 @@ static const struct pci_device_id ath_pci_id_table[] = {
0x11AD, /* LITEON */
0x0842),
.driver_data = ATH9K_PCI_AR9565_1ANT },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
0x11AD, /* LITEON */
0x1842),
.driver_data = ATH9K_PCI_AR9565_1ANT },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
0x11AD, /* LITEON */
@ -444,11 +449,21 @@ static const struct pci_device_id ath_pci_id_table[] = {
0x1B9A, /* XAVI */
0x28A1),
.driver_data = ATH9K_PCI_AR9565_1ANT },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
0x1B9A, /* XAVI */
0x28A3),
.driver_data = ATH9K_PCI_AR9565_1ANT },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
PCI_VENDOR_ID_AZWAVE,
0x218A),
.driver_data = ATH9K_PCI_AR9565_1ANT },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
PCI_VENDOR_ID_AZWAVE,
0x2F8A),
.driver_data = ATH9K_PCI_AR9565_1ANT },
/* WB335 1-ANT / Antenna Diversity */
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
@ -506,6 +521,11 @@ static const struct pci_device_id ath_pci_id_table[] = {
PCI_VENDOR_ID_AZWAVE,
0x213A),
.driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
PCI_VENDOR_ID_AZWAVE,
0x213C),
.driver_data = ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
PCI_VENDOR_ID_HP,
@ -553,6 +573,16 @@ static const struct pci_device_id ath_pci_id_table[] = {
PCI_VENDOR_ID_SAMSUNG,
0x411E),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
PCI_VENDOR_ID_SAMSUNG,
0x4129),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
PCI_VENDOR_ID_SAMSUNG,
0x412A),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
PCI_VENDOR_ID_ATHEROS,
@ -583,11 +613,26 @@ static const struct pci_device_id ath_pci_id_table[] = {
0x11AD, /* LITEON */
0x0832),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
0x11AD, /* LITEON */
0x1832),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
0x11AD, /* LITEON */
0x0692),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
0x11AD, /* LITEON */
0x0803),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
0x11AD, /* LITEON */
0x0813),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
PCI_VENDOR_ID_AZWAVE,
@ -603,6 +648,21 @@ static const struct pci_device_id ath_pci_id_table[] = {
PCI_VENDOR_ID_AZWAVE,
0x2182),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
PCI_VENDOR_ID_AZWAVE,
0x218B),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
PCI_VENDOR_ID_AZWAVE,
0x218C),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
PCI_VENDOR_ID_AZWAVE,
0x2F82),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
0x144F, /* ASKEY */
@ -613,11 +673,21 @@ static const struct pci_device_id ath_pci_id_table[] = {
0x1B9A, /* XAVI */
0x2810),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
0x1B9A, /* XAVI */
0x2813),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
0x1B9A, /* XAVI */
0x28A2),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
0x1B9A, /* XAVI */
0x28A4),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
0x185F, /* WNC */
@ -633,11 +703,26 @@ static const struct pci_device_id ath_pci_id_table[] = {
PCI_VENDOR_ID_FOXCONN,
0xE07F),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
PCI_VENDOR_ID_FOXCONN,
0xE08F),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
PCI_VENDOR_ID_FOXCONN,
0xE081),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
PCI_VENDOR_ID_FOXCONN,
0xE091),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
PCI_VENDOR_ID_FOXCONN,
0xE099),
.driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0036,
PCI_VENDOR_ID_LENOVO,

View file

@ -425,7 +425,8 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL;
}
if (AR_SREV_9550(sc->sc_ah) || AR_SREV_9531(sc->sc_ah))
if (AR_SREV_9550(sc->sc_ah) || AR_SREV_9531(sc->sc_ah) ||
AR_SREV_9561(sc->sc_ah))
rfilt |= ATH9K_RX_FILTER_4ADDRESS;
if (ath9k_is_chanctx_enabled() &&

View file

@ -814,6 +814,7 @@
#define AR_SREV_REVISION_9531_10 0
#define AR_SREV_REVISION_9531_11 1
#define AR_SREV_REVISION_9531_20 2
#define AR_SREV_VERSION_9561 0x600
#define AR_SREV_5416(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
@ -974,6 +975,9 @@
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9531) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9531_20))
#define AR_SREV_9561(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9561))
/* NOTE: When adding chips newer than Peacock, add chip check here */
#define AR_SREV_9580_10_OR_LATER(_ah) \
(AR_SREV_9580(_ah))

View file

@ -1097,24 +1097,65 @@ void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop)
}
static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf,
u8 rateidx)
u8 rateidx, bool is_40, bool is_cck)
{
u8 max_power;
struct sk_buff *skb;
struct ath_frame_info *fi;
struct ieee80211_tx_info *info;
struct ath_hw *ah = sc->sc_ah;
if (sc->tx99_state)
if (sc->tx99_state || !ah->tpc_enabled)
return MAX_RATE_POWER;
skb = bf->bf_mpdu;
fi = get_frame_info(skb);
info = IEEE80211_SKB_CB(skb);
if (!AR_SREV_9300_20_OR_LATER(ah)) {
/* ar9002 does not support TPC for the moment */
return MAX_RATE_POWER;
}
int txpower = fi->tx_power;
if (!bf->bf_state.bfs_paprd) {
struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ath_frame_info *fi = get_frame_info(skb);
if (is_40) {
u8 power_ht40delta;
struct ar5416_eeprom_def *eep = &ah->eeprom.def;
if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) {
bool is_2ghz;
struct modal_eep_header *pmodal;
is_2ghz = info->band == IEEE80211_BAND_2GHZ;
pmodal = &eep->modalHeader[is_2ghz];
power_ht40delta = pmodal->ht40PowerIncForPdadc;
} else {
power_ht40delta = 2;
}
txpower += power_ht40delta;
}
if (AR_SREV_9287(ah) || AR_SREV_9285(ah) ||
AR_SREV_9271(ah)) {
txpower -= 2 * AR9287_PWR_TABLE_OFFSET_DB;
} else if (AR_SREV_9280_20_OR_LATER(ah)) {
s8 power_offset;
power_offset = ah->eep_ops->get_eeprom(ah,
EEP_PWR_TABLE_OFFSET);
txpower -= 2 * power_offset;
}
if (OLC_FOR_AR9280_20_LATER && is_cck)
txpower -= 2;
txpower = max(txpower, 0);
max_power = min_t(u8, ah->tx_power[rateidx], txpower);
/* XXX: clamp minimum TX power at 1 for AR9160 since if
* max_power is set to 0, frames are transmitted at max
* TX power
*/
if (!max_power && !AR_SREV_9280_20_OR_LATER(ah))
max_power = 1;
} else if (!bf->bf_state.bfs_paprd) {
if (rateidx < 8 && (info->flags & IEEE80211_TX_CTL_STBC))
max_power = min(ah->tx_power_stbc[rateidx],
fi->tx_power);
@ -1152,7 +1193,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
info->rtscts_rate = fi->rtscts_rate;
for (i = 0; i < ARRAY_SIZE(bf->rates); i++) {
bool is_40, is_sgi, is_sp;
bool is_40, is_sgi, is_sp, is_cck;
int phy;
if (!rates[i].count || (rates[i].idx < 0))
@ -1198,7 +1239,8 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC;
info->txpower[i] = ath_get_rate_txpower(sc, bf, rix);
info->txpower[i] = ath_get_rate_txpower(sc, bf, rix,
is_40, false);
continue;
}
@ -1227,7 +1269,9 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
phy, rate->bitrate * 100, len, rix, is_sp);
info->txpower[i] = ath_get_rate_txpower(sc, bf, rix);
is_cck = IS_CCK_RATE(info->rates[i].Rate);
info->txpower[i] = ath_get_rate_txpower(sc, bf, rix, false,
is_cck);
}
/* For AR5416 - RTS cannot be followed by a frame larger than 8K */
@ -2445,9 +2489,12 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
if (sc->sc_ah->caldata)
set_bit(PAPRD_PACKET_SENT, &sc->sc_ah->caldata->cal_flags);
if (!(tx_flags & ATH_TX_ERROR))
/* Frame was ACKed */
tx_info->flags |= IEEE80211_TX_STAT_ACK;
if (!(tx_flags & ATH_TX_ERROR)) {
if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
tx_info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
else
tx_info->flags |= IEEE80211_TX_STAT_ACK;
}
padpos = ieee80211_hdrlen(hdr->frame_control);
padsize = padpos & 3;

View file

@ -84,6 +84,7 @@ static int wcn36xx_dxe_allocate_ctl_block(struct wcn36xx_dxe_ch *ch)
if (!cur_ctl)
goto out_fail;
spin_lock_init(&cur_ctl->skb_lock);
cur_ctl->ctl_blk_order = i;
if (i == 0) {
ch->head_blk_ctl = cur_ctl;
@ -354,6 +355,8 @@ static void reap_tx_dxes(struct wcn36xx *wcn, struct wcn36xx_dxe_ch *ch)
* and while-do will not make any cycles.
*/
do {
if (ctl->desc->ctrl & WCN36XX_DXE_CTRL_VALID_MASK)
break;
if (ctl->skb) {
dma_unmap_single(NULL, ctl->desc->src_addr_l,
ctl->skb->len, DMA_TO_DEVICE);

View file

@ -298,6 +298,8 @@ static int wcn36xx_start(struct ieee80211_hw *hw)
wcn36xx_debugfs_init(wcn);
INIT_LIST_HEAD(&wcn->vif_list);
spin_lock_init(&wcn->dxe_lock);
return 0;
out_smd_stop:
@ -795,6 +797,7 @@ static int wcn36xx_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
wcn36xx_dbg(WCN36XX_DBG_MAC, "mac sta add vif %p sta %pM\n",
vif, sta->addr);
spin_lock_init(&sta_priv->ampdu_lock);
vif_priv->sta = sta_priv;
sta_priv->vif = vif_priv;
/*
@ -873,21 +876,32 @@ static int wcn36xx_ampdu_action(struct ieee80211_hw *hw,
get_sta_index(vif, sta_priv));
wcn36xx_smd_add_ba(wcn);
wcn36xx_smd_trigger_ba(wcn, get_sta_index(vif, sta_priv));
ieee80211_start_tx_ba_session(sta, tid, 0);
break;
case IEEE80211_AMPDU_RX_STOP:
wcn36xx_smd_del_ba(wcn, tid, get_sta_index(vif, sta_priv));
break;
case IEEE80211_AMPDU_TX_START:
spin_lock_bh(&sta_priv->ampdu_lock);
sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START;
spin_unlock_bh(&sta_priv->ampdu_lock);
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_OPERATIONAL:
spin_lock_bh(&sta_priv->ampdu_lock);
sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_OPERATIONAL;
spin_unlock_bh(&sta_priv->ampdu_lock);
wcn36xx_smd_add_ba_session(wcn, sta, tid, ssn, 1,
get_sta_index(vif, sta_priv));
break;
case IEEE80211_AMPDU_TX_STOP_FLUSH:
case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
case IEEE80211_AMPDU_TX_STOP_CONT:
spin_lock_bh(&sta_priv->ampdu_lock);
sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_NONE;
spin_unlock_bh(&sta_priv->ampdu_lock);
ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
break;
default:

View file

@ -21,6 +21,61 @@
#include <linux/bitops.h>
#include "smd.h"
struct wcn36xx_cfg_val {
u32 cfg_id;
u32 value;
};
#define WCN36XX_CFG_VAL(id, val) \
{ \
.cfg_id = WCN36XX_HAL_CFG_ ## id, \
.value = val \
}
static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = {
WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1),
WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1),
WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE, 0),
WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN, 785),
WCN36XX_CFG_VAL(CAL_PERIOD, 5),
WCN36XX_CFG_VAL(CAL_CONTROL, 1),
WCN36XX_CFG_VAL(PROXIMITY, 0),
WCN36XX_CFG_VAL(NETWORK_DENSITY, 3),
WCN36XX_CFG_VAL(MAX_MEDIUM_TIME, 6000),
WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU, 64),
WCN36XX_CFG_VAL(RTS_THRESHOLD, 2347),
WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 6),
WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 6),
WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD, 8000),
WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO, 5),
WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE, 10),
WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO, 15),
WCN36XX_CFG_VAL(FIXED_RATE, 0),
WCN36XX_CFG_VAL(RETRYRATE_POLICY, 4),
WCN36XX_CFG_VAL(RETRYRATE_SECONDARY, 0),
WCN36XX_CFG_VAL(RETRYRATE_TERTIARY, 0),
WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION, 5),
WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ, 1),
WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ, 5),
WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ, 5),
WCN36XX_CFG_VAL(MAX_BA_SESSIONS, 40),
WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT, 200),
WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER, 1),
WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR, 1),
WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE, 20),
WCN36XX_CFG_VAL(STATS_PERIOD, 10),
WCN36XX_CFG_VAL(CFP_MAX_DURATION, 30000),
WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED, 0),
WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH, 128),
WCN36XX_CFG_VAL(MAX_BA_BUFFERS, 2560),
WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0),
WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1),
WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1),
WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),
WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
};
static int put_cfg_tlv_u32(struct wcn36xx *wcn, size_t *len, u32 id, u32 value)
{
struct wcn36xx_hal_cfg *entry;
@ -357,8 +412,10 @@ static int wcn36xx_smd_start_rsp(struct wcn36xx *wcn, void *buf, size_t len)
int wcn36xx_smd_start(struct wcn36xx *wcn)
{
struct wcn36xx_hal_mac_start_req_msg msg_body;
struct wcn36xx_hal_mac_start_req_msg msg_body, *body;
int ret = 0;
int i;
size_t len;
mutex_lock(&wcn->hal_mutex);
INIT_HAL_MSG(msg_body, WCN36XX_HAL_START_REQ);
@ -368,10 +425,22 @@ int wcn36xx_smd_start(struct wcn36xx *wcn)
PREPARE_HAL_BUF(wcn->hal_buf, msg_body);
body = (struct wcn36xx_hal_mac_start_req_msg *)wcn->hal_buf;
len = body->header.len;
for (i = 0; i < ARRAY_SIZE(wcn36xx_cfg_vals); i++) {
ret = put_cfg_tlv_u32(wcn, &len, wcn36xx_cfg_vals[i].cfg_id,
wcn36xx_cfg_vals[i].value);
if (ret)
goto out;
}
body->header.len = len;
body->params.len = len - sizeof(*body);
wcn36xx_dbg(WCN36XX_DBG_HAL, "hal start type %d\n",
msg_body.params.type);
ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len);
ret = wcn36xx_smd_send_and_wait(wcn, body->header.len);
if (ret) {
wcn36xx_err("Sending hal_start failed\n");
goto out;

View file

@ -93,6 +93,7 @@ static void wcn36xx_set_tx_pdu(struct wcn36xx_tx_bd *bd,
bd->pdu.mpdu_header_off;
bd->pdu.mpdu_len = len;
bd->pdu.tid = tid;
bd->pdu.bd_ssn = WCN36XX_TXBD_SSN_FILL_DPU_QOS;
}
static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn,
@ -110,15 +111,54 @@ static inline struct wcn36xx_vif *get_vif_by_addr(struct wcn36xx *wcn,
wcn36xx_warn("vif %pM not found\n", addr);
return NULL;
}
static void wcn36xx_tx_start_ampdu(struct wcn36xx *wcn,
struct wcn36xx_sta *sta_priv,
struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_sta *sta;
u8 *qc, tid;
if (!conf_is_ht(&wcn->hw->conf))
return;
sta = wcn36xx_priv_to_sta(sta_priv);
if (WARN_ON(!ieee80211_is_data_qos(hdr->frame_control)))
return;
if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
return;
qc = ieee80211_get_qos_ctl(hdr);
tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
spin_lock(&sta_priv->ampdu_lock);
if (sta_priv->ampdu_state[tid] != WCN36XX_AMPDU_NONE)
goto out_unlock;
if (sta_priv->non_agg_frame_ct++ >= WCN36XX_AMPDU_START_THRESH) {
sta_priv->ampdu_state[tid] = WCN36XX_AMPDU_START;
sta_priv->non_agg_frame_ct = 0;
ieee80211_start_tx_ba_session(sta, tid, 0);
}
out_unlock:
spin_unlock(&sta_priv->ampdu_lock);
}
static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd,
struct wcn36xx *wcn,
struct wcn36xx_vif **vif_priv,
struct wcn36xx_sta *sta_priv,
struct ieee80211_hdr *hdr,
struct sk_buff *skb,
bool bcast)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_vif *vif = NULL;
struct wcn36xx_vif *__vif_priv = NULL;
bool is_data_qos;
bd->bd_rate = WCN36XX_BD_RATE_DATA;
/*
@ -157,14 +197,26 @@ static void wcn36xx_set_tx_data(struct wcn36xx_tx_bd *bd,
bd->ack_policy = 1;
}
*vif_priv = __vif_priv;
is_data_qos = ieee80211_is_data_qos(hdr->frame_control);
wcn36xx_set_tx_pdu(bd,
is_data_qos ?
sizeof(struct ieee80211_qos_hdr) :
sizeof(struct ieee80211_hdr_3addr),
skb->len, sta_priv ? sta_priv->tid : 0);
if (sta_priv && is_data_qos)
wcn36xx_tx_start_ampdu(wcn, sta_priv, skb);
}
static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd,
struct wcn36xx *wcn,
struct wcn36xx_vif **vif_priv,
struct ieee80211_hdr *hdr,
struct sk_buff *skb,
bool bcast)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct wcn36xx_vif *__vif_priv =
get_vif_by_addr(wcn, hdr->addr2);
bd->sta_index = __vif_priv->self_sta_index;
@ -198,6 +250,12 @@ static void wcn36xx_set_tx_mgmt(struct wcn36xx_tx_bd *bd,
} else
bd->queue_id = WCN36XX_TX_U_WQ_ID;
*vif_priv = __vif_priv;
wcn36xx_set_tx_pdu(bd,
ieee80211_is_data_qos(hdr->frame_control) ?
sizeof(struct ieee80211_qos_hdr) :
sizeof(struct ieee80211_hdr_3addr),
skb->len, WCN36XX_TID);
}
int wcn36xx_start_tx(struct wcn36xx *wcn,
@ -237,7 +295,7 @@ int wcn36xx_start_tx(struct wcn36xx *wcn,
bd->dpu_rf = WCN36XX_BMU_WQ_TX;
bd->tx_comp = info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS;
bd->tx_comp = !!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS);
if (bd->tx_comp) {
wcn36xx_dbg(WCN36XX_DBG_DXE, "TX_ACK status requested\n");
spin_lock_irqsave(&wcn->dxe_lock, flags);
@ -259,22 +317,11 @@ int wcn36xx_start_tx(struct wcn36xx *wcn,
}
/* Data frames served first*/
if (is_low) {
wcn36xx_set_tx_data(bd, wcn, &vif_priv, sta_priv, hdr, bcast);
wcn36xx_set_tx_pdu(bd,
ieee80211_is_data_qos(hdr->frame_control) ?
sizeof(struct ieee80211_qos_hdr) :
sizeof(struct ieee80211_hdr_3addr),
skb->len, sta_priv ? sta_priv->tid : 0);
} else {
if (is_low)
wcn36xx_set_tx_data(bd, wcn, &vif_priv, sta_priv, skb, bcast);
else
/* MGMT and CTRL frames are handeld here*/
wcn36xx_set_tx_mgmt(bd, wcn, &vif_priv, hdr, bcast);
wcn36xx_set_tx_pdu(bd,
ieee80211_is_data_qos(hdr->frame_control) ?
sizeof(struct ieee80211_qos_hdr) :
sizeof(struct ieee80211_hdr_3addr),
skb->len, WCN36XX_TID);
}
wcn36xx_set_tx_mgmt(bd, wcn, &vif_priv, skb, bcast);
buff_to_be((u32 *)bd, sizeof(*bd)/sizeof(u32));
bd->tx_bd_sign = 0xbdbdbdbd;

View file

@ -32,6 +32,12 @@
#define WCN36XX_BD_RATE_MGMT 2
#define WCN36XX_BD_RATE_CTRL 3
enum wcn36xx_txbd_ssn_type {
WCN36XX_TXBD_SSN_FILL_HOST = 0,
WCN36XX_TXBD_SSN_FILL_DPU_NON_QOS = 1,
WCN36XX_TXBD_SSN_FILL_DPU_QOS = 2,
};
struct wcn36xx_pdu {
u32 dpu_fb:8;
u32 adu_fb:8;
@ -50,7 +56,8 @@ struct wcn36xx_pdu {
/* 0x0c*/
u32 reserved4:8;
u32 tid:4;
u32 reserved3:4;
u32 bd_ssn:2;
u32 reserved3:2;
u32 mpdu_len:16;
};

View file

@ -32,6 +32,9 @@
#define WLAN_NV_FILE "wlan/prima/WCNSS_qcom_wlan_nv.bin"
#define WCN36XX_AGGR_BUFFER_SIZE 64
/* How many frames until we start a-mpdu TX session */
#define WCN36XX_AMPDU_START_THRESH 20
extern unsigned int wcn36xx_dbg_mask;
enum wcn36xx_debug_mask {
@ -74,6 +77,13 @@ enum wcn36xx_debug_mask {
buf, len, false); \
} while (0)
enum wcn36xx_ampdu_state {
WCN36XX_AMPDU_NONE,
WCN36XX_AMPDU_INIT,
WCN36XX_AMPDU_START,
WCN36XX_AMPDU_OPERATIONAL,
};
#define WCN36XX_HW_CHANNEL(__wcn) (__wcn->hw->conf.chandef.chan->hw_value)
#define WCN36XX_BAND(__wcn) (__wcn->hw->conf.chandef.chan->band)
#define WCN36XX_CENTER_FREQ(__wcn) (__wcn->hw->conf.chandef.chan->center_freq)
@ -165,6 +175,10 @@ struct wcn36xx_sta {
bool is_data_encrypted;
/* Rates */
struct wcn36xx_hal_supported_rates supported_rates;
spinlock_t ampdu_lock; /* protects next two fields */
enum wcn36xx_ampdu_state ampdu_state[16];
int non_agg_frame_ct;
};
struct wcn36xx_dxe_ch;
struct wcn36xx {
@ -243,4 +257,10 @@ static inline bool wcn36xx_is_fw_version(struct wcn36xx *wcn,
}
void wcn36xx_set_default_rates(struct wcn36xx_hal_supported_rates *rates);
static inline
struct ieee80211_sta *wcn36xx_priv_to_sta(struct wcn36xx_sta *sta_priv)
{
return container_of((void *)sta_priv, struct ieee80211_sta, drv_priv);
}
#endif /* _WCN36XX_H_ */

View file

@ -162,7 +162,7 @@ int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
sinfo->tx_packets = stats->tx_packets;
sinfo->tx_failed = stats->tx_errors;
if (test_bit(wil_status_fwconnected, &wil->status)) {
if (test_bit(wil_status_fwconnected, wil->status)) {
sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
sinfo->signal = reply.evt.sqi;
}
@ -282,7 +282,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
}
/* FW don't support scan after connection attempt */
if (test_bit(wil_status_dontscan, &wil->status)) {
if (test_bit(wil_status_dontscan, wil->status)) {
wil_err(wil, "Can't scan now\n");
return -EBUSY;
}
@ -362,8 +362,8 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
int ch;
int rc = 0;
if (test_bit(wil_status_fwconnecting, &wil->status) ||
test_bit(wil_status_fwconnected, &wil->status))
if (test_bit(wil_status_fwconnecting, wil->status) ||
test_bit(wil_status_fwconnected, wil->status))
return -EALREADY;
wil_print_connect_params(wil, sme);
@ -450,7 +450,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
memcpy(conn.bssid, bss->bssid, ETH_ALEN);
memcpy(conn.dst_mac, bss->bssid, ETH_ALEN);
set_bit(wil_status_fwconnecting, &wil->status);
set_bit(wil_status_fwconnecting, wil->status);
rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn));
if (rc == 0) {
@ -458,7 +458,7 @@ static int wil_cfg80211_connect(struct wiphy *wiphy,
mod_timer(&wil->connect_timer,
jiffies + msecs_to_jiffies(2000));
} else {
clear_bit(wil_status_fwconnecting, &wil->status);
clear_bit(wil_status_fwconnecting, wil->status);
}
out:

View file

@ -50,6 +50,7 @@ static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil,
char _s, char _h)
{
void __iomem *x = wmi_addr(wil, vring->hwtail);
u32 v;
seq_printf(s, "VRING %s = {\n", name);
seq_printf(s, " pa = %pad\n", &vring->pa);
@ -58,10 +59,12 @@ static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil,
seq_printf(s, " swtail = %d\n", vring->swtail);
seq_printf(s, " swhead = %d\n", vring->swhead);
seq_printf(s, " hwtail = [0x%08x] -> ", vring->hwtail);
if (x)
seq_printf(s, "0x%08x\n", ioread32(x));
else
if (x) {
v = ioread32(x);
seq_printf(s, "0x%08x = %d\n", v, v);
} else {
seq_puts(s, "???\n");
}
if (vring->va && (vring->size < 1025)) {
uint i;
@ -101,8 +104,8 @@ static int wil_vring_debugfs_show(struct seq_file *s, void *data)
char name[10];
/* performance monitoring */
cycles_t now = get_cycles();
cycles_t idle = txdata->idle * 100;
cycles_t total = now - txdata->begin;
uint64_t idle = txdata->idle * 100;
uint64_t total = now - txdata->begin;
do_div(idle, total);
txdata->begin = now;
@ -110,9 +113,12 @@ static int wil_vring_debugfs_show(struct seq_file *s, void *data)
snprintf(name, sizeof(name), "tx_%2d", i);
seq_printf(s, "\n%pM CID %d TID %d [%3d|%3d] idle %3d%%\n",
wil->sta[cid].addr, cid, tid, used, avail,
(int)idle);
seq_printf(s,
"\n%pM CID %d TID %d BACK([%d] %d TU A%s) [%3d|%3d] idle %3d%%\n",
wil->sta[cid].addr, cid, tid,
txdata->agg_wsize, txdata->agg_timeout,
txdata->agg_amsdu ? "+" : "-",
used, avail, (int)idle);
wil_print_vring(s, wil, name, vring, '_', 'H');
}
@ -384,24 +390,67 @@ static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil,
return 0;
}
static const struct dbg_off itr_cnt_off[] = {
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},
{},
};
static const struct dbg_off tx_itr_cnt_off[] = {
{"TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_CNT_TRSH),
doff_io32},
{"DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_CNT_DATA),
doff_io32},
{"CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_CNT_CTL),
doff_io32},
{"IDL_TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_TRSH),
doff_io32},
{"IDL_DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_TX_IDL_CNT_DATA),
doff_io32},
{"IDL_CTL", S_IRUGO | S_IWUSR, 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),
doff_io32},
{"DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_CNT_DATA),
doff_io32},
{"CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_CNT_CTL),
doff_io32},
{"IDL_TRSH", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_TRSH),
doff_io32},
{"IDL_DATA", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_DATA),
doff_io32},
{"IDL_CTL", S_IRUGO | S_IWUSR, HOSTADDR(RGF_DMA_ITR_RX_IDL_CNT_CTL),
doff_io32},
{},
};
static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil,
struct dentry *parent)
{
struct dentry *d = debugfs_create_dir("ITR_CNT", parent);
struct dentry *d, *dtx, *drx;
d = debugfs_create_dir("ITR_CNT", parent);
if (IS_ERR_OR_NULL(d))
return -ENODEV;
wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr,
itr_cnt_off);
dtx = debugfs_create_dir("TX", d);
drx = debugfs_create_dir("RX", d);
if (IS_ERR_OR_NULL(dtx) || IS_ERR_OR_NULL(drx))
return -ENODEV;
wil6210_debugfs_init_offset(wil, d, (void * __force)wil->csr,
lgc_itr_cnt_off);
wil6210_debugfs_init_offset(wil, dtx, (void * __force)wil->csr,
tx_itr_cnt_off);
wil6210_debugfs_init_offset(wil, drx, (void * __force)wil->csr,
rx_itr_cnt_off);
return 0;
}
@ -558,6 +607,87 @@ static const struct file_operations fops_rxon = {
.open = simple_open,
};
/* block ack control, write:
* - "add <ringid> <agg_size> <timeout>" to trigger ADDBA
* - "del_tx <ringid> <reason>" to trigger DELBA for Tx side
* - "del_rx <CID> <TID> <reason>" to trigger DELBA for Rx side
*/
static ssize_t wil_write_back(struct file *file, const char __user *buf,
size_t len, loff_t *ppos)
{
struct wil6210_priv *wil = file->private_data;
int rc;
char *kbuf = kmalloc(len + 1, GFP_KERNEL);
char cmd[8];
int p1, p2, p3;
if (!kbuf)
return -ENOMEM;
rc = simple_write_to_buffer(kbuf, len, ppos, buf, len);
if (rc != len) {
kfree(kbuf);
return rc >= 0 ? -EIO : rc;
}
kbuf[len] = '\0';
rc = sscanf(kbuf, "%8s %d %d %d", cmd, &p1, &p2, &p3);
kfree(kbuf);
if (rc < 0)
return rc;
if (rc < 2)
return -EINVAL;
if (0 == strcmp(cmd, "add")) {
if (rc < 3) {
wil_err(wil, "BACK: add require at least 2 params\n");
return -EINVAL;
}
if (rc < 4)
p3 = 0;
wmi_addba(wil, p1, p2, p3);
} else if (0 == strcmp(cmd, "del_tx")) {
if (rc < 3)
p2 = WLAN_REASON_QSTA_LEAVE_QBSS;
wmi_delba_tx(wil, p1, p2);
} else if (0 == strcmp(cmd, "del_rx")) {
if (rc < 3) {
wil_err(wil,
"BACK: del_rx require at least 2 params\n");
return -EINVAL;
}
if (rc < 4)
p3 = WLAN_REASON_QSTA_LEAVE_QBSS;
wmi_delba_rx(wil, mk_cidxtid(p1, p2), p3);
} else {
wil_err(wil, "BACK: Unrecognized command \"%s\"\n", cmd);
return -EINVAL;
}
return len;
}
static ssize_t wil_read_back(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
static const char text[] = "block ack control, write:\n"
" - \"add <ringid> <agg_size> <timeout>\" to trigger ADDBA\n"
"If missing, <timeout> defaults to 0\n"
" - \"del_tx <ringid> <reason>\" to trigger DELBA for Tx side\n"
" - \"del_rx <CID> <TID> <reason>\" to trigger DELBA for Rx side\n"
"If missing, <reason> set to \"STA_LEAVING\" (36)\n";
return simple_read_from_buffer(user_buf, count, ppos, text,
sizeof(text));
}
static const struct file_operations fops_back = {
.read = wil_read_back,
.write = wil_write_back,
.open = simple_open,
};
/*---tx_mgmt---*/
/* Write mgmt frame to this file to send it */
static ssize_t wil_write_file_txmgmt(struct file *file, const char __user *buf,
@ -1116,7 +1246,8 @@ static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r)
int i;
u16 index = ((r->head_seq_num - r->ssn) & 0xfff) % r->buf_size;
seq_printf(s, "0x%03x [", r->head_seq_num);
seq_printf(s, "([%2d] %3d TU) 0x%03x [", r->buf_size, r->timeout,
r->head_seq_num);
for (i = 0; i < r->buf_size; i++) {
if (i == index)
seq_printf(s, "%c", r->reorder_buf[i] ? 'O' : '|');
@ -1127,10 +1258,10 @@ static void wil_print_rxtid(struct seq_file *s, struct wil_tid_ampdu_rx *r)
}
static int wil_sta_debugfs_show(struct seq_file *s, void *data)
__acquires(&p->tid_rx_lock) __releases(&p->tid_rx_lock)
{
struct wil6210_priv *wil = s->private;
int i, tid;
unsigned long flags;
for (i = 0; i < ARRAY_SIZE(wil->sta); i++) {
struct wil_sta_info *p = &wil->sta[i];
@ -1151,7 +1282,7 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data)
(p->data_port_open ? " data_port_open" : ""));
if (p->status == wil_sta_connected) {
spin_lock_irqsave(&p->tid_rx_lock, flags);
spin_lock_bh(&p->tid_rx_lock);
for (tid = 0; tid < WIL_STA_TID_NUM; tid++) {
struct wil_tid_ampdu_rx *r = p->tid_rx[tid];
@ -1160,7 +1291,7 @@ static int wil_sta_debugfs_show(struct seq_file *s, void *data)
wil_print_rxtid(s, r);
}
}
spin_unlock_irqrestore(&p->tid_rx_lock, flags);
spin_unlock_bh(&p->tid_rx_lock);
}
}
@ -1217,6 +1348,7 @@ static const struct {
{"rxon", S_IWUSR, &fops_rxon},
{"tx_mgmt", S_IWUSR, &fops_txmgmt},
{"wmi_send", S_IWUSR, &fops_wmi},
{"back", S_IRUGO | S_IWUSR, &fops_back},
{"temp", S_IRUGO, &fops_temp},
{"freq", S_IRUGO, &fops_freq},
{"link", S_IRUGO, &fops_link},
@ -1261,7 +1393,7 @@ 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(secure_pcp, S_IRUGO | S_IWUSR, doff_u32),
WIL_FIELD(status, S_IRUGO | S_IWUSR, doff_ulong),
WIL_FIELD(status[0], S_IRUGO | S_IWUSR, doff_ulong),
WIL_FIELD(fw_version, S_IRUGO, doff_u32),
WIL_FIELD(hw_version, S_IRUGO, doff_x32),
WIL_FIELD(recovery_count, S_IRUGO, doff_u32),

View file

@ -45,16 +45,35 @@ static int wil_ethtoolops_get_coalesce(struct net_device *ndev,
struct ethtool_coalesce *cp)
{
struct wil6210_priv *wil = ndev_to_wil(ndev);
u32 itr_en, itr_val = 0;
u32 tx_itr_en, tx_itr_val = 0;
u32 rx_itr_en, rx_itr_val = 0;
wil_dbg_misc(wil, "%s()\n", __func__);
itr_en = ioread32(wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_CRL));
if (itr_en & BIT_DMA_ITR_CNT_CRL_EN)
itr_val = ioread32(wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_TRSH));
if (test_bit(hw_capability_advanced_itr_moderation,
wil->hw_capabilities)) {
tx_itr_en = ioread32(wil->csr +
HOSTADDR(RGF_DMA_ITR_TX_CNT_CTL));
if (tx_itr_en & BIT_DMA_ITR_TX_CNT_CTL_EN)
tx_itr_val =
ioread32(wil->csr +
HOSTADDR(RGF_DMA_ITR_TX_CNT_TRSH));
cp->rx_coalesce_usecs = itr_val;
rx_itr_en = ioread32(wil->csr +
HOSTADDR(RGF_DMA_ITR_RX_CNT_CTL));
if (rx_itr_en & BIT_DMA_ITR_RX_CNT_CTL_EN)
rx_itr_val =
ioread32(wil->csr +
HOSTADDR(RGF_DMA_ITR_RX_CNT_TRSH));
} else {
rx_itr_en = ioread32(wil->csr + HOSTADDR(RGF_DMA_ITR_CNT_CRL));
if (rx_itr_en & BIT_DMA_ITR_CNT_CRL_EN)
rx_itr_val = ioread32(wil->csr +
HOSTADDR(RGF_DMA_ITR_CNT_TRSH));
}
cp->tx_coalesce_usecs = tx_itr_val;
cp->rx_coalesce_usecs = rx_itr_val;
return 0;
}
@ -63,22 +82,25 @@ static int wil_ethtoolops_set_coalesce(struct net_device *ndev,
{
struct wil6210_priv *wil = ndev_to_wil(ndev);
wil_dbg_misc(wil, "%s(%d usec)\n", __func__, cp->rx_coalesce_usecs);
wil_dbg_misc(wil, "%s(rx %d usec, tx %d usec)\n", __func__,
cp->rx_coalesce_usecs, cp->tx_coalesce_usecs);
if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) {
wil_dbg_misc(wil, "No IRQ coalescing in monitor mode\n");
return -EINVAL;
}
/* only @rx_coalesce_usecs supported, ignore
* other parameters
/* only @rx_coalesce_usecs and @tx_coalesce_usecs supported,
* ignore other parameters
*/
if (cp->rx_coalesce_usecs > WIL6210_ITR_TRSH_MAX)
if (cp->rx_coalesce_usecs > WIL6210_ITR_TRSH_MAX ||
cp->tx_coalesce_usecs > WIL6210_ITR_TRSH_MAX)
goto out_bad;
wil->itr_trsh = cp->rx_coalesce_usecs;
wil_set_itr_trsh(wil);
wil->tx_max_burst_duration = cp->tx_coalesce_usecs;
wil->rx_max_burst_duration = cp->rx_coalesce_usecs;
wil_configure_interrupt_moderation(wil);
return 0;

View file

@ -102,7 +102,7 @@ static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil)
iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW));
clear_bit(wil_status_irqen, &wil->status);
clear_bit(wil_status_irqen, wil->status);
}
void wil6210_unmask_irq_tx(struct wil6210_priv *wil)
@ -130,7 +130,7 @@ static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil)
{
wil_dbg_irq(wil, "%s()\n", __func__);
set_bit(wil_status_irqen, &wil->status);
set_bit(wil_status_irqen, wil->status);
iowrite32(WIL6210_IRQ_PSEUDO_MASK, wil->csr +
HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW));
@ -157,15 +157,91 @@ void wil_unmask_irq(struct wil6210_priv *wil)
iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) +
offsetof(struct RGF_ICR, ICC));
/* interrupt moderation parameters */
wil_set_itr_trsh(wil);
wil6210_unmask_irq_pseudo(wil);
wil6210_unmask_irq_tx(wil);
wil6210_unmask_irq_rx(wil);
wil6210_unmask_irq_misc(wil);
}
/* target write operation */
#define W(a, v) do { iowrite32(v, wil->csr + HOSTADDR(a)); wmb(); } while (0)
static
void wil_configure_interrupt_moderation_new(struct wil6210_priv *wil)
{
/* Disable and clear tx counter before (re)configuration */
W(RGF_DMA_ITR_TX_CNT_CTL, BIT_DMA_ITR_TX_CNT_CTL_CLR);
W(RGF_DMA_ITR_TX_CNT_TRSH, wil->tx_max_burst_duration);
wil_info(wil, "set ITR_TX_CNT_TRSH = %d usec\n",
wil->tx_max_burst_duration);
/* Configure TX max burst duration timer to use usec units */
W(RGF_DMA_ITR_TX_CNT_CTL,
BIT_DMA_ITR_TX_CNT_CTL_EN | BIT_DMA_ITR_TX_CNT_CTL_EXT_TIC_SEL);
/* Disable and clear tx idle counter before (re)configuration */
W(RGF_DMA_ITR_TX_IDL_CNT_CTL, BIT_DMA_ITR_TX_IDL_CNT_CTL_CLR);
W(RGF_DMA_ITR_TX_IDL_CNT_TRSH, wil->tx_interframe_timeout);
wil_info(wil, "set ITR_TX_IDL_CNT_TRSH = %d usec\n",
wil->tx_interframe_timeout);
/* Configure TX max burst duration timer to use usec units */
W(RGF_DMA_ITR_TX_IDL_CNT_CTL, BIT_DMA_ITR_TX_IDL_CNT_CTL_EN |
BIT_DMA_ITR_TX_IDL_CNT_CTL_EXT_TIC_SEL);
/* Disable and clear rx counter before (re)configuration */
W(RGF_DMA_ITR_RX_CNT_CTL, BIT_DMA_ITR_RX_CNT_CTL_CLR);
W(RGF_DMA_ITR_RX_CNT_TRSH, wil->rx_max_burst_duration);
wil_info(wil, "set ITR_RX_CNT_TRSH = %d usec\n",
wil->rx_max_burst_duration);
/* Configure TX max burst duration timer to use usec units */
W(RGF_DMA_ITR_RX_CNT_CTL,
BIT_DMA_ITR_RX_CNT_CTL_EN | BIT_DMA_ITR_RX_CNT_CTL_EXT_TIC_SEL);
/* Disable and clear rx idle counter before (re)configuration */
W(RGF_DMA_ITR_RX_IDL_CNT_CTL, BIT_DMA_ITR_RX_IDL_CNT_CTL_CLR);
W(RGF_DMA_ITR_RX_IDL_CNT_TRSH, wil->rx_interframe_timeout);
wil_info(wil, "set ITR_RX_IDL_CNT_TRSH = %d usec\n",
wil->rx_interframe_timeout);
/* Configure TX max burst duration timer to use usec units */
W(RGF_DMA_ITR_RX_IDL_CNT_CTL, BIT_DMA_ITR_RX_IDL_CNT_CTL_EN |
BIT_DMA_ITR_RX_IDL_CNT_CTL_EXT_TIC_SEL);
}
static
void wil_configure_interrupt_moderation_lgc(struct wil6210_priv *wil)
{
/* disable, use usec resolution */
W(RGF_DMA_ITR_CNT_CRL, BIT_DMA_ITR_CNT_CRL_CLR);
wil_info(wil, "set ITR_TRSH = %d usec\n", wil->rx_max_burst_duration);
W(RGF_DMA_ITR_CNT_TRSH, wil->rx_max_burst_duration);
/* start it */
W(RGF_DMA_ITR_CNT_CRL,
BIT_DMA_ITR_CNT_CRL_EN | BIT_DMA_ITR_CNT_CRL_EXT_TICK);
}
#undef W
void wil_configure_interrupt_moderation(struct wil6210_priv *wil)
{
wil_dbg_irq(wil, "%s()\n", __func__);
/* disable interrupt moderation for monitor
* to get better timestamp precision
*/
if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR)
return;
if (test_bit(hw_capability_advanced_itr_moderation,
wil->hw_capabilities))
wil_configure_interrupt_moderation_new(wil);
else {
/* Advanced interrupt moderation is not available before
* Sparrow v2. Will use legacy interrupt moderation
*/
wil_configure_interrupt_moderation_lgc(wil);
}
}
static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
{
struct wil6210_priv *wil = cookie;
@ -194,18 +270,19 @@ static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
wil_dbg_irq(wil, "RX done\n");
if (isr & BIT_DMA_EP_RX_ICR_RX_HTRSH)
wil_err_ratelimited(wil, "Received \"Rx buffer is in risk "
"of overflow\" interrupt\n");
wil_err_ratelimited(wil,
"Received \"Rx buffer is in risk of overflow\" interrupt\n");
isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH);
if (test_bit(wil_status_reset_done, &wil->status)) {
if (test_bit(wil_status_napi_en, &wil->status)) {
isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE |
BIT_DMA_EP_RX_ICR_RX_HTRSH);
if (test_bit(wil_status_reset_done, wil->status)) {
if (test_bit(wil_status_napi_en, wil->status)) {
wil_dbg_txrx(wil, "NAPI(Rx) schedule\n");
need_unmask = false;
napi_schedule(&wil->napi_rx);
} else {
wil_err(wil, "Got Rx interrupt while "
"stopping interface\n");
wil_err(wil,
"Got Rx interrupt while stopping interface\n");
}
} else {
wil_err(wil, "Got Rx interrupt while in reset\n");
@ -248,7 +325,7 @@ static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE;
/* clear also all VRING interrupts */
isr &= ~(BIT(25) - 1UL);
if (test_bit(wil_status_reset_done, &wil->status)) {
if (test_bit(wil_status_reset_done, wil->status)) {
wil_dbg_txrx(wil, "NAPI(Tx) schedule\n");
need_unmask = false;
napi_schedule(&wil->napi_tx);
@ -310,7 +387,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
if (isr & ISR_MISC_FW_ERROR) {
wil_err(wil, "Firmware error detected\n");
clear_bit(wil_status_fwready, &wil->status);
clear_bit(wil_status_fwready, wil->status);
/*
* do not clear @isr here - we do 2-nd part in thread
* there, user space get notified, and it should be done
@ -321,7 +398,7 @@ static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
if (isr & ISR_MISC_FW_READY) {
wil_dbg_irq(wil, "IRQ: FW ready\n");
wil_cache_mbox_regs(wil);
set_bit(wil_status_reset_done, &wil->status);
set_bit(wil_status_reset_done, wil->status);
/**
* Actual FW ready indicated by the
* WMI_FW_READY_EVENTID
@ -394,7 +471,7 @@ static irqreturn_t wil6210_thread_irq(int irq, void *cookie)
*/
static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause)
{
if (!test_bit(wil_status_irqen, &wil->status)) {
if (!test_bit(wil_status_irqen, wil->status)) {
u32 icm_rx = wil_ioread32_and_clear(wil->csr +
HOSTADDR(RGF_DMA_EP_RX_ICR) +
offsetof(struct RGF_ICR, ICM));

View file

@ -33,15 +33,46 @@ static bool no_fw_load = true;
module_param(no_fw_load, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(no_fw_load, " do not download FW, use one in on-card flash.");
static unsigned int itr_trsh = WIL6210_ITR_TRSH_DEFAULT;
static unsigned int tx_interframe_timeout =
WIL6210_ITR_TX_INTERFRAME_TIMEOUT_DEFAULT;
module_param(itr_trsh, uint, S_IRUGO);
MODULE_PARM_DESC(itr_trsh, " Interrupt moderation threshold, usecs.");
module_param(tx_interframe_timeout, uint, S_IRUGO);
MODULE_PARM_DESC(tx_interframe_timeout,
" Interrupt moderation TX interframe timeout, usecs.");
static unsigned int rx_interframe_timeout =
WIL6210_ITR_RX_INTERFRAME_TIMEOUT_DEFAULT;
module_param(rx_interframe_timeout, uint, S_IRUGO);
MODULE_PARM_DESC(rx_interframe_timeout,
" Interrupt moderation RX interframe timeout, usecs.");
static unsigned int tx_max_burst_duration =
WIL6210_ITR_TX_MAX_BURST_DURATION_DEFAULT;
module_param(tx_max_burst_duration, uint, S_IRUGO);
MODULE_PARM_DESC(tx_max_burst_duration,
" Interrupt moderation TX max burst duration, usecs.");
static unsigned int rx_max_burst_duration =
WIL6210_ITR_RX_MAX_BURST_DURATION_DEFAULT;
module_param(rx_max_burst_duration, uint, S_IRUGO);
MODULE_PARM_DESC(rx_max_burst_duration,
" Interrupt moderation RX max burst duration, usecs.");
/* 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_PARM_DESC(rx_ring_overflow_thrsh,
" RX ring overflow threshold in descriptors.");
/* We allow allocation of more than 1 page buffers to support large packets.
* It is suboptimal behavior performance wise in case MTU above page size.
*/
unsigned int mtu_max = TXRX_BUF_LEN_DEFAULT - ETH_HLEN;
unsigned int mtu_max = TXRX_BUF_LEN_DEFAULT - WIL_MAX_MPDU_OVERHEAD;
static int mtu_max_set(const char *val, const struct kernel_param *kp)
{
int ret;
@ -53,7 +84,7 @@ static int mtu_max_set(const char *val, const struct kernel_param *kp)
if (ret)
return ret;
if (mtu_max < 68 || mtu_max > IEEE80211_MAX_DATA_LEN_DMG)
if (mtu_max < 68 || mtu_max > WIL_MAX_ETH_MTU)
ret = -EINVAL;
return ret;
@ -135,12 +166,14 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
static void wil_disconnect_cid(struct wil6210_priv *wil, int cid,
u16 reason_code, bool from_event)
__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
{
uint i;
struct net_device *ndev = wil_to_ndev(wil);
struct wireless_dev *wdev = wil->wdev;
struct wil_sta_info *sta = &wil->sta[cid];
might_sleep();
wil_dbg_misc(wil, "%s(CID %d, status %d)\n", __func__, cid,
sta->status);
@ -163,15 +196,14 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid,
for (i = 0; i < WIL_STA_TID_NUM; i++) {
struct wil_tid_ampdu_rx *r;
unsigned long flags;
spin_lock_irqsave(&sta->tid_rx_lock, flags);
spin_lock_bh(&sta->tid_rx_lock);
r = sta->tid_rx[i];
sta->tid_rx[i] = NULL;
wil_tid_ampdu_rx_free(wil, r);
spin_unlock_irqrestore(&sta->tid_rx_lock, flags);
spin_unlock_bh(&sta->tid_rx_lock);
}
for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
if (wil->vring2cid_tid[i][0] == cid)
@ -188,34 +220,45 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
struct wireless_dev *wdev = wil->wdev;
might_sleep();
if (bssid) {
cid = wil_find_cid(wil, bssid);
wil_dbg_misc(wil, "%s(%pM, CID %d)\n", __func__, bssid, cid);
} else {
wil_dbg_misc(wil, "%s(all)\n", __func__);
}
wil_dbg_misc(wil, "%s(bssid=%pM, reason=%d, ev%s)\n", __func__, bssid,
reason_code, from_event ? "+" : "-");
if (cid >= 0) /* disconnect 1 peer */
wil_disconnect_cid(wil, cid, reason_code, from_event);
else /* disconnect all */
/* Cases are:
* - disconnect single STA, still connected
* - disconnect single STA, already disconnected
* - disconnect all
*
* For "disconnect all", there are 2 options:
* - bssid == NULL
* - bssid is our MAC address
*/
if (bssid && memcmp(ndev->dev_addr, bssid, ETH_ALEN)) {
cid = wil_find_cid(wil, bssid);
wil_dbg_misc(wil, "Disconnect %pM, CID=%d, reason=%d\n",
bssid, cid, reason_code);
if (cid >= 0) /* disconnect 1 peer */
wil_disconnect_cid(wil, cid, reason_code, from_event);
} else { /* all */
wil_dbg_misc(wil, "Disconnect all\n");
for (cid = 0; cid < WIL6210_MAX_CID; cid++)
wil_disconnect_cid(wil, cid, reason_code, from_event);
}
/* link state */
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT:
wil_link_off(wil);
if (test_bit(wil_status_fwconnected, &wil->status)) {
clear_bit(wil_status_fwconnected, &wil->status);
if (test_bit(wil_status_fwconnected, wil->status)) {
clear_bit(wil_status_fwconnected, wil->status);
cfg80211_disconnected(ndev, reason_code,
NULL, 0, GFP_KERNEL);
} else if (test_bit(wil_status_fwconnecting, &wil->status)) {
} else if (test_bit(wil_status_fwconnecting, wil->status)) {
cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
GFP_KERNEL);
}
clear_bit(wil_status_fwconnecting, &wil->status);
clear_bit(wil_status_fwconnecting, wil->status);
break;
default:
break;
@ -248,7 +291,7 @@ static void wil_scan_timer_fn(ulong x)
{
struct wil6210_priv *wil = (void *)x;
clear_bit(wil_status_fwready, &wil->status);
clear_bit(wil_status_fwready, wil->status);
wil_err(wil, "Scan timeout detected, start fw error recovery\n");
wil->recovery_state = fw_recovery_pending;
schedule_work(&wil->fw_error_worker);
@ -384,6 +427,8 @@ int wil_priv_init(struct wil6210_priv *wil)
mutex_init(&wil->mutex);
mutex_init(&wil->wmi_mutex);
mutex_init(&wil->back_rx_mutex);
mutex_init(&wil->back_tx_mutex);
init_completion(&wil->wmi_ready);
init_completion(&wil->wmi_call);
@ -396,25 +441,37 @@ int wil_priv_init(struct wil6210_priv *wil)
INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker);
INIT_WORK(&wil->wmi_event_worker, wmi_event_worker);
INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker);
INIT_WORK(&wil->back_rx_worker, wil_back_rx_worker);
INIT_WORK(&wil->back_tx_worker, wil_back_tx_worker);
INIT_LIST_HEAD(&wil->pending_wmi_ev);
INIT_LIST_HEAD(&wil->back_rx_pending);
INIT_LIST_HEAD(&wil->back_tx_pending);
spin_lock_init(&wil->wmi_ev_lock);
init_waitqueue_head(&wil->wq);
wil->wmi_wq = create_singlethread_workqueue(WIL_NAME"_wmi");
wil->wmi_wq = create_singlethread_workqueue(WIL_NAME "_wmi");
if (!wil->wmi_wq)
return -EAGAIN;
wil->wmi_wq_conn = create_singlethread_workqueue(WIL_NAME"_connect");
if (!wil->wmi_wq_conn) {
destroy_workqueue(wil->wmi_wq);
return -EAGAIN;
}
wil->wq_service = create_singlethread_workqueue(WIL_NAME "_service");
if (!wil->wq_service)
goto out_wmi_wq;
wil->last_fw_recovery = jiffies;
wil->itr_trsh = itr_trsh;
wil->tx_interframe_timeout = tx_interframe_timeout;
wil->rx_interframe_timeout = rx_interframe_timeout;
wil->tx_max_burst_duration = tx_max_burst_duration;
wil->rx_max_burst_duration = rx_max_burst_duration;
if (rx_ring_overflow_thrsh == WIL6210_RX_HIGH_TRSH_INIT)
rx_ring_overflow_thrsh = WIL6210_RX_HIGH_TRSH_DEFAULT;
return 0;
out_wmi_wq:
destroy_workqueue(wil->wmi_wq);
return -EAGAIN;
}
/**
@ -448,7 +505,11 @@ void wil_priv_deinit(struct wil6210_priv *wil)
wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
mutex_unlock(&wil->mutex);
wmi_event_flush(wil);
destroy_workqueue(wil->wmi_wq_conn);
wil_back_rx_flush(wil);
cancel_work_sync(&wil->back_rx_worker);
wil_back_tx_flush(wil);
cancel_work_sync(&wil->back_tx_worker);
destroy_workqueue(wil->wq_service);
destroy_workqueue(wil->wmi_wq);
}
@ -478,13 +539,10 @@ static int wil_target_reset(struct wil6210_priv *wil)
{
int delay = 0;
u32 x;
u32 rev_id;
bool is_sparrow = (wil->board->board == WIL_BOARD_SPARROW);
bool is_reset_v2 = test_bit(hw_capability_reset_v2,
wil->hw_capabilities);
wil_dbg_misc(wil, "Resetting \"%s\"...\n", wil->board->name);
wil->hw_version = R(RGF_USER_FW_REV_ID);
rev_id = wil->hw_version & 0xff;
wil_dbg_misc(wil, "Resetting \"%s\"...\n", wil->hw_name);
/* Clear MAC link up */
S(RGF_HP_CTRL, BIT(15));
@ -496,7 +554,7 @@ static int wil_target_reset(struct wil6210_priv *wil)
/* Clear Fw Download notification */
C(RGF_USER_USAGE_6, BIT(0));
if (is_sparrow) {
if (is_reset_v2) {
S(RGF_CAF_OSC_CONTROL, BIT_CAF_OSC_XTAL_EN);
/* XTAL stabilization should take about 3ms */
usleep_range(5000, 7000);
@ -517,10 +575,11 @@ static int wil_target_reset(struct wil6210_priv *wil)
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, is_sparrow ? 0x000000f0 : 0x00000170);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_3,
is_reset_v2 ? 0x000000f0 : 0x00000170);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FE00);
if (is_sparrow) {
if (is_reset_v2) {
W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x0);
W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0x0);
}
@ -530,19 +589,14 @@ static int wil_target_reset(struct wil6210_priv *wil)
W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
if (is_sparrow) {
if (is_reset_v2) {
W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000003);
/* reset A2 PCIE AHB */
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000);
} else {
W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001);
if (rev_id == 1) {
/* reset A1 BOTH PCIE AHB & PCIE RGF */
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080);
} else {
W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8));
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000);
}
W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8));
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000);
}
/* TODO: check order here!!! Erez code is different */
@ -559,8 +613,7 @@ static int wil_target_reset(struct wil6210_priv *wil)
}
} while (x != HW_MACHINE_BOOT_DONE);
/* TODO: Erez check rev_id != 1 */
if (!is_sparrow && (rev_id != 1))
if (!is_reset_v2)
W(RGF_PCIE_LOS_COUNTER_CTL, BIT(8));
C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
@ -569,26 +622,6 @@ static int wil_target_reset(struct wil6210_priv *wil)
return 0;
}
/**
* wil_set_itr_trsh: - apply interrupt coalescing params
*/
void wil_set_itr_trsh(struct wil6210_priv *wil)
{
/* disable, use usec resolution */
W(RGF_DMA_ITR_CNT_CRL, BIT_DMA_ITR_CNT_CRL_EXT_TICK);
/* disable interrupt moderation for monitor
* to get better timestamp precision
*/
if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR)
return;
wil_info(wil, "set ITR_TRSH = %d usec\n", wil->itr_trsh);
W(RGF_DMA_ITR_CNT_TRSH, wil->itr_trsh);
W(RGF_DMA_ITR_CNT_CRL, BIT_DMA_ITR_CNT_CRL_EN |
BIT_DMA_ITR_CNT_CRL_EXT_TICK); /* start it */
}
#undef R
#undef W
#undef S
@ -629,13 +662,17 @@ int wil_reset(struct wil6210_priv *wil)
wil_dbg_misc(wil, "%s()\n", __func__);
if (wil->hw_version == HW_VER_UNKNOWN)
return -ENODEV;
WARN_ON(!mutex_is_locked(&wil->mutex));
WARN_ON(test_bit(wil_status_napi_en, &wil->status));
WARN_ON(test_bit(wil_status_napi_en, wil->status));
cancel_work_sync(&wil->disconnect_worker);
wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
wil->status = 0; /* prevent NAPI from being scheduled */
/* prevent NAPI from being scheduled */
bitmap_zero(wil->status, wil_status_last);
if (wil->scan_request) {
wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
@ -649,7 +686,7 @@ int wil_reset(struct wil6210_priv *wil)
wmi_event_flush(wil);
flush_workqueue(wil->wmi_wq_conn);
flush_workqueue(wil->wq_service);
flush_workqueue(wil->wmi_wq);
rc = wil_target_reset(wil);
@ -688,6 +725,7 @@ int wil_reset(struct wil6210_priv *wil)
reinit_completion(&wil->wmi_ready);
reinit_completion(&wil->wmi_call);
wil_configure_interrupt_moderation(wil);
wil_unmask_irq(wil);
/* we just started MAC, wait for FW ready */
@ -774,7 +812,7 @@ int __wil_up(struct wil6210_priv *wil)
wil_dbg_misc(wil, "NAPI enable\n");
napi_enable(&wil->napi_rx);
napi_enable(&wil->napi_tx);
set_bit(wil_status_napi_en, &wil->status);
set_bit(wil_status_napi_en, wil->status);
if (wil->platform_ops.bus_request)
wil->platform_ops.bus_request(wil->platform_handle,
@ -807,7 +845,7 @@ int __wil_down(struct wil6210_priv *wil)
wil->platform_ops.bus_request(wil->platform_handle, 0);
wil_disable_irq(wil);
if (test_and_clear_bit(wil_status_napi_en, &wil->status)) {
if (test_and_clear_bit(wil_status_napi_en, wil->status)) {
napi_disable(&wil->napi_rx);
napi_disable(&wil->napi_tx);
wil_dbg_misc(wil, "NAPI disable\n");
@ -822,15 +860,15 @@ int __wil_down(struct wil6210_priv *wil)
wil->scan_request = NULL;
}
if (test_bit(wil_status_fwconnected, &wil->status) ||
test_bit(wil_status_fwconnecting, &wil->status))
if (test_bit(wil_status_fwconnected, wil->status) ||
test_bit(wil_status_fwconnecting, wil->status))
wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0);
/* make sure wil is idle (not connected) */
mutex_unlock(&wil->mutex);
while (iter--) {
int idle = !test_bit(wil_status_fwconnected, &wil->status) &&
!test_bit(wil_status_fwconnecting, &wil->status);
int idle = !test_bit(wil_status_fwconnected, wil->status) &&
!test_bit(wil_status_fwconnecting, wil->status);
if (idle)
break;
msleep(WAIT_FOR_DISCONNECT_INTERVAL_MS);

View file

@ -31,6 +31,46 @@ static bool debug_fw; /* = false; */
module_param(debug_fw, bool, S_IRUGO);
MODULE_PARM_DESC(debug_fw, " load driver if FW not ready. For FW debug");
static
void wil_set_capabilities(struct wil6210_priv *wil)
{
u32 rev_id = ioread32(wil->csr + HOSTADDR(RGF_USER_JTAG_DEV_ID));
bitmap_zero(wil->hw_capabilities, hw_capability_last);
switch (rev_id) {
case JTAG_DEV_ID_MARLON_B0:
wil->hw_name = "Marlon B0";
wil->hw_version = HW_VER_MARLON_B0;
break;
case JTAG_DEV_ID_SPARROW_A0:
wil->hw_name = "Sparrow A0";
wil->hw_version = HW_VER_SPARROW_A0;
break;
case JTAG_DEV_ID_SPARROW_A1:
wil->hw_name = "Sparrow A1";
wil->hw_version = HW_VER_SPARROW_A1;
break;
case JTAG_DEV_ID_SPARROW_B0:
wil->hw_name = "Sparrow B0";
wil->hw_version = HW_VER_SPARROW_B0;
break;
default:
wil_err(wil, "Unknown board hardware 0x%08x\n", rev_id);
wil->hw_name = "Unknown";
wil->hw_version = HW_VER_UNKNOWN;
}
wil_info(wil, "Board hardware is %s\n", wil->hw_name);
if (wil->hw_version >= HW_VER_SPARROW_A0)
set_bit(hw_capability_reset_v2, wil->hw_capabilities);
if (wil->hw_version >= HW_VER_SPARROW_B0)
set_bit(hw_capability_advanced_itr_moderation,
wil->hw_capabilities);
}
void wil_disable_irq(struct wil6210_priv *wil)
{
int irq = wil->pdev->irq;
@ -149,12 +189,11 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct wil6210_priv *wil;
struct device *dev = &pdev->dev;
void __iomem *csr;
struct wil_board *board = (struct wil_board *)id->driver_data;
int rc;
/* check HW */
dev_info(&pdev->dev, WIL_NAME
" \"%s\" device found [%04x:%04x] (rev %x)\n", board->name,
" device found [%04x:%04x] (rev %x)\n",
(int)pdev->vendor, (int)pdev->device, (int)pdev->revision);
if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) {
@ -204,8 +243,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_drvdata(pdev, wil);
wil->pdev = pdev;
wil->board = board;
wil_set_capabilities(wil);
wil6210_clear_irq(wil);
wil->platform_handle =
@ -266,23 +304,10 @@ static void wil_pcie_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}
static const struct wil_board wil_board_marlon = {
.board = WIL_BOARD_MARLON,
.name = "marlon",
};
static const struct wil_board wil_board_sparrow = {
.board = WIL_BOARD_SPARROW,
.name = "sparrow",
};
static const struct pci_device_id wil6210_pcie_ids[] = {
{ PCI_DEVICE(0x1ae9, 0x0301),
.driver_data = (kernel_ulong_t)&wil_board_marlon },
{ PCI_DEVICE(0x1ae9, 0x0310),
.driver_data = (kernel_ulong_t)&wil_board_sparrow },
{ PCI_DEVICE(0x1ae9, 0x0302), /* same as above, firmware broken */
.driver_data = (kernel_ulong_t)&wil_board_sparrow },
{ PCI_DEVICE(0x1ae9, 0x0301) },
{ PCI_DEVICE(0x1ae9, 0x0310) },
{ PCI_DEVICE(0x1ae9, 0x0302) }, /* same as above, firmware broken */
{ /* end: all zeroes */ },
};
MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids);

View file

@ -89,7 +89,9 @@ static void wil_reorder_release(struct wil6210_priv *wil,
}
}
/* called in NAPI context */
void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb)
__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
{
struct net_device *ndev = wil_to_ndev(wil);
struct vring_rx_desc *d = wil_skb_rxdesc(skb);
@ -97,22 +99,26 @@ void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb)
int cid = wil_rxdesc_cid(d);
int mid = wil_rxdesc_mid(d);
u16 seq = wil_rxdesc_seq(d);
int mcast = wil_rxdesc_mcast(d);
struct wil_sta_info *sta = &wil->sta[cid];
struct wil_tid_ampdu_rx *r;
u16 hseq;
int index;
unsigned long flags;
wil_dbg_txrx(wil, "MID %d CID %d TID %d Seq 0x%03x\n",
mid, cid, tid, seq);
wil_dbg_txrx(wil, "MID %d CID %d TID %d Seq 0x%03x mcast %01x\n",
mid, cid, tid, seq, mcast);
spin_lock_irqsave(&sta->tid_rx_lock, flags);
if (unlikely(mcast)) {
wil_netif_rx_any(skb, ndev);
return;
}
spin_lock(&sta->tid_rx_lock);
r = sta->tid_rx[tid];
if (!r) {
spin_unlock_irqrestore(&sta->tid_rx_lock, flags);
wil_netif_rx_any(skb, ndev);
return;
goto out;
}
hseq = r->head_seq_num;
@ -121,13 +127,24 @@ void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb)
* reported, and data Rx, few packets may be pass up before reorder
* buffer get allocated. Catch up by pretending SSN is what we
* see in the 1-st Rx packet
*
* Another scenario, Rx get delayed and we got packet from before
* BACK. Pass it to the stack and wait.
*/
if (r->first_time) {
r->first_time = false;
if (seq != r->head_seq_num) {
wil_err(wil, "Error: 1-st frame with wrong sequence"
" %d, should be %d. Fixing...\n", seq,
r->head_seq_num);
if (seq_less(seq, r->head_seq_num)) {
wil_err(wil,
"Error: frame with early sequence 0x%03x, should be 0x%03x. Waiting...\n",
seq, r->head_seq_num);
r->first_time = true;
wil_netif_rx_any(skb, ndev);
goto out;
}
wil_err(wil,
"Error: 1-st frame with wrong sequence 0x%03x, should be 0x%03x. Fixing...\n",
seq, r->head_seq_num);
r->head_seq_num = seq;
r->ssn = seq;
}
@ -179,7 +196,7 @@ void wil_rx_reorder(struct wil6210_priv *wil, struct sk_buff *skb)
wil_reorder_release(wil, r);
out:
spin_unlock_irqrestore(&sta->tid_rx_lock, flags);
spin_unlock(&sta->tid_rx_lock);
}
struct wil_tid_ampdu_rx *wil_tid_ampdu_rx_alloc(struct wil6210_priv *wil,
@ -219,3 +236,241 @@ void wil_tid_ampdu_rx_free(struct wil6210_priv *wil,
kfree(r->reorder_time);
kfree(r);
}
/* ADDBA processing */
static u16 wil_agg_size(struct wil6210_priv *wil, u16 req_agg_wsize)
{
u16 max_agg_size = min_t(u16, WIL_MAX_AGG_WSIZE, WIL_MAX_AMPDU_SIZE /
(mtu_max + WIL_MAX_MPDU_OVERHEAD));
if (!req_agg_wsize)
return max_agg_size;
return min(max_agg_size, req_agg_wsize);
}
/* Block Ack - Rx side (recipient */
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)
{
struct wil_back_rx *req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
req->cidxtid = cidxtid;
req->dialog_token = dialog_token;
req->ba_param_set = le16_to_cpu(ba_param_set);
req->ba_timeout = le16_to_cpu(ba_timeout);
req->ba_seq_ctrl = le16_to_cpu(ba_seq_ctrl);
mutex_lock(&wil->back_rx_mutex);
list_add_tail(&req->list, &wil->back_rx_pending);
mutex_unlock(&wil->back_rx_mutex);
queue_work(wil->wq_service, &wil->back_rx_worker);
return 0;
}
static void wil_back_rx_handle(struct wil6210_priv *wil,
struct wil_back_rx *req)
__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
{
struct wil_sta_info *sta;
u8 cid, tid;
u16 agg_wsize = 0;
/* bit 0: A-MSDU supported
* bit 1: policy (should be 0 for us)
* bits 2..5: TID
* bits 6..15: buffer size
*/
u16 req_agg_wsize = WIL_GET_BITS(req->ba_param_set, 6, 15);
bool agg_amsdu = !!(req->ba_param_set & BIT(0));
int ba_policy = req->ba_param_set & BIT(1);
u16 agg_timeout = req->ba_timeout;
u16 status = WLAN_STATUS_SUCCESS;
u16 ssn = req->ba_seq_ctrl >> 4;
int rc;
might_sleep();
parse_cidxtid(req->cidxtid, &cid, &tid);
/* sanity checks */
if (cid >= WIL6210_MAX_CID) {
wil_err(wil, "BACK: invalid CID %d\n", cid);
return;
}
sta = &wil->sta[cid];
if (sta->status != wil_sta_connected) {
wil_err(wil, "BACK: CID %d not connected\n", cid);
return;
}
wil_dbg_wmi(wil,
"ADDBA request for CID %d %pM TID %d size %d timeout %d AMSDU%s policy %d token %d SSN 0x%03x\n",
cid, sta->addr, tid, req_agg_wsize, req->ba_timeout,
agg_amsdu ? "+" : "-", !!ba_policy, req->dialog_token, ssn);
/* apply policies */
if (ba_policy) {
wil_err(wil, "BACK requested unsupported ba_policy == 1\n");
status = WLAN_STATUS_INVALID_QOS_PARAM;
}
if (status == WLAN_STATUS_SUCCESS)
agg_wsize = wil_agg_size(wil, req_agg_wsize);
rc = wmi_addba_rx_resp(wil, cid, tid, req->dialog_token, status,
agg_amsdu, agg_wsize, agg_timeout);
if (rc || (status != WLAN_STATUS_SUCCESS))
return;
/* apply */
spin_lock_bh(&sta->tid_rx_lock);
wil_tid_ampdu_rx_free(wil, sta->tid_rx[tid]);
sta->tid_rx[tid] = wil_tid_ampdu_rx_alloc(wil, agg_wsize, ssn);
spin_unlock_bh(&sta->tid_rx_lock);
}
void wil_back_rx_flush(struct wil6210_priv *wil)
{
struct wil_back_rx *evt, *t;
wil_dbg_misc(wil, "%s()\n", __func__);
mutex_lock(&wil->back_rx_mutex);
list_for_each_entry_safe(evt, t, &wil->back_rx_pending, list) {
list_del(&evt->list);
kfree(evt);
}
mutex_unlock(&wil->back_rx_mutex);
}
/* Retrieve next ADDBA request from the pending list */
static struct list_head *next_back_rx(struct wil6210_priv *wil)
{
struct list_head *ret = NULL;
mutex_lock(&wil->back_rx_mutex);
if (!list_empty(&wil->back_rx_pending)) {
ret = wil->back_rx_pending.next;
list_del(ret);
}
mutex_unlock(&wil->back_rx_mutex);
return ret;
}
void wil_back_rx_worker(struct work_struct *work)
{
struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
back_rx_worker);
struct wil_back_rx *evt;
struct list_head *lh;
while ((lh = next_back_rx(wil)) != NULL) {
evt = list_entry(lh, struct wil_back_rx, list);
wil_back_rx_handle(wil, evt);
kfree(evt);
}
}
/* BACK - Tx (originator) side */
static void wil_back_tx_handle(struct wil6210_priv *wil,
struct wil_back_tx *req)
{
struct vring_tx_data *txdata = &wil->vring_tx_data[req->ringid];
int rc;
if (txdata->addba_in_progress) {
wil_dbg_misc(wil, "ADDBA for vring[%d] already in progress\n",
req->ringid);
return;
}
if (txdata->agg_wsize) {
wil_dbg_misc(wil,
"ADDBA for vring[%d] already established wsize %d\n",
req->ringid, txdata->agg_wsize);
return;
}
txdata->addba_in_progress = true;
rc = wmi_addba(wil, req->ringid, req->agg_wsize, req->agg_timeout);
if (rc)
txdata->addba_in_progress = false;
}
static struct list_head *next_back_tx(struct wil6210_priv *wil)
{
struct list_head *ret = NULL;
mutex_lock(&wil->back_tx_mutex);
if (!list_empty(&wil->back_tx_pending)) {
ret = wil->back_tx_pending.next;
list_del(ret);
}
mutex_unlock(&wil->back_tx_mutex);
return ret;
}
void wil_back_tx_worker(struct work_struct *work)
{
struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
back_tx_worker);
struct wil_back_tx *evt;
struct list_head *lh;
while ((lh = next_back_tx(wil)) != NULL) {
evt = list_entry(lh, struct wil_back_tx, list);
wil_back_tx_handle(wil, evt);
kfree(evt);
}
}
void wil_back_tx_flush(struct wil6210_priv *wil)
{
struct wil_back_tx *evt, *t;
wil_dbg_misc(wil, "%s()\n", __func__);
mutex_lock(&wil->back_tx_mutex);
list_for_each_entry_safe(evt, t, &wil->back_tx_pending, list) {
list_del(&evt->list);
kfree(evt);
}
mutex_unlock(&wil->back_tx_mutex);
}
int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize)
{
struct wil_back_tx *req = kzalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
req->ringid = ringid;
req->agg_wsize = wil_agg_size(wil, wsize);
req->agg_timeout = 0;
mutex_lock(&wil->back_tx_mutex);
list_add_tail(&req->list, &wil->back_tx_pending);
mutex_unlock(&wil->back_tx_mutex);
queue_work(wil->wq_service, &wil->back_tx_worker);
return 0;
}

View file

@ -463,7 +463,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
* and in case of error drop the packet
* higher stack layers will handle retransmission (if required)
*/
if (d->dma.status & RX_DMA_STATUS_L4_IDENT) {
if (d->dma.status & RX_DMA_STATUS_L4I) {
/* L4 protocol identified, csum calculated */
if ((d->dma.error & RX_DMA_ERROR_L4_ERR) == 0)
skb->ip_summed = CHECKSUM_UNNECESSARY;
@ -581,14 +581,8 @@ void wil_rx_handle(struct wil6210_priv *wil, int *quota)
skb->protocol = htons(ETH_P_802_2);
wil_netif_rx_any(skb, ndev);
} else {
struct ethhdr *eth = (void *)skb->data;
skb->protocol = eth_type_trans(skb, ndev);
if (is_unicast_ether_addr(eth->h_dest))
wil_rx_reorder(wil, skb);
else
wil_netif_rx_any(skb, ndev);
wil_rx_reorder(wil, skb);
}
}
wil_rx_refill(wil, v->size);
@ -645,7 +639,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
.vring_cfg = {
.tx_sw_ring = {
.max_mpdu_size =
cpu_to_le16(mtu_max + ETH_HLEN),
cpu_to_le16(wil_mtu2macbuf(mtu_max)),
.ring_size = cpu_to_le16(size),
},
.ringid = id,
@ -653,7 +647,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
.encap_trans_type = WMI_VRING_ENC_TYPE_802_3,
.mac_ctrl = 0,
.to_resolution = 0,
.agg_max_wsize = 16,
.agg_max_wsize = 0,
.schd_params = {
.priority = cpu_to_le16(0),
.timeslot_us = cpu_to_le16(0xfff),
@ -701,6 +695,8 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr);
txdata->enabled = 1;
if (wil->sta[cid].data_port_open && (agg_wsize >= 0))
wil_addba_tx_request(wil, id, agg_wsize);
return 0;
out_free:
@ -713,6 +709,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
{
struct vring *vring = &wil->vring_tx[id];
struct vring_tx_data *txdata = &wil->vring_tx_data[id];
WARN_ON(!mutex_is_locked(&wil->mutex));
@ -723,10 +720,11 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
/* make sure NAPI won't touch this vring */
wil->vring_tx_data[id].enabled = 0;
if (test_bit(wil_status_napi_en, &wil->status))
if (test_bit(wil_status_napi_en, wil->status))
napi_synchronize(&wil->napi_tx);
wil_vring_free(wil, vring, 1);
memset(txdata, 0, sizeof(*txdata));
}
static struct vring *wil_find_tx_vring(struct wil6210_priv *wil,
@ -773,6 +771,38 @@ static void wil_set_da_for_vring(struct wil6210_priv *wil,
static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
struct sk_buff *skb);
static struct vring *wil_find_tx_vring_sta(struct wil6210_priv *wil,
struct sk_buff *skb)
{
struct vring *v;
int i;
u8 cid;
/* In the STA mode, it is expected to have only 1 VRING
* for the AP we connected to.
* find 1-st vring and see whether it is eligible for data
*/
for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
v = &wil->vring_tx[i];
if (!v->va)
continue;
cid = wil->vring2cid_tid[i][0];
if (!wil->sta[cid].data_port_open &&
(skb->protocol != cpu_to_be16(ETH_P_PAE)))
break;
wil_dbg_txrx(wil, "Tx -> ring %d\n", i);
return v;
}
wil_dbg_txrx(wil, "Tx while no vrings active?\n");
return NULL;
}
/*
* Find 1-st vring and return it; set dest address for this vring in skb
* duplicate skb and send it to other active vrings
@ -1034,14 +1064,14 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
int rc;
wil_dbg_txrx(wil, "%s()\n", __func__);
if (!test_bit(wil_status_fwready, &wil->status)) {
if (!test_bit(wil_status_fwready, wil->status)) {
if (!pr_once_fw) {
wil_err(wil, "FW not ready\n");
pr_once_fw = true;
}
goto drop;
}
if (!test_bit(wil_status_fwconnected, &wil->status)) {
if (!test_bit(wil_status_fwconnected, wil->status)) {
wil_err(wil, "FW not connected\n");
goto drop;
}
@ -1052,15 +1082,19 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
pr_once_fw = false;
/* find vring */
if (is_unicast_ether_addr(eth->h_dest))
vring = wil_find_tx_vring(wil, skb);
else
vring = wil_tx_bcast(wil, skb);
if (wil->wdev->iftype == NL80211_IFTYPE_STATION) {
/* in STA mode (ESS), all to same VRING */
vring = wil_find_tx_vring_sta(wil, skb);
} else { /* direct communication, find matching VRING */
if (is_unicast_ether_addr(eth->h_dest))
vring = wil_find_tx_vring(wil, skb);
else
vring = wil_tx_bcast(wil, skb);
}
if (!vring) {
wil_dbg_txrx(wil, "No Tx VRING found for %pM\n", eth->h_dest);
goto drop;
}
/* set up vring entry */
rc = wil_tx_vring(wil, vring, skb);

View file

@ -20,17 +20,15 @@
#define BUF_SW_OWNED (1)
#define BUF_HW_OWNED (0)
/* size of max. Tx/Rx buffers, as supported by FW */
#define TXRX_BUF_LEN_DEFAULT (2242)
/* default size of MAC Tx/Rx buffers */
#define TXRX_BUF_LEN_DEFAULT (2048)
/* how many bytes to reserve for rtap header? */
#define WIL6210_RTAP_SIZE (128)
/* Tx/Rx path */
/*
* Common representation of physical address in Vring
*/
/* Common representation of physical address in Vring */
struct vring_dma_addr {
__le32 addr_low;
__le16 addr_high;
@ -49,11 +47,10 @@ static inline void wil_desc_addr_set(struct vring_dma_addr *addr,
addr->addr_high = cpu_to_le16((u16)upper_32_bits(pa));
}
/*
* Tx descriptor - MAC part
/* Tx descriptor - MAC part
* [dword 0]
* bit 0.. 9 : lifetime_expiry_value:10
* bit 10 : interrup_en:1
* bit 10 : interrupt_en:1
* bit 11 : status_en:1
* bit 12..13 : txss_override:2
* bit 14 : timestamp_insertion:1
@ -61,15 +58,12 @@ static inline void wil_desc_addr_set(struct vring_dma_addr *addr,
* bit 16..21 : reserved0:6
* bit 22..26 : mcs_index:5
* bit 27 : mcs_en:1
* bit 28..29 : reserved1:2
* bit 30 : reserved2:1
* bit 28..30 : reserved1:3
* bit 31 : sn_preserved:1
* [dword 1]
* bit 0.. 3 : pkt_mode:4
* bit 4 : pkt_mode_en:1
* bit 5.. 7 : reserved0:3
* bit 8..13 : reserved1:6
* bit 14 : reserved2:1
* bit 5..14 : reserved0:10
* bit 15 : ack_policy_en:1
* bit 16..19 : dst_index:4
* bit 20 : dst_index_en:1
@ -80,7 +74,7 @@ static inline void wil_desc_addr_set(struct vring_dma_addr *addr,
* [dword 2]
* bit 0.. 7 : num_of_descriptors:8
* bit 8..17 : reserved:10
* bit 18..19 : l2_translation_type:2
* bit 18..19 : l2_translation_type:2 00 - bypass, 01 - 802.3, 10 - 802.11
* bit 20 : snap_hdr_insertion_en:1
* bit 21 : vlan_removal_en:1
* bit 22..31 : reserved0:10
@ -247,6 +241,46 @@ struct vring_tx_mac {
#define TX_DMA_STATUS_DU BIT(0)
/* Tx descriptor - DMA part
* [dword 0]
* bit 0.. 7 : l4_length:8 layer 4 length
* bit 8 : cmd_eop:1 This descriptor is the last one in the packet
* bit 9 : reserved
* bit 10 : cmd_dma_it:1 immediate interrupt
* bit 11..12 : SBD - Segment Buffer Details
* 00 - Header Segment
* 01 - First Data Segment
* 10 - Medium Data Segment
* 11 - Last Data Segment
* bit 13 : TSE - TCP Segmentation Enable
* bit 14 : IIC - Directs the HW to Insert IPv4 Checksum
* bit 15 : ITC - Directs the HW to Insert TCP/UDP Checksum
* bit 16..20 : QID - The target QID that the packet should be stored
* in the MAC.
* bit 21 : PO - Pseudo header Offload:
* 0 - Use the pseudo header value from the TCP checksum field
* 1- Calculate Pseudo header Checksum
* bit 22 : NC - No UDP Checksum
* bit 23..29 : reserved
* bit 30..31 : L4T - Layer 4 Type: 00 - UDP , 10 - TCP , 10, 11 - Reserved
* If L4Len equal 0, no L4 at all
* [dword 1]
* bit 0..31 : addr_low:32 The payload buffer low address
* [dword 2]
* bit 0..15 : addr_high:16 The payload buffer high address
* bit 16..23 : ip_length:8 The IP header length for the TX IP checksum
* offload feature
* bit 24..30 : mac_length:7
* bit 31 : ip_version:1 1 - IPv4, 0 - IPv6
* [dword 3]
* [byte 12] error
* bit 0 2 : mac_status:3
* bit 3 7 : reserved:5
* [byte 13] status
* bit 0 : DU:1 Descriptor Used
* bit 1 7 : reserved:7
* [word 7] length
*/
struct vring_tx_dma {
u32 d0;
struct vring_dma_addr addr;
@ -257,45 +291,45 @@ struct vring_tx_dma {
__le16 length;
} __packed;
/*
* Rx descriptor - MAC part
/* Rx descriptor - MAC part
* [dword 0]
* bit 0.. 3 : tid:4 The QoS (b3-0) TID Field
* bit 4.. 6 : connection_id:3 :The Source index that was found during
* Parsing the TA. This field is used to define the source of the packet
* bit 4.. 6 : cid:3 The Source index that was found during parsing the TA.
* This field is used to define the source of the packet
* bit 7 : reserved:1
* bit 8.. 9 : mac_id:2 : The MAC virtual Ring number (always zero)
* bit 10..11 : frame_type:2 : The FC Control (b3-2) - MPDU Type
* (management, data, control and extension)
* bit 12..15 : frame_subtype:4 : The FC Control (b7-4) - Frame Subtype
* bit 8.. 9 : mid:2 The MAC virtual number
* bit 10..11 : frame_type:2 : The FC (b3-2) - MPDU Type
* (management, data, control and extension)
* bit 12..15 : frame_subtype:4 : The FC (b7-4) - Frame Subtype
* bit 16..27 : seq_number:12 The received Sequence number field
* bit 28..31 : extended:4 extended subtype
* [dword 1]
* bit 0.. 3 : reserved
* bit 4.. 5 : key_id:2
* bit 6 : decrypt_bypass:1
* bit 7 : security:1
* bit 8.. 9 : ds_bits:2
* bit 10 : a_msdu_present:1 from qos header
* bit 11 : a_msdu_type:1 from qos header
* bit 7 : security:1 FC (b14)
* bit 8.. 9 : ds_bits:2 FC (b9-8)
* bit 10 : a_msdu_present:1 QoS (b7)
* bit 11 : a_msdu_type:1 QoS (b8)
* bit 12 : a_mpdu:1 part of AMPDU aggregation
* bit 13 : broadcast:1
* bit 14 : mutlicast:1
* bit 15 : reserved:1
* bit 16..20 : rx_mac_qid:5 The Queue Identifier that the packet
* is received from
* bit 16..20 : rx_mac_qid:5 The Queue Identifier that the packet
* is received from
* bit 21..24 : mcs:4
* bit 25..28 : mic_icr:4
* bit 25..28 : mic_icr:4 this signal tells the DMA to assert an interrupt
* after it writes the packet
* bit 29..31 : reserved:3
* [dword 2]
* bit 0.. 2 : time_slot:3 The timeslot that the MPDU is received
* bit 3 : fc_protocol_ver:1 The FC Control (b0) - Protocol Version
* bit 4 : fc_order:1 The FC Control (b15) -Order
* bit 5.. 7 : qos_ack_policy:3 The QoS (b6-5) ack policy Field
* bit 3.. 4 : fc_protocol_ver:1 The FC (b1-0) - Protocol Version
* bit 5 : fc_order:1 The FC Control (b15) -Order
* bit 6.. 7 : qos_ack_policy:2 The QoS (b6-5) ack policy Field
* bit 8 : esop:1 The QoS (b4) ESOP field
* bit 9 : qos_rdg_more_ppdu:1 The QoS (b9) RDG field
* bit 10..14 : qos_reserved:5 The QoS (b14-10) Reserved field
* bit 15 : qos_ac_constraint:1
* bit 9 : qos_rdg_more_ppdu:1 The QoS (b9) RDG field
* bit 10..14 : qos_reserved:5 The QoS (b14-10) Reserved field
* bit 15 : qos_ac_constraint:1 QoS (b15)
* bit 16..31 : pn_15_0:16 low 2 bytes of PN
* [dword 3]
* bit 0..31 : pn_47_16:32 high 4 bytes of PN
@ -308,35 +342,46 @@ struct vring_rx_mac {
u32 pn_47_16;
} __packed;
/*
* Rx descriptor - DMA part
/* Rx descriptor - DMA part
* [dword 0]
* bit 0.. 7 : l4_length:8 layer 4 length
* bit 8.. 9 : reserved:2
* bit 10 : cmd_dma_it:1
* bit 0.. 7 : l4_length:8 layer 4 length. The field is only valid if
* L4I bit is set
* bit 8 : cmd_eop:1 set to 1
* bit 9 : cmd_rt:1 set to 1
* bit 10 : cmd_dma_it:1 immediate interrupt
* bit 11..15 : reserved:5
* bit 16..29 : phy_info_length:14
* bit 16..29 : phy_info_length:14 It is valid when the PII is set.
* When the FFM bit is set bits 29-27 are used for for
* Flex Filter Match. Matching Index to one of the L2
* EtherType Flex Filter
* bit 30..31 : l4_type:2 valid if the L4I bit is set in the status field
* 00 - UDP, 01 - TCP, 10, 11 - reserved
* [dword 1]
* bit 0..31 : addr_low:32 The payload buffer low address
* [dword 2]
* bit 0..15 : addr_high:16 The payload buffer high address
* bit 16..23 : ip_length:8
* bit 16..23 : ip_length:8 The filed is valid only if the L3I bit is set
* bit 24..30 : mac_length:7
* bit 31 : ip_version:1
* bit 31 : ip_version:1 1 - IPv4, 0 - IPv6
* [dword 3]
* [byte 12] error
* bit 0 : FCS:1
* bit 1 : MIC:1
* bit 2 : Key miss:1
* bit 3 : Replay:1
* bit 4 : L3:1 IPv4 checksum
* bit 5 : L4:1 TCP/UDP checksum
* bit 6 7 : reserved:2
* [byte 13] status
* bit 0 : du:1
* bit 1 : eop:1
* bit 0 : DU:1 Descriptor Used
* bit 1 : EOP:1 The descriptor indicates the End of Packet
* bit 2 : error:1
* bit 3 : mi:1
* bit 4 : l3_identified:1
* bit 5 : l4_identified:1
* bit 6 : phy_info_included:1
* bit 7 : reserved:1
* bit 3 : MI:1 MAC Interrupt is asserted (according to parser decision)
* bit 4 : L3I:1 L3 identified and checksum calculated
* bit 5 : L4I:1 L4 identified and checksum calculated
* bit 6 : PII:1 PHY Info Included in the packet
* bit 7 : FFM:1 EtherType Flex Filter Match
* [word 7] length
*
*/
#define RX_DMA_D0_CMD_DMA_IT BIT(10)
@ -349,9 +394,9 @@ struct vring_rx_mac {
#define RX_DMA_STATUS_DU BIT(0)
#define RX_DMA_STATUS_ERROR BIT(2)
#define RX_DMA_STATUS_L3_IDENT BIT(4)
#define RX_DMA_STATUS_L4_IDENT BIT(5)
#define RX_DMA_STATUS_PHY_INFO BIT(6)
#define RX_DMA_STATUS_L3I BIT(4)
#define RX_DMA_STATUS_L4I BIT(5)
#define RX_DMA_STATUS_PHY_INFO BIT(6)
struct vring_rx_dma {
u32 d0;
@ -423,6 +468,11 @@ static inline int wil_rxdesc_mcs(struct vring_rx_desc *d)
return WIL_GET_BITS(d->mac.d1, 21, 24);
}
static inline int wil_rxdesc_mcast(struct vring_rx_desc *d)
{
return WIL_GET_BITS(d->mac.d1, 13, 14);
}
static inline int wil_rxdesc_phy_length(struct vring_rx_desc *d)
{
return WIL_GET_BITS(d->dma.d0, 16, 29);

View file

@ -25,19 +25,14 @@
extern bool no_fw_recovery;
extern unsigned int mtu_max;
extern unsigned short rx_ring_overflow_thrsh;
extern int agg_wsize;
#define WIL_NAME "wil6210"
#define WIL_FW_NAME "wil6210.fw"
#define WIL_MAX_BUS_REQUEST_KBPS 800000 /* ~6.1Gbps */
struct wil_board {
int board;
#define WIL_BOARD_MARLON (1)
#define WIL_BOARD_SPARROW (2)
const char * const name;
};
/**
* extract bits [@b0:@b1] (inclusive) from the value @x
* it should be @b0 <= @b1, or result is incorrect
@ -57,13 +52,41 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
#define WIL6210_MAX_TX_RINGS (24) /* HW limit */
#define WIL6210_MAX_CID (8) /* HW limit */
#define WIL6210_NAPI_BUDGET (16) /* arbitrary */
#define WIL_MAX_AMPDU_SIZE (64 * 1024) /* FW/HW limit */
#define WIL_MAX_AGG_WSIZE (32) /* FW/HW limit */
/* Hardware offload block adds the following:
* 26 bytes - 3-address QoS data header
* 8 bytes - IV + EIV (for GCMP)
* 8 bytes - SNAP
* 16 bytes - MIC (for GCMP)
* 4 bytes - CRC
*/
#define WIL_MAX_MPDU_OVERHEAD (62)
/* Calculate MAC buffer size for the firmware. It includes all overhead,
* as it will go over the air, and need to be 8 byte aligned
*/
static inline u32 wil_mtu2macbuf(u32 mtu)
{
return ALIGN(mtu + WIL_MAX_MPDU_OVERHEAD, 8);
}
/* MTU for Ethernet need to take into account 8-byte SNAP header
* to be added when encapsulating Ethernet frame into 802.11
*/
#define WIL_MAX_ETH_MTU (IEEE80211_MAX_DATA_LEN_DMG - 8)
/* Max supported by wil6210 value for interrupt threshold is 5sec. */
#define WIL6210_ITR_TRSH_MAX (5000000)
#define WIL6210_ITR_TRSH_DEFAULT (300) /* usec */
#define WIL6210_ITR_TX_INTERFRAME_TIMEOUT_DEFAULT (15) /* usec */
#define WIL6210_ITR_RX_INTERFRAME_TIMEOUT_DEFAULT (15) /* usec */
#define WIL6210_ITR_TX_MAX_BURST_DURATION_DEFAULT (500) /* usec */
#define WIL6210_ITR_RX_MAX_BURST_DURATION_DEFAULT (500) /* usec */
#define WIL6210_FW_RECOVERY_RETRIES (5) /* try to recover this many times */
#define WIL6210_FW_RECOVERY_TO msecs_to_jiffies(5000)
#define WIL6210_SCAN_TO msecs_to_jiffies(10000)
#define WIL6210_RX_HIGH_TRSH_INIT (0)
#define WIL6210_RX_HIGH_TRSH_DEFAULT \
(1 << (WIL_RX_RING_SIZE_ORDER_DEFAULT - 3))
/* Hardware definitions begin */
/*
@ -135,7 +158,7 @@ struct RGF_ICR {
#define BIT_DMA_EP_MISC_ICR_TX_NO_ACT BIT(1)
#define BIT_DMA_EP_MISC_ICR_FW_INT(n) BIT(28+n) /* n = [0..3] */
/* Interrupt moderation control */
/* Legacy interrupt moderation control (before Sparrow v2)*/
#define RGF_DMA_ITR_CNT_TRSH (0x881c5c)
#define RGF_DMA_ITR_CNT_DATA (0x881c60)
#define RGF_DMA_ITR_CNT_CRL (0x881c64)
@ -145,6 +168,46 @@ struct RGF_ICR {
#define BIT_DMA_ITR_CNT_CRL_CLR BIT(3)
#define BIT_DMA_ITR_CNT_CRL_REACH_TRSH BIT(4)
/* New (sparrow v2+) interrupt moderation control */
#define RGF_DMA_ITR_TX_DESQ_NO_MOD (0x881d40)
#define RGF_DMA_ITR_TX_CNT_TRSH (0x881d34)
#define RGF_DMA_ITR_TX_CNT_DATA (0x881d38)
#define RGF_DMA_ITR_TX_CNT_CTL (0x881d3c)
#define BIT_DMA_ITR_TX_CNT_CTL_EN BIT(0)
#define BIT_DMA_ITR_TX_CNT_CTL_EXT_TIC_SEL BIT(1)
#define BIT_DMA_ITR_TX_CNT_CTL_FOREVER BIT(2)
#define BIT_DMA_ITR_TX_CNT_CTL_CLR BIT(3)
#define BIT_DMA_ITR_TX_CNT_CTL_REACHED_TRESH BIT(4)
#define BIT_DMA_ITR_TX_CNT_CTL_CROSS_EN BIT(5)
#define BIT_DMA_ITR_TX_CNT_CTL_FREE_RUNNIG BIT(6)
#define RGF_DMA_ITR_TX_IDL_CNT_TRSH (0x881d60)
#define RGF_DMA_ITR_TX_IDL_CNT_DATA (0x881d64)
#define RGF_DMA_ITR_TX_IDL_CNT_CTL (0x881d68)
#define BIT_DMA_ITR_TX_IDL_CNT_CTL_EN BIT(0)
#define BIT_DMA_ITR_TX_IDL_CNT_CTL_EXT_TIC_SEL BIT(1)
#define BIT_DMA_ITR_TX_IDL_CNT_CTL_FOREVER BIT(2)
#define BIT_DMA_ITR_TX_IDL_CNT_CTL_CLR BIT(3)
#define BIT_DMA_ITR_TX_IDL_CNT_CTL_REACHED_TRESH BIT(4)
#define RGF_DMA_ITR_RX_DESQ_NO_MOD (0x881d50)
#define RGF_DMA_ITR_RX_CNT_TRSH (0x881d44)
#define RGF_DMA_ITR_RX_CNT_DATA (0x881d48)
#define RGF_DMA_ITR_RX_CNT_CTL (0x881d4c)
#define BIT_DMA_ITR_RX_CNT_CTL_EN BIT(0)
#define BIT_DMA_ITR_RX_CNT_CTL_EXT_TIC_SEL BIT(1)
#define BIT_DMA_ITR_RX_CNT_CTL_FOREVER BIT(2)
#define BIT_DMA_ITR_RX_CNT_CTL_CLR BIT(3)
#define BIT_DMA_ITR_RX_CNT_CTL_REACHED_TRESH BIT(4)
#define BIT_DMA_ITR_RX_CNT_CTL_CROSS_EN BIT(5)
#define BIT_DMA_ITR_RX_CNT_CTL_FREE_RUNNIG BIT(6)
#define RGF_DMA_ITR_RX_IDL_CNT_TRSH (0x881d54)
#define RGF_DMA_ITR_RX_IDL_CNT_DATA (0x881d58)
#define RGF_DMA_ITR_RX_IDL_CNT_CTL (0x881d5c)
#define BIT_DMA_ITR_RX_IDL_CNT_CTL_EN BIT(0)
#define BIT_DMA_ITR_RX_IDL_CNT_CTL_EXT_TIC_SEL BIT(1)
#define BIT_DMA_ITR_RX_IDL_CNT_CTL_FOREVER BIT(2)
#define BIT_DMA_ITR_RX_IDL_CNT_CTL_CLR BIT(3)
#define BIT_DMA_ITR_RX_IDL_CNT_CTL_REACHED_TRESH BIT(4)
#define RGF_DMA_PSEUDO_CAUSE (0x881c68)
#define RGF_DMA_PSEUDO_CAUSE_MASK_SW (0x881c6c)
#define RGF_DMA_PSEUDO_CAUSE_MASK_FW (0x881c70)
@ -164,6 +227,20 @@ struct RGF_ICR {
#define RGF_CAF_PLL_LOCK_STATUS (0x88afec)
#define BIT_CAF_OSC_DIG_XTAL_STABLE BIT(0)
#define RGF_USER_JTAG_DEV_ID (0x880b34) /* device ID */
#define JTAG_DEV_ID_MARLON_B0 (0x0612072f)
#define JTAG_DEV_ID_SPARROW_A0 (0x0632072f)
#define JTAG_DEV_ID_SPARROW_A1 (0x1632072f)
#define JTAG_DEV_ID_SPARROW_B0 (0x2632072f)
enum {
HW_VER_UNKNOWN,
HW_VER_MARLON_B0, /* JTAG_DEV_ID_MARLON_B0 */
HW_VER_SPARROW_A0, /* JTAG_DEV_ID_SPARROW_A0 */
HW_VER_SPARROW_A1, /* JTAG_DEV_ID_SPARROW_A1 */
HW_VER_SPARROW_B0, /* JTAG_DEV_ID_SPARROW_B0 */
};
/* popular locations */
#define HOST_MBOX HOSTADDR(RGF_USER_USER_SCRATCH_PAD)
#define HOST_SW_INT (HOSTADDR(RGF_USER_USER_ICR) + \
@ -303,6 +380,10 @@ struct vring {
struct vring_tx_data {
int enabled;
cycles_t idle, last_idle, begin;
u8 agg_wsize; /* agreed aggregation window, 0 - no agg */
u16 agg_timeout;
u8 agg_amsdu;
bool addba_in_progress; /* if set, agg_xxx is for request in progress */
};
enum { /* for wil6210_priv.status */
@ -313,6 +394,7 @@ enum { /* for wil6210_priv.status */
wil_status_reset_done,
wil_status_irqen, /* FIXME: interrupts enabled - for debug */
wil_status_napi_en, /* NAPI enabled protected by wil->mutex */
wil_status_last /* keep last */
};
struct pci_dev;
@ -397,15 +479,40 @@ enum {
fw_recovery_running = 2,
};
enum {
hw_capability_reset_v2 = 0,
hw_capability_advanced_itr_moderation = 1,
hw_capability_last
};
struct wil_back_rx {
struct list_head list;
/* request params, converted to CPU byte order - what we asked for */
u8 cidxtid;
u8 dialog_token;
u16 ba_param_set;
u16 ba_timeout;
u16 ba_seq_ctrl;
};
struct wil_back_tx {
struct list_head list;
/* request params, converted to CPU byte order - what we asked for */
u8 ringid;
u8 agg_wsize;
u16 agg_timeout;
};
struct wil6210_priv {
struct pci_dev *pdev;
int n_msi;
struct wireless_dev *wdev;
void __iomem *csr;
ulong status;
DECLARE_BITMAP(status, wil_status_last);
u32 fw_version;
u32 hw_version;
struct wil_board *board;
const char *hw_name;
DECLARE_BITMAP(hw_capabilities, hw_capability_last);
u8 n_mids; /* number of additional MIDs as reported by FW */
u32 recovery_count; /* num of FW recovery attempts in a short time */
u32 recovery_state; /* FW recovery state machine */
@ -415,7 +522,11 @@ struct wil6210_priv {
u32 monitor_flags;
u32 secure_pcp; /* create secure PCP? */
int sinfo_gen;
u32 itr_trsh;
/* interrupt moderation */
u32 tx_max_burst_duration;
u32 tx_interframe_timeout;
u32 rx_max_burst_duration;
u32 rx_interframe_timeout;
/* cached ISR registers */
u32 isr_misc;
/* mailbox related */
@ -429,7 +540,7 @@ struct wil6210_priv {
u16 reply_size;
struct workqueue_struct *wmi_wq; /* for deferred calls */
struct work_struct wmi_event_worker;
struct workqueue_struct *wmi_wq_conn; /* for connect worker */
struct workqueue_struct *wq_service;
struct work_struct connect_worker;
struct work_struct disconnect_worker;
struct work_struct fw_error_worker; /* for FW error recovery */
@ -445,6 +556,13 @@ struct wil6210_priv {
spinlock_t wmi_ev_lock;
struct napi_struct napi_rx;
struct napi_struct napi_tx;
/* BACK */
struct list_head back_rx_pending;
struct mutex back_rx_mutex; /* protect @back_rx_pending */
struct work_struct back_rx_worker;
struct list_head back_tx_pending;
struct mutex back_tx_mutex; /* protect @back_tx_pending */
struct work_struct back_tx_worker;
/* DMA related */
struct vring vring_rx;
struct vring vring_tx[WIL6210_MAX_TX_RINGS];
@ -529,7 +647,6 @@ void wil_if_remove(struct wil6210_priv *wil);
int wil_priv_init(struct wil6210_priv *wil);
void wil_priv_deinit(struct wil6210_priv *wil);
int wil_reset(struct wil6210_priv *wil);
void wil_set_itr_trsh(struct wil6210_priv *wil);
void wil_fw_error_recovery(struct wil6210_priv *wil);
void wil_set_recovery_state(struct wil6210_priv *wil, int state);
void wil_link_on(struct wil6210_priv *wil);
@ -567,12 +684,26 @@ int wmi_p2p_cfg(struct wil6210_priv *wil, int channel);
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);
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);
int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
u16 status, bool amsdu, u16 agg_wsize, u16 timeout);
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);
void wil_back_rx_worker(struct work_struct *work);
void wil_back_rx_flush(struct wil6210_priv *wil);
int wil_addba_tx_request(struct wil6210_priv *wil, u8 ringid, u16 wsize);
void wil_back_tx_worker(struct work_struct *work);
void wil_back_tx_flush(struct wil6210_priv *wil);
void wil6210_clear_irq(struct wil6210_priv *wil);
int wil6210_init_irq(struct wil6210_priv *wil, int irq);
void wil6210_fini_irq(struct wil6210_priv *wil, int irq);
void wil_mask_irq(struct wil6210_priv *wil);
void wil_unmask_irq(struct wil6210_priv *wil);
void wil_configure_interrupt_moderation(struct wil6210_priv *wil);
void wil_disable_irq(struct wil6210_priv *wil);
void wil_enable_irq(struct wil6210_priv *wil);
int wil_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,

View file

@ -23,10 +23,15 @@
#include "wmi.h"
#include "trace.h"
static uint max_assoc_sta = 1;
static uint max_assoc_sta = WIL6210_MAX_CID;
module_param(max_assoc_sta, uint, S_IRUGO | S_IWUSR);
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_PARM_DESC(agg_wsize, " Window size for Tx Block Ack after connect;"
" 0 - use default; < 0 - don't auto-establish");
/**
* WMI event receiving - theory of operations
*
@ -197,7 +202,7 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
might_sleep();
if (!test_bit(wil_status_fwready, &wil->status)) {
if (!test_bit(wil_status_fwready, wil->status)) {
wil_err(wil, "WMI: cannot send command while FW not ready\n");
return -EAGAIN;
}
@ -300,7 +305,7 @@ static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d,
wil_dbg_wmi(wil, "WMI: got FW ready event\n");
wil_set_recovery_state(wil, fw_recovery_idle);
set_bit(wil_status_fwready, &wil->status);
set_bit(wil_status_fwready, wil->status);
/* let the reset sequence continue */
complete(&wil->wmi_ready);
}
@ -438,7 +443,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
(wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
if (!test_bit(wil_status_fwconnecting, &wil->status)) {
if (!test_bit(wil_status_fwconnecting, wil->status)) {
wil_err(wil, "Not in connecting state\n");
return;
}
@ -461,8 +466,8 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL);
}
clear_bit(wil_status_fwconnecting, &wil->status);
set_bit(wil_status_fwconnected, &wil->status);
clear_bit(wil_status_fwconnecting, wil->status);
set_bit(wil_status_fwconnected, wil->status);
/* FIXME FW can transmit only ucast frames to peer */
/* FIXME real ring_id instead of hard coded 0 */
@ -470,7 +475,7 @@ static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
wil->sta[evt->cid].status = wil_sta_conn_pending;
wil->pending_connect_cid = evt->cid;
queue_work(wil->wmi_wq_conn, &wil->connect_worker);
queue_work(wil->wq_service, &wil->connect_worker);
}
static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
@ -543,6 +548,22 @@ static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
}
}
static void wil_addba_tx_cid(struct wil6210_priv *wil, u8 cid, u16 wsize)
{
struct vring_tx_data *t;
int i;
for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
if (cid != wil->vring2cid_tid[i][0])
continue;
t = &wil->vring_tx_data[i];
if (!t->enabled)
continue;
wil_addba_tx_request(wil, i, wsize);
}
}
static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len)
{
struct net_device *ndev = wil_to_ndev(wil);
@ -557,6 +578,8 @@ static void wmi_evt_linkup(struct wil6210_priv *wil, int id, void *d, int len)
}
wil->sta[cid].data_port_open = true;
if (agg_wsize >= 0)
wil_addba_tx_cid(wil, cid, agg_wsize);
netif_carrier_on(ndev);
}
@ -582,55 +605,89 @@ static void wmi_evt_ba_status(struct wil6210_priv *wil, int id, void *d,
int len)
{
struct wmi_vring_ba_status_event *evt = d;
struct wil_sta_info *sta;
uint i, cid;
struct vring_tx_data *txdata;
/* TODO: use Rx BA status, not Tx one */
wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d\n",
wil_dbg_wmi(wil, "BACK[%d] %s {%d} timeout %d AMSDU%s\n",
evt->ringid,
evt->status == WMI_BA_AGREED ? "OK" : "N/A",
evt->agg_wsize, __le16_to_cpu(evt->ba_timeout));
evt->agg_wsize, __le16_to_cpu(evt->ba_timeout),
evt->amsdu ? "+" : "-");
if (evt->ringid >= WIL6210_MAX_TX_RINGS) {
wil_err(wil, "invalid ring id %d\n", evt->ringid);
return;
}
mutex_lock(&wil->mutex);
if (evt->status != WMI_BA_AGREED) {
evt->ba_timeout = 0;
evt->agg_wsize = 0;
evt->amsdu = 0;
}
cid = wil->vring2cid_tid[evt->ringid][0];
if (cid >= WIL6210_MAX_CID) {
wil_err(wil, "invalid CID %d for vring %d\n", cid, evt->ringid);
goto out;
txdata = &wil->vring_tx_data[evt->ringid];
txdata->agg_timeout = le16_to_cpu(evt->ba_timeout);
txdata->agg_wsize = evt->agg_wsize;
txdata->agg_amsdu = evt->amsdu;
txdata->addba_in_progress = false;
}
static void wmi_evt_addba_rx_req(struct wil6210_priv *wil, int id, void *d,
int len)
{
struct wmi_rcp_addba_req_event *evt = d;
wil_addba_rx_request(wil, evt->cidxtid, evt->dialog_token,
evt->ba_param_set, evt->ba_timeout,
evt->ba_seq_ctrl);
}
static void wmi_evt_delba(struct wil6210_priv *wil, int id, void *d, int len)
__acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
{
struct wmi_delba_event *evt = d;
u8 cid, tid;
u16 reason = __le16_to_cpu(evt->reason);
struct wil_sta_info *sta;
struct wil_tid_ampdu_rx *r;
might_sleep();
parse_cidxtid(evt->cidxtid, &cid, &tid);
wil_dbg_wmi(wil, "DELBA CID %d TID %d from %s reason %d\n",
cid, tid,
evt->from_initiator ? "originator" : "recipient",
reason);
if (!evt->from_initiator) {
int i;
/* find Tx vring it belongs to */
for (i = 0; i < ARRAY_SIZE(wil->vring2cid_tid); i++) {
if ((wil->vring2cid_tid[i][0] == cid) &&
(wil->vring2cid_tid[i][1] == tid)) {
struct vring_tx_data *txdata =
&wil->vring_tx_data[i];
wil_dbg_wmi(wil, "DELBA Tx vring %d\n", i);
txdata->agg_timeout = 0;
txdata->agg_wsize = 0;
txdata->addba_in_progress = false;
break; /* max. 1 matching ring */
}
}
if (i >= ARRAY_SIZE(wil->vring2cid_tid))
wil_err(wil, "DELBA: unable to find Tx vring\n");
return;
}
sta = &wil->sta[cid];
if (sta->status == wil_sta_unused) {
wil_err(wil, "CID %d unused\n", cid);
goto out;
}
wil_dbg_wmi(wil, "BACK for CID %d %pM\n", cid, sta->addr);
for (i = 0; i < WIL_STA_TID_NUM; i++) {
struct wil_tid_ampdu_rx *r;
unsigned long flags;
spin_lock_bh(&sta->tid_rx_lock);
spin_lock_irqsave(&sta->tid_rx_lock, flags);
r = sta->tid_rx[tid];
sta->tid_rx[tid] = NULL;
wil_tid_ampdu_rx_free(wil, r);
r = sta->tid_rx[i];
sta->tid_rx[i] = NULL;
wil_tid_ampdu_rx_free(wil, r);
spin_unlock_irqrestore(&sta->tid_rx_lock, flags);
if ((evt->status == WMI_BA_AGREED) && evt->agg_wsize)
sta->tid_rx[i] = wil_tid_ampdu_rx_alloc(wil,
evt->agg_wsize, 0);
}
out:
mutex_unlock(&wil->mutex);
spin_unlock_bh(&sta->tid_rx_lock);
}
static const struct {
@ -648,6 +705,8 @@ static const struct {
{WMI_DATA_PORT_OPEN_EVENTID, wmi_evt_linkup},
{WMI_WBE_LINKDOWN_EVENTID, wmi_evt_linkdown},
{WMI_BA_STATUS_EVENTID, wmi_evt_ba_status},
{WMI_RCP_ADDBA_REQ_EVENTID, wmi_evt_addba_rx_req},
{WMI_DELBA_EVENTID, wmi_evt_delba},
};
/*
@ -667,7 +726,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
ulong flags;
unsigned n;
if (!test_bit(wil_status_reset_done, &wil->status)) {
if (!test_bit(wil_status_reset_done, wil->status)) {
wil_err(wil, "Reset in progress. Cannot handle WMI event\n");
return;
}
@ -1024,13 +1083,14 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
struct wmi_cfg_rx_chain_cmd cmd = {
.action = WMI_RX_CHAIN_ADD,
.rx_sw_ring = {
.max_mpdu_size = cpu_to_le16(mtu_max + ETH_HLEN),
.max_mpdu_size = cpu_to_le16(wil_mtu2macbuf(mtu_max)),
.ring_mem_base = cpu_to_le64(vring->pa),
.ring_size = cpu_to_le16(vring->size),
},
.mid = 0, /* TODO - what is it? */
.decap_trans_type = WMI_DECAP_TYPE_802_3,
.reorder_type = WMI_RX_SW_REORDER,
.host_thrsh = cpu_to_le16(rx_ring_overflow_thrsh),
};
struct {
struct wil6210_mbox_hdr_wmi wmi;
@ -1110,6 +1170,87 @@ int wmi_disconnect_sta(struct wil6210_priv *wil, const u8 *mac, u16 reason)
return wmi_send(wil, WMI_DISCONNECT_STA_CMDID, &cmd, sizeof(cmd));
}
int wmi_addba(struct wil6210_priv *wil, u8 ringid, u8 size, u16 timeout)
{
struct wmi_vring_ba_en_cmd cmd = {
.ringid = ringid,
.agg_max_wsize = size,
.ba_timeout = cpu_to_le16(timeout),
.amsdu = 0,
};
wil_dbg_wmi(wil, "%s(ring %d size %d timeout %d)\n", __func__,
ringid, size, timeout);
return wmi_send(wil, WMI_VRING_BA_EN_CMDID, &cmd, sizeof(cmd));
}
int wmi_delba_tx(struct wil6210_priv *wil, u8 ringid, u16 reason)
{
struct wmi_vring_ba_dis_cmd cmd = {
.ringid = ringid,
.reason = cpu_to_le16(reason),
};
wil_dbg_wmi(wil, "%s(ring %d reason %d)\n", __func__,
ringid, reason);
return wmi_send(wil, WMI_VRING_BA_DIS_CMDID, &cmd, sizeof(cmd));
}
int wmi_delba_rx(struct wil6210_priv *wil, u8 cidxtid, u16 reason)
{
struct wmi_rcp_delba_cmd cmd = {
.cidxtid = cidxtid,
.reason = cpu_to_le16(reason),
};
wil_dbg_wmi(wil, "%s(CID %d TID %d reason %d)\n", __func__,
cidxtid & 0xf, (cidxtid >> 4) & 0xf, reason);
return wmi_send(wil, WMI_RCP_DELBA_CMDID, &cmd, sizeof(cmd));
}
int wmi_addba_rx_resp(struct wil6210_priv *wil, u8 cid, u8 tid, u8 token,
u16 status, bool amsdu, u16 agg_wsize, u16 timeout)
{
int rc;
struct wmi_rcp_addba_resp_cmd cmd = {
.cidxtid = mk_cidxtid(cid, tid),
.dialog_token = token,
.status_code = cpu_to_le16(status),
/* bit 0: A-MSDU supported
* bit 1: policy (should be 0 for us)
* bits 2..5: TID
* bits 6..15: buffer size
*/
.ba_param_set = cpu_to_le16((amsdu ? 1 : 0) | (tid << 2) |
(agg_wsize << 6)),
.ba_timeout = cpu_to_le16(timeout),
};
struct {
struct wil6210_mbox_hdr_wmi wmi;
struct wmi_rcp_addba_resp_sent_event evt;
} __packed reply;
wil_dbg_wmi(wil,
"ADDBA response for CID %d TID %d size %d timeout %d status %d AMSDU%s\n",
cid, tid, agg_wsize, timeout, status, amsdu ? "+" : "-");
rc = wmi_call(wil, WMI_RCP_ADDBA_RESP_CMDID, &cmd, sizeof(cmd),
WMI_ADDBA_RESP_SENT_EVENTID, &reply, sizeof(reply), 100);
if (rc)
return rc;
if (reply.evt.status) {
wil_err(wil, "ADDBA response failed with status %d\n",
le16_to_cpu(reply.evt.status));
rc = -EINVAL;
}
return rc;
}
void wmi_event_flush(struct wil6210_priv *wil)
{
struct pending_wmi_event *evt, *t;

View file

@ -586,6 +586,7 @@ struct wmi_vring_ba_en_cmd {
u8 ringid;
u8 agg_max_wsize;
__le16 ba_timeout;
u8 amsdu;
} __packed;
/*
@ -1052,14 +1053,23 @@ struct wmi_scan_complete_event {
enum wmi_vring_ba_status {
WMI_BA_AGREED = 0,
WMI_BA_NON_AGREED = 1,
/* BA_EN in middle of teardown flow */
WMI_BA_TD_WIP = 2,
/* BA_DIS or BA_EN in middle of BA SETUP flow */
WMI_BA_SETUP_WIP = 3,
/* BA_EN when the BA session is already active */
WMI_BA_SESSION_ACTIVE = 4,
/* BA_DIS when the BA session is not active */
WMI_BA_SESSION_NOT_ACTIVE = 5,
};
struct wmi_vring_ba_status_event {
__le16 status;
__le16 status; /* enum wmi_vring_ba_status */
u8 reserved[2];
u8 ringid;
u8 agg_wsize;
__le16 ba_timeout;
u8 amsdu;
} __packed;
/*

View file

@ -45,7 +45,6 @@
#include <linux/ptrace.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/ctype.h>
#include <linux/timer.h>
#include <asm/byteorder.h>
#include <asm/io.h>
@ -2699,16 +2698,7 @@ static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
domain[REGDOMAINSZ] = 0;
rc = -EINVAL;
for (i = 0; i < ARRAY_SIZE(channel_table); i++) {
/* strcasecmp doesn't exist in the library */
char *a = channel_table[i].name;
char *b = domain;
while (*a) {
char c1 = *a++;
char c2 = *b++;
if (tolower(c1) != tolower(c2))
break;
}
if (!*a && !*b) {
if (!strcasecmp(channel_table[i].name, domain)) {
priv->config_reg_domain = channel_table[i].reg_domain;
rc = 0;
}

View file

@ -4318,6 +4318,7 @@ redo:
mutex_unlock(&wl->mutex);
cancel_delayed_work_sync(&dev->periodic_work);
cancel_work_sync(&wl->tx_work);
b43_leds_stop(dev);
mutex_lock(&wl->mutex);
dev = wl->current_dev;
if (!dev || b43_status(dev) < B43_STAT_STARTED) {

View file

@ -1743,25 +1743,6 @@ u16 freq_r3A_value(u16 frequency)
return value;
}
void b43legacy_radio_set_tx_iq(struct b43legacy_wldev *dev)
{
static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 };
static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A };
u16 tmp = b43legacy_radio_read16(dev, 0x001E);
int i;
int j;
for (i = 0; i < 5; i++) {
for (j = 0; j < 5; j++) {
if (tmp == (data_high[i] | data_low[j])) {
b43legacy_phy_write(dev, 0x0069, (i - j) << 8 |
0x00C0);
return;
}
}
}
}
int b43legacy_radio_selectchannel(struct b43legacy_wldev *dev,
u8 channel,
int synthetic_pu_workaround)

View file

@ -92,7 +92,6 @@ void b43legacy_nrssi_hw_write(struct b43legacy_wldev *dev, u16 offset, s16 val);
void b43legacy_nrssi_hw_update(struct b43legacy_wldev *dev, u16 val);
void b43legacy_nrssi_mem_update(struct b43legacy_wldev *dev);
void b43legacy_radio_set_tx_iq(struct b43legacy_wldev *dev);
u16 b43legacy_radio_calibrationvalue(struct b43legacy_wldev *dev);
#endif /* B43legacy_RADIO_H_ */

View file

@ -996,18 +996,20 @@ out:
}
#define BRCMF_SDIO_DEVICE(dev_id) \
{SDIO_DEVICE(BRCM_SDIO_VENDOR_ID_BROADCOM, dev_id)}
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, dev_id)}
/* devices we support, null terminated */
static const struct sdio_device_id brcmf_sdmmc_ids[] = {
BRCMF_SDIO_DEVICE(BRCM_SDIO_43143_DEVICE_ID),
BRCMF_SDIO_DEVICE(BRCM_SDIO_43241_DEVICE_ID),
BRCMF_SDIO_DEVICE(BRCM_SDIO_4329_DEVICE_ID),
BRCMF_SDIO_DEVICE(BRCM_SDIO_4330_DEVICE_ID),
BRCMF_SDIO_DEVICE(BRCM_SDIO_4334_DEVICE_ID),
BRCMF_SDIO_DEVICE(BRCM_SDIO_43362_DEVICE_ID),
BRCMF_SDIO_DEVICE(BRCM_SDIO_4335_4339_DEVICE_ID),
BRCMF_SDIO_DEVICE(BRCM_SDIO_4354_DEVICE_ID),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43143),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43241),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4329),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4330),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4334),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43340),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43341),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_43362),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4335_4339),
BRCMF_SDIO_DEVICE(SDIO_DEVICE_ID_BROADCOM_4354),
{ /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);

View file

@ -38,6 +38,7 @@
#include "proto.h"
#include "vendor.h"
#include "bus.h"
#include "common.h"
#define BRCMF_SCAN_IE_LEN_MAX 2048
#define BRCMF_PNO_VERSION 2
@ -452,16 +453,16 @@ static void convert_key_from_CPU(struct brcmf_wsec_key *key,
}
static int
send_key_to_dongle(struct net_device *ndev, struct brcmf_wsec_key *key)
send_key_to_dongle(struct brcmf_if *ifp, struct brcmf_wsec_key *key)
{
int err;
struct brcmf_wsec_key_le key_le;
convert_key_from_CPU(key, &key_le);
brcmf_netdev_wait_pend8021x(ndev);
brcmf_netdev_wait_pend8021x(ifp);
err = brcmf_fil_bsscfg_data_set(netdev_priv(ndev), "wsec_key", &key_le,
err = brcmf_fil_bsscfg_data_set(ifp, "wsec_key", &key_le,
sizeof(key_le));
if (err)
@ -1670,7 +1671,7 @@ brcmf_set_sharedkey(struct net_device *ndev,
brcmf_dbg(CONN, "key length (%d) key index (%d) algo (%d)\n",
key.len, key.index, key.algo);
brcmf_dbg(CONN, "key \"%s\"\n", key.data);
err = send_key_to_dongle(ndev, &key);
err = send_key_to_dongle(netdev_priv(ndev), &key);
if (err)
return err;
@ -2052,7 +2053,7 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
/* check for key index change */
if (key.len == 0) {
/* key delete */
err = send_key_to_dongle(ndev, &key);
err = send_key_to_dongle(ifp, &key);
if (err)
brcmf_err("key delete error (%d)\n", err);
} else {
@ -2108,7 +2109,7 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev,
brcmf_err("Invalid cipher (0x%x)\n", params->cipher);
return -EINVAL;
}
err = send_key_to_dongle(ndev, &key);
err = send_key_to_dongle(ifp, &key);
if (err)
brcmf_err("wsec_key error (%d)\n", err);
}
@ -2121,7 +2122,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
struct key_params *params)
{
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_wsec_key key;
struct brcmf_wsec_key *key;
s32 val;
s32 wsec;
s32 err = 0;
@ -2132,54 +2133,62 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
if (!check_vif_up(ifp->vif))
return -EIO;
if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) {
/* we ignore this key index in this case */
brcmf_err("invalid key index (%d)\n", key_idx);
return -EINVAL;
}
if (mac_addr &&
(params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
(params->cipher != WLAN_CIPHER_SUITE_WEP104)) {
brcmf_dbg(TRACE, "Exit");
return brcmf_add_keyext(wiphy, ndev, key_idx, mac_addr, params);
}
memset(&key, 0, sizeof(key));
key.len = (u32) params->key_len;
key.index = (u32) key_idx;
key = &ifp->vif->profile.key[key_idx];
memset(key, 0, sizeof(*key));
if (key.len > sizeof(key.data)) {
brcmf_err("Too long key length (%u)\n", key.len);
if (params->key_len > sizeof(key->data)) {
brcmf_err("Too long key length (%u)\n", params->key_len);
err = -EINVAL;
goto done;
}
memcpy(key.data, params->key, key.len);
key->len = params->key_len;
key->index = key_idx;
key.flags = BRCMF_PRIMARY_KEY;
memcpy(key->data, params->key, key->len);
key->flags = BRCMF_PRIMARY_KEY;
switch (params->cipher) {
case WLAN_CIPHER_SUITE_WEP40:
key.algo = CRYPTO_ALGO_WEP1;
key->algo = CRYPTO_ALGO_WEP1;
val = WEP_ENABLED;
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP40\n");
break;
case WLAN_CIPHER_SUITE_WEP104:
key.algo = CRYPTO_ALGO_WEP128;
key->algo = CRYPTO_ALGO_WEP128;
val = WEP_ENABLED;
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_WEP104\n");
break;
case WLAN_CIPHER_SUITE_TKIP:
if (!brcmf_is_apmode(ifp->vif)) {
brcmf_dbg(CONN, "Swapping RX/TX MIC key\n");
memcpy(keybuf, &key.data[24], sizeof(keybuf));
memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
memcpy(&key.data[16], keybuf, sizeof(keybuf));
memcpy(keybuf, &key->data[24], sizeof(keybuf));
memcpy(&key->data[24], &key->data[16], sizeof(keybuf));
memcpy(&key->data[16], keybuf, sizeof(keybuf));
}
key.algo = CRYPTO_ALGO_TKIP;
key->algo = CRYPTO_ALGO_TKIP;
val = TKIP_ENABLED;
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_TKIP\n");
break;
case WLAN_CIPHER_SUITE_AES_CMAC:
key.algo = CRYPTO_ALGO_AES_CCM;
key->algo = CRYPTO_ALGO_AES_CCM;
val = AES_ENABLED;
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_AES_CMAC\n");
break;
case WLAN_CIPHER_SUITE_CCMP:
key.algo = CRYPTO_ALGO_AES_CCM;
key->algo = CRYPTO_ALGO_AES_CCM;
val = AES_ENABLED;
brcmf_dbg(CONN, "WLAN_CIPHER_SUITE_CCMP\n");
break;
@ -2189,7 +2198,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
goto done;
}
err = send_key_to_dongle(ndev, &key);
err = send_key_to_dongle(ifp, key);
if (err)
goto done;
@ -2222,7 +2231,7 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
if (!check_vif_up(ifp->vif))
return -EIO;
if (key_idx >= DOT11_MAX_DEFAULT_KEYS) {
if (key_idx >= BRCMF_MAX_DEFAULT_KEYS) {
/* we ignore this key index in this case */
brcmf_err("invalid key index (%d)\n", key_idx);
return -EINVAL;
@ -2237,7 +2246,7 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
brcmf_dbg(CONN, "key index (%d)\n", key_idx);
/* Set the new key/index */
err = send_key_to_dongle(ndev, &key);
err = send_key_to_dongle(ifp, &key);
brcmf_dbg(TRACE, "Exit\n");
return err;
@ -2305,6 +2314,39 @@ brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
return -EOPNOTSUPP;
}
static void
brcmf_cfg80211_reconfigure_wep(struct brcmf_if *ifp)
{
s32 err;
u8 key_idx;
struct brcmf_wsec_key *key;
s32 wsec;
for (key_idx = 0; key_idx < BRCMF_MAX_DEFAULT_KEYS; key_idx++) {
key = &ifp->vif->profile.key[key_idx];
if ((key->algo == CRYPTO_ALGO_WEP1) ||
(key->algo == CRYPTO_ALGO_WEP128))
break;
}
if (key_idx == BRCMF_MAX_DEFAULT_KEYS)
return;
err = send_key_to_dongle(ifp, key);
if (err) {
brcmf_err("Setting WEP key failed (%d)\n", err);
return;
}
err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec);
if (err) {
brcmf_err("get wsec error (%d)\n", err);
return;
}
wsec |= WEP_ENABLED;
err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec);
if (err)
brcmf_err("set wsec error (%d)\n", err);
}
static s32
brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
const u8 *mac, struct station_info *sinfo)
@ -3695,17 +3737,12 @@ static u32
brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd)
{
__le32 iecount_le;
__le32 pktflag_le;
strncpy(iebuf, add_del_cmd, VNDR_IE_CMD_LEN - 1);
iebuf[VNDR_IE_CMD_LEN - 1] = '\0';
iecount_le = cpu_to_le32(1);
memcpy(&iebuf[VNDR_IE_COUNT_OFFSET], &iecount_le, sizeof(iecount_le));
put_unaligned_le32(1, &iebuf[VNDR_IE_COUNT_OFFSET]);
pktflag_le = cpu_to_le32(pktflag);
memcpy(&iebuf[VNDR_IE_PKTFLAG_OFFSET], &pktflag_le, sizeof(pktflag_le));
put_unaligned_le32(pktflag, &iebuf[VNDR_IE_PKTFLAG_OFFSET]);
memcpy(&iebuf[VNDR_IE_VSIE_OFFSET], ie_ptr, ie_len);
@ -3924,6 +3961,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_if *ifp = netdev_priv(ndev);
const struct brcmf_tlv *ssid_ie;
const struct brcmf_tlv *country_ie;
struct brcmf_ssid_le ssid_le;
s32 err = -EPERM;
const struct brcmf_tlv *rsn_ie;
@ -3933,6 +3971,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
struct brcmf_fil_bss_enable_le bss_enable;
u16 chanspec;
bool mbss;
int is_11d;
brcmf_dbg(TRACE, "ctrlchn=%d, center=%d, bw=%d, beacon_interval=%d, dtim_period=%d,\n",
settings->chandef.chan->hw_value,
@ -3941,10 +3980,16 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
brcmf_dbg(TRACE, "ssid=%s(%zu), auth_type=%d, inactivity_timeout=%d\n",
settings->ssid, settings->ssid_len, settings->auth_type,
settings->inactivity_timeout);
dev_role = ifp->vif->wdev.iftype;
mbss = ifp->vif->mbss;
/* store current 11d setting */
brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_REGULATORY, &ifp->vif->is_11d);
country_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
settings->beacon.tail_len,
WLAN_EID_COUNTRY);
is_11d = country_ie ? 1 : 0;
memset(&ssid_le, 0, sizeof(ssid_le));
if (settings->ssid == NULL || settings->ssid_len == 0) {
ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
@ -4010,6 +4055,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
goto exit;
}
if (is_11d != ifp->vif->is_11d) {
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY,
is_11d);
if (err < 0) {
brcmf_err("Regulatory Set Error, %d\n", err);
goto exit;
}
}
if (settings->beacon_interval) {
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
settings->beacon_interval);
@ -4042,6 +4095,10 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
brcmf_err("SET INFRA error %d\n", err);
goto exit;
}
} else if (WARN_ON(is_11d != ifp->vif->is_11d)) {
/* Multiple-BSS should use same 11d configuration */
err = -EINVAL;
goto exit;
}
if (dev_role == NL80211_IFTYPE_AP) {
if ((brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) && (!mbss))
@ -4057,6 +4114,10 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
brcmf_err("BRCMF_C_UP error (%d)\n", err);
goto exit;
}
/* On DOWN the firmware removes the WEP keys, reconfigure
* them if they were set.
*/
brcmf_cfg80211_reconfigure_wep(ifp);
memset(&join_params, 0, sizeof(join_params));
/* join parameters starts with ssid */
@ -4133,6 +4194,11 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev)
brcmf_err("setting INFRA mode failed %d\n", err);
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS))
brcmf_fil_iovar_int_set(ifp, "mbss", 0);
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_REGULATORY,
ifp->vif->is_11d);
if (err < 0)
brcmf_err("restoring REGULATORY setting failed %d\n",
err);
/* Bring device back up so it can be used again */
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
if (err < 0)
@ -4197,6 +4263,34 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
return err;
}
static int
brcmf_cfg80211_change_station(struct wiphy *wiphy, struct net_device *ndev,
const u8 *mac, struct station_parameters *params)
{
struct brcmf_if *ifp = netdev_priv(ndev);
s32 err;
brcmf_dbg(TRACE, "Enter, MAC %pM, mask 0x%04x set 0x%04x\n", mac,
params->sta_flags_mask, params->sta_flags_set);
/* Ignore all 00 MAC */
if (is_zero_ether_addr(mac))
return 0;
if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)))
return 0;
if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SCB_AUTHORIZE,
(void *)mac, ETH_ALEN);
else
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SCB_DEAUTHORIZE,
(void *)mac, ETH_ALEN);
if (err < 0)
brcmf_err("Setting SCB (de-)authorize failed, %d\n", err);
return err;
}
static void
brcmf_cfg80211_mgmt_frame_register(struct wiphy *wiphy,
@ -4471,6 +4565,7 @@ static struct cfg80211_ops wl_cfg80211_ops = {
.stop_ap = brcmf_cfg80211_stop_ap,
.change_beacon = brcmf_cfg80211_change_beacon,
.del_station = brcmf_cfg80211_del_station,
.change_station = brcmf_cfg80211_change_station,
.sched_scan_start = brcmf_cfg80211_sched_scan_start,
.sched_scan_stop = brcmf_cfg80211_sched_scan_stop,
.mgmt_frame_register = brcmf_cfg80211_mgmt_frame_register,
@ -5875,6 +5970,29 @@ int brcmf_cfg80211_wait_vif_event_timeout(struct brcmf_cfg80211_info *cfg,
vif_event_equals(event, action), timeout);
}
static void brcmf_cfg80211_reg_notifier(struct wiphy *wiphy,
struct regulatory_request *req)
{
struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
struct brcmf_fil_country_le ccreq;
int i;
brcmf_dbg(TRACE, "enter: initiator=%d, alpha=%c%c\n", req->initiator,
req->alpha2[0], req->alpha2[1]);
/* ignore non-ISO3166 country codes */
for (i = 0; i < sizeof(req->alpha2); i++)
if (req->alpha2[i] < 'A' || req->alpha2[i] > 'Z') {
brcmf_err("not a ISO3166 code\n");
return;
}
memset(&ccreq, 0, sizeof(ccreq));
ccreq.rev = cpu_to_le32(-1);
memcpy(ccreq.ccode, req->alpha2, sizeof(req->alpha2));
brcmf_fil_iovar_data_set(ifp, "country", &ccreq, sizeof(ccreq));
}
static void brcmf_free_wiphy(struct wiphy *wiphy)
{
kfree(wiphy->iface_combinations);
@ -5951,6 +6069,7 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr,
goto priv_out;
brcmf_dbg(INFO, "Registering custom regulatory\n");
wiphy->reg_notifier = brcmf_cfg80211_reg_notifier;
wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);

View file

@ -75,6 +75,8 @@
#define BRCMF_VNDR_IE_P2PAF_SHIFT 12
#define BRCMF_MAX_DEFAULT_KEYS 4
/**
* enum brcmf_scan_status - scan engine status
@ -125,11 +127,13 @@ struct brcmf_cfg80211_security {
* @ssid: ssid of associated/associating ap.
* @bssid: bssid of joined/joining ibss.
* @sec: security information.
* @key: key information
*/
struct brcmf_cfg80211_profile {
struct brcmf_ssid ssid;
u8 bssid[ETH_ALEN];
struct brcmf_cfg80211_security sec;
struct brcmf_wsec_key key[BRCMF_MAX_DEFAULT_KEYS];
};
/**
@ -196,6 +200,7 @@ struct brcmf_cfg80211_vif {
struct list_head list;
u16 mgmt_rx_reg;
bool mbss;
int is_11d;
};
/* association inform */

View file

@ -101,14 +101,7 @@
/* ARM Cortex M3 core, ID 0x82a */
#define BCM4329_CORE_ARM_BASE 0x18002000
#define BCM4329_RAMSIZE 0x48000
/* bcm43143 */
/* SDIO device core */
#define BCM43143_CORE_BUS_BASE 0x18002000
/* internal memory core */
#define BCM43143_CORE_SOCRAM_BASE 0x18004000
/* ARM Cortex M3 core, ID 0x82a */
#define BCM43143_CORE_ARM_BASE 0x18003000
#define BCM43143_RAMSIZE 0x70000
#define CORE_SB(base, field) \
@ -164,13 +157,6 @@ struct brcmf_core_priv {
struct brcmf_chip_priv *chip;
};
/* ARM CR4 core specific control flag bits */
#define ARMCR4_BCMA_IOCTL_CPUHALT 0x0020
/* D11 core specific control flag bits */
#define D11_BCMA_IOCTL_PHYCLOCKEN 0x0004
#define D11_BCMA_IOCTL_PHYRESET 0x0008
struct brcmf_chip_priv {
struct brcmf_chip pub;
const struct brcmf_buscore_ops *ops;
@ -495,6 +481,7 @@ static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
ci->pub.ramsize = 0x48000;
break;
case BRCM_CC_4334_CHIP_ID:
case BRCM_CC_43340_CHIP_ID:
ci->pub.ramsize = 0x80000;
break;
case BRCM_CC_4335_CHIP_ID:

View file

@ -25,6 +25,9 @@
#include "fwil.h"
#include "fwil_types.h"
#include "tracepoint.h"
#include "common.h"
const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
#define BRCMF_DEFAULT_BCN_TIMEOUT 3
#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40

View file

@ -0,0 +1,20 @@
/* Copyright (c) 2014 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef BRCMFMAC_COMMON_H
#define BRCMFMAC_COMMON_H
extern const u8 ALLFFMAC[ETH_ALEN];
#endif /* BRCMFMAC_COMMON_H */

View file

@ -1093,9 +1093,8 @@ static int brcmf_get_pend_8021x_cnt(struct brcmf_if *ifp)
return atomic_read(&ifp->pend_8021x_cnt);
}
int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp)
{
struct brcmf_if *ifp = netdev_priv(ndev);
int err;
err = wait_event_timeout(ifp->pend_8021x_wait,

View file

@ -29,8 +29,6 @@
/* For supporting multiple interfaces */
#define BRCMF_MAX_IFS 16
#define DOT11_MAX_DEFAULT_KEYS 4
/* Small, medium and maximum buffer size for dcmd
*/
#define BRCMF_DCMD_SMLEN 256
@ -167,7 +165,7 @@ struct brcmf_skb_reorder_data {
u8 *reorder;
};
int brcmf_netdev_wait_pend8021x(struct net_device *ndev);
int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp);
/* Return pointer to interface name */
char *brcmf_ifname(struct brcmf_pub *drvr, int idx);

View file

@ -25,6 +25,7 @@
#include "proto.h"
#include "flowring.h"
#include "msgbuf.h"
#include "common.h"
#define BRCMF_FLOWRING_HIGH 1024
@ -34,9 +35,6 @@
#define BRCMF_FLOWRING_HASH_AP(da, fifo, ifidx) (da[5] + fifo + ifidx * 16)
#define BRCMF_FLOWRING_HASH_STA(fifo, ifidx) (fifo + ifidx * 16)
static const u8 ALLZEROMAC[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
static const u8 ALLFFMAC[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
static const u8 brcmf_flowring_prio2fifo[] = {
1,
0,
@ -137,7 +135,7 @@ u32 brcmf_flowring_create(struct brcmf_flowring *flow, u8 da[ETH_ALEN],
hash = flow->hash;
for (i = 0; i < BRCMF_FLOWRING_HASHSIZE; i++) {
if ((hash[hash_idx].ifidx == BRCMF_FLOWRING_INVALID_IFIDX) &&
(memcmp(hash[hash_idx].mac, ALLZEROMAC, ETH_ALEN) == 0)) {
(is_zero_ether_addr(hash[hash_idx].mac))) {
found = true;
break;
}

View file

@ -43,6 +43,8 @@
#define BRCMF_C_SET_RADIO 38
#define BRCMF_C_GET_PHYTYPE 39
#define BRCMF_C_SET_KEY 45
#define BRCMF_C_GET_REGULATORY 46
#define BRCMF_C_SET_REGULATORY 47
#define BRCMF_C_SET_PASSIVE_SCAN 49
#define BRCMF_C_SCAN 50
#define BRCMF_C_SCAN_RESULTS 51
@ -60,6 +62,8 @@
#define BRCMF_C_GET_CURR_RATESET 114
#define BRCMF_C_GET_AP 117
#define BRCMF_C_SET_AP 118
#define BRCMF_C_SET_SCB_AUTHORIZE 121
#define BRCMF_C_SET_SCB_DEAUTHORIZE 122
#define BRCMF_C_GET_RSSI 127
#define BRCMF_C_GET_WSEC 133
#define BRCMF_C_SET_WSEC 134

View file

@ -112,6 +112,7 @@
#define BRCMF_WOWL_MAXPATTERNS 8
#define BRCMF_WOWL_MAXPATTERNSIZE 128
#define BRCMF_COUNTRY_BUF_SZ 4
/* join preference types for join_pref iovar */
enum brcmf_join_pref_types {
@ -525,4 +526,17 @@ struct brcmf_mbss_ssid_le {
unsigned char SSID[32];
};
/**
* struct brcmf_fil_country_le - country configuration structure.
*
* @country_abbrev: null-terminated country code used in the country IE.
* @rev: revision specifier for ccode. on set, -1 indicates unspecified.
* @ccode: null-terminated built-in country code.
*/
struct brcmf_fil_country_le {
char country_abbrev[BRCMF_COUNTRY_BUF_SZ];
__le32 rev;
char ccode[BRCMF_COUNTRY_BUF_SZ];
};
#endif /* FWIL_TYPES_H_ */

View file

@ -583,7 +583,7 @@ brcmf_msgbuf_flowring_create_worker(struct brcmf_msgbuf *msgbuf,
u32 flowid;
void *dma_buf;
u32 dma_sz;
long long address;
u64 address;
int err;
flowid = work->flowid;
@ -620,7 +620,7 @@ brcmf_msgbuf_flowring_create_worker(struct brcmf_msgbuf *msgbuf,
BRCMF_NROF_H2D_COMMON_MSGRINGS);
memcpy(create->sa, work->sa, ETH_ALEN);
memcpy(create->da, work->da, ETH_ALEN);
address = (long long)(long)msgbuf->flowring_dma_handle[flowid];
address = (u64)msgbuf->flowring_dma_handle[flowid];
create->flow_ring_addr.high_addr = cpu_to_le32(address >> 32);
create->flow_ring_addr.low_addr = cpu_to_le32(address & 0xffffffff);
create->max_items = cpu_to_le16(BRCMF_H2D_TXFLOWRING_MAX_ITEM);
@ -698,7 +698,7 @@ static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u8 flowid)
dma_addr_t physaddr;
u32 pktid;
struct msgbuf_tx_msghdr *tx_msghdr;
long long address;
u64 address;
commonring = msgbuf->flowrings[flowid];
if (!brcmf_commonring_write_available(commonring))
@ -742,7 +742,7 @@ static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u8 flowid)
tx_msghdr->seg_cnt = 1;
memcpy(tx_msghdr->txhdr, skb->data, ETH_HLEN);
tx_msghdr->data_len = cpu_to_le16(skb->len - ETH_HLEN);
address = (long long)(long)physaddr;
address = (u64)physaddr;
tx_msghdr->data_buf_addr.high_addr = cpu_to_le32(address >> 32);
tx_msghdr->data_buf_addr.low_addr =
cpu_to_le32(address & 0xffffffff);
@ -885,7 +885,7 @@ static u32 brcmf_msgbuf_rxbuf_data_post(struct brcmf_msgbuf *msgbuf, u32 count)
u32 pktlen;
dma_addr_t physaddr;
struct msgbuf_rx_bufpost *rx_bufpost;
long long address;
u64 address;
u32 pktid;
u32 i;
@ -894,7 +894,7 @@ static u32 brcmf_msgbuf_rxbuf_data_post(struct brcmf_msgbuf *msgbuf, u32 count)
count,
&alloced);
if (!ret_ptr) {
brcmf_err("Failed to reserve space in commonring\n");
brcmf_dbg(MSGBUF, "Failed to reserve space in commonring\n");
return 0;
}
@ -921,7 +921,7 @@ static u32 brcmf_msgbuf_rxbuf_data_post(struct brcmf_msgbuf *msgbuf, u32 count)
}
if (msgbuf->rx_metadata_offset) {
address = (long long)(long)physaddr;
address = (u64)physaddr;
rx_bufpost->metadata_buf_len =
cpu_to_le16(msgbuf->rx_metadata_offset);
rx_bufpost->metadata_buf_addr.high_addr =
@ -936,7 +936,7 @@ static u32 brcmf_msgbuf_rxbuf_data_post(struct brcmf_msgbuf *msgbuf, u32 count)
rx_bufpost->msg.msgtype = MSGBUF_TYPE_RXBUF_POST;
rx_bufpost->msg.request_id = cpu_to_le32(pktid);
address = (long long)(long)physaddr;
address = (u64)physaddr;
rx_bufpost->data_buf_len = cpu_to_le16((u16)pktlen);
rx_bufpost->data_buf_addr.high_addr =
cpu_to_le32(address >> 32);
@ -992,7 +992,7 @@ brcmf_msgbuf_rxbuf_ctrl_post(struct brcmf_msgbuf *msgbuf, bool event_buf,
u32 pktlen;
dma_addr_t physaddr;
struct msgbuf_rx_ioctl_resp_or_event *rx_bufpost;
long long address;
u64 address;
u32 pktid;
u32 i;
@ -1035,7 +1035,7 @@ brcmf_msgbuf_rxbuf_ctrl_post(struct brcmf_msgbuf *msgbuf, bool event_buf,
MSGBUF_TYPE_IOCTLRESP_BUF_POST;
rx_bufpost->msg.request_id = cpu_to_le32(pktid);
address = (long long)(long)physaddr;
address = (u64)physaddr;
rx_bufpost->host_buf_len = cpu_to_le16((u16)pktlen);
rx_bufpost->host_buf_addr.high_addr =
cpu_to_le32(address >> 32);
@ -1348,7 +1348,7 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
{
struct brcmf_bus_msgbuf *if_msgbuf;
struct brcmf_msgbuf *msgbuf;
long long address;
u64 address;
u32 count;
if_msgbuf = drvr->bus_if->msgbuf;
@ -1379,7 +1379,7 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
GFP_KERNEL);
if (!msgbuf->ioctbuf)
goto fail;
address = (long long)(long)msgbuf->ioctbuf_handle;
address = (u64)msgbuf->ioctbuf_handle;
msgbuf->ioctbuf_phys_hi = address >> 32;
msgbuf->ioctbuf_phys_lo = address & 0xffffffff;

View file

@ -959,14 +959,14 @@ brcmf_pcie_init_dmabuffer_for_device(struct brcmf_pciedev_info *devinfo,
dma_addr_t *dma_handle)
{
void *ring;
long long address;
u64 address;
ring = dma_alloc_coherent(&devinfo->pdev->dev, size, dma_handle,
GFP_KERNEL);
if (!ring)
return NULL;
address = (long long)(long)*dma_handle;
address = (u64)*dma_handle;
brcmf_pcie_write_tcm32(devinfo, tcm_dma_phys_addr,
address & 0xffffffff);
brcmf_pcie_write_tcm32(devinfo, tcm_dma_phys_addr + 4, address >> 32);
@ -1166,7 +1166,7 @@ brcmf_pcie_release_scratchbuffers(struct brcmf_pciedev_info *devinfo)
static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
{
long long address;
u64 address;
u32 addr;
devinfo->shared.scratch = dma_alloc_coherent(&devinfo->pdev->dev,
@ -1180,7 +1180,7 @@ static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
addr = devinfo->shared.tcm_base_address +
BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET;
address = (long long)(long)devinfo->shared.scratch_dmahandle;
address = (u64)devinfo->shared.scratch_dmahandle;
brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
addr = devinfo->shared.tcm_base_address +
@ -1198,7 +1198,7 @@ static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
addr = devinfo->shared.tcm_base_address +
BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET;
address = (long long)(long)devinfo->shared.ringupd_dmahandle;
address = (u64)devinfo->shared.ringupd_dmahandle;
brcmf_pcie_write_tcm32(devinfo, addr, address & 0xffffffff);
brcmf_pcie_write_tcm32(devinfo, addr + 4, address >> 32);
addr = devinfo->shared.tcm_base_address +

View file

@ -608,6 +608,8 @@ static const struct sdiod_drive_str sdiod_drvstr_tab2_3v3[] = {
#define BCM4330_NVRAM_NAME "brcm/brcmfmac4330-sdio.txt"
#define BCM4334_FIRMWARE_NAME "brcm/brcmfmac4334-sdio.bin"
#define BCM4334_NVRAM_NAME "brcm/brcmfmac4334-sdio.txt"
#define BCM43340_FIRMWARE_NAME "brcm/brcmfmac43340-sdio.bin"
#define BCM43340_NVRAM_NAME "brcm/brcmfmac43340-sdio.txt"
#define BCM4335_FIRMWARE_NAME "brcm/brcmfmac4335-sdio.bin"
#define BCM4335_NVRAM_NAME "brcm/brcmfmac4335-sdio.txt"
#define BCM43362_FIRMWARE_NAME "brcm/brcmfmac43362-sdio.bin"
@ -629,6 +631,8 @@ MODULE_FIRMWARE(BCM4330_FIRMWARE_NAME);
MODULE_FIRMWARE(BCM4330_NVRAM_NAME);
MODULE_FIRMWARE(BCM4334_FIRMWARE_NAME);
MODULE_FIRMWARE(BCM4334_NVRAM_NAME);
MODULE_FIRMWARE(BCM43340_FIRMWARE_NAME);
MODULE_FIRMWARE(BCM43340_NVRAM_NAME);
MODULE_FIRMWARE(BCM4335_FIRMWARE_NAME);
MODULE_FIRMWARE(BCM4335_NVRAM_NAME);
MODULE_FIRMWARE(BCM43362_FIRMWARE_NAME);
@ -660,6 +664,7 @@ static const struct brcmf_firmware_names brcmf_fwname_data[] = {
{ BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) },
{ BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) },
{ BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) },
{ BRCM_CC_43340_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43340) },
{ BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) },
{ BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) },
{ BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) },
@ -3811,7 +3816,7 @@ static u32 brcmf_sdio_buscore_read32(void *ctx, u32 addr)
u32 val, rev;
val = brcmf_sdiod_regrl(sdiodev, addr, NULL);
if (sdiodev->func[0]->device == BRCM_SDIO_4335_4339_DEVICE_ID &&
if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 &&
addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
rev = (val & CID_REV_MASK) >> CID_REV_SHIFT;
if (rev >= 2) {

View file

@ -22,7 +22,6 @@
#define BRCM_USB_VENDOR_ID_BROADCOM 0x0a5c
#define BRCM_PCIE_VENDOR_ID_BROADCOM PCI_VENDOR_ID_BROADCOM
#define BRCM_SDIO_VENDOR_ID_BROADCOM SDIO_VENDOR_ID_BROADCOM
/* Chipcommon Core Chip IDs */
#define BRCM_CC_43143_CHIP_ID 43143
@ -34,6 +33,7 @@
#define BRCM_CC_4329_CHIP_ID 0x4329
#define BRCM_CC_4330_CHIP_ID 0x4330
#define BRCM_CC_4334_CHIP_ID 0x4334
#define BRCM_CC_43340_CHIP_ID 43340
#define BRCM_CC_43362_CHIP_ID 43362
#define BRCM_CC_4335_CHIP_ID 0x4335
#define BRCM_CC_4339_CHIP_ID 0x4339
@ -45,16 +45,6 @@
#define BRCM_CC_43570_CHIP_ID 43570
#define BRCM_CC_43602_CHIP_ID 43602
/* SDIO Device IDs */
#define BRCM_SDIO_43143_DEVICE_ID BRCM_CC_43143_CHIP_ID
#define BRCM_SDIO_43241_DEVICE_ID BRCM_CC_43241_CHIP_ID
#define BRCM_SDIO_4329_DEVICE_ID BRCM_CC_4329_CHIP_ID
#define BRCM_SDIO_4330_DEVICE_ID BRCM_CC_4330_CHIP_ID
#define BRCM_SDIO_4334_DEVICE_ID BRCM_CC_4334_CHIP_ID
#define BRCM_SDIO_43362_DEVICE_ID BRCM_CC_43362_CHIP_ID
#define BRCM_SDIO_4335_4339_DEVICE_ID BRCM_CC_4335_CHIP_ID
#define BRCM_SDIO_4354_DEVICE_ID BRCM_CC_4354_CHIP_ID
/* USB Device IDs */
#define BRCM_USB_43143_DEVICE_ID 0xbd1e
#define BRCM_USB_43236_DEVICE_ID 0xbd17

View file

@ -373,9 +373,8 @@ static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr,
INIT_WORK(&priv->update_filtering_work, cw1200_update_filtering_work);
INIT_WORK(&priv->set_beacon_wakeup_period_work,
cw1200_set_beacon_wakeup_period_work);
init_timer(&priv->mcast_timeout);
priv->mcast_timeout.data = (unsigned long)priv;
priv->mcast_timeout.function = cw1200_mcast_timeout;
setup_timer(&priv->mcast_timeout, cw1200_mcast_timeout,
(unsigned long)priv);
if (cw1200_queue_stats_init(&priv->tx_queue_stats,
CW1200_LINK_ID_MAX,

View file

@ -101,9 +101,8 @@ int cw1200_pm_init(struct cw1200_pm_state *pm,
{
spin_lock_init(&pm->lock);
init_timer(&pm->stay_awake);
pm->stay_awake.data = (unsigned long)pm;
pm->stay_awake.function = cw1200_pm_stay_awake_tmo;
setup_timer(&pm->stay_awake, cw1200_pm_stay_awake_tmo,
(unsigned long)pm);
return 0;
}

View file

@ -179,9 +179,7 @@ int cw1200_queue_init(struct cw1200_queue *queue,
INIT_LIST_HEAD(&queue->pending);
INIT_LIST_HEAD(&queue->free_pool);
spin_lock_init(&queue->lock);
init_timer(&queue->gc);
queue->gc.data = (unsigned long)queue;
queue->gc.function = cw1200_queue_gc;
setup_timer(&queue->gc, cw1200_queue_gc, (unsigned long)queue);
queue->pool = kzalloc(sizeof(struct cw1200_queue_item) * capacity,
GFP_KERNEL);

View file

@ -3429,9 +3429,7 @@ il3945_setup_deferred_work(struct il_priv *il)
il3945_hw_setup_deferred_work(il);
init_timer(&il->watchdog);
il->watchdog.data = (unsigned long)il;
il->watchdog.function = il_bg_watchdog;
setup_timer(&il->watchdog, il_bg_watchdog, (unsigned long)il);
tasklet_init(&il->irq_tasklet,
(void (*)(unsigned long))il3945_irq_tasklet,

View file

@ -6247,13 +6247,10 @@ il4965_setup_deferred_work(struct il_priv *il)
INIT_WORK(&il->txpower_work, il4965_bg_txpower_work);
init_timer(&il->stats_periodic);
il->stats_periodic.data = (unsigned long)il;
il->stats_periodic.function = il4965_bg_stats_periodic;
setup_timer(&il->stats_periodic, il4965_bg_stats_periodic,
(unsigned long)il);
init_timer(&il->watchdog);
il->watchdog.data = (unsigned long)il;
il->watchdog.function = il_bg_watchdog;
setup_timer(&il->watchdog, il_bg_watchdog, (unsigned long)il);
tasklet_init(&il->irq_tasklet,
(void (*)(unsigned long))il4965_irq_tasklet,

View file

@ -64,22 +64,8 @@
*
******************************************************************************/
/*
* module name, copyright, version, etc.
*/
#define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link AGN driver for Linux"
#ifdef CONFIG_IWLWIFI_DEBUG
#define VD "d"
#else
#define VD
#endif
#define DRV_VERSION IWLWIFI_VERSION VD
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_VERSION(DRV_VERSION);
MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
MODULE_LICENSE("GPL");
@ -1011,13 +997,11 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
if (priv->lib->bt_params)
iwlagn_bt_setup_deferred_work(priv);
init_timer(&priv->statistics_periodic);
priv->statistics_periodic.data = (unsigned long)priv;
priv->statistics_periodic.function = iwl_bg_statistics_periodic;
setup_timer(&priv->statistics_periodic, iwl_bg_statistics_periodic,
(unsigned long)priv);
init_timer(&priv->ucode_trace);
priv->ucode_trace.data = (unsigned long)priv;
priv->ucode_trace.function = iwl_bg_ucode_trace;
setup_timer(&priv->ucode_trace, iwl_bg_ucode_trace,
(unsigned long)priv);
}
void iwl_cancel_deferred_work(struct iwl_priv *priv)

View file

@ -612,15 +612,10 @@ void iwl_tt_initialize(struct iwl_priv *priv)
memset(tt, 0, sizeof(struct iwl_tt_mgmt));
tt->state = IWL_TI_0;
init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv;
priv->thermal_throttle.ct_kill_exit_tm.function =
iwl_tt_check_exit_ct_kill;
init_timer(&priv->thermal_throttle.ct_kill_waiting_tm);
priv->thermal_throttle.ct_kill_waiting_tm.data =
(unsigned long)priv;
priv->thermal_throttle.ct_kill_waiting_tm.function =
iwl_tt_ready_for_ct_kill;
setup_timer(&priv->thermal_throttle.ct_kill_exit_tm,
iwl_tt_check_exit_ct_kill, (unsigned long)priv);
setup_timer(&priv->thermal_throttle.ct_kill_waiting_tm,
iwl_tt_ready_for_ct_kill, (unsigned long)priv);
/* setup deferred ct kill work */
INIT_WORK(&priv->tt_work, iwl_bg_tt_work);
INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter);

View file

@ -92,6 +92,12 @@
#define IWL7265D_NVM_VERSION 0x0c11
#define IWL7265_TX_POWER_VERSION 0xffff /* meaningless */
/* DCCM offsets and lengths */
#define IWL7000_DCCM_OFFSET 0x800000
#define IWL7260_DCCM_LEN 0x14000
#define IWL3160_DCCM_LEN 0x10000
#define IWL7265_DCCM_LEN 0x17A00
#define IWL7260_FW_PRE "iwlwifi-7260-"
#define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode"
@ -138,7 +144,8 @@ static const struct iwl_ht_params iwl7000_ht_params = {
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_7000, \
.non_shared_ant = ANT_A, \
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K, \
.dccm_offset = IWL7000_DCCM_OFFSET
const struct iwl_cfg iwl7260_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 7260",
@ -149,6 +156,7 @@ const struct iwl_cfg iwl7260_2ac_cfg = {
.nvm_calib_ver = IWL7260_TX_POWER_VERSION,
.host_interrupt_operation_mode = true,
.lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
};
const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
@ -161,6 +169,7 @@ const struct iwl_cfg iwl7260_2ac_cfg_high_temp = {
.high_temp = true,
.host_interrupt_operation_mode = true,
.lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
};
const struct iwl_cfg iwl7260_2n_cfg = {
@ -172,6 +181,7 @@ const struct iwl_cfg iwl7260_2n_cfg = {
.nvm_calib_ver = IWL7260_TX_POWER_VERSION,
.host_interrupt_operation_mode = true,
.lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
};
const struct iwl_cfg iwl7260_n_cfg = {
@ -183,6 +193,7 @@ const struct iwl_cfg iwl7260_n_cfg = {
.nvm_calib_ver = IWL7260_TX_POWER_VERSION,
.host_interrupt_operation_mode = true,
.lp_xtal_workaround = true,
.dccm_len = IWL7260_DCCM_LEN,
};
const struct iwl_cfg iwl3160_2ac_cfg = {
@ -193,6 +204,7 @@ const struct iwl_cfg iwl3160_2ac_cfg = {
.nvm_ver = IWL3160_NVM_VERSION,
.nvm_calib_ver = IWL3160_TX_POWER_VERSION,
.host_interrupt_operation_mode = true,
.dccm_len = IWL3160_DCCM_LEN,
};
const struct iwl_cfg iwl3160_2n_cfg = {
@ -203,6 +215,7 @@ const struct iwl_cfg iwl3160_2n_cfg = {
.nvm_ver = IWL3160_NVM_VERSION,
.nvm_calib_ver = IWL3160_TX_POWER_VERSION,
.host_interrupt_operation_mode = true,
.dccm_len = IWL3160_DCCM_LEN,
};
const struct iwl_cfg iwl3160_n_cfg = {
@ -213,6 +226,7 @@ const struct iwl_cfg iwl3160_n_cfg = {
.nvm_ver = IWL3160_NVM_VERSION,
.nvm_calib_ver = IWL3160_TX_POWER_VERSION,
.host_interrupt_operation_mode = true,
.dccm_len = IWL3160_DCCM_LEN,
};
static const struct iwl_pwr_tx_backoff iwl7265_pwr_tx_backoffs[] = {
@ -240,6 +254,7 @@ const struct iwl_cfg iwl3165_2ac_cfg = {
.nvm_ver = IWL3165_NVM_VERSION,
.nvm_calib_ver = IWL3165_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265_2ac_cfg = {
@ -250,6 +265,7 @@ const struct iwl_cfg iwl7265_2ac_cfg = {
.nvm_ver = IWL7265_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265_2n_cfg = {
@ -260,6 +276,7 @@ const struct iwl_cfg iwl7265_2n_cfg = {
.nvm_ver = IWL7265_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265_n_cfg = {
@ -270,6 +287,7 @@ const struct iwl_cfg iwl7265_n_cfg = {
.nvm_ver = IWL7265_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265d_2ac_cfg = {
@ -280,6 +298,7 @@ const struct iwl_cfg iwl7265d_2ac_cfg = {
.nvm_ver = IWL7265D_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265d_2n_cfg = {
@ -290,6 +309,7 @@ const struct iwl_cfg iwl7265d_2n_cfg = {
.nvm_ver = IWL7265D_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
const struct iwl_cfg iwl7265d_n_cfg = {
@ -300,6 +320,7 @@ const struct iwl_cfg iwl7265d_n_cfg = {
.nvm_ver = IWL7265D_NVM_VERSION,
.nvm_calib_ver = IWL7265_TX_POWER_VERSION,
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
.dccm_len = IWL7265_DCCM_LEN,
};
MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));

View file

@ -81,12 +81,21 @@
#define IWL8000_NVM_VERSION 0x0a1d
#define IWL8000_TX_POWER_VERSION 0xffff /* meaningless */
/* Memory offsets and lengths */
#define IWL8260_DCCM_OFFSET 0x800000
#define IWL8260_DCCM_LEN 0x18000
#define IWL8260_DCCM2_OFFSET 0x880000
#define IWL8260_DCCM2_LEN 0x8000
#define IWL8260_SMEM_OFFSET 0x400000
#define IWL8260_SMEM_LEN 0x68000
#define IWL8000_FW_PRE "iwlwifi-8000"
#define IWL8000_MODULE_FIRMWARE(api) \
IWL8000_FW_PRE "-" __stringify(api) ".ucode"
#define NVM_HW_SECTION_NUM_FAMILY_8000 10
#define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000.bin"
#define DEFAULT_NVM_FILE_FAMILY_8000A "iwl_nvm_8000.bin"
#define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000B.bin"
/* Max SDIO RX aggregation size of the ADDBA request/response */
#define MAX_RX_AGG_SIZE_8260_SDIO 28
@ -124,7 +133,13 @@ static const struct iwl_ht_params iwl8000_ht_params = {
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000, \
.d0i3 = true, \
.non_shared_ant = ANT_A
.non_shared_ant = ANT_A, \
.dccm_offset = IWL8260_DCCM_OFFSET, \
.dccm_len = IWL8260_DCCM_LEN, \
.dccm2_offset = IWL8260_DCCM2_OFFSET, \
.dccm2_len = IWL8260_DCCM2_LEN, \
.smem_offset = IWL8260_SMEM_OFFSET, \
.smem_len = IWL8260_SMEM_LEN
const struct iwl_cfg iwl8260_2n_cfg = {
.name = "Intel(R) Dual Band Wireless N 8260",
@ -145,6 +160,16 @@ const struct iwl_cfg iwl8260_2ac_cfg = {
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
};
const struct iwl_cfg iwl4165_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 4165",
.fw_name_pre = IWL8000_FW_PRE,
IWL_DEVICE_8000,
.ht_params = &iwl8000_ht_params,
.nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
.max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
};
const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
.name = "Intel(R) Dual Band Wireless-AC 8260",
.fw_name_pre = IWL8000_FW_PRE,
@ -153,6 +178,7 @@ const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
.nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
.default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
.default_nvm_file_8000A = DEFAULT_NVM_FILE_FAMILY_8000A,
.max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
.disable_dummy_notification = true,
.max_ht_ampdu_exponent = MAX_HT_AMPDU_EXPONENT_8260_SDIO,
@ -167,6 +193,7 @@ const struct iwl_cfg iwl4165_2ac_sdio_cfg = {
.nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
.default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
.default_nvm_file_8000A = DEFAULT_NVM_FILE_FAMILY_8000A,
.max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
.bt_shared_single_ant = true,
.disable_dummy_notification = true,

View file

@ -261,6 +261,12 @@ struct iwl_pwr_tx_backoff {
* station can receive in HT
* @max_vht_ampdu_exponent: the exponent of the max length of A-MPDU that the
* station can receive in VHT
* @dccm_offset: offset from which DCCM begins
* @dccm_len: length of DCCM (including runtime stack CCM)
* @dccm2_offset: offset from which the second DCCM begins
* @dccm2_len: length of the second DCCM
* @smem_offset: offset from which the SMEM begins
* @smem_len: the length of SMEM
*
* We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs
@ -298,11 +304,18 @@ struct iwl_cfg {
const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
bool no_power_up_nic_in_init;
const char *default_nvm_file;
const char *default_nvm_file_8000A;
unsigned int max_rx_agg_size;
bool disable_dummy_notification;
unsigned int max_tx_agg_size;
unsigned int max_ht_ampdu_exponent;
unsigned int max_vht_ampdu_exponent;
const u32 dccm_offset;
const u32 dccm_len;
const u32 dccm2_offset;
const u32 dccm2_len;
const u32 smem_offset;
const u32 smem_len;
};
/*
@ -369,8 +382,8 @@ extern const struct iwl_cfg iwl7265d_2n_cfg;
extern const struct iwl_cfg iwl7265d_n_cfg;
extern const struct iwl_cfg iwl8260_2n_cfg;
extern const struct iwl_cfg iwl8260_2ac_cfg;
extern const struct iwl_cfg iwl4165_2ac_cfg;
extern const struct iwl_cfg iwl8260_2ac_sdio_cfg;
extern const struct iwl_cfg iwl4265_2ac_sdio_cfg;
extern const struct iwl_cfg iwl4165_2ac_sdio_cfg;
#endif /* CONFIG_IWLMVM */

View file

@ -184,6 +184,7 @@
#define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) /* PCI_OWN_SEM */
#define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */
#define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000) /* WAKE_ME */
#define CSR_HW_IF_CONFIG_REG_ENABLE_PME (0x10000000)
#define CSR_HW_IF_CONFIG_REG_PERSIST_MODE (0x40000000) /* PERSISTENCE */
#define CSR_MBOX_SET_REG_OS_ALIVE BIT(5)
@ -306,6 +307,7 @@
enum {
SILICON_A_STEP = 0,
SILICON_B_STEP,
SILICON_C_STEP,
};

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