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 tag 'master-2014-12-08' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
John W. Linville says: ==================== pull request: wireless-next 2014-12-08 Please pull this last batch of pending wireless updates for the 3.19 tree... For the wireless bits, Johannes says: "This time I have Felix's no-status rate control work, which will allow drivers to work better with rate control even if they don't have perfect status reporting. In addition to this, a small hwsim fix from Patrik, one of the regulatory patches from Arik, and a number of cleanups and fixes I did myself. Of note is a patch where I disable CFG80211_WEXT so that compatibility is no longer selectable - this is intended as a wake-up call for anyone who's still using it, and is still easily worked around (it's a one-line patch) before we fully remove the code as well in the future." For the Bluetooth bits, Johan says: "Here's one more bluetooth-next pull request for 3.19: - Minor cleanups for ieee802154 & mac802154 - Fix for the kernel warning with !TASK_RUNNING reported by Kirill A. Shutemov - Support for another ath3k device - Fix for tracking link key based security level - Device tree bindings for btmrvl + a state update fix - Fix for wrong ACL flags on LE links" And... "In addition to the previous one this contains two more cleanups to mac802154 as well as support for some new HCI features from the Bluetooth 4.2 specification. From the original request: 'Here's what should be the last bluetooth-next pull request for 3.19. It's rather large but the majority of it is the Low Energy Secure Connections feature that's part of the Bluetooth 4.2 specification. The specification went public only this week so we couldn't publish the corresponding code before that. The code itself can nevertheless be considered fairly mature as it's been in development for over 6 months and gone through several interoperability test events. Besides LE SC the pull request contains an important fix for command complete events for mgmt sockets which also fixes some leaks of hci_conn objects when powering off or unplugging Bluetooth adapters. A smaller feature that's part of the pull request is service discovery support. This is like normal device discovery except that devices not matching specific UUIDs or strong enough RSSI are filtered out. Other changes that the pull request contains are firmware dump support to the btmrvl driver, firmware download support for Broadcom BCM20702A0 variants, as well as some coding style cleanups in 6lowpan & ieee802154/mac802154 code.'" For the NFC bits, Samuel says: "With this one we get: - NFC digital improvements for DEP support: Chaining, NACK and ATN support added. - NCI improvements: Support for p2p target, SE IO operand addition, SE operands extensions to support proprietary implementations, and a few fixes. - NFC HCI improvements: OPEN_PIPE and NOTIFY_ALL_CLEARED support, and SE IO operand addition. - A bunch of minor improvements and fixes for STMicro st21nfcb and st21nfca" For the iwlwifi bits, Emmanuel says: "Major works are CSA and TDLS. On top of that I have a new firmware API for scan and a few rate control improvements. Johannes find a few tricks to improve our CPU utilization and adds support for a new spin of 7265 called 7265D. Along with this a few random things that don't stand out." And... "I deprecate here -8.ucode since -9 has been published long ago. Along with that I have a new activity, we have now better a infrastructure for firmware debugging. This will allow to have configurable probes insides the firmware. Luca continues his work on NetDetect, this feature is now complete. All the rest is minor fixes here and there." For the Atheros bits, Kalle says: "Only ath10k changes this time and no major changes. Most visible are: o new debugfs interface for runtime firmware debugging (Yanbo) o fix shared WEP (Sujith) o don't rebuild whenever kernel version changes (Johannes) o lots of refactoring to make it easier to add new hw support (Michal) There's also smaller fixes and improvements with no point of listing here." In addition, there are a few last minute updates to ath5k, ath9k, brcmfmac, brcmsmac, mwifiex, rt2x00, rtlwifi, and wil6210. Also included is a pull of the wireless tree to pick-up the fixes originally included in "pull request: wireless 2014-12-03"... Please let me know if there are problems! ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
btmrvl
|
||||
------
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible : must be "btmrvl,cfgdata"
|
||||
|
||||
Optional properties:
|
||||
|
||||
- btmrvl,cal-data : Calibration data downloaded to the device during
|
||||
initialization. This is an array of 28 values(u8).
|
||||
|
||||
- btmrvl,gpio-gap : gpio and gap (in msecs) combination to be
|
||||
configured.
|
||||
|
||||
Example:
|
||||
|
||||
GPIO pin 13 is configured as a wakeup source and GAP is set to 100 msecs
|
||||
in below example.
|
||||
|
||||
btmrvl {
|
||||
compatible = "btmrvl,cfgdata";
|
||||
|
||||
btmrvl,cal-data = /bits/ 8 <
|
||||
0x37 0x01 0x1c 0x00 0xff 0xff 0xff 0xff 0x01 0x7f 0x04 0x02
|
||||
0x00 0x00 0xba 0xce 0xc0 0xc6 0x2d 0x00 0x00 0x00 0x00 0x00
|
||||
0x00 0x00 0xf0 0x00>;
|
||||
btmrvl,gpio-gap = <0x0d64>;
|
||||
};
|
||||
+1
-2
@@ -7919,11 +7919,10 @@ S: Maintained
|
||||
F: drivers/media/dvb-frontends/rtl2832_sdr*
|
||||
|
||||
RTL8180 WIRELESS DRIVER
|
||||
M: "John W. Linville" <linville@tuxdriver.com>
|
||||
L: linux-wireless@vger.kernel.org
|
||||
W: http://wireless.kernel.org/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
|
||||
S: Maintained
|
||||
S: Orphan
|
||||
F: drivers/net/wireless/rtl818x/rtl8180/
|
||||
|
||||
RTL8187 WIRELESS DRIVER
|
||||
|
||||
@@ -210,6 +210,7 @@ config BT_MRVL_SDIO
|
||||
tristate "Marvell BT-over-SDIO driver"
|
||||
depends on BT_MRVL && MMC
|
||||
select FW_LOADER
|
||||
select WANT_DEV_COREDUMP
|
||||
help
|
||||
The driver for Marvell Bluetooth chipsets with SDIO interface.
|
||||
|
||||
|
||||
@@ -106,6 +106,7 @@ static const struct usb_device_id ath3k_table[] = {
|
||||
{ USB_DEVICE(0x13d3, 0x3375) },
|
||||
{ USB_DEVICE(0x13d3, 0x3393) },
|
||||
{ USB_DEVICE(0x13d3, 0x3402) },
|
||||
{ USB_DEVICE(0x13d3, 0x3408) },
|
||||
{ USB_DEVICE(0x13d3, 0x3432) },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
@@ -158,6 +159,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
|
||||
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Atheros AR5BBU22 with sflash firmware */
|
||||
|
||||
@@ -167,6 +167,35 @@ static const struct file_operations btmrvl_hscmd_fops = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t btmrvl_fwdump_write(struct file *file, const char __user *ubuf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct btmrvl_private *priv = file->private_data;
|
||||
char buf[16];
|
||||
bool result;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
|
||||
return -EFAULT;
|
||||
|
||||
if (strtobool(buf, &result))
|
||||
return -EINVAL;
|
||||
|
||||
if (!result)
|
||||
return -EINVAL;
|
||||
|
||||
btmrvl_firmware_dump(priv);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations btmrvl_fwdump_fops = {
|
||||
.write = btmrvl_fwdump_write,
|
||||
.open = simple_open,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
void btmrvl_debugfs_init(struct hci_dev *hdev)
|
||||
{
|
||||
struct btmrvl_private *priv = hci_get_drvdata(hdev);
|
||||
@@ -197,6 +226,8 @@ void btmrvl_debugfs_init(struct hci_dev *hdev)
|
||||
priv, &btmrvl_hscmd_fops);
|
||||
debugfs_create_file("hscfgcmd", 0644, dbg->config_dir,
|
||||
priv, &btmrvl_hscfgcmd_fops);
|
||||
debugfs_create_file("fw_dump", 0200, dbg->config_dir,
|
||||
priv, &btmrvl_fwdump_fops);
|
||||
|
||||
dbg->status_dir = debugfs_create_dir("status", hdev->debugfs);
|
||||
debugfs_create_u8("curpsmode", 0444, dbg->status_dir,
|
||||
|
||||
@@ -32,6 +32,24 @@
|
||||
/* Time to wait for command response in millisecond */
|
||||
#define WAIT_UNTIL_CMD_RESP 5000
|
||||
|
||||
enum rdwr_status {
|
||||
RDWR_STATUS_SUCCESS = 0,
|
||||
RDWR_STATUS_FAILURE = 1,
|
||||
RDWR_STATUS_DONE = 2
|
||||
};
|
||||
|
||||
#define FW_DUMP_MAX_NAME_LEN 8
|
||||
#define FW_DUMP_HOST_READY 0xEE
|
||||
#define FW_DUMP_DONE 0xFF
|
||||
#define FW_DUMP_READ_DONE 0xFE
|
||||
|
||||
struct memory_type_mapping {
|
||||
u8 mem_name[FW_DUMP_MAX_NAME_LEN];
|
||||
u8 *mem_ptr;
|
||||
u32 mem_size;
|
||||
u8 done_flag;
|
||||
};
|
||||
|
||||
struct btmrvl_thread {
|
||||
struct task_struct *task;
|
||||
wait_queue_head_t wait_q;
|
||||
@@ -81,6 +99,7 @@ struct btmrvl_private {
|
||||
u8 *payload, u16 nb);
|
||||
int (*hw_wakeup_firmware) (struct btmrvl_private *priv);
|
||||
int (*hw_process_int_status) (struct btmrvl_private *priv);
|
||||
void (*firmware_dump)(struct btmrvl_private *priv);
|
||||
spinlock_t driver_lock; /* spinlock used by driver */
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void *debugfs_data;
|
||||
@@ -151,6 +170,7 @@ int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv);
|
||||
int btmrvl_enable_ps(struct btmrvl_private *priv);
|
||||
int btmrvl_prepare_command(struct btmrvl_private *priv);
|
||||
int btmrvl_enable_hs(struct btmrvl_private *priv);
|
||||
void btmrvl_firmware_dump(struct btmrvl_private *priv);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void btmrvl_debugfs_init(struct hci_dev *hdev);
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <linux/of.h>
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
|
||||
#include "btmrvl_drv.h"
|
||||
#include "btmrvl_sdio.h"
|
||||
@@ -41,6 +42,11 @@ void btmrvl_interrupt(struct btmrvl_private *priv)
|
||||
|
||||
priv->adapter->int_count++;
|
||||
|
||||
if (priv->adapter->hs_state == HS_ACTIVATED) {
|
||||
BT_DBG("BT: HS DEACTIVATED in ISR!");
|
||||
priv->adapter->hs_state = HS_DEACTIVATED;
|
||||
}
|
||||
|
||||
wake_up_interruptible(&priv->main_thread.wait_q);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(btmrvl_interrupt);
|
||||
@@ -209,7 +215,7 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, u8 subcmd)
|
||||
|
||||
ret = btmrvl_send_sync_cmd(priv, BT_CMD_MODULE_CFG_REQ, &subcmd, 1);
|
||||
if (ret)
|
||||
BT_ERR("module_cfg_cmd(%x) failed\n", subcmd);
|
||||
BT_ERR("module_cfg_cmd(%x) failed", subcmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -245,7 +251,7 @@ int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv)
|
||||
|
||||
ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_CONFIG, param, 2);
|
||||
if (ret)
|
||||
BT_ERR("HSCFG command failed\n");
|
||||
BT_ERR("HSCFG command failed");
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -263,7 +269,7 @@ int btmrvl_enable_ps(struct btmrvl_private *priv)
|
||||
|
||||
ret = btmrvl_send_sync_cmd(priv, BT_CMD_AUTO_SLEEP_MODE, ¶m, 1);
|
||||
if (ret)
|
||||
BT_ERR("PSMODE command failed\n");
|
||||
BT_ERR("PSMODE command failed");
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -276,7 +282,7 @@ int btmrvl_enable_hs(struct btmrvl_private *priv)
|
||||
|
||||
ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_ENABLE, NULL, 0);
|
||||
if (ret) {
|
||||
BT_ERR("Host sleep enable command failed\n");
|
||||
BT_ERR("Host sleep enable command failed");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -323,12 +329,19 @@ int btmrvl_prepare_command(struct btmrvl_private *priv)
|
||||
} else {
|
||||
ret = priv->hw_wakeup_firmware(priv);
|
||||
priv->adapter->hs_state = HS_DEACTIVATED;
|
||||
BT_DBG("BT: HS DEACTIVATED due to host activity!");
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void btmrvl_firmware_dump(struct btmrvl_private *priv)
|
||||
{
|
||||
if (priv->firmware_dump)
|
||||
priv->firmware_dump(priv);
|
||||
}
|
||||
|
||||
static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -487,34 +500,36 @@ static int btmrvl_download_cal_data(struct btmrvl_private *priv,
|
||||
ret = btmrvl_send_sync_cmd(priv, BT_CMD_LOAD_CONFIG_DATA, data,
|
||||
BT_CAL_HDR_LEN + len);
|
||||
if (ret)
|
||||
BT_ERR("Failed to download caibration data\n");
|
||||
BT_ERR("Failed to download caibration data");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int btmrvl_cal_data_dt(struct btmrvl_private *priv)
|
||||
static int btmrvl_check_device_tree(struct btmrvl_private *priv)
|
||||
{
|
||||
struct device_node *dt_node;
|
||||
u8 cal_data[BT_CAL_HDR_LEN + BT_CAL_DATA_SIZE];
|
||||
const char name[] = "btmrvl_caldata";
|
||||
const char property[] = "btmrvl,caldata";
|
||||
int ret;
|
||||
u32 val;
|
||||
|
||||
dt_node = of_find_node_by_name(NULL, name);
|
||||
if (!dt_node)
|
||||
return -ENODEV;
|
||||
for_each_compatible_node(dt_node, NULL, "btmrvl,cfgdata") {
|
||||
ret = of_property_read_u32(dt_node, "btmrvl,gpio-gap", &val);
|
||||
if (!ret)
|
||||
priv->btmrvl_dev.gpio_gap = val;
|
||||
|
||||
ret = of_property_read_u8_array(dt_node, property,
|
||||
cal_data + BT_CAL_HDR_LEN,
|
||||
BT_CAL_DATA_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = of_property_read_u8_array(dt_node, "btmrvl,cal-data",
|
||||
cal_data + BT_CAL_HDR_LEN,
|
||||
BT_CAL_DATA_SIZE);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
BT_DBG("Use cal data from device tree");
|
||||
ret = btmrvl_download_cal_data(priv, cal_data, BT_CAL_DATA_SIZE);
|
||||
if (ret) {
|
||||
BT_ERR("Fail to download calibrate data");
|
||||
return ret;
|
||||
BT_DBG("Use cal data from device tree");
|
||||
ret = btmrvl_download_cal_data(priv, cal_data,
|
||||
BT_CAL_DATA_SIZE);
|
||||
if (ret) {
|
||||
BT_ERR("Fail to download calibrate data");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -526,14 +541,15 @@ static int btmrvl_setup(struct hci_dev *hdev)
|
||||
|
||||
btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
|
||||
|
||||
btmrvl_cal_data_dt(priv);
|
||||
priv->btmrvl_dev.gpio_gap = 0xffff;
|
||||
|
||||
btmrvl_check_device_tree(priv);
|
||||
|
||||
btmrvl_pscan_window_reporting(priv, 0x01);
|
||||
|
||||
priv->btmrvl_dev.psmode = 1;
|
||||
btmrvl_enable_ps(priv);
|
||||
|
||||
priv->btmrvl_dev.gpio_gap = 0xffff;
|
||||
btmrvl_send_hscfg_cmd(priv);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <linux/mmc/sdio_ids.h>
|
||||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/devcoredump.h>
|
||||
|
||||
#include <net/bluetooth/bluetooth.h>
|
||||
#include <net/bluetooth/hci_core.h>
|
||||
@@ -33,6 +34,24 @@
|
||||
|
||||
#define VERSION "1.0"
|
||||
|
||||
static struct memory_type_mapping mem_type_mapping_tbl[] = {
|
||||
{"ITCM", NULL, 0, 0xF0},
|
||||
{"DTCM", NULL, 0, 0xF1},
|
||||
{"SQRAM", NULL, 0, 0xF2},
|
||||
{"APU", NULL, 0, 0xF3},
|
||||
{"CIU", NULL, 0, 0xF4},
|
||||
{"ICU", NULL, 0, 0xF5},
|
||||
{"MAC", NULL, 0, 0xF6},
|
||||
{"EXT7", NULL, 0, 0xF7},
|
||||
{"EXT8", NULL, 0, 0xF8},
|
||||
{"EXT9", NULL, 0, 0xF9},
|
||||
{"EXT10", NULL, 0, 0xFA},
|
||||
{"EXT11", NULL, 0, 0xFB},
|
||||
{"EXT12", NULL, 0, 0xFC},
|
||||
{"EXT13", NULL, 0, 0xFD},
|
||||
{"EXTLAST", NULL, 0, 0xFE},
|
||||
};
|
||||
|
||||
/* The btmrvl_sdio_remove() callback function is called
|
||||
* when user removes this module from kernel space or ejects
|
||||
* the card from the slot. The driver handles these 2 cases
|
||||
@@ -122,6 +141,9 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_8897 = {
|
||||
.int_read_to_clear = true,
|
||||
.host_int_rsr = 0x01,
|
||||
.card_misc_cfg = 0xcc,
|
||||
.fw_dump_ctrl = 0xe2,
|
||||
.fw_dump_start = 0xe3,
|
||||
.fw_dump_end = 0xea,
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
|
||||
@@ -130,6 +152,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
|
||||
.reg = &btmrvl_reg_8688,
|
||||
.support_pscan_win_report = false,
|
||||
.sd_blksz_fw_dl = 64,
|
||||
.supports_fw_dump = false,
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
|
||||
@@ -138,6 +161,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
|
||||
.reg = &btmrvl_reg_87xx,
|
||||
.support_pscan_win_report = false,
|
||||
.sd_blksz_fw_dl = 256,
|
||||
.supports_fw_dump = false,
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
|
||||
@@ -146,6 +170,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
|
||||
.reg = &btmrvl_reg_87xx,
|
||||
.support_pscan_win_report = false,
|
||||
.sd_blksz_fw_dl = 256,
|
||||
.supports_fw_dump = false,
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8887 = {
|
||||
@@ -154,6 +179,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8887 = {
|
||||
.reg = &btmrvl_reg_8887,
|
||||
.support_pscan_win_report = true,
|
||||
.sd_blksz_fw_dl = 256,
|
||||
.supports_fw_dump = false,
|
||||
};
|
||||
|
||||
static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
|
||||
@@ -162,6 +188,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
|
||||
.reg = &btmrvl_reg_8897,
|
||||
.support_pscan_win_report = true,
|
||||
.sd_blksz_fw_dl = 256,
|
||||
.supports_fw_dump = true,
|
||||
};
|
||||
|
||||
static const struct sdio_device_id btmrvl_sdio_ids[] = {
|
||||
@@ -764,8 +791,8 @@ static void btmrvl_sdio_interrupt(struct sdio_func *func)
|
||||
|
||||
card = sdio_get_drvdata(func);
|
||||
if (!card || !card->priv) {
|
||||
BT_ERR("sbi_interrupt(%p) card or priv is "
|
||||
"NULL, card=%p\n", func, card);
|
||||
BT_ERR("sbi_interrupt(%p) card or priv is NULL, card=%p",
|
||||
func, card);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1080,6 +1107,277 @@ static int btmrvl_sdio_wakeup_fw(struct btmrvl_private *priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void btmrvl_sdio_dump_regs(struct btmrvl_private *priv)
|
||||
{
|
||||
struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
|
||||
int ret = 0;
|
||||
unsigned int reg, reg_start, reg_end;
|
||||
char buf[256], *ptr;
|
||||
u8 loop, func, data;
|
||||
int MAX_LOOP = 2;
|
||||
|
||||
btmrvl_sdio_wakeup_fw(priv);
|
||||
sdio_claim_host(card->func);
|
||||
|
||||
for (loop = 0; loop < MAX_LOOP; loop++) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
ptr = buf;
|
||||
|
||||
if (loop == 0) {
|
||||
/* Read the registers of SDIO function0 */
|
||||
func = loop;
|
||||
reg_start = 0;
|
||||
reg_end = 9;
|
||||
} else {
|
||||
func = 2;
|
||||
reg_start = 0;
|
||||
reg_end = 0x09;
|
||||
}
|
||||
|
||||
ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ",
|
||||
func, reg_start, reg_end);
|
||||
for (reg = reg_start; reg <= reg_end; reg++) {
|
||||
if (func == 0)
|
||||
data = sdio_f0_readb(card->func, reg, &ret);
|
||||
else
|
||||
data = sdio_readb(card->func, reg, &ret);
|
||||
|
||||
if (!ret) {
|
||||
ptr += sprintf(ptr, "%02x ", data);
|
||||
} else {
|
||||
ptr += sprintf(ptr, "ERR");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BT_INFO("%s", buf);
|
||||
}
|
||||
|
||||
sdio_release_host(card->func);
|
||||
}
|
||||
|
||||
/* This function read/write firmware */
|
||||
static enum
|
||||
rdwr_status btmrvl_sdio_rdwr_firmware(struct btmrvl_private *priv,
|
||||
u8 doneflag)
|
||||
{
|
||||
struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
|
||||
int ret, tries;
|
||||
u8 ctrl_data = 0;
|
||||
|
||||
sdio_writeb(card->func, FW_DUMP_HOST_READY, card->reg->fw_dump_ctrl,
|
||||
&ret);
|
||||
|
||||
if (ret) {
|
||||
BT_ERR("SDIO write err");
|
||||
return RDWR_STATUS_FAILURE;
|
||||
}
|
||||
|
||||
for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
|
||||
ctrl_data = sdio_readb(card->func, card->reg->fw_dump_ctrl,
|
||||
&ret);
|
||||
|
||||
if (ret) {
|
||||
BT_ERR("SDIO read err");
|
||||
return RDWR_STATUS_FAILURE;
|
||||
}
|
||||
|
||||
if (ctrl_data == FW_DUMP_DONE)
|
||||
break;
|
||||
if (doneflag && ctrl_data == doneflag)
|
||||
return RDWR_STATUS_DONE;
|
||||
if (ctrl_data != FW_DUMP_HOST_READY) {
|
||||
BT_INFO("The ctrl reg was changed, re-try again!");
|
||||
sdio_writeb(card->func, FW_DUMP_HOST_READY,
|
||||
card->reg->fw_dump_ctrl, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("SDIO write err");
|
||||
return RDWR_STATUS_FAILURE;
|
||||
}
|
||||
}
|
||||
usleep_range(100, 200);
|
||||
}
|
||||
|
||||
if (ctrl_data == FW_DUMP_HOST_READY) {
|
||||
BT_ERR("Fail to pull ctrl_data");
|
||||
return RDWR_STATUS_FAILURE;
|
||||
}
|
||||
|
||||
return RDWR_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* This function dump sdio register and memory data */
|
||||
static void btmrvl_sdio_dump_firmware(struct btmrvl_private *priv)
|
||||
{
|
||||
struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
|
||||
int ret = 0;
|
||||
unsigned int reg, reg_start, reg_end;
|
||||
enum rdwr_status stat;
|
||||
u8 *dbg_ptr, *end_ptr, *fw_dump_data, *fw_dump_ptr;
|
||||
u8 dump_num, idx, i, read_reg, doneflag = 0;
|
||||
u32 memory_size, fw_dump_len = 0;
|
||||
|
||||
/* dump sdio register first */
|
||||
btmrvl_sdio_dump_regs(priv);
|
||||
|
||||
if (!card->supports_fw_dump) {
|
||||
BT_ERR("Firmware dump not supported for this card!");
|
||||
return;
|
||||
}
|
||||
|
||||
for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) {
|
||||
struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
|
||||
|
||||
if (entry->mem_ptr) {
|
||||
vfree(entry->mem_ptr);
|
||||
entry->mem_ptr = NULL;
|
||||
}
|
||||
entry->mem_size = 0;
|
||||
}
|
||||
|
||||
btmrvl_sdio_wakeup_fw(priv);
|
||||
sdio_claim_host(card->func);
|
||||
|
||||
BT_INFO("== btmrvl firmware dump start ==");
|
||||
|
||||
stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
|
||||
if (stat == RDWR_STATUS_FAILURE)
|
||||
goto done;
|
||||
|
||||
reg = card->reg->fw_dump_start;
|
||||
/* Read the number of the memories which will dump */
|
||||
dump_num = sdio_readb(card->func, reg, &ret);
|
||||
|
||||
if (ret) {
|
||||
BT_ERR("SDIO read memory length err");
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Read the length of every memory which will dump */
|
||||
for (idx = 0; idx < dump_num; idx++) {
|
||||
struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
|
||||
|
||||
stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
|
||||
if (stat == RDWR_STATUS_FAILURE)
|
||||
goto done;
|
||||
|
||||
memory_size = 0;
|
||||
reg = card->reg->fw_dump_start;
|
||||
for (i = 0; i < 4; i++) {
|
||||
read_reg = sdio_readb(card->func, reg, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("SDIO read err");
|
||||
goto done;
|
||||
}
|
||||
memory_size |= (read_reg << i*8);
|
||||
reg++;
|
||||
}
|
||||
|
||||
if (memory_size == 0) {
|
||||
BT_INFO("Firmware dump finished!");
|
||||
break;
|
||||
}
|
||||
|
||||
BT_INFO("%s_SIZE=0x%x", entry->mem_name, memory_size);
|
||||
entry->mem_ptr = vzalloc(memory_size + 1);
|
||||
entry->mem_size = memory_size;
|
||||
if (!entry->mem_ptr) {
|
||||
BT_ERR("Vzalloc %s failed", entry->mem_name);
|
||||
goto done;
|
||||
}
|
||||
|
||||
fw_dump_len += (strlen("========Start dump ") +
|
||||
strlen(entry->mem_name) +
|
||||
strlen("========\n") +
|
||||
(memory_size + 1) +
|
||||
strlen("\n========End dump========\n"));
|
||||
|
||||
dbg_ptr = entry->mem_ptr;
|
||||
end_ptr = dbg_ptr + memory_size;
|
||||
|
||||
doneflag = entry->done_flag;
|
||||
BT_INFO("Start %s output, please wait...",
|
||||
entry->mem_name);
|
||||
|
||||
do {
|
||||
stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
|
||||
if (stat == RDWR_STATUS_FAILURE)
|
||||
goto done;
|
||||
|
||||
reg_start = card->reg->fw_dump_start;
|
||||
reg_end = card->reg->fw_dump_end;
|
||||
for (reg = reg_start; reg <= reg_end; reg++) {
|
||||
*dbg_ptr = sdio_readb(card->func, reg, &ret);
|
||||
if (ret) {
|
||||
BT_ERR("SDIO read err");
|
||||
goto done;
|
||||
}
|
||||
if (dbg_ptr < end_ptr)
|
||||
dbg_ptr++;
|
||||
else
|
||||
BT_ERR("Allocated buffer not enough");
|
||||
}
|
||||
|
||||
if (stat != RDWR_STATUS_DONE) {
|
||||
continue;
|
||||
} else {
|
||||
BT_INFO("%s done: size=0x%tx",
|
||||
entry->mem_name,
|
||||
dbg_ptr - entry->mem_ptr);
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
BT_INFO("== btmrvl firmware dump end ==");
|
||||
|
||||
done:
|
||||
sdio_release_host(card->func);
|
||||
|
||||
if (fw_dump_len == 0)
|
||||
return;
|
||||
|
||||
fw_dump_data = vzalloc(fw_dump_len+1);
|
||||
if (!fw_dump_data) {
|
||||
BT_ERR("Vzalloc fw_dump_data fail!");
|
||||
return;
|
||||
}
|
||||
fw_dump_ptr = fw_dump_data;
|
||||
|
||||
/* Dump all the memory data into single file, a userspace script will
|
||||
be used to split all the memory data to multiple files*/
|
||||
BT_INFO("== btmrvl firmware dump to /sys/class/devcoredump start");
|
||||
for (idx = 0; idx < dump_num; idx++) {
|
||||
struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
|
||||
|
||||
if (entry->mem_ptr) {
|
||||
strcpy(fw_dump_ptr, "========Start dump ");
|
||||
fw_dump_ptr += strlen("========Start dump ");
|
||||
|
||||
strcpy(fw_dump_ptr, entry->mem_name);
|
||||
fw_dump_ptr += strlen(entry->mem_name);
|
||||
|
||||
strcpy(fw_dump_ptr, "========\n");
|
||||
fw_dump_ptr += strlen("========\n");
|
||||
|
||||
memcpy(fw_dump_ptr, entry->mem_ptr, entry->mem_size);
|
||||
fw_dump_ptr += entry->mem_size;
|
||||
|
||||
strcpy(fw_dump_ptr, "\n========End dump========\n");
|
||||
fw_dump_ptr += strlen("\n========End dump========\n");
|
||||
|
||||
vfree(mem_type_mapping_tbl[idx].mem_ptr);
|
||||
mem_type_mapping_tbl[idx].mem_ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* fw_dump_data will be free in device coredump release function
|
||||
after 5 min*/
|
||||
dev_coredumpv(&priv->btmrvl_dev.hcidev->dev, fw_dump_data,
|
||||
fw_dump_len, GFP_KERNEL);
|
||||
BT_INFO("== btmrvl firmware dump to /sys/class/devcoredump end");
|
||||
}
|
||||
|
||||
static int btmrvl_sdio_probe(struct sdio_func *func,
|
||||
const struct sdio_device_id *id)
|
||||
{
|
||||
@@ -1103,6 +1401,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
|
||||
card->reg = data->reg;
|
||||
card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
|
||||
card->support_pscan_win_report = data->support_pscan_win_report;
|
||||
card->supports_fw_dump = data->supports_fw_dump;
|
||||
}
|
||||
|
||||
if (btmrvl_sdio_register_dev(card) < 0) {
|
||||
@@ -1134,6 +1433,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
|
||||
priv->hw_host_to_card = btmrvl_sdio_host_to_card;
|
||||
priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw;
|
||||
priv->hw_process_int_status = btmrvl_sdio_process_int_status;
|
||||
priv->firmware_dump = btmrvl_sdio_dump_firmware;
|
||||
|
||||
if (btmrvl_register_hdev(priv)) {
|
||||
BT_ERR("Register hdev failed!");
|
||||
|
||||
@@ -81,6 +81,9 @@ struct btmrvl_sdio_card_reg {
|
||||
bool int_read_to_clear;
|
||||
u8 host_int_rsr;
|
||||
u8 card_misc_cfg;
|
||||
u8 fw_dump_ctrl;
|
||||
u8 fw_dump_start;
|
||||
u8 fw_dump_end;
|
||||
};
|
||||
|
||||
struct btmrvl_sdio_card {
|
||||
@@ -90,6 +93,7 @@ struct btmrvl_sdio_card {
|
||||
const char *firmware;
|
||||
const struct btmrvl_sdio_card_reg *reg;
|
||||
bool support_pscan_win_report;
|
||||
bool supports_fw_dump;
|
||||
u16 sd_blksz_fw_dl;
|
||||
u8 rx_unit;
|
||||
struct btmrvl_private *priv;
|
||||
@@ -101,6 +105,7 @@ struct btmrvl_sdio_device {
|
||||
const struct btmrvl_sdio_card_reg *reg;
|
||||
const bool support_pscan_win_report;
|
||||
u16 sd_blksz_fw_dl;
|
||||
bool supports_fw_dump;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -110,7 +110,8 @@ static const struct usb_device_id btusb_table[] = {
|
||||
.driver_info = BTUSB_BCM_PATCHRAM },
|
||||
|
||||
/* Foxconn - Hon Hai */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) },
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01),
|
||||
.driver_info = BTUSB_BCM_PATCHRAM },
|
||||
|
||||
/* Broadcom devices with vendor specific id */
|
||||
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01),
|
||||
@@ -185,6 +186,7 @@ static const struct usb_device_id blacklist_table[] = {
|
||||
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
|
||||
@@ -2104,6 +2104,7 @@ static int b44_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
|
||||
bp->flags &= ~B44_FLAG_WOL_ENABLE;
|
||||
spin_unlock_irq(&bp->lock);
|
||||
|
||||
device_set_wakeup_enable(bp->sdev->dev, wol->wolopts & WAKE_MAGIC);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2452,6 +2453,7 @@ static int b44_init_one(struct ssb_device *sdev,
|
||||
}
|
||||
}
|
||||
|
||||
device_set_wakeup_capable(sdev->dev, true);
|
||||
netdev_info(dev, "%s %pM\n", DRV_DESCRIPTION, dev->dev_addr);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -858,7 +858,7 @@ static int cc2520_probe(struct spi_device *spi)
|
||||
pinctrl = devm_pinctrl_get_select_default(&spi->dev);
|
||||
if (IS_ERR(pinctrl))
|
||||
dev_warn(&spi->dev,
|
||||
"pinctrl pins are not configured");
|
||||
"pinctrl pins are not configured\n");
|
||||
|
||||
pdata = cc2520_get_platform_data(spi);
|
||||
if (!pdata) {
|
||||
|
||||
@@ -799,6 +799,17 @@ static void ath10k_core_restart(struct work_struct *work)
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
}
|
||||
|
||||
static void ath10k_core_init_max_sta_count(struct ath10k *ar)
|
||||
{
|
||||
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
|
||||
ar->max_num_peers = TARGET_10X_NUM_PEERS;
|
||||
ar->max_num_stations = TARGET_10X_NUM_STATIONS;
|
||||
} else {
|
||||
ar->max_num_peers = TARGET_NUM_PEERS;
|
||||
ar->max_num_stations = TARGET_NUM_STATIONS;
|
||||
}
|
||||
}
|
||||
|
||||
int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
|
||||
{
|
||||
int status;
|
||||
@@ -1035,6 +1046,8 @@ static int ath10k_core_probe_fw(struct ath10k *ar)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ath10k_core_init_max_sta_count(ar);
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
|
||||
|
||||
@@ -79,10 +79,12 @@ static inline const char *ath10k_bus_str(enum ath10k_bus bus)
|
||||
|
||||
struct ath10k_skb_cb {
|
||||
dma_addr_t paddr;
|
||||
u8 eid;
|
||||
u8 vdev_id;
|
||||
|
||||
struct {
|
||||
u8 tid;
|
||||
u16 freq;
|
||||
bool is_offchan;
|
||||
struct ath10k_htt_txbuf *txbuf;
|
||||
u32 txbuf_paddr;
|
||||
@@ -122,6 +124,7 @@ struct ath10k_wmi {
|
||||
struct completion service_ready;
|
||||
struct completion unified_ready;
|
||||
wait_queue_head_t tx_credits_wq;
|
||||
DECLARE_BITMAP(svc_map, WMI_SERVICE_MAX);
|
||||
struct wmi_cmd_map *cmd;
|
||||
struct wmi_vdev_param_map *vdev_param;
|
||||
struct wmi_pdev_param_map *pdev_param;
|
||||
@@ -218,6 +221,8 @@ struct ath10k_peer {
|
||||
int vdev_id;
|
||||
u8 addr[ETH_ALEN];
|
||||
DECLARE_BITMAP(peer_ids, ATH10K_MAX_NUM_PEER_IDS);
|
||||
|
||||
/* protected by ar->data_lock */
|
||||
struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
|
||||
};
|
||||
|
||||
@@ -310,7 +315,6 @@ struct ath10k_debug {
|
||||
struct ath10k_fw_stats fw_stats;
|
||||
struct completion fw_stats_complete;
|
||||
bool fw_stats_done;
|
||||
DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_MAX);
|
||||
|
||||
unsigned long htt_stats_mask;
|
||||
struct delayed_work htt_stats_dwork;
|
||||
@@ -320,6 +324,7 @@ struct ath10k_debug {
|
||||
/* protected by conf_mutex */
|
||||
u32 fw_dbglog_mask;
|
||||
u32 pktlog_filter;
|
||||
u32 reg_addr;
|
||||
|
||||
u8 htt_max_amsdu;
|
||||
u8 htt_max_ampdu;
|
||||
@@ -560,8 +565,12 @@ struct ath10k {
|
||||
struct list_head peers;
|
||||
wait_queue_head_t peer_mapping_wq;
|
||||
|
||||
/* number of created peers; protected by data_lock */
|
||||
/* protected by conf_mutex */
|
||||
int num_peers;
|
||||
int num_stations;
|
||||
|
||||
int max_num_peers;
|
||||
int max_num_stations;
|
||||
|
||||
struct work_struct offchan_tx_work;
|
||||
struct sk_buff_head offchan_tx_queue;
|
||||
|
||||
@@ -17,9 +17,8 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/vermagic.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/utsname.h>
|
||||
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
@@ -124,7 +123,7 @@ EXPORT_SYMBOL(ath10k_info);
|
||||
|
||||
void ath10k_print_driver_info(struct ath10k *ar)
|
||||
{
|
||||
ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d.%d.%d.%d cal %s\n",
|
||||
ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d.%d.%d.%d cal %s max_sta %d\n",
|
||||
ar->hw_params.name,
|
||||
ar->target_version,
|
||||
ar->chip_id,
|
||||
@@ -136,7 +135,8 @@ void ath10k_print_driver_info(struct ath10k *ar)
|
||||
ar->fw_version_minor,
|
||||
ar->fw_version_release,
|
||||
ar->fw_version_build,
|
||||
ath10k_cal_mode_str(ar->cal_mode));
|
||||
ath10k_cal_mode_str(ar->cal_mode),
|
||||
ar->max_num_stations);
|
||||
ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
|
||||
config_enabled(CONFIG_ATH10K_DEBUG),
|
||||
config_enabled(CONFIG_ATH10K_DEBUGFS),
|
||||
@@ -179,13 +179,6 @@ EXPORT_SYMBOL(ath10k_warn);
|
||||
|
||||
#ifdef CONFIG_ATH10K_DEBUGFS
|
||||
|
||||
void ath10k_debug_read_service_map(struct ath10k *ar,
|
||||
const void *service_map,
|
||||
size_t map_size)
|
||||
{
|
||||
memcpy(ar->debug.wmi_service_bitmap, service_map, map_size);
|
||||
}
|
||||
|
||||
static ssize_t ath10k_read_wmi_services(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
@@ -207,8 +200,9 @@ static ssize_t ath10k_read_wmi_services(struct file *file,
|
||||
if (len > buf_len)
|
||||
len = buf_len;
|
||||
|
||||
spin_lock_bh(&ar->data_lock);
|
||||
for (i = 0; i < WMI_SERVICE_MAX; i++) {
|
||||
enabled = test_bit(i, ar->debug.wmi_service_bitmap);
|
||||
enabled = test_bit(i, ar->wmi.svc_map);
|
||||
name = wmi_service_name(i);
|
||||
|
||||
if (!name) {
|
||||
@@ -224,6 +218,7 @@ static ssize_t ath10k_read_wmi_services(struct file *file,
|
||||
"%-40s %s\n",
|
||||
name, enabled ? "enabled" : "-");
|
||||
}
|
||||
spin_unlock_bh(&ar->data_lock);
|
||||
|
||||
ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
|
||||
@@ -866,8 +861,8 @@ static struct ath10k_dump_file_data *ath10k_build_dump_file(struct ath10k *ar)
|
||||
strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
|
||||
sizeof(dump_data->fw_ver));
|
||||
|
||||
dump_data->kernel_ver_code = cpu_to_le32(LINUX_VERSION_CODE);
|
||||
strlcpy(dump_data->kernel_ver, VERMAGIC_STRING,
|
||||
dump_data->kernel_ver_code = 0;
|
||||
strlcpy(dump_data->kernel_ver, init_utsname()->release,
|
||||
sizeof(dump_data->kernel_ver));
|
||||
|
||||
dump_data->tv_sec = cpu_to_le64(crash_data->timestamp.tv_sec);
|
||||
@@ -929,6 +924,236 @@ static const struct file_operations fops_fw_crash_dump = {
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t ath10k_reg_addr_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
u8 buf[32];
|
||||
unsigned int len = 0;
|
||||
u32 reg_addr;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
reg_addr = ar->debug.reg_addr;
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", reg_addr);
|
||||
|
||||
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
}
|
||||
|
||||
static ssize_t ath10k_reg_addr_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
u32 reg_addr;
|
||||
int ret;
|
||||
|
||||
ret = kstrtou32_from_user(user_buf, count, 0, ®_addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!IS_ALIGNED(reg_addr, 4))
|
||||
return -EFAULT;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
ar->debug.reg_addr = reg_addr;
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_reg_addr = {
|
||||
.read = ath10k_reg_addr_read,
|
||||
.write = ath10k_reg_addr_write,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t ath10k_reg_value_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
u8 buf[48];
|
||||
unsigned int len;
|
||||
u32 reg_addr, reg_val;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH10K_STATE_ON &&
|
||||
ar->state != ATH10K_STATE_UTF) {
|
||||
ret = -ENETDOWN;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
reg_addr = ar->debug.reg_addr;
|
||||
|
||||
reg_val = ath10k_hif_read32(ar, reg_addr);
|
||||
len = scnprintf(buf, sizeof(buf), "0x%08x:0x%08x\n", reg_addr, reg_val);
|
||||
|
||||
ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ath10k_reg_value_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
u32 reg_addr, reg_val;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
if (ar->state != ATH10K_STATE_ON &&
|
||||
ar->state != ATH10K_STATE_UTF) {
|
||||
ret = -ENETDOWN;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
reg_addr = ar->debug.reg_addr;
|
||||
|
||||
ret = kstrtou32_from_user(user_buf, count, 0, ®_val);
|
||||
if (ret)
|
||||
goto exit;
|
||||
|
||||
ath10k_hif_write32(ar, reg_addr, reg_val);
|
||||
|
||||
ret = count;
|
||||
|
||||
exit:
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_reg_value = {
|
||||
.read = ath10k_reg_value_read,
|
||||
.write = ath10k_reg_value_write,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static ssize_t ath10k_mem_value_read(struct file *file,
|
||||
char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
u8 *buf;
|
||||
int ret;
|
||||
|
||||
if (*ppos < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
buf = vmalloc(count);
|
||||
if (!buf) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (ar->state != ATH10K_STATE_ON &&
|
||||
ar->state != ATH10K_STATE_UTF) {
|
||||
ret = -ENETDOWN;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = ath10k_hif_diag_read(ar, *ppos, buf, count);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to read address 0x%08x via diagnose window fnrom debugfs: %d\n",
|
||||
(u32)(*ppos), ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = copy_to_user(user_buf, buf, count);
|
||||
if (ret) {
|
||||
ret = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
count -= ret;
|
||||
*ppos += count;
|
||||
ret = count;
|
||||
|
||||
exit:
|
||||
vfree(buf);
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t ath10k_mem_value_write(struct file *file,
|
||||
const char __user *user_buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct ath10k *ar = file->private_data;
|
||||
u8 *buf;
|
||||
int ret;
|
||||
|
||||
if (*ppos < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&ar->conf_mutex);
|
||||
|
||||
buf = vmalloc(count);
|
||||
if (!buf) {
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (ar->state != ATH10K_STATE_ON &&
|
||||
ar->state != ATH10K_STATE_UTF) {
|
||||
ret = -ENETDOWN;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = copy_from_user(buf, user_buf, count);
|
||||
if (ret) {
|
||||
ret = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
ret = ath10k_hif_diag_write(ar, *ppos, buf, count);
|
||||
if (ret) {
|
||||
ath10k_warn(ar, "failed to write address 0x%08x via diagnose window from debugfs: %d\n",
|
||||
(u32)(*ppos), ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
*ppos += count;
|
||||
ret = count;
|
||||
|
||||
exit:
|
||||
vfree(buf);
|
||||
mutex_unlock(&ar->conf_mutex);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations fops_mem_value = {
|
||||
.read = ath10k_mem_value_read,
|
||||
.write = ath10k_mem_value_write,
|
||||
.open = simple_open,
|
||||
.owner = THIS_MODULE,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
static int ath10k_debug_htt_stats_req(struct ath10k *ar)
|
||||
{
|
||||
u64 cookie;
|
||||
@@ -1630,6 +1855,15 @@ int ath10k_debug_register(struct ath10k *ar)
|
||||
debugfs_create_file("fw_crash_dump", S_IRUSR, ar->debug.debugfs_phy,
|
||||
ar, &fops_fw_crash_dump);
|
||||
|
||||
debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR,
|
||||
ar->debug.debugfs_phy, ar, &fops_reg_addr);
|
||||
|
||||
debugfs_create_file("reg_value", S_IRUSR | S_IWUSR,
|
||||
ar->debug.debugfs_phy, ar, &fops_reg_value);
|
||||
|
||||
debugfs_create_file("mem_value", S_IRUSR | S_IWUSR,
|
||||
ar->debug.debugfs_phy, ar, &fops_mem_value);
|
||||
|
||||
debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
|
||||
ar, &fops_chip_id);
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ enum ath10k_debug_mask {
|
||||
ATH10K_DBG_BMI = 0x00000400,
|
||||
ATH10K_DBG_REGULATORY = 0x00000800,
|
||||
ATH10K_DBG_TESTMODE = 0x00001000,
|
||||
ATH10K_DBG_WMI_PRINT = 0x00002000,
|
||||
ATH10K_DBG_ANY = 0xffffffff,
|
||||
};
|
||||
|
||||
@@ -61,9 +62,6 @@ int ath10k_debug_create(struct ath10k *ar);
|
||||
void ath10k_debug_destroy(struct ath10k *ar);
|
||||
int ath10k_debug_register(struct ath10k *ar);
|
||||
void ath10k_debug_unregister(struct ath10k *ar);
|
||||
void ath10k_debug_read_service_map(struct ath10k *ar,
|
||||
const void *service_map,
|
||||
size_t map_size);
|
||||
void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb);
|
||||
struct ath10k_fw_crash_data *
|
||||
ath10k_debug_get_new_fw_crash_data(struct ath10k *ar);
|
||||
@@ -108,12 +106,6 @@ static inline void ath10k_debug_unregister(struct ath10k *ar)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void ath10k_debug_read_service_map(struct ath10k *ar,
|
||||
const void *service_map,
|
||||
size_t map_size)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void ath10k_debug_fw_stats_process(struct ath10k *ar,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include "core.h"
|
||||
#include "debug.h"
|
||||
|
||||
struct ath10k_hif_sg_item {
|
||||
u16 transfer_id;
|
||||
@@ -31,11 +32,9 @@ struct ath10k_hif_sg_item {
|
||||
|
||||
struct ath10k_hif_cb {
|
||||
int (*tx_completion)(struct ath10k *ar,
|
||||
struct sk_buff *wbuf,
|
||||
unsigned transfer_id);
|
||||
struct sk_buff *wbuf);
|
||||
int (*rx_completion)(struct ath10k *ar,
|
||||
struct sk_buff *wbuf,
|
||||
u8 pipe_id);
|
||||
struct sk_buff *wbuf);
|
||||
};
|
||||
|
||||
struct ath10k_hif_ops {
|
||||
@@ -47,6 +46,8 @@ struct ath10k_hif_ops {
|
||||
int (*diag_read)(struct ath10k *ar, u32 address, void *buf,
|
||||
size_t buf_len);
|
||||
|
||||
int (*diag_write)(struct ath10k *ar, u32 address, const void *data,
|
||||
int nbytes);
|
||||
/*
|
||||
* API to handle HIF-specific BMI message exchanges, this API is
|
||||
* synchronous and only allowed to be called from a context that
|
||||
@@ -84,6 +85,10 @@ struct ath10k_hif_ops {
|
||||
|
||||
u16 (*get_free_queue_number)(struct ath10k *ar, u8 pipe_id);
|
||||
|
||||
u32 (*read32)(struct ath10k *ar, u32 address);
|
||||
|
||||
void (*write32)(struct ath10k *ar, u32 address, u32 value);
|
||||
|
||||
/* Power up the device and enter BMI transfer mode for FW download */
|
||||
int (*power_up)(struct ath10k *ar);
|
||||
|
||||
@@ -108,6 +113,15 @@ static inline int ath10k_hif_diag_read(struct ath10k *ar, u32 address, void *buf
|
||||
return ar->hif.ops->diag_read(ar, address, buf, buf_len);
|
||||
}
|
||||
|
||||
static inline int ath10k_hif_diag_write(struct ath10k *ar, u32 address,
|
||||
const void *data, int nbytes)
|
||||
{
|
||||
if (!ar->hif.ops->diag_write)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return ar->hif.ops->diag_write(ar, address, data, nbytes);
|
||||
}
|
||||
|
||||
static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar,
|
||||
void *request, u32 request_len,
|
||||
void *response, u32 *response_len)
|
||||
@@ -187,4 +201,25 @@ static inline int ath10k_hif_resume(struct ath10k *ar)
|
||||
return ar->hif.ops->resume(ar);
|
||||
}
|
||||
|
||||
static inline u32 ath10k_hif_read32(struct ath10k *ar, u32 address)
|
||||
{
|
||||
if (!ar->hif.ops->read32) {
|
||||
ath10k_warn(ar, "hif read32 not supported\n");
|
||||
return 0xdeaddead;
|
||||
}
|
||||
|
||||
return ar->hif.ops->read32(ar, address);
|
||||
}
|
||||
|
||||
static inline void ath10k_hif_write32(struct ath10k *ar,
|
||||
u32 address, u32 data)
|
||||
{
|
||||
if (!ar->hif.ops->write32) {
|
||||
ath10k_warn(ar, "hif write32 not supported\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ar->hif.ops->write32(ar, address, data);
|
||||
}
|
||||
|
||||
#endif /* _HIF_H_ */
|
||||
|
||||
@@ -160,6 +160,7 @@ int ath10k_htc_send(struct ath10k_htc *htc,
|
||||
|
||||
ath10k_htc_prepare_tx_skb(ep, skb);
|
||||
|
||||
skb_cb->eid = eid;
|
||||
skb_cb->paddr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE);
|
||||
ret = dma_mapping_error(dev, skb_cb->paddr);
|
||||
if (ret)
|
||||
@@ -197,15 +198,18 @@ err_pull:
|
||||
}
|
||||
|
||||
static int ath10k_htc_tx_completion_handler(struct ath10k *ar,
|
||||
struct sk_buff *skb,
|
||||
unsigned int eid)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct ath10k_htc *htc = &ar->htc;
|
||||
struct ath10k_htc_ep *ep = &htc->endpoint[eid];
|
||||
struct ath10k_skb_cb *skb_cb;
|
||||
struct ath10k_htc_ep *ep;
|
||||
|
||||
if (WARN_ON_ONCE(!skb))
|
||||
return 0;
|
||||
|
||||
skb_cb = ATH10K_SKB_CB(skb);
|
||||
ep = &htc->endpoint[skb_cb->eid];
|
||||
|
||||
ath10k_htc_notify_tx_completion(ep, skb);
|
||||
/* the skb now belongs to the completion handler */
|
||||
|
||||
@@ -317,8 +321,7 @@ static int ath10k_htc_process_trailer(struct ath10k_htc *htc,
|
||||
}
|
||||
|
||||
static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
|
||||
struct sk_buff *skb,
|
||||
u8 pipe_id)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
int status = 0;
|
||||
struct ath10k_htc *htc = &ar->htc;
|
||||
|
||||
@@ -126,6 +126,7 @@ enum htt_data_tx_ext_tid {
|
||||
* (HL hosts manage queues on the host )
|
||||
* more_in_batch: only for HL hosts. indicates if more packets are
|
||||
* pending. this allows target to wait and aggregate
|
||||
* freq: 0 means home channel of given vdev. intended for offchannel
|
||||
*/
|
||||
struct htt_data_tx_desc {
|
||||
u8 flags0; /* %HTT_DATA_TX_DESC_FLAGS0_ */
|
||||
@@ -133,7 +134,8 @@ struct htt_data_tx_desc {
|
||||
__le16 len;
|
||||
__le16 id;
|
||||
__le32 frags_paddr;
|
||||
__le32 peerid;
|
||||
__le16 peerid;
|
||||
__le16 freq;
|
||||
u8 prefetch[0]; /* start of frame, for FW classification engine */
|
||||
} __packed;
|
||||
|
||||
@@ -156,6 +158,9 @@ enum htt_rx_ring_flags {
|
||||
HTT_RX_RING_FLAGS_PHY_DATA_RX = 1 << 15
|
||||
};
|
||||
|
||||
#define HTT_RX_RING_SIZE_MIN 128
|
||||
#define HTT_RX_RING_SIZE_MAX 2048
|
||||
|
||||
struct htt_rx_ring_setup_ring {
|
||||
__le32 fw_idx_shadow_reg_paddr;
|
||||
__le32 rx_ring_base_paddr;
|
||||
|
||||
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