Commit 9277326e authored by Johannes Berg's avatar Johannes Berg

Merge remote-tracking branch 'wireless-next/master' into iwlwifi-next

parents cfb4e624 9fbdc751
...@@ -127,12 +127,11 @@ ...@@ -127,12 +127,11 @@
!Finclude/net/cfg80211.h cfg80211_ibss_params !Finclude/net/cfg80211.h cfg80211_ibss_params
!Finclude/net/cfg80211.h cfg80211_connect_params !Finclude/net/cfg80211.h cfg80211_connect_params
!Finclude/net/cfg80211.h cfg80211_pmksa !Finclude/net/cfg80211.h cfg80211_pmksa
!Finclude/net/cfg80211.h cfg80211_send_rx_auth !Finclude/net/cfg80211.h cfg80211_rx_mlme_mgmt
!Finclude/net/cfg80211.h cfg80211_send_auth_timeout !Finclude/net/cfg80211.h cfg80211_auth_timeout
!Finclude/net/cfg80211.h cfg80211_send_rx_assoc !Finclude/net/cfg80211.h cfg80211_rx_assoc_resp
!Finclude/net/cfg80211.h cfg80211_send_assoc_timeout !Finclude/net/cfg80211.h cfg80211_assoc_timeout
!Finclude/net/cfg80211.h cfg80211_send_deauth !Finclude/net/cfg80211.h cfg80211_tx_mlme_mgmt
!Finclude/net/cfg80211.h cfg80211_send_disassoc
!Finclude/net/cfg80211.h cfg80211_ibss_joined !Finclude/net/cfg80211.h cfg80211_ibss_joined
!Finclude/net/cfg80211.h cfg80211_connect_result !Finclude/net/cfg80211.h cfg80211_connect_result
!Finclude/net/cfg80211.h cfg80211_roamed !Finclude/net/cfg80211.h cfg80211_roamed
......
...@@ -26,6 +26,7 @@ config BCMA_HOST_PCI_POSSIBLE ...@@ -26,6 +26,7 @@ config BCMA_HOST_PCI_POSSIBLE
config BCMA_HOST_PCI config BCMA_HOST_PCI
bool "Support for BCMA on PCI-host bus" bool "Support for BCMA on PCI-host bus"
depends on BCMA_HOST_PCI_POSSIBLE depends on BCMA_HOST_PCI_POSSIBLE
default y
config BCMA_DRIVER_PCI_HOSTMODE config BCMA_DRIVER_PCI_HOSTMODE
bool "Driver for PCI core working in hostmode" bool "Driver for PCI core working in hostmode"
......
...@@ -9,6 +9,25 @@ ...@@ -9,6 +9,25 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/bcma/bcma.h> #include <linux/bcma/bcma.h>
static bool bcma_core_wait_value(struct bcma_device *core, u16 reg, u32 mask,
u32 value, int timeout)
{
unsigned long deadline = jiffies + timeout;
u32 val;
do {
val = bcma_aread32(core, reg);
if ((val & mask) == value)
return true;
cpu_relax();
udelay(10);
} while (!time_after_eq(jiffies, deadline));
bcma_warn(core->bus, "Timeout waiting for register 0x%04X!\n", reg);
return false;
}
bool bcma_core_is_enabled(struct bcma_device *core) bool bcma_core_is_enabled(struct bcma_device *core)
{ {
if ((bcma_aread32(core, BCMA_IOCTL) & (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC)) if ((bcma_aread32(core, BCMA_IOCTL) & (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC))
...@@ -25,13 +44,15 @@ void bcma_core_disable(struct bcma_device *core, u32 flags) ...@@ -25,13 +44,15 @@ void bcma_core_disable(struct bcma_device *core, u32 flags)
if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET) if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET)
return; return;
bcma_awrite32(core, BCMA_IOCTL, flags); bcma_core_wait_value(core, BCMA_RESET_ST, ~0, 0, 300);
bcma_aread32(core, BCMA_IOCTL);
udelay(10);
bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET);
bcma_aread32(core, BCMA_RESET_CTL); bcma_aread32(core, BCMA_RESET_CTL);
udelay(1); udelay(1);
bcma_awrite32(core, BCMA_IOCTL, flags);
bcma_aread32(core, BCMA_IOCTL);
udelay(10);
} }
EXPORT_SYMBOL_GPL(bcma_core_disable); EXPORT_SYMBOL_GPL(bcma_core_disable);
...@@ -43,6 +64,7 @@ int bcma_core_enable(struct bcma_device *core, u32 flags) ...@@ -43,6 +64,7 @@ int bcma_core_enable(struct bcma_device *core, u32 flags)
bcma_aread32(core, BCMA_IOCTL); bcma_aread32(core, BCMA_IOCTL);
bcma_awrite32(core, BCMA_RESET_CTL, 0); bcma_awrite32(core, BCMA_RESET_CTL, 0);
bcma_aread32(core, BCMA_RESET_CTL);
udelay(1); udelay(1);
bcma_awrite32(core, BCMA_IOCTL, (BCMA_IOCTL_CLK | flags)); bcma_awrite32(core, BCMA_IOCTL, (BCMA_IOCTL_CLK | flags));
......
...@@ -30,7 +30,7 @@ struct bcma_sflash_tbl_e { ...@@ -30,7 +30,7 @@ struct bcma_sflash_tbl_e {
u16 numblocks; u16 numblocks;
}; };
static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { static const struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = {
{ "M25P20", 0x11, 0x10000, 4, }, { "M25P20", 0x11, 0x10000, 4, },
{ "M25P40", 0x12, 0x10000, 8, }, { "M25P40", 0x12, 0x10000, 8, },
...@@ -41,7 +41,7 @@ static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { ...@@ -41,7 +41,7 @@ static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = {
{ 0 }, { 0 },
}; };
static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { static const struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
{ "SST25WF512", 1, 0x1000, 16, }, { "SST25WF512", 1, 0x1000, 16, },
{ "SST25VF512", 0x48, 0x1000, 16, }, { "SST25VF512", 0x48, 0x1000, 16, },
{ "SST25WF010", 2, 0x1000, 32, }, { "SST25WF010", 2, 0x1000, 32, },
...@@ -59,7 +59,7 @@ static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { ...@@ -59,7 +59,7 @@ static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
{ 0 }, { 0 },
}; };
static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { static const struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = {
{ "AT45DB011", 0xc, 256, 512, }, { "AT45DB011", 0xc, 256, 512, },
{ "AT45DB021", 0x14, 256, 1024, }, { "AT45DB021", 0x14, 256, 1024, },
{ "AT45DB041", 0x1c, 256, 2048, }, { "AT45DB041", 0x1c, 256, 2048, },
...@@ -89,7 +89,7 @@ int bcma_sflash_init(struct bcma_drv_cc *cc) ...@@ -89,7 +89,7 @@ int bcma_sflash_init(struct bcma_drv_cc *cc)
{ {
struct bcma_bus *bus = cc->core->bus; struct bcma_bus *bus = cc->core->bus;
struct bcma_sflash *sflash = &cc->sflash; struct bcma_sflash *sflash = &cc->sflash;
struct bcma_sflash_tbl_e *e; const struct bcma_sflash_tbl_e *e;
u32 id, id2; u32 id, id2;
switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
......
...@@ -84,6 +84,8 @@ static const struct bcma_device_id_name bcma_bcm_device_names[] = { ...@@ -84,6 +84,8 @@ static const struct bcma_device_id_name bcma_bcm_device_names[] = {
{ BCMA_CORE_I2S, "I2S" }, { BCMA_CORE_I2S, "I2S" },
{ BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" }, { BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" },
{ BCMA_CORE_SHIM, "SHIM" }, { BCMA_CORE_SHIM, "SHIM" },
{ BCMA_CORE_PCIE2, "PCIe Gen2" },
{ BCMA_CORE_ARM_CR4, "ARM CR4" },
{ BCMA_CORE_DEFAULT, "Default" }, { BCMA_CORE_DEFAULT, "Default" },
}; };
......
...@@ -201,7 +201,7 @@ config BT_MRVL ...@@ -201,7 +201,7 @@ config BT_MRVL
The core driver to support Marvell Bluetooth devices. The core driver to support Marvell Bluetooth devices.
This driver is required if you want to support This driver is required if you want to support
Marvell Bluetooth devices, such as 8688/8787/8797. Marvell Bluetooth devices, such as 8688/8787/8797/8897.
Say Y here to compile Marvell Bluetooth driver Say Y here to compile Marvell Bluetooth driver
into the kernel or say M to compile it as module. into the kernel or say M to compile it as module.
...@@ -214,7 +214,7 @@ config BT_MRVL_SDIO ...@@ -214,7 +214,7 @@ config BT_MRVL_SDIO
The driver for Marvell Bluetooth chipsets with SDIO interface. The driver for Marvell Bluetooth chipsets with SDIO interface.
This driver is required if you want to use Marvell Bluetooth This driver is required if you want to use Marvell Bluetooth
devices with SDIO interface. Currently SD8688/SD8787/SD8797 devices with SDIO interface. Currently SD8688/SD8787/SD8797/SD8897
chipsets are supported. chipsets are supported.
Say Y here to compile support for Marvell BT-over-SDIO driver Say Y here to compile support for Marvell BT-over-SDIO driver
......
...@@ -498,6 +498,10 @@ static int btmrvl_service_main_thread(void *data) ...@@ -498,6 +498,10 @@ static int btmrvl_service_main_thread(void *data)
add_wait_queue(&thread->wait_q, &wait); add_wait_queue(&thread->wait_q, &wait);
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (kthread_should_stop()) {
BT_DBG("main_thread: break from main thread");
break;
}
if (adapter->wakeup_tries || if (adapter->wakeup_tries ||
((!adapter->int_count) && ((!adapter->int_count) &&
...@@ -513,11 +517,6 @@ static int btmrvl_service_main_thread(void *data) ...@@ -513,11 +517,6 @@ static int btmrvl_service_main_thread(void *data)
BT_DBG("main_thread woke up"); BT_DBG("main_thread woke up");
if (kthread_should_stop()) {
BT_DBG("main_thread: break from main thread");
break;
}
spin_lock_irqsave(&priv->driver_lock, flags); spin_lock_irqsave(&priv->driver_lock, flags);
if (adapter->int_count) { if (adapter->int_count) {
adapter->int_count = 0; adapter->int_count = 0;
......
...@@ -82,6 +82,23 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = { ...@@ -82,6 +82,23 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_87xx = {
.io_port_2 = 0x7a, .io_port_2 = 0x7a,
}; };
static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = {
.cfg = 0x00,
.host_int_mask = 0x02,
.host_intstatus = 0x03,
.card_status = 0x50,
.sq_read_base_addr_a0 = 0x60,
.sq_read_base_addr_a1 = 0x61,
.card_revision = 0xbc,
.card_fw_status0 = 0xc0,
.card_fw_status1 = 0xc1,
.card_rx_len = 0xc2,
.card_rx_unit = 0xc3,
.io_port_0 = 0xd8,
.io_port_1 = 0xd9,
.io_port_2 = 0xda,
};
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
.helper = "mrvl/sd8688_helper.bin", .helper = "mrvl/sd8688_helper.bin",
.firmware = "mrvl/sd8688.bin", .firmware = "mrvl/sd8688.bin",
...@@ -103,6 +120,13 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { ...@@ -103,6 +120,13 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
.sd_blksz_fw_dl = 256, .sd_blksz_fw_dl = 256,
}; };
static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
.helper = NULL,
.firmware = "mrvl/sd8897_uapsta.bin",
.reg = &btmrvl_reg_88xx,
.sd_blksz_fw_dl = 256,
};
static const struct sdio_device_id btmrvl_sdio_ids[] = { static const struct sdio_device_id btmrvl_sdio_ids[] = {
/* Marvell SD8688 Bluetooth device */ /* Marvell SD8688 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x9105),
...@@ -116,6 +140,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = { ...@@ -116,6 +140,9 @@ static const struct sdio_device_id btmrvl_sdio_ids[] = {
/* Marvell SD8797 Bluetooth device */ /* Marvell SD8797 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A), { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912A),
.driver_data = (unsigned long) &btmrvl_sdio_sd8797 }, .driver_data = (unsigned long) &btmrvl_sdio_sd8797 },
/* Marvell SD8897 Bluetooth device */
{ SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, 0x912E),
.driver_data = (unsigned long) &btmrvl_sdio_sd8897 },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
...@@ -527,6 +554,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) ...@@ -527,6 +554,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC); skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC);
if (skb == NULL) { if (skb == NULL) {
BT_ERR("No free skb"); BT_ERR("No free skb");
ret = -ENOMEM;
goto exit; goto exit;
} }
...@@ -1194,3 +1222,4 @@ MODULE_FIRMWARE("mrvl/sd8688_helper.bin"); ...@@ -1194,3 +1222,4 @@ MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
MODULE_FIRMWARE("mrvl/sd8688.bin"); MODULE_FIRMWARE("mrvl/sd8688.bin");
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin"); MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
...@@ -57,6 +57,9 @@ static struct usb_device_id btusb_table[] = { ...@@ -57,6 +57,9 @@ static struct usb_device_id btusb_table[] = {
/* Apple-specific (Broadcom) devices */ /* Apple-specific (Broadcom) devices */
{ USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) }, { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) },
/* MediaTek MT76x0E */
{ USB_DEVICE(0x0e8d, 0x763f) },
/* Broadcom SoftSailing reporting vendor specific */ /* Broadcom SoftSailing reporting vendor specific */
{ USB_DEVICE(0x0a5c, 0x21e1) }, { USB_DEVICE(0x0a5c, 0x21e1) },
...@@ -1616,6 +1619,7 @@ static struct usb_driver btusb_driver = { ...@@ -1616,6 +1619,7 @@ static struct usb_driver btusb_driver = {
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = btusb_suspend, .suspend = btusb_suspend,
.resume = btusb_resume, .resume = btusb_resume,
.reset_resume = btusb_resume,
#endif #endif
.id_table = btusb_table, .id_table = btusb_table,
.supports_autosuspend = 1, .supports_autosuspend = 1,
......
...@@ -31,5 +31,6 @@ source "drivers/net/wireless/ath/carl9170/Kconfig" ...@@ -31,5 +31,6 @@ source "drivers/net/wireless/ath/carl9170/Kconfig"
source "drivers/net/wireless/ath/ath6kl/Kconfig" source "drivers/net/wireless/ath/ath6kl/Kconfig"
source "drivers/net/wireless/ath/ar5523/Kconfig" source "drivers/net/wireless/ath/ar5523/Kconfig"
source "drivers/net/wireless/ath/wil6210/Kconfig" source "drivers/net/wireless/ath/wil6210/Kconfig"
source "drivers/net/wireless/ath/ath10k/Kconfig"
endif endif
...@@ -4,6 +4,7 @@ obj-$(CONFIG_CARL9170) += carl9170/ ...@@ -4,6 +4,7 @@ obj-$(CONFIG_CARL9170) += carl9170/
obj-$(CONFIG_ATH6KL) += ath6kl/ obj-$(CONFIG_ATH6KL) += ath6kl/
obj-$(CONFIG_AR5523) += ar5523/ obj-$(CONFIG_AR5523) += ar5523/
obj-$(CONFIG_WIL6210) += wil6210/ obj-$(CONFIG_WIL6210) += wil6210/
obj-$(CONFIG_ATH10K) += ath10k/
obj-$(CONFIG_ATH_COMMON) += ath.o obj-$(CONFIG_ATH_COMMON) += ath.o
......
...@@ -239,13 +239,12 @@ enum ATH_DEBUG { ...@@ -239,13 +239,12 @@ enum ATH_DEBUG {
ATH_DBG_CONFIG = 0x00000200, ATH_DBG_CONFIG = 0x00000200,
ATH_DBG_FATAL = 0x00000400, ATH_DBG_FATAL = 0x00000400,
ATH_DBG_PS = 0x00000800, ATH_DBG_PS = 0x00000800,
ATH_DBG_HWTIMER = 0x00001000, ATH_DBG_BTCOEX = 0x00001000,
ATH_DBG_BTCOEX = 0x00002000, ATH_DBG_WMI = 0x00002000,
ATH_DBG_WMI = 0x00004000, ATH_DBG_BSTUCK = 0x00004000,
ATH_DBG_BSTUCK = 0x00008000, ATH_DBG_MCI = 0x00008000,
ATH_DBG_MCI = 0x00010000, ATH_DBG_DFS = 0x00010000,
ATH_DBG_DFS = 0x00020000, ATH_DBG_WOW = 0x00020000,
ATH_DBG_WOW = 0x00040000,
ATH_DBG_ANY = 0xffffffff ATH_DBG_ANY = 0xffffffff
}; };
......
config ATH10K
tristate "Atheros 802.11ac wireless cards support"
depends on MAC80211
select ATH_COMMON
---help---
This module adds support for wireless adapters based on
Atheros IEEE 802.11ac family of chipsets.
If you choose to build a module, it'll be called ath10k.
config ATH10K_PCI
tristate "Atheros ath10k PCI support"
depends on ATH10K && PCI
---help---
This module adds support for PCIE bus
config ATH10K_DEBUG
bool "Atheros ath10k debugging"
depends on ATH10K
---help---
Enables debug support
If unsure, say Y to make it easier to debug problems.
config ATH10K_DEBUGFS
bool "Atheros ath10k debugfs support"
depends on ATH10K
---help---
Enabled debugfs support
If unsure, say Y to make it easier to debug problems.
config ATH10K_TRACING
bool "Atheros ath10k tracing support"
depends on ATH10K
depends on EVENT_TRACING
---help---
Select this to ath10k use tracing infrastructure.
obj-$(CONFIG_ATH10K) += ath10k_core.o
ath10k_core-y += mac.o \
debug.o \
core.o \
htc.o \
htt.o \
htt_rx.o \
htt_tx.o \
txrx.o \
wmi.o \
bmi.o
ath10k_core-$(CONFIG_ATH10K_TRACING) += trace.o
obj-$(CONFIG_ATH10K_PCI) += ath10k_pci.o
ath10k_pci-y += pci.o \
ce.o
# for tracing framework to find trace.h
CFLAGS_trace.o := -I$(src)
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2013 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 "bmi.h"
#include "hif.h"
#include "debug.h"
#include "htc.h"
int ath10k_bmi_done(struct ath10k *ar)
{
struct bmi_cmd cmd;
u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.done);
int ret;
if (ar->bmi.done_sent) {
ath10k_dbg(ATH10K_DBG_CORE, "%s skipped\n", __func__);
return 0;
}
ar->bmi.done_sent = true;
cmd.id = __cpu_to_le32(BMI_DONE);
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, NULL, NULL);
if (ret) {
ath10k_warn("unable to write to the device: %d\n", ret);
return ret;
}
ath10k_dbg(ATH10K_DBG_CORE, "BMI done\n");
return 0;
}
int ath10k_bmi_get_target_info(struct ath10k *ar,
struct bmi_target_info *target_info)
{
struct bmi_cmd cmd;
union bmi_resp resp;
u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.get_target_info);
u32 resplen = sizeof(resp.get_target_info);
int ret;
if (ar->bmi.done_sent) {
ath10k_warn("BMI Get Target Info Command disallowed\n");
return -EBUSY;
}
cmd.id = __cpu_to_le32(BMI_GET_TARGET_INFO);
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &resp, &resplen);
if (ret) {
ath10k_warn("unable to get target info from device\n");
return ret;
}
if (resplen < sizeof(resp.get_target_info)) {
ath10k_warn("invalid get_target_info response length (%d)\n",
resplen);
return -EIO;
}
target_info->version = __le32_to_cpu(resp.get_target_info.version);
target_info->type = __le32_to_cpu(resp.get_target_info.type);
return 0;
}
int ath10k_bmi_read_memory(struct ath10k *ar,
u32 address, void *buffer, u32 length)
{
struct bmi_cmd cmd;
union bmi_resp resp;
u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.read_mem);
u32 rxlen;
int ret;
if (ar->bmi.done_sent) {
ath10k_warn("command disallowed\n");
return -EBUSY;
}
ath10k_dbg(ATH10K_DBG_CORE,
"%s: (device: 0x%p, address: 0x%x, length: %d)\n",
__func__, ar, address, length);
while (length) {
rxlen = min_t(u32, length, BMI_MAX_DATA_SIZE);
cmd.id = __cpu_to_le32(BMI_READ_MEMORY);
cmd.read_mem.addr = __cpu_to_le32(address);
cmd.read_mem.len = __cpu_to_le32(rxlen);
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen,
&resp, &rxlen);
if (ret) {
ath10k_warn("unable to read from the device\n");
return ret;
}
memcpy(buffer, resp.read_mem.payload, rxlen);
address += rxlen;
buffer += rxlen;
length -= rxlen;
}
return 0;
}
int ath10k_bmi_write_memory(struct ath10k *ar,
u32 address, const void *buffer, u32 length)
{
struct bmi_cmd cmd;
u32 hdrlen = sizeof(cmd.id) + sizeof(cmd.write_mem);
u32 txlen;
int ret;
if (ar->bmi.done_sent) {
ath10k_warn("command disallowed\n");
return -EBUSY;
}
ath10k_dbg(ATH10K_DBG_CORE,
"%s: (device: 0x%p, address: 0x%x, length: %d)\n",
__func__, ar, address, length);
while (length) {
txlen = min(length, BMI_MAX_DATA_SIZE - hdrlen);
/* copy before roundup to avoid reading beyond buffer*/
memcpy(cmd.write_mem.payload, buffer, txlen);
txlen = roundup(txlen, 4);
cmd.id = __cpu_to_le32(BMI_WRITE_MEMORY);
cmd.write_mem.addr = __cpu_to_le32(address);
cmd.write_mem.len = __cpu_to_le32(txlen);
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, hdrlen + txlen,
NULL, NULL);
if (ret) {
ath10k_warn("unable to write to the device\n");
return ret;
}
/* fixup roundup() so `length` zeroes out for last chunk */
txlen = min(txlen, length);
address += txlen;
buffer += txlen;
length -= txlen;
}
return 0;
}
int ath10k_bmi_execute(struct ath10k *ar, u32 address, u32 *param)
{
struct bmi_cmd cmd;
union bmi_resp resp;
u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.execute);
u32 resplen = sizeof(resp.execute);
int ret;
if (ar->bmi.done_sent) {
ath10k_warn("command disallowed\n");
return -EBUSY;
}
ath10k_dbg(ATH10K_DBG_CORE,
"%s: (device: 0x%p, address: 0x%x, param: %d)\n",
__func__, ar, address, *param);
cmd.id = __cpu_to_le32(BMI_EXECUTE);
cmd.execute.addr = __cpu_to_le32(address);
cmd.execute.param = __cpu_to_le32(*param);
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, &resp, &resplen);
if (ret) {
ath10k_warn("unable to read from the device\n");
return ret;
}
if (resplen < sizeof(resp.execute)) {
ath10k_warn("invalid execute response length (%d)\n",
resplen);
return ret;
}
*param = __le32_to_cpu(resp.execute.result);
return 0;
}
int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length)
{
struct bmi_cmd cmd;
u32 hdrlen = sizeof(cmd.id) + sizeof(cmd.lz_data);
u32 txlen;
int ret;
if (ar->bmi.done_sent) {
ath10k_warn("command disallowed\n");
return -EBUSY;
}
while (length) {
txlen = min(length, BMI_MAX_DATA_SIZE - hdrlen);
WARN_ON_ONCE(txlen & 3);
cmd.id = __cpu_to_le32(BMI_LZ_DATA);
cmd.lz_data.len = __cpu_to_le32(txlen);
memcpy(cmd.lz_data.payload, buffer, txlen);
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, hdrlen + txlen,
NULL, NULL);
if (ret) {
ath10k_warn("unable to write to the device\n");
return ret;
}
buffer += txlen;
length -= txlen;
}
return 0;
}
int ath10k_bmi_lz_stream_start(struct ath10k *ar, u32 address)
{
struct bmi_cmd cmd;
u32 cmdlen = sizeof(cmd.id) + sizeof(cmd.lz_start);
int ret;
if (ar->bmi.done_sent) {
ath10k_warn("command disallowed\n");
return -EBUSY;
}
cmd.id = __cpu_to_le32(BMI_LZ_STREAM_START);
cmd.lz_start.addr = __cpu_to_le32(address);
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen, NULL, NULL);
if (ret) {
ath10k_warn("unable to Start LZ Stream to the device\n");
return ret;
}
return 0;
}
int ath10k_bmi_fast_download(struct ath10k *ar,
u32 address, const void *buffer, u32 length)
{
u8 trailer[4] = {};
u32 head_len = rounddown(length, 4);
u32 trailer_len = length - head_len;
int ret;
ret = ath10k_bmi_lz_stream_start(ar, address);
if (ret)
return ret;
/* copy the last word into a zero padded buffer */
if (trailer_len > 0)
memcpy(trailer, buffer + head_len, trailer_len);
ret = ath10k_bmi_lz_data(ar, buffer, head_len);
if (ret)
return ret;
if (trailer_len > 0)
ret = ath10k_bmi_lz_data(ar, trailer, 4);
if (ret != 0)
return ret;
/*
* Close compressed stream and open a new (fake) one.
* This serves mainly to flush Target caches.
*/
ret = ath10k_bmi_lz_stream_start(ar, 0x00);
return ret;
}
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2013 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 _BMI_H_
#define _BMI_H_
#include "core.h"
/*
* Bootloader Messaging Interface (BMI)
*
* BMI is a very simple messaging interface used during initialization
* to read memory, write memory, execute code, and to define an
* application entry PC.
*
* It is used to download an application to QCA988x, to provide
* patches to code that is already resident on QCA988x, and generally
* to examine and modify state. The Host has an opportunity to use
* BMI only once during bootup. Once the Host issues a BMI_DONE
* command, this opportunity ends.
*
* The Host writes BMI requests to mailbox0, and reads BMI responses
* from mailbox0. BMI requests all begin with a command
* (see below for specific commands), and are followed by
* command-specific data.
*
* Flow control:
* The Host can only issue a command once the Target gives it a
* "BMI Command Credit", using AR8K Counter #4. As soon as the
* Target has completed a command, it issues another BMI Command
* Credit (so the Host can issue the next command).
*
* BMI handles all required Target-side cache flushing.
*/
/* Maximum data size used for BMI transfers */
#define BMI_MAX_DATA_SIZE 256
/* len = cmd + addr + length */
#define BMI_MAX_CMDBUF_SIZE (BMI_MAX_DATA_SIZE + \
sizeof(u32) + \
sizeof(u32) + \
sizeof(u32))
/* BMI Commands */
enum bmi_cmd_id {
BMI_NO_COMMAND = 0,
BMI_DONE = 1,
BMI_READ_MEMORY = 2,
BMI_WRITE_MEMORY = 3,
BMI_EXECUTE = 4,
BMI_SET_APP_START = 5,
BMI_READ_SOC_REGISTER = 6,
BMI_READ_SOC_WORD = 6,
BMI_WRITE_SOC_REGISTER = 7,
BMI_WRITE_SOC_WORD = 7,
BMI_GET_TARGET_ID = 8,
BMI_GET_TARGET_INFO = 8,
BMI_ROMPATCH_INSTALL = 9,
BMI_ROMPATCH_UNINSTALL = 10,
BMI_ROMPATCH_ACTIVATE = 11,
BMI_ROMPATCH_DEACTIVATE = 12,
BMI_LZ_STREAM_START = 13, /* should be followed by LZ_DATA */
BMI_LZ_DATA = 14,
BMI_NVRAM_PROCESS = 15,
};
#define BMI_NVRAM_SEG_NAME_SZ 16
struct bmi_cmd {
__le32 id; /* enum bmi_cmd_id */
union {
struct {
} done;
struct {
__le32 addr;
__le32 len;
} read_mem;
struct {
__le32 addr;
__le32 len;
u8 payload[0];
} write_mem;
struct {
__le32 addr;
__le32 param;
} execute;
struct {
__le32 addr;
} set_app_start;
struct {
__le32 addr;
} read_soc_reg;
struct {
__le32 addr;
__le32 value;
} write_soc_reg;
struct {
} get_target_info;
struct {
__le32 rom_addr;
__le32 ram_addr; /* or value */
__le32 size;
__le32 activate; /* 0=install, but dont activate */
} rompatch_install;
struct {
__le32 patch_id;
} rompatch_uninstall;
struct {
__le32 count;
__le32 patch_ids[0]; /* length of @count */
} rompatch_activate;
struct {
__le32 count;
__le32 patch_ids[0]; /* length of @count */
} rompatch_deactivate;
struct {
__le32 addr;
} lz_start;
struct {
__le32 len; /* max BMI_MAX_DATA_SIZE */
u8 payload[0]; /* length of @len */
} lz_data;
struct {
u8 name[BMI_NVRAM_SEG_NAME_SZ];
} nvram_process;
u8 payload[BMI_MAX_CMDBUF_SIZE];
};
} __packed;
union bmi_resp {
struct {
u8 payload[0];
} read_mem;
struct {
__le32 result;
} execute;
struct {
__le32 value;
} read_soc_reg;
struct {
__le32 len;
__le32 version;
__le32 type;
} get_target_info;
struct {
__le32 patch_id;
} rompatch_install;
struct {
__le32 patch_id;
} rompatch_uninstall;
struct {
/* 0 = nothing executed
* otherwise = NVRAM segment return value */
__le32 result;
} nvram_process;
u8 payload[BMI_MAX_CMDBUF_SIZE];
} __packed;
struct bmi_target_info {
u32 version;
u32 type;
};
/* in msec */
#define BMI_COMMUNICATION_TIMEOUT_HZ (1*HZ)
#define BMI_CE_NUM_TO_TARG 0
#define BMI_CE_NUM_TO_HOST 1
int ath10k_bmi_done(struct ath10k *ar);
int ath10k_bmi_get_target_info(struct ath10k *ar,
struct bmi_target_info *target_info);
int ath10k_bmi_read_memory(struct ath10k *ar, u32 address,
void *buffer, u32 length);
int ath10k_bmi_write_memory(struct ath10k *ar, u32 address,
const void *buffer, u32 length);
#define ath10k_bmi_read32(ar, item, val) \
({ \
int ret; \
u32 addr; \
__le32 tmp; \
\
addr = host_interest_item_address(HI_ITEM(item)); \
ret = ath10k_bmi_read_memory(ar, addr, (u8 *)&tmp, 4); \
*val = __le32_to_cpu(tmp); \
ret; \
})
#define ath10k_bmi_write32(ar, item, val) \
({ \
int ret; \
u32 address; \
__le32 v = __cpu_to_le32(val); \
\
address = host_interest_item_address(HI_ITEM(item)); \
ret = ath10k_bmi_write_memory(ar, address, \
(u8 *)&v, sizeof(v)); \
ret; \
})
int ath10k_bmi_execute(struct ath10k *ar, u32 address, u32 *param);
int ath10k_bmi_lz_stream_start(struct ath10k *ar, u32 address);
int ath10k_bmi_lz_data(struct ath10k *ar, const void *buffer, u32 length);
int ath10k_bmi_fast_download(struct ath10k *ar, u32 address,
const void *buffer, u32 length);
#endif /* _BMI_H_ */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2013 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 _CORE_H_
#define _CORE_H_
#include <linux/completion.h>
#include <linux/if_ether.h>
#include <linux/types.h>
#include <linux/pci.h>
#include "htc.h"
#include "hw.h"
#include "targaddrs.h"
#include "wmi.h"
#include "../ath.h"
#include "../regd.h"
#define MS(_v, _f) (((_v) & _f##_MASK) >> _f##_LSB)
#define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK)
#define WO(_f) ((_f##_OFFSET) >> 2)
#define ATH10K_SCAN_ID 0
#define WMI_READY_TIMEOUT (5 * HZ)
#define ATH10K_FLUSH_TIMEOUT_HZ (5*HZ)
/* Antenna noise floor */
#define ATH10K_DEFAULT_NOISE_FLOOR -95
struct ath10k;
enum ath10k_bus {
ATH10K_BUS_PCI,
};
struct ath10k_skb_cb {
dma_addr_t paddr;
bool is_mapped;
bool is_aborted;
struct {
u8 vdev_id;
u16 msdu_id;
u8 tid;
bool is_offchan;
bool is_conf;
bool discard;
bool no_ack;
u8 refcount;
struct sk_buff *txfrag;
struct sk_buff *msdu;
} __packed htt;
/* 4 bytes left on 64bit arch */
} __packed;
static inline struct ath10k_skb_cb *ATH10K_SKB_CB(struct sk_buff *skb)
{
BUILD_BUG_ON(sizeof(struct ath10k_skb_cb) >
IEEE80211_TX_INFO_DRIVER_DATA_SIZE);
return (struct ath10k_skb_cb *)&IEEE80211_SKB_CB(skb)->driver_data;
}
static inline int ath10k_skb_map(struct device *dev, struct sk_buff *skb)
{
if (ATH10K_SKB_CB(skb)->is_mapped)
return -EINVAL;
ATH10K_SKB_CB(skb)->paddr = dma_map_single(dev, skb->data, skb->len,
DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(dev, ATH10K_SKB_CB(skb)->paddr)))
return -EIO;
ATH10K_SKB_CB(skb)->is_mapped = true;
return 0;
}
static inline int ath10k_skb_unmap(struct device *dev, struct sk_buff *skb)
{
if (!ATH10K_SKB_CB(skb)->is_mapped)
return -EINVAL;
dma_unmap_single(dev, ATH10K_SKB_CB(skb)->paddr, skb->len,
DMA_TO_DEVICE);
ATH10K_SKB_CB(skb)->is_mapped = false;
return 0;
}
static inline u32 host_interest_item_address(u32 item_offset)
{
return QCA988X_HOST_INTEREST_ADDRESS + item_offset;
}
struct ath10k_bmi {
bool done_sent;
};
struct ath10k_wmi {
enum ath10k_htc_ep_id eid;
struct completion service_ready;
struct completion unified_ready;
atomic_t pending_tx_count;
wait_queue_head_t wq;
struct sk_buff_head wmi_event_list;
struct work_struct wmi_event_work;
};
struct ath10k_peer_stat {
u8 peer_macaddr[ETH_ALEN];
u32 peer_rssi;
u32 peer_tx_rate;
};
struct ath10k_target_stats {
/* PDEV stats */
s32 ch_noise_floor;
u32 tx_frame_count;
u32 rx_frame_count;
u32 rx_clear_count;
u32 cycle_count;
u32 phy_err_count;
u32 chan_tx_power;
/* PDEV TX stats */
s32 comp_queued;
s32 comp_delivered;
s32 msdu_enqued;
s32 mpdu_enqued;
s32 wmm_drop;
s32 local_enqued;
s32 local_freed;
s32 hw_queued;
s32 hw_reaped;
s32 underrun;
s32 tx_abort;
s32 mpdus_requed;
u32 tx_ko;
u32 data_rc;
u32 self_triggers;
u32 sw_retry_failure;
u32 illgl_rate_phy_err;
u32 pdev_cont_xretry;
u32 pdev_tx_timeout;
u32 pdev_resets;
u32 phy_underrun;
u32 txop_ovf;
/* PDEV RX stats */
s32 mid_ppdu_route_change;
s32 status_rcvd;
s32 r0_frags;
s32 r1_frags;
s32 r2_frags;
s32 r3_frags;
s32 htt_msdus;
s32 htt_mpdus;
s32 loc_msdus;
s32 loc_mpdus;
s32 oversize_amsdu;
s32 phy_errs;
s32 phy_err_drop;
s32 mpdu_errs;
/* VDEV STATS */
/* PEER STATS */
u8 peers;
struct ath10k_peer_stat peer_stat[TARGET_NUM_PEERS];
/* TODO: Beacon filter stats */
};
#define ATH10K_MAX_NUM_PEER_IDS (1 << 11) /* htt rx_desc limit */
struct ath10k_peer {
struct list_head list;
int vdev_id;
u8 addr[ETH_ALEN];
DECLARE_BITMAP(peer_ids, ATH10K_MAX_NUM_PEER_IDS);
struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
};
#define ATH10K_VDEV_SETUP_TIMEOUT_HZ (5*HZ)
struct ath10k_vif {
u32 vdev_id;
enum wmi_vdev_type vdev_type;
enum wmi_vdev_subtype vdev_subtype;
u32 beacon_interval;
u32 dtim_period;
struct ath10k *ar;
struct ieee80211_vif *vif;
struct ieee80211_key_conf *wep_keys[WMI_MAX_KEY_INDEX + 1];
u8 def_wep_key_index;
u16 tx_seq_no;
union {
struct {
u8 bssid[ETH_ALEN];
u32 uapsd;
} sta;
struct {
/* 127 stations; wmi limit */
u8 tim_bitmap[16];
u8 tim_len;
u32 ssid_len;
u8 ssid[IEEE80211_MAX_SSID_LEN];
bool hidden_ssid;
/* P2P_IE with NoA attribute for P2P_GO case */
u32 noa_len;
u8 *noa_data;
} ap;
struct {
u8 bssid[ETH_ALEN];
} ibss;
} u;
};
struct ath10k_vif_iter {
u32 vdev_id;
struct ath10k_vif *arvif;
};
struct ath10k_debug {
struct dentry *debugfs_phy;
struct ath10k_target_stats target_stats;
u32 wmi_service_bitmap[WMI_SERVICE_BM_SIZE];
struct completion event_stats_compl;
};
struct ath10k {
struct ath_common ath_common;
struct ieee80211_hw *hw;
struct device *dev;
u8 mac_addr[ETH_ALEN];
u32 target_version;
u8 fw_version_major;
u32 fw_version_minor;
u16 fw_version_release;
u16 fw_version_build;
u32 phy_capability;
u32 hw_min_tx_power;
u32 hw_max_tx_power;
u32 ht_cap_info;
u32 vht_cap_info;
struct targetdef *targetdef;
struct hostdef *hostdef;
bool p2p;
struct {
void *priv;
enum ath10k_bus bus;
const struct ath10k_hif_ops *ops;
} hif;
struct ath10k_wmi wmi;
wait_queue_head_t event_queue;
bool is_target_paused;
struct ath10k_bmi bmi;
struct ath10k_htc *htc;
struct ath10k_htt *htt;
struct ath10k_hw_params {
u32 id;
const char *name;
u32 patch_load_addr;
struct ath10k_hw_params_fw {
const char *dir;
const char *fw;
const char *otp;
const char *board;
} fw;
} hw_params;
struct {
struct completion started;
struct completion completed;
struct completion on_channel;
struct timer_list timeout;
bool is_roc;
bool in_progress;
bool aborting;
int vdev_id;
int roc_freq;
} scan;
struct {
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
} mac;
/* should never be NULL; needed for regular htt rx */
struct ieee80211_channel *rx_channel;
/* valid during scan; needed for mgmt rx during scan */
struct ieee80211_channel *scan_channel;
int free_vdev_map;
int monitor_vdev_id;
bool monitor_enabled;
bool monitor_present;
unsigned int filter_flags;
struct wmi_pdev_set_wmm_params_arg wmm_params;
struct completion install_key_done;
struct completion vdev_setup_done;
struct workqueue_struct *workqueue;
/* prevents concurrent FW reconfiguration */
struct mutex conf_mutex;
/* protects shared structure data */
spinlock_t data_lock;
struct list_head peers;
wait_queue_head_t peer_mapping_wq;
struct work_struct offchan_tx_work;
struct sk_buff_head offchan_tx_queue;
struct completion offchan_tx_completed;
struct sk_buff *offchan_tx_skb;
#ifdef CONFIG_ATH10K_DEBUGFS
struct ath10k_debug debug;
#endif
};
struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
enum ath10k_bus bus,
const struct ath10k_hif_ops *hif_ops);
void ath10k_core_destroy(struct ath10k *ar);
int ath10k_core_register(struct ath10k *ar);
void ath10k_core_unregister(struct ath10k *ar);
int ath10k_core_target_suspend(struct ath10k *ar);
int ath10k_core_target_resume(struct ath10k *ar);
#endif /* _CORE_H_ */
This diff is collapsed.
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2013 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 _DEBUG_H_
#define _DEBUG_H_
#include <linux/types.h>
#include "trace.h"
enum ath10k_debug_mask {
ATH10K_DBG_PCI = 0x00000001,
ATH10K_DBG_WMI = 0x00000002,
ATH10K_DBG_HTC = 0x00000004,
ATH10K_DBG_HTT = 0x00000008,
ATH10K_DBG_MAC = 0x00000010,
ATH10K_DBG_CORE = 0x00000020,
ATH10K_DBG_PCI_DUMP = 0x00000040,
ATH10K_DBG_HTT_DUMP = 0x00000080,
ATH10K_DBG_MGMT = 0x00000100,
ATH10K_DBG_DATA = 0x00000200,
ATH10K_DBG_ANY = 0xffffffff,
};
extern unsigned int ath10k_debug_mask;
extern __printf(1, 2) int ath10k_info(const char *fmt, ...);
extern __printf(1, 2) int ath10k_err(const char *fmt, ...);
extern __printf(1, 2) int ath10k_warn(const char *fmt, ...);
#ifdef CONFIG_ATH10K_DEBUGFS
int ath10k_debug_create(struct ath10k *ar);
void ath10k_debug_read_service_map(struct ath10k *ar,
void *service_map,
size_t map_size);
void ath10k_debug_read_target_stats(struct ath10k *ar,
struct wmi_stats_event *ev);
#else
static inline int ath10k_debug_create(struct ath10k *ar)
{
return 0;
}
static inline void ath10k_debug_read_service_map(struct ath10k *ar,
void *service_map,
size_t map_size)
{
}
static inline void ath10k_debug_read_target_stats(struct ath10k *ar,
struct wmi_stats_event *ev)
{
}
#endif /* CONFIG_ATH10K_DEBUGFS */
#ifdef CONFIG_ATH10K_DEBUG
extern __printf(2, 3) void ath10k_dbg(enum ath10k_debug_mask mask,
const char *fmt, ...);
void ath10k_dbg_dump(enum ath10k_debug_mask mask,
const char *msg, const char *prefix,
const void *buf, size_t len);
#else /* CONFIG_ATH10K_DEBUG */
static inline int ath10k_dbg(enum ath10k_debug_mask dbg_mask,
const char *fmt, ...)
{
return 0;
}
static inline void ath10k_dbg_dump(enum ath10k_debug_mask mask,
const char *msg, const char *prefix,
const void *buf, size_t len)
{
}
#endif /* CONFIG_ATH10K_DEBUG */
#endif /* _DEBUG_H_ */
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2013 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 _HIF_H_
#define _HIF_H_
#include <linux/kernel.h>
#include "core.h"
struct ath10k_hif_cb {
int (*tx_completion)(struct ath10k *ar,
struct sk_buff *wbuf,
unsigned transfer_id);
int (*rx_completion)(struct ath10k *ar,
struct sk_buff *wbuf,
u8 pipe_id);
};
struct ath10k_hif_ops {
/* Send the head of a buffer to HIF for transmission to the target. */
int (*send_head)(struct ath10k *ar, u8 pipe_id,
unsigned int transfer_id,
unsigned int nbytes,
struct sk_buff *buf);
/*
* API to handle HIF-specific BMI message exchanges, this API is
* synchronous and only allowed to be called from a context that
* can block (sleep)
*/
int (*exchange_bmi_msg)(struct ath10k *ar,
void *request, u32 request_len,
void *response, u32 *response_len);
int (*start)(struct ath10k *ar);
void (*stop)(struct ath10k *ar);
int (*map_service_to_pipe)(struct ath10k *ar, u16 service_id,
u8 *ul_pipe, u8 *dl_pipe,
int *ul_is_polled, int *dl_is_polled);
void (*get_default_pipe)(struct ath10k *ar, u8 *ul_pipe, u8 *dl_pipe);
/*
* Check if prior sends have completed.
*
* Check whether the pipe in question has any completed
* sends that have not yet been processed.
* This function is only relevant for HIF pipes that are configured
* to be polled rather than interrupt-driven.
*/
void (*send_complete_check)(struct ath10k *ar, u8 pipe_id, int force);
void (*init)(struct ath10k *ar,
struct ath10k_hif_cb *callbacks);
u16 (*get_free_queue_number)(struct ath10k *ar, u8 pipe_id);
};
static inline int ath10k_hif_send_head(struct ath10k *ar, u8 pipe_id,
unsigned int transfer_id,
unsigned int nbytes,
struct sk_buff *buf)
{
return ar->hif.ops->send_head(ar, pipe_id, transfer_id, nbytes, buf);
}
static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar,
void *request, u32 request_len,
void *response, u32 *response_len)
{
return ar->hif.ops->exchange_bmi_msg(ar, request, request_len,
response, response_len);
}
static inline int ath10k_hif_start(struct ath10k *ar)
{
return ar->hif.ops->start(ar);
}
static inline void ath10k_hif_stop(struct ath10k *ar)
{
return ar->hif.ops->stop(ar);
}
static inline int ath10k_hif_map_service_to_pipe(struct ath10k *ar,
u16 service_id,
u8 *ul_pipe, u8 *dl_pipe,
int *ul_is_polled,
int *dl_is_polled)
{
return ar->hif.ops->map_service_to_pipe(ar, service_id,
ul_pipe, dl_pipe,
ul_is_polled, dl_is_polled);
}
static inline void ath10k_hif_get_default_pipe(struct ath10k *ar,
u8 *ul_pipe, u8 *dl_pipe)
{
ar->hif.ops->get_default_pipe(ar, ul_pipe, dl_pipe);
}
static inline void ath10k_hif_send_complete_check(struct ath10k *ar,
u8 pipe_id, int force)
{
ar->hif.ops->send_complete_check(ar, pipe_id, force);
}
static inline void ath10k_hif_init(struct ath10k *ar,
struct ath10k_hif_cb *callbacks)
{
ar->hif.ops->init(ar, callbacks);
}
static inline u16 ath10k_hif_get_free_queue_number(struct ath10k *ar,
u8 pipe_id)
{
return ar->hif.ops->get_free_queue_number(ar, pipe_id);
}
#endif /* _HIF_H_ */
This diff is collapsed.
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2013 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 _HTC_H_
#define _HTC_H_
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/bug.h>
#include <linux/skbuff.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
struct ath10k;
/****************/
/* HTC protocol */
/****************/
/*
* HTC - host-target control protocol
*
* tx packets are generally <htc_hdr><payload>
* rx packets are more complex: <htc_hdr><payload><trailer>
*
* The payload + trailer length is stored in len.
* To get payload-only length one needs to payload - trailer_len.
*
* Trailer contains (possibly) multiple <htc_record>.
* Each record is a id-len-value.
*
* HTC header flags, control_byte0, control_byte1
* have different meaning depending whether its tx
* or rx.
*
* Alignment: htc_hdr, payload and trailer are
* 4-byte aligned.
*/
enum ath10k_htc_tx_flags {
ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE = 0x01,
ATH10K_HTC_FLAG_SEND_BUNDLE = 0x02
};
enum ath10k_htc_rx_flags {
ATH10K_HTC_FLAG_TRAILER_PRESENT = 0x02,
ATH10K_HTC_FLAG_BUNDLE_MASK = 0xF0
};
struct ath10k_htc_hdr {
u8 eid; /* @enum ath10k_htc_ep_id */
u8 flags; /* @enum ath10k_htc_tx_flags, ath10k_htc_rx_flags */
__le16 len;
union {
u8 trailer_len; /* for rx */
u8 control_byte0;
} __packed;
union {
u8 seq_no; /* for tx */
u8 control_byte1;
} __packed;
u8 pad0;
u8 pad1;
} __packed __aligned(4);
enum ath10k_ath10k_htc_msg_id {
ATH10K_HTC_MSG_READY_ID = 1,
ATH10K_HTC_MSG_CONNECT_SERVICE_ID = 2,
ATH10K_HTC_MSG_CONNECT_SERVICE_RESP_ID = 3,
ATH10K_HTC_MSG_SETUP_COMPLETE_ID = 4,
ATH10K_HTC_MSG_SETUP_COMPLETE_EX_ID = 5,
ATH10K_HTC_MSG_SEND_SUSPEND_COMPLETE = 6
};
enum ath10k_htc_version {
ATH10K_HTC_VERSION_2P0 = 0x00, /* 2.0 */
ATH10K_HTC_VERSION_2P1 = 0x01, /* 2.1 */
};
enum ath10k_htc_conn_flags {
ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_ONE_FOURTH = 0x0,
ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_ONE_HALF = 0x1,
ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_THREE_FOURTHS = 0x2,
ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_UNITY = 0x3,
#define ATH10K_HTC_CONN_FLAGS_THRESHOLD_LEVEL_MASK 0x3
ATH10K_HTC_CONN_FLAGS_REDUCE_CREDIT_DRIBBLE = 1 << 2,
ATH10K_HTC_CONN_FLAGS_DISABLE_CREDIT_FLOW_CTRL = 1 << 3
#define ATH10K_HTC_CONN_FLAGS_RECV_ALLOC_MASK 0xFF00
#define ATH10K_HTC_CONN_FLAGS_RECV_ALLOC_LSB 8
};
enum ath10k_htc_conn_svc_status {
ATH10K_HTC_CONN_SVC_STATUS_SUCCESS = 0,
ATH10K_HTC_CONN_SVC_STATUS_NOT_FOUND = 1,
ATH10K_HTC_CONN_SVC_STATUS_FAILED = 2,
ATH10K_HTC_CONN_SVC_STATUS_NO_RESOURCES = 3,
ATH10K_HTC_CONN_SVC_STATUS_NO_MORE_EP = 4
};
struct ath10k_ath10k_htc_msg_hdr {
__le16 message_id; /* @enum htc_message_id */
} __packed;
struct ath10k_htc_unknown {
u8 pad0;
u8 pad1;
} __packed;
struct ath10k_htc_ready {
__le16 credit_count;
__le16 credit_size;
u8 max_endpoints;
u8 pad0;
} __packed;
struct ath10k_htc_ready_extended {
struct ath10k_htc_ready base;
u8 htc_version; /* @enum ath10k_htc_version */
u8 max_msgs_per_htc_bundle;
u8 pad0;
u8 pad1;
} __packed;
struct ath10k_htc_conn_svc {
__le16 service_id;
__le16 flags; /* @enum ath10k_htc_conn_flags */
u8 pad0;
u8 pad1;
} __packed;
struct ath10k_htc_conn_svc_response {
__le16 service_id;
u8 status; /* @enum ath10k_htc_conn_svc_status */
u8 eid;
__le16 max_msg_size;
} __packed;
struct ath10k_htc_setup_complete_extended {
u8 pad0;
u8 pad1;
__le32 flags; /* @enum htc_setup_complete_flags */
u8 max_msgs_per_bundled_recv;
u8 pad2;
u8 pad3;
u8 pad4;
} __packed;
struct ath10k_htc_msg {
struct ath10k_ath10k_htc_msg_hdr hdr;
union {
/* host-to-target */
struct ath10k_htc_conn_svc connect_service;
struct ath10k_htc_ready ready;
struct ath10k_htc_ready_extended ready_ext;
struct ath10k_htc_unknown unknown;
struct ath10k_htc_setup_complete_extended setup_complete_ext;
/* target-to-host */
struct ath10k_htc_conn_svc_response connect_service_response;
};
} __packed __aligned(4);
enum ath10k_ath10k_htc_record_id {
ATH10K_HTC_RECORD_NULL = 0,
ATH10K_HTC_RECORD_CREDITS = 1
};
struct ath10k_ath10k_htc_record_hdr {
u8 id; /* @enum ath10k_ath10k_htc_record_id */
u8 len;
u8 pad0;
u8 pad1;
} __packed;
struct ath10k_htc_credit_report {
u8 eid; /* @enum ath10k_htc_ep_id */
u8 credits;
u8 pad0;
u8 pad1;
} __packed;
struct ath10k_htc_record {
struct ath10k_ath10k_htc_record_hdr hdr;
union {
struct ath10k_htc_credit_report credit_report[0];
u8 pauload[0];
};
} __packed __aligned(4);
/*
* note: the trailer offset is dynamic depending
* on payload length. this is only a struct layout draft
*/
struct ath10k_htc_frame {
struct ath10k_htc_hdr hdr;
union {
struct ath10k_htc_msg msg;
u8 payload[0];
};
struct ath10k_htc_record trailer[0];
} __packed __aligned(4);
/*******************/
/* Host-side stuff */
/*******************/
enum ath10k_htc_svc_gid {
ATH10K_HTC_SVC_GRP_RSVD = 0,
ATH10K_HTC_SVC_GRP_WMI = 1,
ATH10K_HTC_SVC_GRP_NMI = 2,
ATH10K_HTC_SVC_GRP_HTT = 3,
ATH10K_HTC_SVC_GRP_TEST = 254,
ATH10K_HTC_SVC_GRP_LAST = 255,
};
#define SVC(group, idx) \
(int)(((int)(group) << 8) | (int)(idx))
enum ath10k_htc_svc_id {
/* NOTE: service ID of 0x0000 is reserved and should never be used */
ATH10K_HTC_SVC_ID_RESERVED = 0x0000,
ATH10K_HTC_SVC_ID_UNUSED = ATH10K_HTC_SVC_ID_RESERVED,
ATH10K_HTC_SVC_ID_RSVD_CTRL = SVC(ATH10K_HTC_SVC_GRP_RSVD, 1),
ATH10K_HTC_SVC_ID_WMI_CONTROL = SVC(ATH10K_HTC_SVC_GRP_WMI, 0),
ATH10K_HTC_SVC_ID_WMI_DATA_BE = SVC(ATH10K_HTC_SVC_GRP_WMI, 1),
ATH10K_HTC_SVC_ID_WMI_DATA_BK = SVC(ATH10K_HTC_SVC_GRP_WMI, 2),
ATH10K_HTC_SVC_ID_WMI_DATA_VI = SVC(ATH10K_HTC_SVC_GRP_WMI, 3),
ATH10K_HTC_SVC_ID_WMI_DATA_VO = SVC(ATH10K_HTC_SVC_GRP_WMI, 4),
ATH10K_HTC_SVC_ID_NMI_CONTROL = SVC(ATH10K_HTC_SVC_GRP_NMI, 0),
ATH10K_HTC_SVC_ID_NMI_DATA = SVC(ATH10K_HTC_SVC_GRP_NMI, 1),
ATH10K_HTC_SVC_ID_HTT_DATA_MSG = SVC(ATH10K_HTC_SVC_GRP_HTT, 0),
/* raw stream service (i.e. flash, tcmd, calibration apps) */
ATH10K_HTC_SVC_ID_TEST_RAW_STREAMS = SVC(ATH10K_HTC_SVC_GRP_TEST, 0),
};
#undef SVC
enum ath10k_htc_ep_id {
ATH10K_HTC_EP_UNUSED = -1,
ATH10K_HTC_EP_0 = 0,
ATH10K_HTC_EP_1 = 1,
ATH10K_HTC_EP_2,
ATH10K_HTC_EP_3,
ATH10K_HTC_EP_4,
ATH10K_HTC_EP_5,
ATH10K_HTC_EP_6,
ATH10K_HTC_EP_7,
ATH10K_HTC_EP_8,
ATH10K_HTC_EP_COUNT,
};
struct ath10k_htc_ops {
void (*target_send_suspend_complete)(struct ath10k *ar);
};
struct ath10k_htc_ep_ops {
void (*ep_tx_complete)(struct ath10k *, struct sk_buff *);
void (*ep_rx_complete)(struct ath10k *, struct sk_buff *);
};
/* service connection information */
struct ath10k_htc_svc_conn_req {
u16 service_id;
struct ath10k_htc_ep_ops ep_ops;
int max_send_queue_depth;
};
/* service connection response information */
struct ath10k_htc_svc_conn_resp {
u8 buffer_len;
u8 actual_len;
enum ath10k_htc_ep_id eid;
unsigned int max_msg_len;
u8 connect_resp_code;
};
#define ATH10K_NUM_CONTROL_TX_BUFFERS 2
#define ATH10K_HTC_MAX_LEN 4096
#define ATH10K_HTC_MAX_CTRL_MSG_LEN 256
#define ATH10K_HTC_WAIT_TIMEOUT_HZ (1*HZ)
#define ATH10K_HTC_CONTROL_BUFFER_SIZE (ATH10K_HTC_MAX_CTRL_MSG_LEN + \
sizeof(struct ath10k_htc_hdr))
#define ATH10K_HTC_CONN_SVC_TIMEOUT_HZ (1*HZ)
struct ath10k_htc_ep {
struct ath10k_htc *htc;
enum ath10k_htc_ep_id eid;
enum ath10k_htc_svc_id service_id;
struct ath10k_htc_ep_ops ep_ops;
int max_tx_queue_depth;
int max_ep_message_len;
u8 ul_pipe_id;
u8 dl_pipe_id;
int ul_is_polled; /* call HIF to get tx completions */
int dl_is_polled; /* call HIF to fetch rx (not implemented) */
struct sk_buff_head tx_queue;
u8 seq_no; /* for debugging */
int tx_credits;
int tx_credit_size;
int tx_credits_per_max_message;
bool tx_credit_flow_enabled;
struct work_struct send_work;
};
struct ath10k_htc_svc_tx_credits {
u16 service_id;
u8 credit_allocation;
};
struct ath10k_htc {
struct ath10k *ar;
struct ath10k_htc_ep endpoint[ATH10K_HTC_EP_COUNT];
/* protects endpoint and stopping fields */
spinlock_t tx_lock;
struct ath10k_htc_ops htc_ops;
u8 control_resp_buffer[ATH10K_HTC_MAX_CTRL_MSG_LEN];
int control_resp_len;
struct completion ctl_resp;
int total_transmit_credits;
struct ath10k_htc_svc_tx_credits service_tx_alloc[ATH10K_HTC_EP_COUNT];
int target_credit_size;
bool stopping;
};
struct ath10k_htc *ath10k_htc_create(struct ath10k *ar,
struct ath10k_htc_ops *htc_ops);
int ath10k_htc_wait_target(struct ath10k_htc *htc);
int ath10k_htc_start(struct ath10k_htc *htc);
int ath10k_htc_connect_service(struct ath10k_htc *htc,
struct ath10k_htc_svc_conn_req *conn_req,
struct ath10k_htc_svc_conn_resp *conn_resp);
int ath10k_htc_send(struct ath10k_htc *htc, enum ath10k_htc_ep_id eid,
struct sk_buff *packet);
void ath10k_htc_stop(struct ath10k_htc *htc);
void ath10k_htc_destroy(struct ath10k_htc *htc);
struct sk_buff *ath10k_htc_alloc_skb(int size);
#endif
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2013 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/slab.h>
#include "htt.h"
#include "core.h"
#include "debug.h"
static int ath10k_htt_htc_attach(struct ath10k_htt *htt)
{
struct ath10k_htc_svc_conn_req conn_req;
struct ath10k_htc_svc_conn_resp conn_resp;
int status;
memset(&conn_req, 0, sizeof(conn_req));
memset(&conn_resp, 0, sizeof(conn_resp));
conn_req.ep_ops.ep_tx_complete = ath10k_htt_htc_tx_complete;
conn_req.ep_ops.ep_rx_complete = ath10k_htt_t2h_msg_handler;
/* connect to control service */
conn_req.service_id = ATH10K_HTC_SVC_ID_HTT_DATA_MSG;
status = ath10k_htc_connect_service(htt->ar->htc, &conn_req,
&conn_resp);
if (status)
return status;
htt->eid = conn_resp.eid;
return 0;
}
struct ath10k_htt *ath10k_htt_attach(struct ath10k *ar)
{
struct ath10k_htt *htt;
int ret;
htt = kzalloc(sizeof(*htt), GFP_KERNEL);
if (!htt)
return NULL;
htt->ar = ar;
htt->max_throughput_mbps = 800;
/*
* Connect to HTC service.
* This has to be done before calling ath10k_htt_rx_attach,
* since ath10k_htt_rx_attach involves sending a rx ring configure
* message to the target.
*/
if (ath10k_htt_htc_attach(htt))
goto err_htc_attach;
ret = ath10k_htt_tx_attach(htt);
if (ret) {
ath10k_err("could not attach htt tx (%d)\n", ret);
goto err_htc_attach;
}
if (ath10k_htt_rx_attach(htt))
goto err_rx_attach;
/*
* Prefetch enough data to satisfy target
* classification engine.
* This is for LL chips. HL chips will probably
* transfer all frame in the tx fragment.
*/
htt->prefetch_len =
36 + /* 802.11 + qos + ht */
4 + /* 802.1q */
8 + /* llc snap */
2; /* ip4 dscp or ip6 priority */
return htt;
err_rx_attach:
ath10k_htt_tx_detach(htt);
err_htc_attach:
kfree(htt);
return NULL;
}
#define HTT_TARGET_VERSION_TIMEOUT_HZ (3*HZ)
static int ath10k_htt_verify_version(struct ath10k_htt *htt)
{
ath10k_dbg(ATH10K_DBG_HTT,
"htt target version %d.%d; host version %d.%d\n",
htt->target_version_major,
htt->target_version_minor,
HTT_CURRENT_VERSION_MAJOR,
HTT_CURRENT_VERSION_MINOR);
if (htt->target_version_major != HTT_CURRENT_VERSION_MAJOR) {
ath10k_err("htt major versions are incompatible!\n");
return -ENOTSUPP;
}
if (htt->target_version_minor != HTT_CURRENT_VERSION_MINOR)
ath10k_warn("htt minor version differ but still compatible\n");
return 0;
}
int ath10k_htt_attach_target(struct ath10k_htt *htt)
{
int status;
init_completion(&htt->target_version_received);
status = ath10k_htt_h2t_ver_req_msg(htt);
if (status)
return status;
status = wait_for_completion_timeout(&htt->target_version_received,
HTT_TARGET_VERSION_TIMEOUT_HZ);
if (status <= 0) {
ath10k_warn("htt version request timed out\n");
return -ETIMEDOUT;
}
status = ath10k_htt_verify_version(htt);
if (status)
return status;
return ath10k_htt_send_rx_ring_cfg_ll(htt);
}
void ath10k_htt_detach(struct ath10k_htt *htt)
{
ath10k_htt_rx_detach(htt);
ath10k_htt_tx_detach(htt);
kfree(htt);
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2013 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 _MAC_H_
#define _MAC_H_
#include <net/mac80211.h>
#include "core.h"
struct ath10k_generic_iter {
struct ath10k *ar;
int ret;
};
struct ath10k *ath10k_mac_create(void);
void ath10k_mac_destroy(struct ath10k *ar);
int ath10k_mac_register(struct ath10k *ar);
void ath10k_mac_unregister(struct ath10k *ar);
struct ath10k_vif *ath10k_get_arvif(struct ath10k *ar, u32 vdev_id);
void ath10k_reset_scan(unsigned long ptr);
void ath10k_offchan_tx_purge(struct ath10k *ar);
void ath10k_offchan_tx_work(struct work_struct *work);
static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
{
return (struct ath10k_vif *)vif->drv_priv;
}
static inline void ath10k_tx_h_seq_no(struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_vif *vif = info->control.vif;
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
if (arvif->tx_seq_no == 0)
arvif->tx_seq_no = 0x1000;
if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
arvif->tx_seq_no += 0x10;
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
hdr->seq_ctrl |= cpu_to_le16(arvif->tx_seq_no);
}
}
#endif /* _MAC_H_ */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (c) 2012 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/module.h>
#define CREATE_TRACE_POINTS
#include "trace.h"
This diff is collapsed.
This diff is collapsed.
/*
* Copyright (c) 2005-2011 Atheros Communications Inc.
* Copyright (c) 2011-2013 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 _TXRX_H_
#define _TXRX_H_
#include "htt.h"
void ath10k_txrx_tx_unref(struct ath10k_htt *htt, struct sk_buff *txdesc);
void ath10k_txrx_tx_completed(struct ath10k_htt *htt,
const struct htt_tx_done *tx_done);
void ath10k_process_rx(struct ath10k *ar, struct htt_rx_info *info);
struct ath10k_peer *ath10k_peer_find(struct ath10k *ar, int vdev_id,
const u8 *addr);
int ath10k_wait_for_peer_created(struct ath10k *ar, int vdev_id,
const u8 *addr);
int ath10k_wait_for_peer_deleted(struct ath10k *ar, int vdev_id,
const u8 *addr);
void ath10k_peer_map_event(struct ath10k_htt *htt,
struct htt_peer_map_event *ev);
void ath10k_peer_unmap_event(struct ath10k_htt *htt,
struct htt_peer_unmap_event *ev);
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -47,6 +47,7 @@ struct ath5k_hw; ...@@ -47,6 +47,7 @@ struct ath5k_hw;
struct ath5k_txq; struct ath5k_txq;
struct ieee80211_channel; struct ieee80211_channel;
struct ath_bus_ops; struct ath_bus_ops;
struct ieee80211_tx_control;
enum nl80211_iftype; enum nl80211_iftype;
enum ath5k_srev_type { enum ath5k_srev_type {
...@@ -61,11 +62,12 @@ struct ath5k_srev_name { ...@@ -61,11 +62,12 @@ struct ath5k_srev_name {
}; };
struct ath5k_buf { struct ath5k_buf {
struct list_head list; struct list_head list;
struct ath5k_desc *desc; /* virtual addr of desc */ struct ath5k_desc *desc; /* virtual addr of desc */
dma_addr_t daddr; /* physical addr of desc */ dma_addr_t daddr; /* physical addr of desc */
struct sk_buff *skb; /* skbuff for buf */ struct sk_buff *skb; /* skbuff for buf */
dma_addr_t skbaddr;/* physical addr of skb data */ dma_addr_t skbaddr; /* physical addr of skb data */
struct ieee80211_tx_rate rates[4]; /* number of multi-rate stages */
}; };
struct ath5k_vif { struct ath5k_vif {
...@@ -103,7 +105,7 @@ int ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan); ...@@ -103,7 +105,7 @@ int ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan);
void ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf); void ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
void ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf); void ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ath5k_txq *txq); struct ath5k_txq *txq, struct ieee80211_tx_control *control);
const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val); const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val);
......
...@@ -66,7 +66,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control, ...@@ -66,7 +66,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
return; return;
} }
ath5k_tx_queue(hw, skb, &ah->txqs[qnum]); ath5k_tx_queue(hw, skb, &ah->txqs[qnum], control);
} }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -8,7 +8,7 @@ ath9k-y += beacon.o \ ...@@ -8,7 +8,7 @@ ath9k-y += beacon.o \
antenna.o antenna.o
ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o
ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o ath9k-$(CONFIG_ATH9K_LEGACY_RATE_CONTROL) += rc.o
ath9k-$(CONFIG_ATH9K_PCI) += pci.o ath9k-$(CONFIG_ATH9K_PCI) += pci.o
ath9k-$(CONFIG_ATH9K_AHB) += ahb.o ath9k-$(CONFIG_ATH9K_AHB) += ahb.o
ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
......
This diff is collapsed.
This diff is collapsed.
...@@ -965,7 +965,7 @@ static void ar9003_hw_do_manual_peak_cal(struct ath_hw *ah, ...@@ -965,7 +965,7 @@ static void ar9003_hw_do_manual_peak_cal(struct ath_hw *ah,
{ {
int i; int i;
if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah)) if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah) && !AR_SREV_9485(ah))
return; return;
for (i = 0; i < AR9300_MAX_CHAINS; i++) { for (i = 0; i < AR9300_MAX_CHAINS; i++) {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment