You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
John W. Linville says: ==================== This is a batch of updates intended for 3.12. It is mostly driver stuff, although Johannes Berg and Simon Wunderlich make a good showing with mac80211 bits (particularly some work on 5/10 MHz channel support). The usual suspects are mostly represented. There are lots of updates to iwlwifi, ath9k, ath10k, mwifiex, rt2x00, wil6210, as usual. The bcma bus gets some love this time, as do cw1200, iwl4965, and a few other bits here and there. I don't think there is much unusual here, FWIW. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
+1
-1
@@ -4360,7 +4360,7 @@ F: drivers/net/wireless/iwlegacy/
|
||||
|
||||
INTEL WIRELESS WIFI LINK (iwlwifi)
|
||||
M: Johannes Berg <johannes.berg@intel.com>
|
||||
M: Wey-Yi Guy <wey-yi.w.guy@intel.com>
|
||||
M: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
|
||||
M: Intel Linux Wireless <ilw@linux.intel.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://intellinuxwireless.org
|
||||
|
||||
@@ -35,8 +35,14 @@ config BCMA_DRIVER_PCI_HOSTMODE
|
||||
PCI core hostmode operation (external PCI bus).
|
||||
|
||||
config BCMA_HOST_SOC
|
||||
bool
|
||||
depends on BCMA_DRIVER_MIPS
|
||||
bool "Support for BCMA in a SoC"
|
||||
depends on BCMA
|
||||
help
|
||||
Host interface for a Broadcom AIX bus directly mapped into
|
||||
the memory. This only works with the Broadcom SoCs from the
|
||||
BCM47XX line.
|
||||
|
||||
If unsure, say N
|
||||
|
||||
config BCMA_DRIVER_MIPS
|
||||
bool "BCMA Broadcom MIPS core driver"
|
||||
|
||||
+1
-1
@@ -237,7 +237,7 @@ int bcma_bus_register(struct bcma_bus *bus)
|
||||
err = bcma_bus_scan(bus);
|
||||
if (err) {
|
||||
bcma_err(bus, "Failed to scan: %d\n", err);
|
||||
return -1;
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Early init CC core */
|
||||
|
||||
+20
-8
@@ -32,6 +32,18 @@ static const struct bcma_device_id_name bcma_bcm_device_names[] = {
|
||||
{ BCMA_CORE_4706_CHIPCOMMON, "BCM4706 ChipCommon" },
|
||||
{ BCMA_CORE_4706_SOC_RAM, "BCM4706 SOC RAM" },
|
||||
{ BCMA_CORE_4706_MAC_GBIT, "BCM4706 GBit MAC" },
|
||||
{ BCMA_CORE_PCIEG2, "PCIe Gen 2" },
|
||||
{ BCMA_CORE_DMA, "DMA" },
|
||||
{ BCMA_CORE_SDIO3, "SDIO3" },
|
||||
{ BCMA_CORE_USB20, "USB 2.0" },
|
||||
{ BCMA_CORE_USB30, "USB 3.0" },
|
||||
{ BCMA_CORE_A9JTAG, "ARM Cortex A9 JTAG" },
|
||||
{ BCMA_CORE_DDR23, "Denali DDR2/DDR3 memory controller" },
|
||||
{ BCMA_CORE_ROM, "ROM" },
|
||||
{ BCMA_CORE_NAND, "NAND flash controller" },
|
||||
{ BCMA_CORE_QSPI, "SPI flash controller" },
|
||||
{ BCMA_CORE_CHIPCOMMON_B, "Chipcommon B" },
|
||||
{ BCMA_CORE_ARMCA9, "ARM Cortex A9 core (ihost)" },
|
||||
{ BCMA_CORE_AMEMC, "AMEMC (DDR)" },
|
||||
{ BCMA_CORE_ALTA, "ALTA (I2S)" },
|
||||
{ BCMA_CORE_INVALID, "Invalid" },
|
||||
@@ -201,7 +213,7 @@ static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 __iomem **eromptr)
|
||||
return ent;
|
||||
}
|
||||
|
||||
static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr,
|
||||
static u32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr,
|
||||
u32 type, u8 port)
|
||||
{
|
||||
u32 addrl, addrh, sizel, sizeh = 0;
|
||||
@@ -213,7 +225,7 @@ static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 __iomem **eromptr,
|
||||
((ent & SCAN_ADDR_TYPE) != type) ||
|
||||
(((ent & SCAN_ADDR_PORT) >> SCAN_ADDR_PORT_SHIFT) != port)) {
|
||||
bcma_erom_push_ent(eromptr);
|
||||
return -EINVAL;
|
||||
return (u32)-EINVAL;
|
||||
}
|
||||
|
||||
addrl = ent & SCAN_ADDR_ADDR;
|
||||
@@ -261,7 +273,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
|
||||
struct bcma_device_id *match, int core_num,
|
||||
struct bcma_device *core)
|
||||
{
|
||||
s32 tmp;
|
||||
u32 tmp;
|
||||
u8 i, j;
|
||||
s32 cia, cib;
|
||||
u8 ports[2], wrappers[2];
|
||||
@@ -339,11 +351,11 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
|
||||
* the main register space for the core
|
||||
*/
|
||||
tmp = bcma_erom_get_addr_desc(bus, eromptr, SCAN_ADDR_TYPE_SLAVE, 0);
|
||||
if (tmp <= 0) {
|
||||
if (tmp == 0 || IS_ERR_VALUE(tmp)) {
|
||||
/* Try again to see if it is a bridge */
|
||||
tmp = bcma_erom_get_addr_desc(bus, eromptr,
|
||||
SCAN_ADDR_TYPE_BRIDGE, 0);
|
||||
if (tmp <= 0) {
|
||||
if (tmp == 0 || IS_ERR_VALUE(tmp)) {
|
||||
return -EILSEQ;
|
||||
} else {
|
||||
bcma_info(bus, "Bridge found\n");
|
||||
@@ -357,7 +369,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
|
||||
for (j = 0; ; j++) {
|
||||
tmp = bcma_erom_get_addr_desc(bus, eromptr,
|
||||
SCAN_ADDR_TYPE_SLAVE, i);
|
||||
if (tmp < 0) {
|
||||
if (IS_ERR_VALUE(tmp)) {
|
||||
/* no more entries for port _i_ */
|
||||
/* pr_debug("erom: slave port %d "
|
||||
* "has %d descriptors\n", i, j); */
|
||||
@@ -374,7 +386,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
|
||||
for (j = 0; ; j++) {
|
||||
tmp = bcma_erom_get_addr_desc(bus, eromptr,
|
||||
SCAN_ADDR_TYPE_MWRAP, i);
|
||||
if (tmp < 0) {
|
||||
if (IS_ERR_VALUE(tmp)) {
|
||||
/* no more entries for port _i_ */
|
||||
/* pr_debug("erom: master wrapper %d "
|
||||
* "has %d descriptors\n", i, j); */
|
||||
@@ -392,7 +404,7 @@ static int bcma_get_next_core(struct bcma_bus *bus, u32 __iomem **eromptr,
|
||||
for (j = 0; ; j++) {
|
||||
tmp = bcma_erom_get_addr_desc(bus, eromptr,
|
||||
SCAN_ADDR_TYPE_SWRAP, i + hack);
|
||||
if (tmp < 0) {
|
||||
if (IS_ERR_VALUE(tmp)) {
|
||||
/* no more entries for port _i_ */
|
||||
/* pr_debug("erom: master wrapper %d "
|
||||
* has %d descriptors\n", i, j); */
|
||||
|
||||
@@ -130,7 +130,7 @@ config BNX2X_SRIOV
|
||||
|
||||
config BGMAC
|
||||
tristate "BCMA bus GBit core support"
|
||||
depends on BCMA_HOST_SOC && HAS_DMA
|
||||
depends on BCMA_HOST_SOC && HAS_DMA && BCM47XX
|
||||
select PHYLIB
|
||||
---help---
|
||||
This driver supports GBit MAC and BCM4706 GBit MAC cores on BCMA bus.
|
||||
|
||||
@@ -159,7 +159,7 @@ struct ath_common {
|
||||
|
||||
bool btcoex_enabled;
|
||||
bool disable_ani;
|
||||
bool antenna_diversity;
|
||||
bool bt_ant_diversity;
|
||||
};
|
||||
|
||||
struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
|
||||
|
||||
@@ -20,6 +20,12 @@
|
||||
#include "debug.h"
|
||||
#include "htc.h"
|
||||
|
||||
void ath10k_bmi_start(struct ath10k *ar)
|
||||
{
|
||||
ath10k_dbg(ATH10K_DBG_CORE, "BMI started\n");
|
||||
ar->bmi.done_sent = false;
|
||||
}
|
||||
|
||||
int ath10k_bmi_done(struct ath10k *ar)
|
||||
{
|
||||
struct bmi_cmd cmd;
|
||||
@@ -105,7 +111,8 @@ int ath10k_bmi_read_memory(struct ath10k *ar,
|
||||
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, cmdlen,
|
||||
&resp, &rxlen);
|
||||
if (ret) {
|
||||
ath10k_warn("unable to read from the device\n");
|
||||
ath10k_warn("unable to read from the device (%d)\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -149,7 +156,8 @@ int ath10k_bmi_write_memory(struct ath10k *ar,
|
||||
ret = ath10k_hif_exchange_bmi_msg(ar, &cmd, hdrlen + txlen,
|
||||
NULL, NULL);
|
||||
if (ret) {
|
||||
ath10k_warn("unable to write to the device\n");
|
||||
ath10k_warn("unable to write to the device (%d)\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -184,6 +184,7 @@ struct bmi_target_info {
|
||||
#define BMI_CE_NUM_TO_TARG 0
|
||||
#define BMI_CE_NUM_TO_HOST 1
|
||||
|
||||
void ath10k_bmi_start(struct ath10k *ar);
|
||||
int ath10k_bmi_done(struct ath10k *ar);
|
||||
int ath10k_bmi_get_target_info(struct ath10k *ar,
|
||||
struct bmi_target_info *target_info);
|
||||
|
||||
@@ -79,7 +79,7 @@ static inline void ath10k_ce_src_ring_write_index_set(struct ath10k *ar,
|
||||
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
|
||||
void __iomem *indicator_addr;
|
||||
|
||||
if (!test_bit(ATH10K_PCI_FEATURE_HW_1_0_WARKAROUND, ar_pci->features)) {
|
||||
if (!test_bit(ATH10K_PCI_FEATURE_HW_1_0_WORKAROUND, ar_pci->features)) {
|
||||
ath10k_pci_write32(ar, ce_ctrl_addr + SR_WR_INDEX_ADDRESS, n);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ static int ath10k_init_connect_htc(struct ath10k *ar)
|
||||
goto conn_fail;
|
||||
|
||||
/* Start HTC */
|
||||
status = ath10k_htc_start(ar->htc);
|
||||
status = ath10k_htc_start(&ar->htc);
|
||||
if (status)
|
||||
goto conn_fail;
|
||||
|
||||
@@ -116,7 +116,7 @@ static int ath10k_init_connect_htc(struct ath10k *ar)
|
||||
return 0;
|
||||
|
||||
timeout:
|
||||
ath10k_htc_stop(ar->htc);
|
||||
ath10k_htc_stop(&ar->htc);
|
||||
conn_fail:
|
||||
return status;
|
||||
}
|
||||
@@ -247,19 +247,11 @@ static int ath10k_push_board_ext_data(struct ath10k *ar,
|
||||
|
||||
static int ath10k_download_board_data(struct ath10k *ar)
|
||||
{
|
||||
const struct firmware *fw = ar->board_data;
|
||||
u32 board_data_size = QCA988X_BOARD_DATA_SZ;
|
||||
u32 address;
|
||||
const struct firmware *fw;
|
||||
int ret;
|
||||
|
||||
fw = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir,
|
||||
ar->hw_params.fw.board);
|
||||
if (IS_ERR(fw)) {
|
||||
ath10k_err("could not fetch board data fw file (%ld)\n",
|
||||
PTR_ERR(fw));
|
||||
return PTR_ERR(fw);
|
||||
}
|
||||
|
||||
ret = ath10k_push_board_ext_data(ar, fw);
|
||||
if (ret) {
|
||||
ath10k_err("could not push board ext data (%d)\n", ret);
|
||||
@@ -286,32 +278,20 @@ static int ath10k_download_board_data(struct ath10k *ar)
|
||||
}
|
||||
|
||||
exit:
|
||||
release_firmware(fw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_download_and_run_otp(struct ath10k *ar)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
u32 address;
|
||||
const struct firmware *fw = ar->otp;
|
||||
u32 address = ar->hw_params.patch_load_addr;
|
||||
u32 exec_param;
|
||||
int ret;
|
||||
|
||||
/* OTP is optional */
|
||||
|
||||
if (ar->hw_params.fw.otp == NULL) {
|
||||
ath10k_info("otp file not defined\n");
|
||||
if (!ar->otp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
address = ar->hw_params.patch_load_addr;
|
||||
|
||||
fw = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir,
|
||||
ar->hw_params.fw.otp);
|
||||
if (IS_ERR(fw)) {
|
||||
ath10k_warn("could not fetch otp (%ld)\n", PTR_ERR(fw));
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = ath10k_bmi_fast_download(ar, address, fw->data, fw->size);
|
||||
if (ret) {
|
||||
@@ -327,28 +307,17 @@ static int ath10k_download_and_run_otp(struct ath10k *ar)
|
||||
}
|
||||
|
||||
exit:
|
||||
release_firmware(fw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ath10k_download_fw(struct ath10k *ar)
|
||||
{
|
||||
const struct firmware *fw;
|
||||
const struct firmware *fw = ar->firmware;
|
||||
u32 address;
|
||||
int ret;
|
||||
|
||||
if (ar->hw_params.fw.fw == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
address = ar->hw_params.patch_load_addr;
|
||||
|
||||
fw = ath10k_fetch_fw_file(ar, ar->hw_params.fw.dir,
|
||||
ar->hw_params.fw.fw);
|
||||
if (IS_ERR(fw)) {
|
||||
ath10k_err("could not fetch fw (%ld)\n", PTR_ERR(fw));
|
||||
return PTR_ERR(fw);
|
||||
}
|
||||
|
||||
ret = ath10k_bmi_fast_download(ar, address, fw->data, fw->size);
|
||||
if (ret) {
|
||||
ath10k_err("could not write fw (%d)\n", ret);
|
||||
@@ -356,7 +325,74 @@ static int ath10k_download_fw(struct ath10k *ar)
|
||||
}
|
||||
|
||||
exit:
|
||||
release_firmware(fw);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ath10k_core_free_firmware_files(struct ath10k *ar)
|
||||
{
|
||||
if (ar->board_data && !IS_ERR(ar->board_data))
|
||||
release_firmware(ar->board_data);
|
||||
|
||||
if (ar->otp && !IS_ERR(ar->otp))
|
||||
release_firmware(ar->otp);
|
||||
|
||||
if (ar->firmware && !IS_ERR(ar->firmware))
|
||||
release_firmware(ar->firmware);
|
||||
|
||||
ar->board_data = NULL;
|
||||
ar->otp = NULL;
|
||||
ar->firmware = NULL;
|
||||
}
|
||||
|
||||
static int ath10k_core_fetch_firmware_files(struct ath10k *ar)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (ar->hw_params.fw.fw == NULL) {
|
||||
ath10k_err("firmware file not defined\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (ar->hw_params.fw.board == NULL) {
|
||||
ath10k_err("board data file not defined");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ar->board_data = ath10k_fetch_fw_file(ar,
|
||||
ar->hw_params.fw.dir,
|
||||
ar->hw_params.fw.board);
|
||||
if (IS_ERR(ar->board_data)) {
|
||||
ret = PTR_ERR(ar->board_data);
|
||||
ath10k_err("could not fetch board data (%d)\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ar->firmware = ath10k_fetch_fw_file(ar,
|
||||
ar->hw_params.fw.dir,
|
||||
ar->hw_params.fw.fw);
|
||||
if (IS_ERR(ar->firmware)) {
|
||||
ret = PTR_ERR(ar->firmware);
|
||||
ath10k_err("could not fetch firmware (%d)\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* OTP may be undefined. If so, don't fetch it at all */
|
||||
if (ar->hw_params.fw.otp == NULL)
|
||||
return 0;
|
||||
|
||||
ar->otp = ath10k_fetch_fw_file(ar,
|
||||
ar->hw_params.fw.dir,
|
||||
ar->hw_params.fw.otp);
|
||||
if (IS_ERR(ar->otp)) {
|
||||
ret = PTR_ERR(ar->otp);
|
||||
ath10k_err("could not fetch otp (%d)\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
ath10k_core_free_firmware_files(ar);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -440,8 +476,35 @@ static int ath10k_init_hw_params(struct ath10k *ar)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ath10k_core_restart(struct work_struct *work)
|
||||
{
|
||||
struct ath10k *ar = container_of(work, struct ath10k, restart_work);
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
switch (ar->state) {
|
||||
case ATH10K_STATE_ON:
|
||||
ath10k_halt(ar);
|
||||
ar->state = ATH10K_STATE_RESTARTING;
|
||||
ieee80211_restart_hw(ar->hw);
|
||||
break;
|
||||
case ATH10K_STATE_OFF:
|
||||
/* this can happen if driver is being unloaded */
|
||||
ath10k_warn("cannot restart a device that hasn't been started\n");
|
||||
break;
|
||||
case ATH10K_STATE_RESTARTING:
|
||||
case ATH10K_STATE_RESTARTED:
|
||||
ar->state = ATH10K_STATE_WEDGED;
|
||||
/* fall through */
|
||||
case ATH10K_STATE_WEDGED:
|
||||
ath10k_warn("device is wedged, will not restart\n");
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
|
||||
enum ath10k_bus bus,
|
||||
const struct ath10k_hif_ops *hif_ops)
|
||||
{
|
||||
struct ath10k *ar;
|
||||
@@ -458,9 +521,6 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
|
||||
|
||||
ar->hif.priv = hif_priv;
|
||||
ar->hif.ops = hif_ops;
|
||||
ar->hif.bus = bus;
|
||||
|
||||
ar->free_vdev_map = 0xFF; /* 8 vdevs */
|
||||
|
||||
init_completion(&ar->scan.started);
|
||||
init_completion(&ar->scan.completed);
|
||||
@@ -487,6 +547,8 @@ struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
|
||||
|
||||
init_waitqueue_head(&ar->event_queue);
|
||||
|
||||
INIT_WORK(&ar->restart_work, ath10k_core_restart);
|
||||
|
||||
return ar;
|
||||
|
||||
err_wq:
|
||||
@@ -504,24 +566,11 @@ void ath10k_core_destroy(struct ath10k *ar)
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_core_destroy);
|
||||
|
||||
|
||||
int ath10k_core_register(struct ath10k *ar)
|
||||
int ath10k_core_start(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_htc_ops htc_ops;
|
||||
struct bmi_target_info target_info;
|
||||
int status;
|
||||
|
||||
memset(&target_info, 0, sizeof(target_info));
|
||||
status = ath10k_bmi_get_target_info(ar, &target_info);
|
||||
if (status)
|
||||
goto err;
|
||||
|
||||
ar->target_version = target_info.version;
|
||||
ar->hw->wiphy->hw_version = target_info.version;
|
||||
|
||||
status = ath10k_init_hw_params(ar);
|
||||
if (status)
|
||||
goto err;
|
||||
ath10k_bmi_start(ar);
|
||||
|
||||
if (ath10k_init_configure_target(ar)) {
|
||||
status = -EINVAL;
|
||||
@@ -536,32 +585,32 @@ int ath10k_core_register(struct ath10k *ar)
|
||||
if (status)
|
||||
goto err;
|
||||
|
||||
htc_ops.target_send_suspend_complete = ath10k_send_suspend_complete;
|
||||
ar->htc.htc_ops.target_send_suspend_complete =
|
||||
ath10k_send_suspend_complete;
|
||||
|
||||
ar->htc = ath10k_htc_create(ar, &htc_ops);
|
||||
if (IS_ERR(ar->htc)) {
|
||||
status = PTR_ERR(ar->htc);
|
||||
ath10k_err("could not create HTC (%d)\n", status);
|
||||
status = ath10k_htc_init(ar);
|
||||
if (status) {
|
||||
ath10k_err("could not init HTC (%d)\n", status);
|
||||
goto err;
|
||||
}
|
||||
|
||||
status = ath10k_bmi_done(ar);
|
||||
if (status)
|
||||
goto err_htc_destroy;
|
||||
goto err;
|
||||
|
||||
status = ath10k_wmi_attach(ar);
|
||||
if (status) {
|
||||
ath10k_err("WMI attach failed: %d\n", status);
|
||||
goto err_htc_destroy;
|
||||
goto err;
|
||||
}
|
||||
|
||||
status = ath10k_htc_wait_target(ar->htc);
|
||||
status = ath10k_htc_wait_target(&ar->htc);
|
||||
if (status)
|
||||
goto err_wmi_detach;
|
||||
|
||||
ar->htt = ath10k_htt_attach(ar);
|
||||
if (!ar->htt) {
|
||||
status = -ENOMEM;
|
||||
status = ath10k_htt_attach(ar);
|
||||
if (status) {
|
||||
ath10k_err("could not attach htt (%d)\n", status);
|
||||
goto err_wmi_detach;
|
||||
}
|
||||
|
||||
@@ -588,13 +637,101 @@ int ath10k_core_register(struct ath10k *ar)
|
||||
goto err_disconnect_htc;
|
||||
}
|
||||
|
||||
status = ath10k_htt_attach_target(ar->htt);
|
||||
status = ath10k_htt_attach_target(&ar->htt);
|
||||
if (status)
|
||||
goto err_disconnect_htc;
|
||||
|
||||
ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
|
||||
|
||||
return 0;
|
||||
|
||||
err_disconnect_htc:
|
||||
ath10k_htc_stop(&ar->htc);
|
||||
err_htt_detach:
|
||||
ath10k_htt_detach(&ar->htt);
|
||||
err_wmi_detach:
|
||||
ath10k_wmi_detach(ar);
|
||||
err:
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_core_start);
|
||||
|
||||
void ath10k_core_stop(struct ath10k *ar)
|
||||
{
|
||||
ath10k_htc_stop(&ar->htc);
|
||||
ath10k_htt_detach(&ar->htt);
|
||||
ath10k_wmi_detach(ar);
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_core_stop);
|
||||
|
||||
/* mac80211 manages fw/hw initialization through start/stop hooks. However in
|
||||
* order to know what hw capabilities should be advertised to mac80211 it is
|
||||
* necessary to load the firmware (and tear it down immediately since start
|
||||
* hook will try to init it again) before registering */
|
||||
static int ath10k_core_probe_fw(struct ath10k *ar)
|
||||
{
|
||||
struct bmi_target_info target_info;
|
||||
int ret = 0;
|
||||
|
||||
ret = ath10k_hif_power_up(ar);
|
||||
if (ret) {
|
||||
ath10k_err("could not start pci hif (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
memset(&target_info, 0, sizeof(target_info));
|
||||
ret = ath10k_bmi_get_target_info(ar, &target_info);
|
||||
if (ret) {
|
||||
ath10k_err("could not get target info (%d)\n", ret);
|
||||
ath10k_hif_power_down(ar);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ar->target_version = target_info.version;
|
||||
ar->hw->wiphy->hw_version = target_info.version;
|
||||
|
||||
ret = ath10k_init_hw_params(ar);
|
||||
if (ret) {
|
||||
ath10k_err("could not get hw params (%d)\n", ret);
|
||||
ath10k_hif_power_down(ar);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath10k_core_fetch_firmware_files(ar);
|
||||
if (ret) {
|
||||
ath10k_err("could not fetch firmware files (%d)\n", ret);
|
||||
ath10k_hif_power_down(ar);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ath10k_core_start(ar);
|
||||
if (ret) {
|
||||
ath10k_err("could not init core (%d)\n", ret);
|
||||
ath10k_core_free_firmware_files(ar);
|
||||
ath10k_hif_power_down(ar);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ath10k_core_stop(ar);
|
||||
ath10k_hif_power_down(ar);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ath10k_core_register(struct ath10k *ar)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = ath10k_core_probe_fw(ar);
|
||||
if (status) {
|
||||
ath10k_err("could not probe fw (%d)\n", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = ath10k_mac_register(ar);
|
||||
if (status)
|
||||
goto err_disconnect_htc;
|
||||
if (status) {
|
||||
ath10k_err("could not register to mac80211 (%d)\n", status);
|
||||
goto err_release_fw;
|
||||
}
|
||||
|
||||
status = ath10k_debug_create(ar);
|
||||
if (status) {
|
||||
@@ -606,15 +743,8 @@ int ath10k_core_register(struct ath10k *ar)
|
||||
|
||||
err_unregister_mac:
|
||||
ath10k_mac_unregister(ar);
|
||||
err_disconnect_htc:
|
||||
ath10k_htc_stop(ar->htc);
|
||||
err_htt_detach:
|
||||
ath10k_htt_detach(ar->htt);
|
||||
err_wmi_detach:
|
||||
ath10k_wmi_detach(ar);
|
||||
err_htc_destroy:
|
||||
ath10k_htc_destroy(ar->htc);
|
||||
err:
|
||||
err_release_fw:
|
||||
ath10k_core_free_firmware_files(ar);
|
||||
return status;
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_core_register);
|
||||
@@ -625,41 +755,10 @@ void ath10k_core_unregister(struct ath10k *ar)
|
||||
* Otherwise we will fail to submit commands to FW and mac80211 will be
|
||||
* unhappy about callback failures. */
|
||||
ath10k_mac_unregister(ar);
|
||||
ath10k_htc_stop(ar->htc);
|
||||
ath10k_htt_detach(ar->htt);
|
||||
ath10k_wmi_detach(ar);
|
||||
ath10k_htc_destroy(ar->htc);
|
||||
ath10k_core_free_firmware_files(ar);
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_core_unregister);
|
||||
|
||||
int ath10k_core_target_suspend(struct ath10k *ar)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ATH10K_DBG_CORE, "%s: called", __func__);
|
||||
|
||||
ret = ath10k_wmi_pdev_suspend_target(ar);
|
||||
if (ret)
|
||||
ath10k_warn("could not suspend target (%d)\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_core_target_suspend);
|
||||
|
||||
int ath10k_core_target_resume(struct ath10k *ar)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ath10k_dbg(ATH10K_DBG_CORE, "%s: called", __func__);
|
||||
|
||||
ret = ath10k_wmi_pdev_resume_target(ar);
|
||||
if (ret)
|
||||
ath10k_warn("could not resume target (%d)\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(ath10k_core_target_resume);
|
||||
|
||||
MODULE_AUTHOR("Qualcomm Atheros");
|
||||
MODULE_DESCRIPTION("Core module for QCA988X PCIe devices.");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "htt.h"
|
||||
#include "htc.h"
|
||||
#include "hw.h"
|
||||
#include "targaddrs.h"
|
||||
@@ -43,10 +44,6 @@
|
||||
|
||||
struct ath10k;
|
||||
|
||||
enum ath10k_bus {
|
||||
ATH10K_BUS_PCI,
|
||||
};
|
||||
|
||||
struct ath10k_skb_cb {
|
||||
dma_addr_t paddr;
|
||||
bool is_mapped;
|
||||
@@ -250,6 +247,28 @@ struct ath10k_debug {
|
||||
struct completion event_stats_compl;
|
||||
};
|
||||
|
||||
enum ath10k_state {
|
||||
ATH10K_STATE_OFF = 0,
|
||||
ATH10K_STATE_ON,
|
||||
|
||||
/* When doing firmware recovery the device is first powered down.
|
||||
* mac80211 is supposed to call in to start() hook later on. It is
|
||||
* however possible that driver unloading and firmware crash overlap.
|
||||
* mac80211 can wait on conf_mutex in stop() while the device is
|
||||
* stopped in ath10k_core_restart() work holding conf_mutex. The state
|
||||
* RESTARTED means that the device is up and mac80211 has started hw
|
||||
* reconfiguration. Once mac80211 is done with the reconfiguration we
|
||||
* set the state to STATE_ON in restart_complete(). */
|
||||
ATH10K_STATE_RESTARTING,
|
||||
ATH10K_STATE_RESTARTED,
|
||||
|
||||
/* The device has crashed while restarting hw. This state is like ON
|
||||
* but commands are blocked in HTC and -ECOMM response is given. This
|
||||
* prevents completion timeouts and makes the driver more responsive to
|
||||
* userspace commands. This is also prevents recursive recovery. */
|
||||
ATH10K_STATE_WEDGED,
|
||||
};
|
||||
|
||||
struct ath10k {
|
||||
struct ath_common ath_common;
|
||||
struct ieee80211_hw *hw;
|
||||
@@ -274,19 +293,16 @@ struct ath10k {
|
||||
|
||||
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_wmi wmi;
|
||||
struct ath10k_htc htc;
|
||||
struct ath10k_htt htt;
|
||||
|
||||
struct ath10k_hw_params {
|
||||
u32 id;
|
||||
@@ -301,6 +317,10 @@ struct ath10k {
|
||||
} fw;
|
||||
} hw_params;
|
||||
|
||||
const struct firmware *board_data;
|
||||
const struct firmware *otp;
|
||||
const struct firmware *firmware;
|
||||
|
||||
struct {
|
||||
struct completion started;
|
||||
struct completion completed;
|
||||
@@ -350,20 +370,22 @@ struct ath10k {
|
||||
struct completion offchan_tx_completed;
|
||||
struct sk_buff *offchan_tx_skb;
|
||||
|
||||
enum ath10k_state state;
|
||||
|
||||
struct work_struct restart_work;
|
||||
|
||||
#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_start(struct ath10k *ar);
|
||||
void ath10k_core_stop(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_ */
|
||||
|
||||
@@ -161,7 +161,7 @@ void ath10k_debug_read_target_stats(struct ath10k *ar,
|
||||
struct wmi_pdev_stats *ps;
|
||||
int i;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
|
||||
stats = &ar->debug.target_stats;
|
||||
|
||||
@@ -259,6 +259,7 @@ void ath10k_debug_read_target_stats(struct ath10k *ar,
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
complete(&ar->debug.event_stats_compl);
|
||||
}
|
||||
@@ -268,35 +269,35 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
struct ath10k_target_stats *fw_stats;
|
||||
char *buf;
|
||||
char *buf = NULL;
|
||||
unsigned int len = 0, buf_len = 2500;
|
||||
ssize_t ret_cnt;
|
||||
ssize_t ret_cnt = 0;
|
||||
long left;
|
||||
int i;
|
||||
int ret;
|
||||
|
||||
fw_stats = &ar->debug.target_stats;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH10K_STATE_ON)
|
||||
goto exit;
|
||||
|
||||
buf = kzalloc(buf_len, GFP_KERNEL);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
goto exit;
|
||||
|
||||
ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
|
||||
if (ret) {
|
||||
ath10k_warn("could not request stats (%d)\n", ret);
|
||||
kfree(buf);
|
||||
return -EIO;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
left = wait_for_completion_timeout(&ar->debug.event_stats_compl, 1*HZ);
|
||||
if (left <= 0)
|
||||
goto exit;
|
||||
|
||||
if (left <= 0) {
|
||||
kfree(buf);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
len += scnprintf(buf + len, buf_len - len, "\n");
|
||||
len += scnprintf(buf + len, buf_len - len, "%30s\n",
|
||||
"ath10k PDEV stats");
|
||||
@@ -424,14 +425,15 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
|
||||
fw_stats->peer_stat[i].peer_tx_rate);
|
||||
len += scnprintf(buf + len, buf_len - len, "\n");
|
||||
}
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
if (len > buf_len)
|
||||
len = buf_len;
|
||||
|
||||
ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
kfree(buf);
|
||||
return ret_cnt;
|
||||
}
|
||||
@@ -443,6 +445,60 @@ static const struct file_operations fops_fw_stats = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t ath10k_read_simulate_fw_crash(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
const char buf[] = "To simulate firmware crash write the keyword"
|
||||
" `crash` to this file.\nThis will force firmware"
|
||||
" to report a crash to the host system.\n";
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
|
||||
}
|
||||
|
||||
static ssize_t ath10k_write_simulate_fw_crash(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
char buf[32] = {};
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
|
||||
if (strcmp(buf, "crash") && strcmp(buf, "crash\n")) {
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (ar->state != ATH10K_STATE_ON &&
|
||||
ar->state != ATH10K_STATE_RESTARTED) {
|
||||
ret = -ENETDOWN;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ath10k_info("simulating firmware crash\n");
|
||||
|
||||
ret = ath10k_wmi_force_fw_hang(ar, WMI_FORCE_FW_HANG_ASSERT, 0);
|
||||
if (ret)
|
||||
ath10k_warn("failed to force fw hang (%d)\n", ret);
|
||||
|
||||
if (ret == 0)
|
||||
ret = count;
|
||||
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_simulate_fw_crash = {
|
||||
.read = ath10k_read_simulate_fw_crash,
|
||||
.write = ath10k_write_simulate_fw_crash,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
int ath10k_debug_create(struct ath10k *ar)
|
||||
{
|
||||
ar->debug.debugfs_phy = debugfs_create_dir("ath10k",
|
||||
@@ -459,6 +515,9 @@ int ath10k_debug_create(struct ath10k *ar)
|
||||
debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
|
||||
&fops_wmi_services);
|
||||
|
||||
debugfs_create_file("simulate_fw_crash", S_IRUSR, ar->debug.debugfs_phy,
|
||||
ar, &fops_simulate_fw_crash);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_ATH10K_DEBUGFS */
|
||||
|
||||
@@ -46,8 +46,11 @@ struct ath10k_hif_ops {
|
||||
void *request, u32 request_len,
|
||||
void *response, u32 *response_len);
|
||||
|
||||
/* Post BMI phase, after FW is loaded. Starts regular operation */
|
||||
int (*start)(struct ath10k *ar);
|
||||
|
||||
/* Clean up what start() did. This does not revert to BMI phase. If
|
||||
* desired so, call power_down() and power_up() */
|
||||
void (*stop)(struct ath10k *ar);
|
||||
|
||||
int (*map_service_to_pipe)(struct ath10k *ar, u16 service_id,
|
||||
@@ -66,10 +69,20 @@ struct ath10k_hif_ops {
|
||||
*/
|
||||
void (*send_complete_check)(struct ath10k *ar, u8 pipe_id, int force);
|
||||
|
||||
void (*init)(struct ath10k *ar,
|
||||
struct ath10k_hif_cb *callbacks);
|
||||
void (*set_callbacks)(struct ath10k *ar,
|
||||
struct ath10k_hif_cb *callbacks);
|
||||
|
||||
u16 (*get_free_queue_number)(struct ath10k *ar, u8 pipe_id);
|
||||
|
||||
/* Power up the device and enter BMI transfer mode for FW download */
|
||||
int (*power_up)(struct ath10k *ar);
|
||||
|
||||
/* Power down the device and free up resources. stop() must be called
|
||||
* before this if start() was called earlier */
|
||||
void (*power_down)(struct ath10k *ar);
|
||||
|
||||
int (*suspend)(struct ath10k *ar);
|
||||
int (*resume)(struct ath10k *ar);
|
||||
};
|
||||
|
||||
|
||||
@@ -122,10 +135,10 @@ static inline void ath10k_hif_send_complete_check(struct ath10k *ar,
|
||||
ar->hif.ops->send_complete_check(ar, pipe_id, force);
|
||||
}
|
||||
|
||||
static inline void ath10k_hif_init(struct ath10k *ar,
|
||||
struct ath10k_hif_cb *callbacks)
|
||||
static inline void ath10k_hif_set_callbacks(struct ath10k *ar,
|
||||
struct ath10k_hif_cb *callbacks)
|
||||
{
|
||||
ar->hif.ops->init(ar, callbacks);
|
||||
ar->hif.ops->set_callbacks(ar, callbacks);
|
||||
}
|
||||
|
||||
static inline u16 ath10k_hif_get_free_queue_number(struct ath10k *ar,
|
||||
@@ -134,4 +147,30 @@ static inline u16 ath10k_hif_get_free_queue_number(struct ath10k *ar,
|
||||
return ar->hif.ops->get_free_queue_number(ar, pipe_id);
|
||||
}
|
||||
|
||||
static inline int ath10k_hif_power_up(struct ath10k *ar)
|
||||
{
|
||||
return ar->hif.ops->power_up(ar);
|
||||
}
|
||||
|
||||
static inline void ath10k_hif_power_down(struct ath10k *ar)
|
||||
{
|
||||
ar->hif.ops->power_down(ar);
|
||||
}
|
||||
|
||||
static inline int ath10k_hif_suspend(struct ath10k *ar)
|
||||
{
|
||||
if (!ar->hif.ops->suspend)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ar->hif.ops->suspend(ar);
|
||||
}
|
||||
|
||||
static inline int ath10k_hif_resume(struct ath10k *ar)
|
||||
{
|
||||
if (!ar->hif.ops->resume)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ar->hif.ops->resume(ar);
|
||||
}
|
||||
|
||||
#endif /* _HIF_H_ */
|
||||
|
||||
@@ -246,15 +246,22 @@ int ath10k_htc_send(struct ath10k_htc *htc,
|
||||
{
|
||||
struct ath10k_htc_ep *ep = &htc->endpoint[eid];
|
||||
|
||||
if (htc->ar->state == ATH10K_STATE_WEDGED)
|
||||
return -ECOMM;
|
||||
|
||||
if (eid >= ATH10K_HTC_EP_COUNT) {
|
||||
ath10k_warn("Invalid endpoint id: %d\n", eid);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
skb_push(skb, sizeof(struct ath10k_htc_hdr));
|
||||
|
||||
spin_lock_bh(&htc->tx_lock);
|
||||
if (htc->stopped) {
|
||||
spin_unlock_bh(&htc->tx_lock);
|
||||
return -ESHUTDOWN;
|
||||
}
|
||||
|
||||
__skb_queue_tail(&ep->tx_queue, skb);
|
||||
skb_push(skb, sizeof(struct ath10k_htc_hdr));
|
||||
spin_unlock_bh(&htc->tx_lock);
|
||||
|
||||
queue_work(htc->ar->workqueue, &ep->send_work);
|
||||
@@ -265,25 +272,19 @@ static int ath10k_htc_tx_completion_handler(struct ath10k *ar,
|
||||
struct sk_buff *skb,
|
||||
unsigned int eid)
|
||||
{
|
||||
struct ath10k_htc *htc = ar->htc;
|
||||
struct ath10k_htc *htc = &ar->htc;
|
||||
struct ath10k_htc_ep *ep = &htc->endpoint[eid];
|
||||
bool stopping;
|
||||
|
||||
ath10k_htc_notify_tx_completion(ep, skb);
|
||||
/* the skb now belongs to the completion handler */
|
||||
|
||||
/* note: when using TX credit flow, the re-checking of queues happens
|
||||
* when credits flow back from the target. in the non-TX credit case,
|
||||
* we recheck after the packet completes */
|
||||
spin_lock_bh(&htc->tx_lock);
|
||||
stopping = htc->stopping;
|
||||
spin_unlock_bh(&htc->tx_lock);
|
||||
|
||||
if (!ep->tx_credit_flow_enabled && !stopping)
|
||||
/*
|
||||
* note: when using TX credit flow, the re-checking of
|
||||
* queues happens when credits flow back from the target.
|
||||
* in the non-TX credit case, we recheck after the packet
|
||||
* completes
|
||||
*/
|
||||
if (!ep->tx_credit_flow_enabled && !htc->stopped)
|
||||
queue_work(ar->workqueue, &ep->send_work);
|
||||
spin_unlock_bh(&htc->tx_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -414,7 +415,7 @@ static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
|
||||
u8 pipe_id)
|
||||
{
|
||||
int status = 0;
|
||||
struct ath10k_htc *htc = ar->htc;
|
||||
struct ath10k_htc *htc = &ar->htc;
|
||||
struct ath10k_htc_hdr *hdr;
|
||||
struct ath10k_htc_ep *ep;
|
||||
u16 payload_len;
|
||||
@@ -751,8 +752,9 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
|
||||
tx_alloc = ath10k_htc_get_credit_allocation(htc,
|
||||
conn_req->service_id);
|
||||
if (!tx_alloc)
|
||||
ath10k_warn("HTC Service %s does not allocate target credits\n",
|
||||
htc_service_name(conn_req->service_id));
|
||||
ath10k_dbg(ATH10K_DBG_HTC,
|
||||
"HTC Service %s does not allocate target credits\n",
|
||||
htc_service_name(conn_req->service_id));
|
||||
|
||||
skb = ath10k_htc_build_tx_ctrl_skb(htc->ar);
|
||||
if (!skb) {
|
||||
@@ -947,7 +949,7 @@ void ath10k_htc_stop(struct ath10k_htc *htc)
|
||||
struct ath10k_htc_ep *ep;
|
||||
|
||||
spin_lock_bh(&htc->tx_lock);
|
||||
htc->stopping = true;
|
||||
htc->stopped = true;
|
||||
spin_unlock_bh(&htc->tx_lock);
|
||||
|
||||
for (i = ATH10K_HTC_EP_0; i < ATH10K_HTC_EP_COUNT; i++) {
|
||||
@@ -956,26 +958,18 @@ void ath10k_htc_stop(struct ath10k_htc *htc)
|
||||
}
|
||||
|
||||
ath10k_hif_stop(htc->ar);
|
||||
ath10k_htc_reset_endpoint_states(htc);
|
||||
}
|
||||
|
||||
/* registered target arrival callback from the HIF layer */
|
||||
struct ath10k_htc *ath10k_htc_create(struct ath10k *ar,
|
||||
struct ath10k_htc_ops *htc_ops)
|
||||
int ath10k_htc_init(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_hif_cb htc_callbacks;
|
||||
struct ath10k_htc_ep *ep = NULL;
|
||||
struct ath10k_htc *htc = NULL;
|
||||
|
||||
/* FIXME: use struct ath10k instead */
|
||||
htc = kzalloc(sizeof(struct ath10k_htc), GFP_KERNEL);
|
||||
if (!htc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
struct ath10k_htc *htc = &ar->htc;
|
||||
|
||||
spin_lock_init(&htc->tx_lock);
|
||||
|
||||
memcpy(&htc->htc_ops, htc_ops, sizeof(struct ath10k_htc_ops));
|
||||
|
||||
htc->stopped = false;
|
||||
ath10k_htc_reset_endpoint_states(htc);
|
||||
|
||||
/* setup HIF layer callbacks */
|
||||
@@ -986,15 +980,10 @@ struct ath10k_htc *ath10k_htc_create(struct ath10k *ar,
|
||||
/* Get HIF default pipe for HTC message exchange */
|
||||
ep = &htc->endpoint[ATH10K_HTC_EP_0];
|
||||
|
||||
ath10k_hif_init(ar, &htc_callbacks);
|
||||
ath10k_hif_set_callbacks(ar, &htc_callbacks);
|
||||
ath10k_hif_get_default_pipe(ar, &ep->ul_pipe_id, &ep->dl_pipe_id);
|
||||
|
||||
init_completion(&htc->ctl_resp);
|
||||
|
||||
return htc;
|
||||
}
|
||||
|
||||
void ath10k_htc_destroy(struct ath10k_htc *htc)
|
||||
{
|
||||
kfree(htc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -335,7 +335,7 @@ struct ath10k_htc {
|
||||
struct ath10k *ar;
|
||||
struct ath10k_htc_ep endpoint[ATH10K_HTC_EP_COUNT];
|
||||
|
||||
/* protects endpoint and stopping fields */
|
||||
/* protects endpoint and stopped fields */
|
||||
spinlock_t tx_lock;
|
||||
|
||||
struct ath10k_htc_ops htc_ops;
|
||||
@@ -349,11 +349,10 @@ struct ath10k_htc {
|
||||
struct ath10k_htc_svc_tx_credits service_tx_alloc[ATH10K_HTC_EP_COUNT];
|
||||
int target_credit_size;
|
||||
|
||||
bool stopping;
|
||||
bool stopped;
|
||||
};
|
||||
|
||||
struct ath10k_htc *ath10k_htc_create(struct ath10k *ar,
|
||||
struct ath10k_htc_ops *htc_ops);
|
||||
int ath10k_htc_init(struct ath10k *ar);
|
||||
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,
|
||||
@@ -362,7 +361,6 @@ int ath10k_htc_connect_service(struct ath10k_htc *htc,
|
||||
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
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include <linux/if_ether.h>
|
||||
|
||||
#include "htt.h"
|
||||
#include "core.h"
|
||||
@@ -36,7 +37,7 @@ static int ath10k_htt_htc_attach(struct ath10k_htt *htt)
|
||||
/* 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,
|
||||
status = ath10k_htc_connect_service(&htt->ar->htc, &conn_req,
|
||||
&conn_resp);
|
||||
|
||||
if (status)
|
||||
@@ -47,15 +48,11 @@ static int ath10k_htt_htc_attach(struct ath10k_htt *htt)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ath10k_htt *ath10k_htt_attach(struct ath10k *ar)
|
||||
int ath10k_htt_attach(struct ath10k *ar)
|
||||
{
|
||||
struct ath10k_htt *htt;
|
||||
struct ath10k_htt *htt = &ar->htt;
|
||||
int ret;
|
||||
|
||||
htt = kzalloc(sizeof(*htt), GFP_KERNEL);
|
||||
if (!htt)
|
||||
return NULL;
|
||||
|
||||
htt->ar = ar;
|
||||
htt->max_throughput_mbps = 800;
|
||||
|
||||
@@ -65,8 +62,11 @@ struct ath10k_htt *ath10k_htt_attach(struct ath10k *ar)
|
||||
* since ath10k_htt_rx_attach involves sending a rx ring configure
|
||||
* message to the target.
|
||||
*/
|
||||
if (ath10k_htt_htc_attach(htt))
|
||||
ret = ath10k_htt_htc_attach(htt);
|
||||
if (ret) {
|
||||
ath10k_err("could not attach htt htc (%d)\n", ret);
|
||||
goto err_htc_attach;
|
||||
}
|
||||
|
||||
ret = ath10k_htt_tx_attach(htt);
|
||||
if (ret) {
|
||||
@@ -74,8 +74,11 @@ struct ath10k_htt *ath10k_htt_attach(struct ath10k *ar)
|
||||
goto err_htc_attach;
|
||||
}
|
||||
|
||||
if (ath10k_htt_rx_attach(htt))
|
||||
ret = ath10k_htt_rx_attach(htt);
|
||||
if (ret) {
|
||||
ath10k_err("could not attach htt rx (%d)\n", ret);
|
||||
goto err_rx_attach;
|
||||
}
|
||||
|
||||
/*
|
||||
* Prefetch enough data to satisfy target
|
||||
@@ -89,13 +92,12 @@ struct ath10k_htt *ath10k_htt_attach(struct ath10k *ar)
|
||||
8 + /* llc snap */
|
||||
2; /* ip4 dscp or ip6 priority */
|
||||
|
||||
return htt;
|
||||
return 0;
|
||||
|
||||
err_rx_attach:
|
||||
ath10k_htt_tx_detach(htt);
|
||||
err_htc_attach:
|
||||
kfree(htt);
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define HTT_TARGET_VERSION_TIMEOUT_HZ (3*HZ)
|
||||
@@ -148,5 +150,4 @@ void ath10k_htt_detach(struct ath10k_htt *htt)
|
||||
{
|
||||
ath10k_htt_rx_detach(htt);
|
||||
ath10k_htt_tx_detach(htt);
|
||||
kfree(htt);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
#include <linux/bug.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "htc.h"
|
||||
#include "rx_desc.h"
|
||||
|
||||
@@ -1317,7 +1316,7 @@ struct htt_rx_desc {
|
||||
#define HTT_LOG2_MAX_CACHE_LINE_SIZE 7 /* 2^7 = 128 */
|
||||
#define HTT_MAX_CACHE_LINE_SIZE_MASK ((1 << HTT_LOG2_MAX_CACHE_LINE_SIZE) - 1)
|
||||
|
||||
struct ath10k_htt *ath10k_htt_attach(struct ath10k *ar);
|
||||
int ath10k_htt_attach(struct ath10k *ar);
|
||||
int ath10k_htt_attach_target(struct ath10k_htt *htt);
|
||||
void ath10k_htt_detach(struct ath10k_htt *htt);
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "core.h"
|
||||
#include "htc.h"
|
||||
#include "htt.h"
|
||||
#include "txrx.h"
|
||||
@@ -1036,7 +1037,7 @@ end:
|
||||
|
||||
void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct ath10k_htt *htt = ar->htt;
|
||||
struct ath10k_htt *htt = &ar->htt;
|
||||
struct htt_resp *resp = (struct htt_resp *)skb->data;
|
||||
|
||||
/* confirm alignment */
|
||||
|
||||
@@ -92,7 +92,7 @@ int ath10k_htt_tx_attach(struct ath10k_htt *htt)
|
||||
|
||||
/* At the beginning free queue number should hint us the maximum
|
||||
* queue length */
|
||||
pipe = htt->ar->htc->endpoint[htt->eid].ul_pipe_id;
|
||||
pipe = htt->ar->htc.endpoint[htt->eid].ul_pipe_id;
|
||||
htt->max_num_pending_tx = ath10k_hif_get_free_queue_number(htt->ar,
|
||||
pipe);
|
||||
|
||||
@@ -153,7 +153,7 @@ void ath10k_htt_tx_detach(struct ath10k_htt *htt)
|
||||
void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb)
|
||||
{
|
||||
struct ath10k_skb_cb *skb_cb = ATH10K_SKB_CB(skb);
|
||||
struct ath10k_htt *htt = ar->htt;
|
||||
struct ath10k_htt *htt = &ar->htt;
|
||||
|
||||
if (skb_cb->htt.is_conf) {
|
||||
dev_kfree_skb_any(skb);
|
||||
@@ -194,7 +194,7 @@ int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt)
|
||||
|
||||
ATH10K_SKB_CB(skb)->htt.is_conf = true;
|
||||
|
||||
ret = ath10k_htc_send(htt->ar->htc, htt->eid, skb);
|
||||
ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
|
||||
if (ret) {
|
||||
dev_kfree_skb_any(skb);
|
||||
return ret;
|
||||
@@ -281,7 +281,7 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt)
|
||||
|
||||
ATH10K_SKB_CB(skb)->htt.is_conf = true;
|
||||
|
||||
ret = ath10k_htc_send(htt->ar->htc, htt->eid, skb);
|
||||
ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
|
||||
if (ret) {
|
||||
dev_kfree_skb_any(skb);
|
||||
return ret;
|
||||
@@ -346,7 +346,7 @@ int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
||||
skb_cb->htt.refcount = 2;
|
||||
skb_cb->htt.msdu = msdu;
|
||||
|
||||
res = ath10k_htc_send(htt->ar->htc, htt->eid, txdesc);
|
||||
res = ath10k_htc_send(&htt->ar->htc, htt->eid, txdesc);
|
||||
if (res)
|
||||
goto err;
|
||||
|
||||
@@ -486,7 +486,7 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
|
||||
skb_cb->htt.txfrag = txfrag;
|
||||
skb_cb->htt.msdu = msdu;
|
||||
|
||||
res = ath10k_htc_send(htt->ar->htc, htt->eid, txdesc);
|
||||
res = ath10k_htc_send(&htt->ar->htc, htt->eid, txdesc);
|
||||
if (res)
|
||||
goto err;
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user