1
0
Fork 0

Merge tag 'master-2014-07-25' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next

John W. Linville says:

====================
pull request: wireless-next 2014-07-25

Please pull this batch of updates intended for the 3.17 stream!

For the mac80211 bits, Johannes says:

"We have a lot of TDLS patches, among them a fix that should make hwsim
tests happy again. The rest, this time, is mostly small fixes."

For the Bluetooth bits, Gustavo says:

"Some more patches for 3.17. The most important change here is the move of
the 6lowpan code to net/6lowpan. It has been agreed with Davem that this
change will go through the bluetooth tree. The rest are mostly clean up and
fixes."

and,

"Here follows some more patches for 3.17. These are mostly fixes to what
we've sent to you before for next merge window."

For the iwlwifi bits, Emmanuel says:

"I have the usual amount of BT Coex stuff. Arik continues to work
on TDLS and Ariej contributes a few things for HS2.0. I added a few
more things to the firmware debugging infrastructure. Eran fixes a
small bug - pretty normal content."

And for the Atheros bits, Kalle says:

"For ath6kl me and Jessica added support for ar6004 hw3.0, our latest
version of ar6004.

For ath10k Janusz added a printout so that it's easier to check what
ath10k kconfig options are enabled. He also added a debugfs file to
configure maximum amsdu and ampdu values. Also we had few fixes as
usual."

On top of that is the usual large batch of various driver updates --
brcmfmac, mwifiex, the TI drivers, and wil6210 all get some action.
Rafał has also been very busy with b43 and related updates.

Also, I pulled the wireless tree into this in order to resolve a
merge conflict...

P.S.  The change to fs/compat_ioctl.c reflects a name change in a
Bluetooth header file...
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
hifive-unleashed-5.1
David S. Miller 2014-07-28 17:36:25 -07:00
commit 3fd0202a0d
178 changed files with 6572 additions and 2750 deletions

View File

@ -148,6 +148,13 @@ L: linux-scsi@vger.kernel.org
S: Maintained
F: drivers/scsi/53c700*
6LOWPAN GENERIC (BTLE/IEEE 802.15.4)
M: Alexander Aring <alex.aring@gmail.com>
L: linux-zigbee-devel@lists.sourceforge.net (moderated for non-subscribers)
L: linux-bluetooth@vger.kernel.org
S: Maintained
F: net/6lowpan/
6PACK NETWORK DRIVER FOR AX.25
M: Andreas Koensgen <ajk@comnets.uni-bremen.de>
L: linux-hams@vger.kernel.org

View File

@ -603,6 +603,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid)
tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW;
break;
case BCMA_CHIP_ID_BCM43217:
case BCMA_CHIP_ID_BCM43227:
case BCMA_CHIP_ID_BCM43228:
case BCMA_CHIP_ID_BCM43428:

View File

@ -279,6 +279,7 @@ static const struct pci_device_id bcma_pci_bridge_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4358) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
{ 0, },
};

View File

@ -201,6 +201,23 @@ static int bcma_sprom_valid(struct bcma_bus *bus, const u16 *sprom,
SPEX(_field[7], _offset + 14, _mask, _shift); \
} while (0)
static s8 sprom_extract_antgain(const u16 *in, u16 offset, u16 mask, u16 shift)
{
u16 v;
u8 gain;
v = in[SPOFF(offset)];
gain = (v & mask) >> shift;
if (gain == 0xFF) {
gain = 8; /* If unset use 2dBm */
} else {
/* Q5.2 Fractional part is stored in 0xC0 */
gain = ((gain & 0xC0) >> 6) | ((gain & 0x3F) << 2);
}
return (s8)gain;
}
static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
{
u16 v, o;
@ -381,14 +398,22 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0);
/* Extract the antenna gain values. */
SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01,
SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT);
SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01,
SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT);
SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23,
SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT);
SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23,
SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT);
bus->sprom.antenna_gain.a0 = sprom_extract_antgain(sprom,
SSB_SPROM8_AGAIN01,
SSB_SPROM8_AGAIN0,
SSB_SPROM8_AGAIN0_SHIFT);
bus->sprom.antenna_gain.a1 = sprom_extract_antgain(sprom,
SSB_SPROM8_AGAIN01,
SSB_SPROM8_AGAIN1,
SSB_SPROM8_AGAIN1_SHIFT);
bus->sprom.antenna_gain.a2 = sprom_extract_antgain(sprom,
SSB_SPROM8_AGAIN23,
SSB_SPROM8_AGAIN2,
SSB_SPROM8_AGAIN2_SHIFT);
bus->sprom.antenna_gain.a3 = sprom_extract_antgain(sprom,
SSB_SPROM8_AGAIN23,
SSB_SPROM8_AGAIN3,
SSB_SPROM8_AGAIN3_SHIFT);
SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
SSB_SPROM8_LEDDC_ON_SHIFT);
@ -509,6 +534,7 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus)
/* for these chips OTP is always available */
present = true;
break;
case BCMA_CHIP_ID_BCM43217:
case BCMA_CHIP_ID_BCM43227:
case BCMA_CHIP_ID_BCM43228:
case BCMA_CHIP_ID_BCM43428:

View File

@ -27,6 +27,7 @@
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/usb.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
#define VERSION "1.0"
@ -50,12 +51,12 @@
#define ATH3K_NAME_LEN 0xFF
struct ath3k_version {
unsigned int rom_version;
unsigned int build_version;
unsigned int ram_version;
unsigned char ref_clock;
unsigned char reserved[0x07];
};
__le32 rom_version;
__le32 build_version;
__le32 ram_version;
__u8 ref_clock;
__u8 reserved[7];
} __packed;
static const struct usb_device_id ath3k_table[] = {
/* Atheros AR3011 */
@ -349,7 +350,8 @@ static int ath3k_load_patch(struct usb_device *udev)
unsigned char fw_state;
char filename[ATH3K_NAME_LEN] = {0};
const struct firmware *firmware;
struct ath3k_version fw_version, pt_version;
struct ath3k_version fw_version;
__u32 pt_rom_version, pt_build_version;
int ret;
ret = ath3k_get_state(udev, &fw_state);
@ -370,7 +372,7 @@ static int ath3k_load_patch(struct usb_device *udev)
}
snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu",
le32_to_cpu(fw_version.rom_version));
le32_to_cpu(fw_version.rom_version));
ret = request_firmware(&firmware, filename, &udev->dev);
if (ret < 0) {
@ -378,12 +380,13 @@ static int ath3k_load_patch(struct usb_device *udev)
return ret;
}
pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8);
pt_version.build_version = *(int *)
(firmware->data + firmware->size - 4);
pt_rom_version = get_unaligned_le32(firmware->data +
firmware->size - 8);
pt_build_version = get_unaligned_le32(firmware->data +
firmware->size - 4);
if ((pt_version.rom_version != fw_version.rom_version) ||
(pt_version.build_version <= fw_version.build_version)) {
if (pt_rom_version != le32_to_cpu(fw_version.rom_version) ||
pt_build_version <= le32_to_cpu(fw_version.build_version)) {
BT_ERR("Patch file version did not match with firmware");
release_firmware(firmware);
return -EINVAL;

View File

@ -91,6 +91,7 @@ struct btmrvl_private {
/* Vendor specific Bluetooth commands */
#define BT_CMD_PSCAN_WIN_REPORT_ENABLE 0xFC03
#define BT_CMD_SET_BDADDR 0xFC22
#define BT_CMD_AUTO_SLEEP_MODE 0xFC23
#define BT_CMD_HOST_SLEEP_CONFIG 0xFC59
#define BT_CMD_HOST_SLEEP_ENABLE 0xFC5A

View File

@ -539,6 +539,29 @@ static int btmrvl_setup(struct hci_dev *hdev)
return 0;
}
static int btmrvl_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
{
struct sk_buff *skb;
long ret;
u8 buf[8];
buf[0] = MRVL_VENDOR_PKT;
buf[1] = sizeof(bdaddr_t);
memcpy(buf + 2, bdaddr, sizeof(bdaddr_t));
skb = __hci_cmd_sync(hdev, BT_CMD_SET_BDADDR, sizeof(buf), buf,
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
ret = PTR_ERR(skb);
BT_ERR("%s: changing btmrvl device address failed (%ld)",
hdev->name, ret);
return ret;
}
kfree_skb(skb);
return 0;
}
/*
* This function handles the event generated by firmware, rx data
* received from firmware, and tx data sent from kernel.
@ -632,6 +655,7 @@ int btmrvl_register_hdev(struct btmrvl_private *priv)
hdev->flush = btmrvl_flush;
hdev->send = btmrvl_send_frame;
hdev->setup = btmrvl_setup;
hdev->set_bdaddr = btmrvl_set_bdaddr;
hdev->dev_type = priv->btmrvl_dev.dev_type;

View File

@ -1169,6 +1169,10 @@ static int btmrvl_sdio_suspend(struct device *dev)
}
priv = card->priv;
hcidev = priv->btmrvl_dev.hcidev;
BT_DBG("%s: SDIO suspend", hcidev->name);
hci_suspend_dev(hcidev);
skb_queue_purge(&priv->adapter->tx_queue);
if (priv->adapter->hs_state != HS_ACTIVATED) {
if (btmrvl_enable_hs(priv)) {
@ -1176,10 +1180,6 @@ static int btmrvl_sdio_suspend(struct device *dev)
return -EBUSY;
}
}
hcidev = priv->btmrvl_dev.hcidev;
BT_DBG("%s: SDIO suspend", hcidev->name);
hci_suspend_dev(hcidev);
skb_queue_purge(&priv->adapter->tx_queue);
priv->adapter->is_suspended = true;
@ -1221,13 +1221,13 @@ static int btmrvl_sdio_resume(struct device *dev)
return 0;
}
priv->adapter->is_suspended = false;
hcidev = priv->btmrvl_dev.hcidev;
BT_DBG("%s: SDIO resume", hcidev->name);
hci_resume_dev(hcidev);
priv->hw_wakeup_firmware(priv);
priv->adapter->hs_state = HS_DEACTIVATED;
hcidev = priv->btmrvl_dev.hcidev;
BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name);
priv->adapter->is_suspended = false;
BT_DBG("%s: SDIO resume", hcidev->name);
hci_resume_dev(hcidev);
return 0;
}

View File

@ -48,6 +48,7 @@ static struct usb_driver btusb_driver;
#define BTUSB_INTEL 0x100
#define BTUSB_INTEL_BOOT 0x200
#define BTUSB_BCM_PATCHRAM 0x400
#define BTUSB_MARVELL 0x800
static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
@ -113,6 +114,9 @@ static const struct usb_device_id btusb_table[] = {
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM },
/* ASUSTek Computer - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0b05, 0xff, 0x01, 0x01) },
/* Belkin F8065bf - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
@ -242,6 +246,10 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },
/* Marvell device */
{ USB_DEVICE(0x1286, 0x2044), .driver_info = BTUSB_MARVELL },
{ USB_DEVICE(0x1286, 0x2046), .driver_info = BTUSB_MARVELL },
{ } /* Terminating entry */
};
@ -1455,6 +1463,29 @@ static int btusb_set_bdaddr_intel(struct hci_dev *hdev, const bdaddr_t *bdaddr)
return 0;
}
static int btusb_set_bdaddr_marvell(struct hci_dev *hdev,
const bdaddr_t *bdaddr)
{
struct sk_buff *skb;
u8 buf[8];
long ret;
buf[0] = 0xfe;
buf[1] = sizeof(bdaddr_t);
memcpy(buf + 2, bdaddr, sizeof(bdaddr_t));
skb = __hci_cmd_sync(hdev, 0xfc22, sizeof(buf), buf, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
ret = PTR_ERR(skb);
BT_ERR("%s: changing Marvell device address failed (%ld)",
hdev->name, ret);
return ret;
}
kfree_skb(skb);
return 0;
}
#define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}})
static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
@ -1766,6 +1797,9 @@ static int btusb_probe(struct usb_interface *intf,
hdev->set_bdaddr = btusb_set_bdaddr_intel;
}
if (id->driver_info & BTUSB_MARVELL)
hdev->set_bdaddr = btusb_set_bdaddr_marvell;
if (id->driver_info & BTUSB_INTEL_BOOT)
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);

View File

@ -431,6 +431,9 @@ static int hci_uart_register_dev(struct hci_uart *hu)
if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
if (test_bit(HCI_UART_EXT_CONFIG, &hu->hdev_flags))
set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks);
if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags))
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
@ -477,6 +480,22 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
return 0;
}
static int hci_uart_set_flags(struct hci_uart *hu, unsigned long flags)
{
unsigned long valid_flags = BIT(HCI_UART_RAW_DEVICE) |
BIT(HCI_UART_RESET_ON_INIT) |
BIT(HCI_UART_CREATE_AMP) |
BIT(HCI_UART_INIT_PENDING) |
BIT(HCI_UART_EXT_CONFIG);
if ((flags & ~valid_flags))
return -EINVAL;
hu->hdev_flags = flags;
return 0;
}
/* hci_uart_tty_ioctl()
*
* Process IOCTL system call for the tty device.
@ -520,14 +539,16 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
return -EUNATCH;
case HCIUARTGETDEVICE:
if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
if (test_bit(HCI_UART_REGISTERED, &hu->flags))
return hu->hdev->id;
return -EUNATCH;
case HCIUARTSETFLAGS:
if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
return -EBUSY;
hu->hdev_flags = arg;
err = hci_uart_set_flags(hu, arg);
if (err)
return err;
break;
case HCIUARTGETFLAGS:

View File

@ -48,6 +48,7 @@
#define HCI_UART_RESET_ON_INIT 1
#define HCI_UART_CREATE_AMP 2
#define HCI_UART_INIT_PENDING 3
#define HCI_UART_EXT_CONFIG 4
struct hci_uart;

View File

@ -603,16 +603,19 @@ static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
if (ret)
return ret;
src_ring->hw_index =
ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
src_ring->hw_index &= nentries_mask;
read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
if (read_index == 0xffffffff)
return -ENODEV;
read_index &= nentries_mask;
src_ring->hw_index = read_index;
ath10k_pci_sleep(ar);
}
read_index = src_ring->hw_index;
if ((read_index == sw_index) || (read_index == 0xffffffff))
if (read_index == sw_index)
return -EIO;
sbase = src_ring->shadow_base;

View File

@ -802,7 +802,7 @@ int ath10k_core_start(struct ath10k *ar)
INIT_LIST_HEAD(&ar->arvifs);
if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags)) {
ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
ar->hw_params.name,
ar->target_version,
@ -811,6 +811,12 @@ int ath10k_core_start(struct ath10k *ar)
ar->fw_api,
ar->htt.target_version_major,
ar->htt.target_version_minor);
ath10k_info("debug %d debugfs %d tracing %d dfs %d\n",
config_enabled(CONFIG_ATH10K_DEBUG),
config_enabled(CONFIG_ATH10K_DEBUGFS),
config_enabled(CONFIG_ATH10K_TRACING),
config_enabled(CONFIG_ATH10K_DFS_CERTIFIED));
}
__set_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags);
@ -988,7 +994,9 @@ err_unregister_mac:
err_release_fw:
ath10k_core_free_firmware_files(ar);
err:
device_release_driver(ar->dev);
/* TODO: It's probably a good idea to release device from the driver
* but calling device_release_driver() here will cause a deadlock.
*/
return;
}

View File

@ -290,6 +290,9 @@ struct ath10k_debug {
struct ath_dfs_pool_stats dfs_pool_stats;
u32 fw_dbglog_mask;
u8 htt_max_amsdu;
u8 htt_max_ampdu;
};
enum ath10k_state {

View File

@ -671,6 +671,72 @@ static const struct file_operations fops_htt_stats_mask = {
.llseek = default_llseek,
};
static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
char buf[64];
u8 amsdu = 3, ampdu = 64;
unsigned int len;
mutex_lock(&ar->conf_mutex);
if (ar->debug.htt_max_amsdu)
amsdu = ar->debug.htt_max_amsdu;
if (ar->debug.htt_max_ampdu)
ampdu = ar->debug.htt_max_ampdu;
mutex_unlock(&ar->conf_mutex);
len = scnprintf(buf, sizeof(buf), "%u %u\n", amsdu, ampdu);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
static ssize_t ath10k_write_htt_max_amsdu_ampdu(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
int res;
char buf[64];
unsigned int amsdu, ampdu;
simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);
/* make sure that buf is null terminated */
buf[sizeof(buf) - 1] = 0;
res = sscanf(buf, "%u %u", &amsdu, &ampdu);
if (res != 2)
return -EINVAL;
mutex_lock(&ar->conf_mutex);
res = ath10k_htt_h2t_aggr_cfg_msg(&ar->htt, ampdu, amsdu);
if (res)
goto out;
res = count;
ar->debug.htt_max_amsdu = amsdu;
ar->debug.htt_max_ampdu = ampdu;
out:
mutex_unlock(&ar->conf_mutex);
return res;
}
static const struct file_operations fops_htt_max_amsdu_ampdu = {
.read = ath10k_read_htt_max_amsdu_ampdu,
.write = ath10k_write_htt_max_amsdu_ampdu,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
static ssize_t ath10k_read_fw_dbglog(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
@ -757,6 +823,9 @@ void ath10k_debug_stop(struct ath10k *ar)
* warning from del_timer(). */
if (ar->debug.htt_stats_mask != 0)
cancel_delayed_work(&ar->debug.htt_stats_dwork);
ar->debug.htt_max_amsdu = 0;
ar->debug.htt_max_ampdu = 0;
}
static ssize_t ath10k_write_simulate_radar(struct file *file,
@ -867,6 +936,10 @@ int ath10k_debug_create(struct ath10k *ar)
debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_htt_stats_mask);
debugfs_create_file("htt_max_amsdu_ampdu", S_IRUSR | S_IWUSR,
ar->debug.debugfs_phy, ar,
&fops_htt_max_amsdu_ampdu);
debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_fw_dbglog);

View File

@ -240,16 +240,10 @@ struct htt_oob_sync_req {
__le16 rsvd0;
} __packed;
#define HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_MASK 0x1F
#define HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_LSB 0
struct htt_aggr_conf {
u8 max_num_ampdu_subframes;
union {
/* dont use bitfields; undefined behaviour */
u8 flags; /* see %HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_ */
u8 max_num_amsdu_subframes:5;
} __packed;
/* amsdu_subframes is limited by 0x1F mask */
u8 max_num_amsdu_subframes;
} __packed;
#define HTT_MGMT_FRM_HDR_DOWNLOAD_LEN 32
@ -1343,6 +1337,9 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb);
int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt);
int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie);
int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt);
int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
u8 max_subfrms_ampdu,
u8 max_subfrms_amsdu);
void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt);
int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt);

View File

@ -307,6 +307,52 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt)
return 0;
}
int ath10k_htt_h2t_aggr_cfg_msg(struct ath10k_htt *htt,
u8 max_subfrms_ampdu,
u8 max_subfrms_amsdu)
{
struct htt_aggr_conf *aggr_conf;
struct sk_buff *skb;
struct htt_cmd *cmd;
int len;
int ret;
/* Firmware defaults are: amsdu = 3 and ampdu = 64 */
if (max_subfrms_ampdu == 0 || max_subfrms_ampdu > 64)
return -EINVAL;
if (max_subfrms_amsdu == 0 || max_subfrms_amsdu > 31)
return -EINVAL;
len = sizeof(cmd->hdr);
len += sizeof(cmd->aggr_conf);
skb = ath10k_htc_alloc_skb(len);
if (!skb)
return -ENOMEM;
skb_put(skb, len);
cmd = (struct htt_cmd *)skb->data;
cmd->hdr.msg_type = HTT_H2T_MSG_TYPE_AGGR_CFG;
aggr_conf = &cmd->aggr_conf;
aggr_conf->max_num_ampdu_subframes = max_subfrms_ampdu;
aggr_conf->max_num_amsdu_subframes = max_subfrms_amsdu;
ath10k_dbg(ATH10K_DBG_HTT, "htt h2t aggr cfg msg amsdu %d ampdu %d",
aggr_conf->max_num_amsdu_subframes,
aggr_conf->max_num_ampdu_subframes);
ret = ath10k_htc_send(&htt->ar->htc, htt->eid, skb);
if (ret) {
dev_kfree_skb_any(skb);
return ret;
}
return 0;
}
int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
{
struct device *dev = htt->ar->dev;

View File

@ -1362,8 +1362,6 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar,
ath10k_ce_recv_buf_enqueue(ce_rx, &xfer, resp_paddr);
}
init_completion(&xfer.done);
ret = ath10k_ce_send(ce_tx, &xfer, req_paddr, req_len, -1, 0);
if (ret)
goto err_resp;
@ -1414,10 +1412,7 @@ static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state)
&nbytes, &transfer_id))
return;
if (xfer->wait_for_resp)
return;
complete(&xfer->done);
xfer->tx_done = true;
}
static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
@ -1438,7 +1433,7 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
}
xfer->resp_len = nbytes;
complete(&xfer->done);
xfer->rx_done = true;
}
static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
@ -1451,7 +1446,7 @@ static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe,
ath10k_pci_bmi_send_done(tx_pipe);
ath10k_pci_bmi_recv_data(rx_pipe);
if (completion_done(&xfer->done))
if (xfer->tx_done && (xfer->rx_done == xfer->wait_for_resp))
return 0;
schedule();

View File

@ -38,7 +38,8 @@
#define DIAG_TRANSFER_LIMIT 2048
struct bmi_xfer {
struct completion done;
bool tx_done;
bool rx_done;
bool wait_for_resp;
u32 resp_len;
};

View File

@ -2106,7 +2106,6 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_cmd_hdr *cmd_hdr;
enum wmi_event_id id;
u16 len;
cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
@ -2114,8 +2113,6 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb)
if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
return;
len = skb->len;
trace_ath10k_wmi_event(id, skb->data, skb->len);
switch (id) {
@ -2225,7 +2222,6 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_cmd_hdr *cmd_hdr;
enum wmi_10x_event_id id;
u16 len;
cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID);
@ -2233,8 +2229,6 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
return;
len = skb->len;
trace_ath10k_wmi_event(id, skb->data, skb->len);
switch (id) {

View File

@ -242,7 +242,8 @@ struct ath6kl_bmi_target_info {
(void) (check_type == val); \
addr = ath6kl_get_hi_item_addr(ar, HI_ITEM(item)); \
ret = ath6kl_bmi_read(ar, addr, (u8 *) &tmp, 4); \
*val = le32_to_cpu(tmp); \
if (!ret) \
*val = le32_to_cpu(tmp); \
ret; \
})

View File

@ -2899,7 +2899,8 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
if (info->inactivity_timeout) {
inactivity_timeout = info->inactivity_timeout;
if (ar->hw.flags & ATH6KL_HW_AP_INACTIVITY_MINS)
if (test_bit(ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS,
ar->fw_capabilities))
inactivity_timeout = DIV_ROUND_UP(inactivity_timeout,
60);
@ -3782,7 +3783,8 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
ath6kl_band_5ghz.ht_cap.ht_supported = false;
}
if (ar->hw.flags & ATH6KL_HW_64BIT_RATES) {
if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES,
ar->fw_capabilities)) {
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;

View File

@ -123,6 +123,22 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type)
/* FIXME: we should free all firmwares in the error cases below */
/*
* Backwards compatibility support for older ar6004 firmware images
* which do not set these feature flags.
*/
if (ar->target_type == TARGET_TYPE_AR6004 &&
ar->fw_api <= 4) {
__set_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES,
ar->fw_capabilities);
__set_bit(ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS,
ar->fw_capabilities);
if (ar->hw.id == AR6004_HW_1_3_VERSION)
__set_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
ar->fw_capabilities);
}
/* Indicate that WMI is enabled (although not ready yet) */
set_bit(WMI_ENABLED, &ar->flag);
ar->wmi = ath6kl_wmi_init(ar);

View File

@ -136,6 +136,21 @@ enum ath6kl_fw_capability {
*/
ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL,
/* WMI_SET_TX_SELECT_RATES_CMDID uses 64 bit size rate table */
ATH6KL_FW_CAPABILITY_64BIT_RATES,
/* WMI_AP_CONN_INACT_CMDID uses minutes as units */
ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS,
/* use low priority endpoint for all data */
ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
/* ratetable is the 2 stream version (max MCS15) */
ATH6KL_FW_CAPABILITY_RATETABLE_MCS15,
/* firmare doesn't support IP checksumming */
ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM,
/* this needs to be last */
ATH6KL_FW_CAPABILITY_MAX,
};
@ -149,15 +164,13 @@ struct ath6kl_fw_ie {
};
enum ath6kl_hw_flags {
ATH6KL_HW_64BIT_RATES = BIT(0),
ATH6KL_HW_AP_INACTIVITY_MINS = BIT(1),
ATH6KL_HW_MAP_LP_ENDPOINT = BIT(2),
ATH6KL_HW_SDIO_CRC_ERROR_WAR = BIT(3),
};
#define ATH6KL_FW_API2_FILE "fw-2.bin"
#define ATH6KL_FW_API3_FILE "fw-3.bin"
#define ATH6KL_FW_API4_FILE "fw-4.bin"
#define ATH6KL_FW_API5_FILE "fw-5.bin"
/* AR6003 1.0 definitions */
#define AR6003_HW_1_0_VERSION 0x300002ba
@ -215,8 +228,21 @@ enum ath6kl_hw_flags {
#define AR6004_HW_1_3_VERSION 0x31c8088a
#define AR6004_HW_1_3_FW_DIR "ath6k/AR6004/hw1.3"
#define AR6004_HW_1_3_FIRMWARE_FILE "fw.ram.bin"
#define AR6004_HW_1_3_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin"
#define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin"
#define AR6004_HW_1_3_TCMD_FIRMWARE_FILE "utf.bin"
#define AR6004_HW_1_3_UTF_FIRMWARE_FILE "utf.bin"
#define AR6004_HW_1_3_TESTSCRIPT_FILE "nullTestFlow.bin"
#define AR6004_HW_1_3_BOARD_DATA_FILE AR6004_HW_1_3_FW_DIR "/bdata.bin"
#define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE AR6004_HW_1_3_FW_DIR "/bdata.bin"
/* AR6004 3.0 definitions */
#define AR6004_HW_3_0_VERSION 0x31C809F8
#define AR6004_HW_3_0_FW_DIR "ath6k/AR6004/hw3.0"
#define AR6004_HW_3_0_FIRMWARE_FILE "fw.ram.bin"
#define AR6004_HW_3_0_TCMD_FIRMWARE_FILE "utf.bin"
#define AR6004_HW_3_0_UTF_FIRMWARE_FILE "utf.bin"
#define AR6004_HW_3_0_TESTSCRIPT_FILE "nullTestFlow.bin"
#define AR6004_HW_3_0_BOARD_DATA_FILE AR6004_HW_3_0_FW_DIR "/bdata.bin"
#define AR6004_HW_3_0_DEFAULT_BOARD_DATA_FILE AR6004_HW_3_0_FW_DIR "/bdata.bin"
/* Per STA data, used in AP mode */
#define STA_PS_AWAKE BIT(0)

View File

@ -1170,8 +1170,12 @@ static int htc_wait_recv_ctrl_message(struct htc_target *target)
static void htc_rxctrl_complete(struct htc_target *context,
struct htc_packet *packet)
{
/* TODO, can't really receive HTC control messages yet.... */
ath6kl_dbg(ATH6KL_DBG_HTC, "%s: invalid call function\n", __func__);
struct sk_buff *skb = packet->skb;
if (packet->endpoint == ENDPOINT_0 &&
packet->status == -ECANCELED &&
skb != NULL)
dev_kfree_skb(skb);
}
/* htc pipe initialization */
@ -1678,7 +1682,29 @@ static void ath6kl_htc_pipe_activity_changed(struct htc_target *target,
static void ath6kl_htc_pipe_flush_rx_buf(struct htc_target *target)
{
/* TODO */
struct htc_endpoint *endpoint;
struct htc_packet *packet, *tmp_pkt;
int i;
for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
endpoint = &target->endpoint[i];
spin_lock_bh(&target->rx_lock);
list_for_each_entry_safe(packet, tmp_pkt,
&endpoint->rx_bufq, list) {
list_del(&packet->list);
spin_unlock_bh(&target->rx_lock);
ath6kl_dbg(ATH6KL_DBG_HTC,
"htc rx flush pkt 0x%p len %d ep %d\n",
packet, packet->buf_len,
packet->endpoint);
dev_kfree_skb(packet->pkt_cntxt);
spin_lock_bh(&target->rx_lock);
}
spin_unlock_bh(&target->rx_lock);
}
}
static int ath6kl_htc_pipe_credit_setup(struct htc_target *target,

View File

@ -93,8 +93,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x433900,
.refclk_hz = 26000000,
.uarttx_pin = 11,
.flags = ATH6KL_HW_64BIT_RATES |
ATH6KL_HW_AP_INACTIVITY_MINS,
.flags = 0,
.fw = {
.dir = AR6004_HW_1_0_FW_DIR,
@ -114,8 +113,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x43d400,
.refclk_hz = 40000000,
.uarttx_pin = 11,
.flags = ATH6KL_HW_64BIT_RATES |
ATH6KL_HW_AP_INACTIVITY_MINS,
.flags = 0,
.fw = {
.dir = AR6004_HW_1_1_FW_DIR,
.fw = AR6004_HW_1_1_FIRMWARE_FILE,
@ -134,8 +132,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x435c00,
.refclk_hz = 40000000,
.uarttx_pin = 11,
.flags = ATH6KL_HW_64BIT_RATES |
ATH6KL_HW_AP_INACTIVITY_MINS,
.flags = 0,
.fw = {
.dir = AR6004_HW_1_2_FW_DIR,
@ -152,20 +149,43 @@ static const struct ath6kl_hw hw_list[] = {
.board_ext_data_addr = 0x437000,
.reserved_ram_size = 7168,
.board_addr = 0x436400,
.refclk_hz = 40000000,
.refclk_hz = 0,
.uarttx_pin = 11,
.flags = ATH6KL_HW_64BIT_RATES |
ATH6KL_HW_AP_INACTIVITY_MINS |
ATH6KL_HW_MAP_LP_ENDPOINT,
.flags = 0,
.fw = {
.dir = AR6004_HW_1_3_FW_DIR,
.fw = AR6004_HW_1_3_FIRMWARE_FILE,
.tcmd = AR6004_HW_1_3_TCMD_FIRMWARE_FILE,
.utf = AR6004_HW_1_3_UTF_FIRMWARE_FILE,
.testscript = AR6004_HW_1_3_TESTSCRIPT_FILE,
},
.fw_board = AR6004_HW_1_3_BOARD_DATA_FILE,
.fw_default_board = AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE,
},
{
.id = AR6004_HW_3_0_VERSION,
.name = "ar6004 hw 3.0",
.dataset_patch_addr = 0,
.app_load_addr = 0x1234,
.board_ext_data_addr = 0,
.reserved_ram_size = 7168,
.board_addr = 0x436400,
.testscript_addr = 0,
.flags = 0,
.fw = {
.dir = AR6004_HW_3_0_FW_DIR,
.fw = AR6004_HW_3_0_FIRMWARE_FILE,
.tcmd = AR6004_HW_3_0_TCMD_FIRMWARE_FILE,
.utf = AR6004_HW_3_0_UTF_FIRMWARE_FILE,
.testscript = AR6004_HW_3_0_TESTSCRIPT_FILE,
},
.fw_board = AR6004_HW_3_0_BOARD_DATA_FILE,
.fw_default_board = AR6004_HW_3_0_DEFAULT_BOARD_DATA_FILE,
},
};
/*
@ -601,7 +621,9 @@ int ath6kl_configure_target(struct ath6kl *ar)
* but possible in theory.
*/
if (ar->target_type == TARGET_TYPE_AR6003) {
if ((ar->target_type == TARGET_TYPE_AR6003) ||
(ar->version.target_ver == AR6004_HW_1_3_VERSION) ||
(ar->version.target_ver == AR6004_HW_3_0_VERSION)) {
param = ar->hw.board_ext_data_addr;
ram_reserved_size = ar->hw.reserved_ram_size;
@ -629,9 +651,12 @@ int ath6kl_configure_target(struct ath6kl *ar)
return status;
/* Configure target refclk_hz */
status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz, ar->hw.refclk_hz);
if (status)
return status;
if (ar->hw.refclk_hz != 0) {
status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz,
ar->hw.refclk_hz);
if (status)
return status;
}
return 0;
}
@ -1112,6 +1137,12 @@ int ath6kl_init_fetch_firmwares(struct ath6kl *ar)
if (ret)
return ret;
ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API5_FILE);
if (ret == 0) {
ar->fw_api = 5;
goto out;
}
ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API4_FILE);
if (ret == 0) {
ar->fw_api = 4;
@ -1161,11 +1192,19 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
ath6kl_bmi_write_hi32(ar, hi_board_data,
board_address);
} else {
ath6kl_bmi_read_hi32(ar, hi_board_data, &board_address);
ret = ath6kl_bmi_read_hi32(ar, hi_board_data, &board_address);
if (ret) {
ath6kl_err("Failed to get board file target address.\n");
return ret;
}
}
/* determine where in target ram to write extended board data */
ath6kl_bmi_read_hi32(ar, hi_board_ext_data, &board_ext_address);
ret = ath6kl_bmi_read_hi32(ar, hi_board_ext_data, &board_ext_address);
if (ret) {
ath6kl_err("Failed to get extended board file target address.\n");
return ret;
}
if (ar->target_type == TARGET_TYPE_AR6003 &&
board_ext_address == 0) {
@ -1229,7 +1268,13 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
}
/* record the fact that Board Data IS initialized */
ath6kl_bmi_write_hi32(ar, hi_board_data_initialized, 1);
if ((ar->version.target_ver == AR6004_HW_1_3_VERSION) ||
(ar->version.target_ver == AR6004_HW_3_0_VERSION))
param = board_data_size;
else
param = 1;
ath6kl_bmi_write_hi32(ar, hi_board_data_initialized, param);
return ret;
}
@ -1360,7 +1405,11 @@ static int ath6kl_upload_testscript(struct ath6kl *ar)
}
ath6kl_bmi_write_hi32(ar, hi_ota_testscript, address);
ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz, 4096);
if ((ar->version.target_ver != AR6004_HW_1_3_VERSION) &&
(ar->version.target_ver != AR6004_HW_3_0_VERSION))
ath6kl_bmi_write_hi32(ar, hi_end_ram_reserve_sz, 4096);
ath6kl_bmi_write_hi32(ar, hi_test_apps_related, 1);
return 0;
@ -1566,6 +1615,11 @@ static const struct fw_capa_str_map {
{ ATH6KL_FW_CAPABILITY_REGDOMAIN, "regdomain" },
{ ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, "sched-scan-v2" },
{ ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, "hb-poll" },
{ ATH6KL_FW_CAPABILITY_64BIT_RATES, "64bit-rates" },
{ ATH6KL_FW_CAPABILITY_AP_INACTIVITY_MINS, "ap-inactivity-mins" },
{ ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT, "map-lp-endpoint" },
{ ATH6KL_FW_CAPABILITY_RATETABLE_MCS15, "ratetable-mcs15" },
{ ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM, "no-ip-checksum" },
};
static const char *ath6kl_init_get_fw_capa_name(unsigned int id)

View File

@ -702,6 +702,7 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len)
struct ath6kl *ar = vif->ar;
struct target_stats *stats = &vif->target_stats;
struct tkip_ccmp_stats *ccmp_stats;
s32 rate;
u8 ac;
if (len < sizeof(*tgt_stats))
@ -731,8 +732,9 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len)
le32_to_cpu(tgt_stats->stats.tx.mult_retry_cnt);
stats->tx_rts_fail_cnt +=
le32_to_cpu(tgt_stats->stats.tx.rts_fail_cnt);
stats->tx_ucast_rate =
ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.tx.ucast_rate));
rate = a_sle32_to_cpu(tgt_stats->stats.tx.ucast_rate);
stats->tx_ucast_rate = ath6kl_wmi_get_rate(ar->wmi, rate);
stats->rx_pkt += le32_to_cpu(tgt_stats->stats.rx.pkt);
stats->rx_byte += le32_to_cpu(tgt_stats->stats.rx.byte);
@ -749,8 +751,9 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len)
le32_to_cpu(tgt_stats->stats.rx.key_cache_miss);
stats->rx_decrypt_err += le32_to_cpu(tgt_stats->stats.rx.decrypt_err);
stats->rx_dupl_frame += le32_to_cpu(tgt_stats->stats.rx.dupl_frame);
stats->rx_ucast_rate =
ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.rx.ucast_rate));
rate = a_sle32_to_cpu(tgt_stats->stats.rx.ucast_rate);
stats->rx_ucast_rate = ath6kl_wmi_get_rate(ar->wmi, rate);
ccmp_stats = &tgt_stats->stats.tkip_ccmp_stats;
@ -1290,6 +1293,8 @@ static const struct net_device_ops ath6kl_netdev_ops = {
void init_netdev(struct net_device *dev)
{
struct ath6kl *ar = ath6kl_priv(dev);
dev->netdev_ops = &ath6kl_netdev_ops;
dev->destructor = free_netdev;
dev->watchdog_timeo = ATH6KL_TX_TIMEOUT;
@ -1301,7 +1306,9 @@ void init_netdev(struct net_device *dev)
WMI_MAX_TX_META_SZ +
ATH6KL_HTC_ALIGN_BYTES, 4);
dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
if (!test_bit(ATH6KL_FW_CAPABILITY_NO_IP_CHECKSUM,
ar->fw_capabilities))
dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
return;
}

View File

@ -802,7 +802,8 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
break;
case WMI_DATA_VI_SVC:
if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT)
if (test_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
ar->fw_capabilities))
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
else
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
@ -814,7 +815,8 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
break;
case WMI_DATA_VO_SVC:
if (ar->hw.flags & ATH6KL_HW_MAP_LP_ENDPOINT)
if (test_bit(ATH6KL_FW_CAPABILITY_MAP_LP_ENDPOINT,
ar->fw_capabilities))
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
else
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
@ -1208,6 +1210,7 @@ static int ath6kl_usb_pm_reset_resume(struct usb_interface *intf)
/* table of devices that work with this driver */
static struct usb_device_id ath6kl_usb_ids[] = {
{USB_DEVICE(0x0cf3, 0x9375)},
{USB_DEVICE(0x0cf3, 0x9374)},
{ /* Terminating entry */ },
};

View File

@ -59,6 +59,55 @@ static const s32 wmi_rate_tbl[][2] = {
{0, 0}
};
static const s32 wmi_rate_tbl_mcs15[][2] = {
/* {W/O SGI, with SGI} */
{1000, 1000},
{2000, 2000},
{5500, 5500},
{11000, 11000},
{6000, 6000},
{9000, 9000},
{12000, 12000},
{18000, 18000},
{24000, 24000},
{36000, 36000},
{48000, 48000},
{54000, 54000},
{6500, 7200}, /* HT 20, MCS 0 */
{13000, 14400},
{19500, 21700},
{26000, 28900},
{39000, 43300},
{52000, 57800},
{58500, 65000},
{65000, 72200},
{13000, 14400}, /* HT 20, MCS 8 */
{26000, 28900},
{39000, 43300},
{52000, 57800},
{78000, 86700},
{104000, 115600},
{117000, 130000},
{130000, 144400}, /* HT 20, MCS 15 */
{13500, 15000}, /*HT 40, MCS 0 */
{27000, 30000},
{40500, 45000},
{54000, 60000},
{81000, 90000},
{108000, 120000},
{121500, 135000},
{135000, 150000},
{27000, 30000}, /*HT 40, MCS 8 */
{54000, 60000},
{81000, 90000},
{108000, 120000},
{162000, 180000},
{216000, 240000},
{243000, 270000},
{270000, 300000}, /*HT 40, MCS 15 */
{0, 0}
};
/* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
static const u8 up_to_ac[] = {
WMM_AC_BE,
@ -2838,7 +2887,8 @@ int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
{
struct ath6kl *ar = wmi->parent_dev;
if (ar->hw.flags & ATH6KL_HW_64BIT_RATES)
if (test_bit(ATH6KL_FW_CAPABILITY_64BIT_RATES,
ar->fw_capabilities))
return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
else
return ath6kl_set_bitrate_mask32(wmi, if_idx, mask);
@ -3279,9 +3329,11 @@ int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2)
NO_SYNC_WMIFLAG);
}
s32 ath6kl_wmi_get_rate(s8 rate_index)
s32 ath6kl_wmi_get_rate(struct wmi *wmi, s8 rate_index)
{
struct ath6kl *ar = wmi->parent_dev;
u8 sgi = 0;
s32 ret;
if (rate_index == RATE_AUTO)
return 0;
@ -3292,10 +3344,20 @@ s32 ath6kl_wmi_get_rate(s8 rate_index)
sgi = 1;
}
if (WARN_ON(rate_index > RATE_MCS_7_40))
rate_index = RATE_MCS_7_40;
if (test_bit(ATH6KL_FW_CAPABILITY_RATETABLE_MCS15,
ar->fw_capabilities)) {
if (WARN_ON(rate_index >= ARRAY_SIZE(wmi_rate_tbl_mcs15)))
return 0;
return wmi_rate_tbl[(u32) rate_index][sgi];
ret = wmi_rate_tbl_mcs15[(u32) rate_index][sgi];
} else {
if (WARN_ON(rate_index >= ARRAY_SIZE(wmi_rate_tbl)))
return 0;
ret = wmi_rate_tbl[(u32) rate_index][sgi];
}
return ret;
}
static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,

View File

@ -2632,7 +2632,7 @@ int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx,
struct ath6kl_htcap *htcap);
int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len);
s32 ath6kl_wmi_get_rate(s8 rate_index);
s32 ath6kl_wmi_get_rate(struct wmi *wmi, s8 rate_index);
int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
__be32 ips0, __be32 ips1);

View File

@ -281,7 +281,7 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen)
| (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
| SM(i->txpower, AR_XmitPower)
| SM(i->txpower, AR_XmitPower0)
| (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
| (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
@ -306,6 +306,10 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
| set11nRateFlags(i->rates, 2)
| set11nRateFlags(i->rates, 3)
| SM(i->rtscts_rate, AR_RTSCTSRate);
ACCESS_ONCE(ads->ds_ctl9) = SM(i->txpower, AR_XmitPower1);
ACCESS_ONCE(ads->ds_ctl10) = SM(i->txpower, AR_XmitPower2);
ACCESS_ONCE(ads->ds_ctl11) = SM(i->txpower, AR_XmitPower3);
}
static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,

View File

@ -101,7 +101,7 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen)
| (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
| SM(i->txpower, AR_XmitPower)
| SM(i->txpower, AR_XmitPower0)
| (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
| (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0)
@ -151,6 +151,10 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
| SM(i->rtscts_rate, AR_RTSCTSRate);
ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding;
ACCESS_ONCE(ads->ctl20) = SM(i->txpower, AR_XmitPower1);
ACCESS_ONCE(ads->ctl21) = SM(i->txpower, AR_XmitPower2);
ACCESS_ONCE(ads->ctl22) = SM(i->txpower, AR_XmitPower3);
}
static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)

View File

@ -182,7 +182,8 @@ struct ath_atx_ac {
struct ath_frame_info {
struct ath_buf *bf;
int framelen;
u16 framelen;
s8 txq;
enum ath9k_key_type keytype;
u8 keyix;
u8 rtscts_rate;

View File

@ -202,7 +202,7 @@ static ssize_t write_file_ani(struct file *file,
if (kstrtoul(buf, 0, &ani))
return -EINVAL;
if (ani < 0 || ani > 1)
if (ani > 1)
return -EINVAL;
common->disable_ani = !ani;

View File

@ -346,8 +346,14 @@ struct ar5416_desc {
#define AR_FrameLen 0x00000fff
#define AR_VirtMoreFrag 0x00001000
#define AR_TxCtlRsvd00 0x0000e000
#define AR_XmitPower 0x003f0000
#define AR_XmitPower_S 16
#define AR_XmitPower0 0x003f0000
#define AR_XmitPower0_S 16
#define AR_XmitPower1 0x3f000000
#define AR_XmitPower1_S 24
#define AR_XmitPower2 0x3f000000
#define AR_XmitPower2_S 24
#define AR_XmitPower3 0x3f000000
#define AR_XmitPower3_S 24
#define AR_RTSEnable 0x00400000
#define AR_VEOL 0x00800000
#define AR_ClrDestMask 0x01000000

View File

@ -313,7 +313,7 @@ static ssize_t write_file_spectral_short_repeat(struct file *file,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val < 0 || val > 1)
if (val > 1)
return -EINVAL;
sc->spec_config.short_repeat = val;
@ -361,7 +361,7 @@ static ssize_t write_file_spectral_count(struct file *file,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val < 0 || val > 255)
if (val > 255)
return -EINVAL;
sc->spec_config.count = val;
@ -409,7 +409,7 @@ static ssize_t write_file_spectral_period(struct file *file,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val < 0 || val > 255)
if (val > 255)
return -EINVAL;
sc->spec_config.period = val;
@ -457,7 +457,7 @@ static ssize_t write_file_spectral_fft_period(struct file *file,
if (kstrtoul(buf, 0, &val))
return -EINVAL;
if (val < 0 || val > 15)
if (val > 15)
return -EINVAL;
sc->spec_config.fft_period = val;

View File

@ -157,15 +157,14 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
struct sk_buff *skb)
{
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int q, hw_queue;
struct ath_frame_info *fi = get_frame_info(skb);
int hw_queue;
int q = fi->txq;
q = skb_get_queue_mapping(skb);
if (txq == sc->tx.uapsdq)
txq = sc->tx.txq_map[q];
if (txq != sc->tx.txq_map[q])
if (q < 0)
return;
txq = sc->tx.txq_map[q];
if (WARN_ON(--txq->pending_frames < 0))
txq->pending_frames = 0;
@ -898,6 +897,15 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
tx_info = IEEE80211_SKB_CB(skb);
tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT;
/*
* No aggregation session is running, but there may be frames
* from a previous session or a failed attempt in the queue.
* Send them out as normal data frames
*/
if (!tid->active)
tx_info->flags &= ~IEEE80211_TX_CTL_AMPDU;
if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) {
bf->bf_state.bf_type = 0;
return bf;
@ -2036,6 +2044,7 @@ static void setup_frame_info(struct ieee80211_hw *hw,
an = (struct ath_node *) sta->drv_priv;
memset(fi, 0, sizeof(*fi));
fi->txq = -1;
if (hw_key)
fi->keyix = hw_key->hw_key_idx;
else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0)
@ -2187,6 +2196,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_sta *sta = txctl->sta;
struct ieee80211_vif *vif = info->control.vif;
struct ath_frame_info *fi = get_frame_info(skb);
struct ath_vif *avp = NULL;
struct ath_softc *sc = hw->priv;
struct ath_txq *txq = txctl->txq;
@ -2216,11 +2226,13 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
hw_queue = (info->hw_queue >= sc->hw->queues - 2) ? q : info->hw_queue;
ath_txq_lock(sc, txq);
if (txq == sc->tx.txq_map[q] &&
++txq->pending_frames > sc->tx.txq_max_pending[q] &&
!txq->stopped) {
ieee80211_stop_queue(sc->hw, hw_queue);
txq->stopped = true;
if (txq == sc->tx.txq_map[q]) {
fi->txq = q;
if (++txq->pending_frames > sc->tx.txq_max_pending[q] &&
!txq->stopped) {
ieee80211_stop_queue(sc->hw, hw_queue);
txq->stopped = true;
}
}
queue = ieee80211_is_data_present(hdr->frame_control);

View File

@ -448,8 +448,10 @@ static ssize_t wil_write_file_rxon(struct file *file, const char __user *buf,
char *kbuf = kmalloc(len + 1, GFP_KERNEL);
if (!kbuf)
return -ENOMEM;
if (copy_from_user(kbuf, buf, len))
if (copy_from_user(kbuf, buf, len)) {
kfree(kbuf);
return -EIO;
}
kbuf[len] = '\0';
rc = kstrtol(kbuf, 0, &channel);
@ -963,6 +965,26 @@ static const struct file_operations fops_sta = {
};
/*----------------*/
static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
struct dentry *dbg)
{
int i;
char name[32];
for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
struct debugfs_blob_wrapper *blob = &wil->blobs[i];
const struct fw_map *map = &fw_mapping[i];
if (!map->name)
continue;
blob->data = (void * __force)wil->csr + HOSTADDR(map->host);
blob->size = map->to - map->from;
snprintf(name, sizeof(name), "blob_%s", map->name);
wil_debugfs_create_ioblob(name, S_IRUGO, dbg, blob);
}
}
int wil6210_debugfs_init(struct wil6210_priv *wil)
{
struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME,
@ -986,6 +1008,8 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)
&wil->secure_pcp);
wil_debugfs_create_ulong("status", S_IRUGO | S_IWUSR, dbg,
&wil->status);
debugfs_create_u32("fw_version", S_IRUGO, dbg, &wil->fw_version);
debugfs_create_x32("hw_version", S_IRUGO, dbg, &wil->hw_version);
wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg,
HOSTADDR(RGF_USER_USER_ICR));
@ -998,6 +1022,9 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)
wil6210_debugfs_create_pseudo_ISR(wil, dbg);
wil6210_debugfs_create_ITR_CNT(wil, dbg);
wil_debugfs_create_iomem_x32("RGF_USER_USAGE_1", S_IRUGO, dbg,
wil->csr +
HOSTADDR(RGF_USER_USAGE_1));
debugfs_create_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr);
debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread);
@ -1010,34 +1037,7 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)
debugfs_create_file("link", S_IRUGO, dbg, wil, &fops_link);
debugfs_create_file("info", S_IRUGO, dbg, wil, &fops_info);
wil->rgf_blob.data = (void * __force)wil->csr + 0;
wil->rgf_blob.size = 0xa000;
wil_debugfs_create_ioblob("blob_rgf", S_IRUGO, dbg, &wil->rgf_blob);
wil->fw_code_blob.data = (void * __force)wil->csr + 0x40000;
wil->fw_code_blob.size = 0x40000;
wil_debugfs_create_ioblob("blob_fw_code", S_IRUGO, dbg,
&wil->fw_code_blob);
wil->fw_data_blob.data = (void * __force)wil->csr + 0x80000;
wil->fw_data_blob.size = 0x8000;
wil_debugfs_create_ioblob("blob_fw_data", S_IRUGO, dbg,
&wil->fw_data_blob);
wil->fw_peri_blob.data = (void * __force)wil->csr + 0x88000;
wil->fw_peri_blob.size = 0x18000;
wil_debugfs_create_ioblob("blob_fw_peri", S_IRUGO, dbg,
&wil->fw_peri_blob);
wil->uc_code_blob.data = (void * __force)wil->csr + 0xa0000;
wil->uc_code_blob.size = 0x10000;
wil_debugfs_create_ioblob("blob_uc_code", S_IRUGO, dbg,
&wil->uc_code_blob);
wil->uc_data_blob.data = (void * __force)wil->csr + 0xb0000;
wil->uc_data_blob.size = 0x4000;
wil_debugfs_create_ioblob("blob_uc_data", S_IRUGO, dbg,
&wil->uc_data_blob);
wil6210_debugfs_init_blobs(wil, dbg);
return 0;
}

View File

@ -314,8 +314,9 @@ static void wil_target_reset(struct wil6210_priv *wil)
int delay = 0;
u32 hw_state;
u32 rev_id;
bool is_sparrow = (wil->board->board == WIL_BOARD_SPARROW);
wil_dbg_misc(wil, "Resetting...\n");
wil_dbg_misc(wil, "Resetting \"%s\"...\n", wil->board->name);
/* register read */
#define R(a) ioread32(wil->csr + HOSTADDR(a))
@ -328,35 +329,59 @@ static void wil_target_reset(struct wil6210_priv *wil)
wil->hw_version = R(RGF_USER_FW_REV_ID);
rev_id = wil->hw_version & 0xff;
/* Clear MAC link up */
S(RGF_HP_CTRL, BIT(15));
/* hpal_perst_from_pad_src_n_mask */
S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6));
/* car_perst_rst_src_n_mask */
S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7));
wmb(); /* order is important here */
if (is_sparrow) {
W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f);
wmb(); /* order is important here */
}
W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */
W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */
wmb(); /* order is important here */
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, is_sparrow ? 0x000000B0 : 0x00000170);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00);
wmb(); /* order is important here */
if (is_sparrow) {
W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x0);
wmb(); /* order is important here */
}
W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
wmb(); /* order is important here */
W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001);
if (rev_id == 1) {
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080);
} else {
W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8));
if (is_sparrow) {
W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000003);
/* reset A2 PCIE AHB */
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000);
} else {
W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001);
if (rev_id == 1) {
/* reset A1 BOTH PCIE AHB & PCIE RGF */
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080);
} else {
W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8));
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000);
}
}
/* TODO: check order here!!! Erez code is different */
W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
wmb(); /* order is important here */
@ -371,7 +396,8 @@ static void wil_target_reset(struct wil6210_priv *wil)
}
} while (hw_state != HW_MACHINE_BOOT_DONE);
if (rev_id == 2)
/* TODO: Erez check rev_id != 1 */
if (!is_sparrow && (rev_id != 1))
W(RGF_PCIE_LOS_COUNTER_CTL, BIT(8));
C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);

View File

@ -122,10 +122,12 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct wil6210_priv *wil;
struct device *dev = &pdev->dev;
void __iomem *csr;
struct wil_board *board = (struct wil_board *)id->driver_data;
int rc;
/* check HW */
dev_info(&pdev->dev, WIL_NAME " device found [%04x:%04x] (rev %x)\n",
dev_info(&pdev->dev, WIL_NAME
" \"%s\" device found [%04x:%04x] (rev %x)\n", board->name,
(int)pdev->vendor, (int)pdev->device, (int)pdev->revision);
if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) {
@ -175,6 +177,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_drvdata(pdev, wil);
wil->pdev = pdev;
wil->board = board;
wil6210_clear_irq(wil);
/* FW should raise IRQ when ready */
@ -225,8 +228,21 @@ static void wil_pcie_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
}
static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = {
{ PCI_DEVICE(0x1ae9, 0x0301) },
static const struct wil_board wil_board_marlon = {
.board = WIL_BOARD_MARLON,
.name = "marlon",
};
static const struct wil_board wil_board_sparrow = {
.board = WIL_BOARD_SPARROW,
.name = "sparrow",
};
static const struct pci_device_id wil6210_pcie_ids[] = {
{ PCI_DEVICE(0x1ae9, 0x0301),
.driver_data = (kernel_ulong_t)&wil_board_marlon },
{ PCI_DEVICE(0x1ae9, 0x0310),
.driver_data = (kernel_ulong_t)&wil_board_sparrow },
{ /* end: all zeroes */ },
};
MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids);

View File

@ -1108,8 +1108,10 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
while (vring->swtail != new_swtail) {
struct vring_tx_desc dd, *d = &dd;
u16 dmalen;
struct wil_ctx *ctx = &vring->ctx[vring->swtail];
struct sk_buff *skb = ctx->skb;
struct sk_buff *skb;
ctx = &vring->ctx[vring->swtail];
skb = ctx->skb;
_d = &vring->va[vring->swtail].tx;
*d = *_d;

View File

@ -24,6 +24,13 @@
#define WIL_NAME "wil6210"
struct wil_board {
int board;
#define WIL_BOARD_MARLON (1)
#define WIL_BOARD_SPARROW (2)
const char * const name;
};
/**
* extract bits [@b0:@b1] (inclusive) from the value @x
* it should be @b0 <= @b1, or result is incorrect
@ -78,6 +85,7 @@ struct RGF_ICR {
} __packed;
/* registers - FW addresses */
#define RGF_USER_USAGE_1 (0x880004)
#define RGF_USER_HW_MACHINE_STATE (0x8801dc)
#define HW_MACHINE_BOOT_DONE (0x3fffffd)
#define RGF_USER_USER_CPU_0 (0x8801e0)
@ -93,6 +101,7 @@ struct RGF_ICR {
#define RGF_USER_CLKS_CTL_SW_RST_MASK_0 (0x880b14)
#define RGF_USER_USER_ICR (0x880b4c) /* struct RGF_ICR */
#define BIT_USER_USER_ICR_SW_INT_2 BIT(18)
#define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0 (0x880c18)
#define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */
#define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0)
@ -121,6 +130,7 @@ struct RGF_ICR {
#define BIT_DMA_PSEUDO_CAUSE_TX BIT(1)
#define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2)
#define RGF_HP_CTRL (0x88265c)
#define RGF_PCIE_LOS_COUNTER_CTL (0x882dc4)
/* popular locations */
@ -135,6 +145,14 @@ struct RGF_ICR {
#define ISR_MISC_FW_ERROR BIT_DMA_EP_MISC_ICR_FW_INT(3)
/* Hardware definitions end */
struct fw_map {
u32 from; /* linker address - from, inclusive */
u32 to; /* linker address - to, exclusive */
u32 host; /* PCI/Host address - BAR0 + 0x880000 */
const char *name; /* for debugfs */
};
/* array size should be in sync with actual definition in the wmi.c */
extern const struct fw_map fw_mapping[7];
/**
* mk_cidxtid - construct @cidxtid field
@ -365,6 +383,7 @@ struct wil6210_priv {
ulong status;
u32 fw_version;
u32 hw_version;
struct wil_board *board;
u8 n_mids; /* number of additional MIDs as reported by FW */
int recovery_count; /* num of FW recovery attempts in a short time */
unsigned long last_fw_recovery; /* jiffies of last fw recovery */
@ -415,12 +434,7 @@ struct wil6210_priv {
atomic_t isr_count_rx, isr_count_tx;
/* debugfs */
struct dentry *debug;
struct debugfs_blob_wrapper fw_code_blob;
struct debugfs_blob_wrapper fw_data_blob;
struct debugfs_blob_wrapper fw_peri_blob;
struct debugfs_blob_wrapper uc_code_blob;
struct debugfs_blob_wrapper uc_data_blob;
struct debugfs_blob_wrapper rgf_blob;
struct debugfs_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)];
};
#define wil_to_wiphy(i) (i->wdev->wiphy)

View File

@ -65,18 +65,17 @@
/**
* @fw_mapping provides memory remapping table
*
* array size should be in sync with the declaration in the wil6210.h
*/
static const struct {
u32 from; /* linker address - from, inclusive */
u32 to; /* linker address - to, exclusive */
u32 host; /* PCI/Host address - BAR0 + 0x880000 */
} fw_mapping[] = {
{0x000000, 0x040000, 0x8c0000}, /* FW code RAM 256k */
{0x800000, 0x808000, 0x900000}, /* FW data RAM 32k */
{0x840000, 0x860000, 0x908000}, /* peripheral data RAM 128k/96k used */
{0x880000, 0x88a000, 0x880000}, /* various RGF */
{0x88b000, 0x88c000, 0x88b000}, /* Pcie_ext_rgf */
{0x8c0000, 0x949000, 0x8c0000}, /* trivial mapping for upper area */
const struct fw_map fw_mapping[] = {
{0x000000, 0x040000, 0x8c0000, "fw_code"}, /* FW code RAM 256k */
{0x800000, 0x808000, 0x900000, "fw_data"}, /* FW data RAM 32k */
{0x840000, 0x860000, 0x908000, "fw_peri"}, /* periph. data RAM 128k */
{0x880000, 0x88a000, 0x880000, "rgf"}, /* various RGF 40k */
{0x88a000, 0x88b000, 0x88a000, "AGC_tbl"}, /* AGC table 4k */
{0x88b000, 0x88c000, 0x88b000, "rgf_ext"}, /* Pcie_ext_rgf 4k */
{0x8c0000, 0x949000, 0x8c0000, "upper"}, /* upper area 548k */
/*
* 920000..930000 ucode code RAM
* 930000..932000 ucode data RAM

View File

@ -210,6 +210,9 @@ static struct ieee80211_channel b43_2ghz_chantable[] = {
CHAN2G(13, 2472, 0),
CHAN2G(14, 2484, 0),
};
/* No support for the last 3 channels (12, 13, 14) */
#define b43_2ghz_chantable_limited_size 11
#undef CHAN2G
#define CHAN4G(_channel, _flags) { \
@ -287,6 +290,14 @@ static struct ieee80211_channel b43_5ghz_nphy_chantable[] = {
CHAN5G(182, 0),
};
static struct ieee80211_channel b43_5ghz_nphy_chantable_limited[] = {
CHAN5G(36, 0), CHAN5G(40, 0),
CHAN5G(44, 0), CHAN5G(48, 0),
CHAN5G(149, 0), CHAN5G(153, 0),
CHAN5G(157, 0), CHAN5G(161, 0),
CHAN5G(165, 0),
};
static struct ieee80211_channel b43_5ghz_aphy_chantable[] = {
CHAN5G(34, 0), CHAN5G(36, 0),
CHAN5G(38, 0), CHAN5G(40, 0),
@ -319,6 +330,14 @@ static struct ieee80211_supported_band b43_band_5GHz_nphy = {
.n_bitrates = b43_a_ratetable_size,
};
static struct ieee80211_supported_band b43_band_5GHz_nphy_limited = {
.band = IEEE80211_BAND_5GHZ,
.channels = b43_5ghz_nphy_chantable_limited,
.n_channels = ARRAY_SIZE(b43_5ghz_nphy_chantable_limited),
.bitrates = b43_a_ratetable,
.n_bitrates = b43_a_ratetable_size,
};
static struct ieee80211_supported_band b43_band_5GHz_aphy = {
.band = IEEE80211_BAND_5GHZ,
.channels = b43_5ghz_aphy_chantable,
@ -335,6 +354,14 @@ static struct ieee80211_supported_band b43_band_2GHz = {
.n_bitrates = b43_g_ratetable_size,
};
static struct ieee80211_supported_band b43_band_2ghz_limited = {
.band = IEEE80211_BAND_2GHZ,
.channels = b43_2ghz_chantable,
.n_channels = b43_2ghz_chantable_limited_size,
.bitrates = b43_g_ratetable,
.n_bitrates = b43_g_ratetable_size,
};
static void b43_wireless_core_exit(struct b43_wldev *dev);
static int b43_wireless_core_init(struct b43_wldev *dev);
static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev);
@ -2953,6 +2980,45 @@ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on)
}
}
/* brcms_b_switch_macfreq */
void b43_mac_switch_freq(struct b43_wldev *dev, u8 spurmode)
{
u16 chip_id = dev->dev->chip_id;
if (chip_id == BCMA_CHIP_ID_BCM43217 ||
chip_id == BCMA_CHIP_ID_BCM43222 ||
chip_id == BCMA_CHIP_ID_BCM43224 ||
chip_id == BCMA_CHIP_ID_BCM43225 ||
chip_id == BCMA_CHIP_ID_BCM43227 ||
chip_id == BCMA_CHIP_ID_BCM43228) {
switch (spurmode) {
case 2: /* 126 Mhz */
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x2082);
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
break;
case 1: /* 123 Mhz */
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x5341);
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
break;
default: /* 120 Mhz */
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x8889);
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
break;
}
} else if (dev->phy.type == B43_PHYTYPE_LCN) {
switch (spurmode) {
case 1: /* 82 Mhz */
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x7CE0);
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
break;
default: /* 80 Mhz */
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0xCCCD);
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
break;
}
}
}
static void b43_adjust_opmode(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
@ -4335,8 +4401,9 @@ static int b43_phy_versioning(struct b43_wldev *dev)
u8 phy_type;
u8 phy_rev;
u16 radio_manuf;
u16 radio_ver;
u16 radio_id;
u16 radio_rev;
u8 radio_ver;
int unsupported = 0;
/* Get PHY versioning */
@ -4360,7 +4427,7 @@ static int b43_phy_versioning(struct b43_wldev *dev)
#endif
#ifdef CONFIG_B43_PHY_N
case B43_PHYTYPE_N:
if (phy_rev > 9)
if (phy_rev >= 19)
unsupported = 1;
break;
#endif
@ -4402,7 +4469,9 @@ static int b43_phy_versioning(struct b43_wldev *dev)
radio_rev = b43_read16(dev, B43_MMIO_RADIO24_DATA);
b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 1);
radio_ver = b43_read16(dev, B43_MMIO_RADIO24_DATA);
radio_id = b43_read16(dev, B43_MMIO_RADIO24_DATA);
radio_ver = 0; /* Is there version somewhere? */
} else if (core_rev >= 24) {
u16 radio24[3];
@ -4411,12 +4480,10 @@ static int b43_phy_versioning(struct b43_wldev *dev)
radio24[tmp] = b43_read16(dev, B43_MMIO_RADIO24_DATA);
}
/* Broadcom uses "id" for our "ver" and has separated "ver" */
/* radio_ver = (radio24[0] & 0xF0) >> 4; */
radio_manuf = 0x17F;
radio_ver = (radio24[2] << 8) | radio24[1];
radio_id = (radio24[2] << 8) | radio24[1];
radio_rev = (radio24[0] & 0xF);
radio_ver = (radio24[0] & 0xF0) >> 4;
} else {
if (dev->dev->chip_id == 0x4317) {
if (dev->dev->chip_rev == 0)
@ -4435,15 +4502,16 @@ static int b43_phy_versioning(struct b43_wldev *dev)
<< 16;
}
radio_manuf = (tmp & 0x00000FFF);
radio_ver = (tmp & 0x0FFFF000) >> 12;
radio_id = (tmp & 0x0FFFF000) >> 12;
radio_rev = (tmp & 0xF0000000) >> 28;
radio_ver = 0; /* Probably not available on old hw */
}
if (radio_manuf != 0x17F /* Broadcom */)
unsupported = 1;
switch (phy_type) {
case B43_PHYTYPE_A:
if (radio_ver != 0x2060)
if (radio_id != 0x2060)
unsupported = 1;
if (radio_rev != 1)
unsupported = 1;
@ -4451,43 +4519,49 @@ static int b43_phy_versioning(struct b43_wldev *dev)
unsupported = 1;
break;
case B43_PHYTYPE_B:
if ((radio_ver & 0xFFF0) != 0x2050)
if ((radio_id & 0xFFF0) != 0x2050)
unsupported = 1;
break;
case B43_PHYTYPE_G:
if (radio_ver != 0x2050)
if (radio_id != 0x2050)
unsupported = 1;
break;
case B43_PHYTYPE_N:
if (radio_ver != 0x2055 && radio_ver != 0x2056)
if (radio_id != 0x2055 && radio_id != 0x2056 &&
radio_id != 0x2057)
unsupported = 1;
if (radio_id == 0x2057 &&
!(radio_rev == 9 || radio_rev == 14))
unsupported = 1;
break;
case B43_PHYTYPE_LP:
if (radio_ver != 0x2062 && radio_ver != 0x2063)
if (radio_id != 0x2062 && radio_id != 0x2063)
unsupported = 1;
break;
case B43_PHYTYPE_HT:
if (radio_ver != 0x2059)
if (radio_id != 0x2059)
unsupported = 1;
break;
case B43_PHYTYPE_LCN:
if (radio_ver != 0x2064)
if (radio_id != 0x2064)
unsupported = 1;
break;
default:
B43_WARN_ON(1);
}
if (unsupported) {
b43err(dev->wl, "FOUND UNSUPPORTED RADIO "
"(Manuf 0x%X, Version 0x%X, Revision %u)\n",
radio_manuf, radio_ver, radio_rev);
b43err(dev->wl,
"FOUND UNSUPPORTED RADIO (Manuf 0x%X, ID 0x%X, Revision %u, Version %u)\n",
radio_manuf, radio_id, radio_rev, radio_ver);
return -EOPNOTSUPP;
}
b43dbg(dev->wl, "Found Radio: Manuf 0x%X, Version 0x%X, Revision %u\n",
radio_manuf, radio_ver, radio_rev);
b43info(dev->wl,
"Found Radio: Manuf 0x%X, ID 0x%X, Revision %u, Version %u\n",
radio_manuf, radio_id, radio_rev, radio_ver);
/* FIXME: b43 treats "id" as "ver" and ignores the real "ver" */
phy->radio_manuf = radio_manuf;
phy->radio_ver = radio_ver;
phy->radio_ver = radio_id;
phy->radio_rev = radio_rev;
phy->analog = analog_type;
@ -5095,12 +5169,24 @@ static int b43_setup_bands(struct b43_wldev *dev,
bool have_2ghz_phy, bool have_5ghz_phy)
{
struct ieee80211_hw *hw = dev->wl->hw;
struct b43_phy *phy = &dev->phy;
bool limited_2g;
bool limited_5g;
/* We don't support all 2 GHz channels on some devices */
limited_2g = phy->radio_ver == 0x2057 &&
(phy->radio_rev == 9 || phy->radio_rev == 14);
limited_5g = phy->radio_ver == 0x2057 &&
phy->radio_rev == 9;
if (have_2ghz_phy)
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &b43_band_2GHz;
hw->wiphy->bands[IEEE80211_BAND_2GHZ] = limited_2g ?
&b43_band_2ghz_limited : &b43_band_2GHz;
if (dev->phy.type == B43_PHYTYPE_N) {
if (have_5ghz_phy)
hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_nphy;
hw->wiphy->bands[IEEE80211_BAND_5GHZ] = limited_5g ?
&b43_band_5GHz_nphy_limited :
&b43_band_5GHz_nphy;
} else {
if (have_5ghz_phy)
hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy;
@ -5248,14 +5334,15 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
b43_supported_bands(dev, &have_2ghz_phy, &have_5ghz_phy);
/* We don't support 5 GHz on some PHYs yet */
switch (dev->phy.type) {
case B43_PHYTYPE_A:
case B43_PHYTYPE_G:
case B43_PHYTYPE_N:
case B43_PHYTYPE_LP:
case B43_PHYTYPE_HT:
b43warn(wl, "5 GHz band is unsupported on this PHY\n");
have_5ghz_phy = false;
if (have_5ghz_phy) {
switch (dev->phy.type) {
case B43_PHYTYPE_A:
case B43_PHYTYPE_G:
case B43_PHYTYPE_LP:
case B43_PHYTYPE_HT:
b43warn(wl, "5 GHz band is unsupported on this PHY\n");
have_5ghz_phy = false;
}
}
if (!have_2ghz_phy && !have_5ghz_phy) {

View File

@ -99,6 +99,7 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags);
void b43_mac_suspend(struct b43_wldev *dev);
void b43_mac_enable(struct b43_wldev *dev);
void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on);
void b43_mac_switch_freq(struct b43_wldev *dev, u8 spurmode);
struct b43_request_fw_context;

View File

@ -54,39 +54,6 @@ enum lcn_sense_type {
B43_SENSE_VBAT,
};
/* In theory it's PHY common function, move if needed */
/* brcms_b_switch_macfreq */
static void b43_phy_switch_macfreq(struct b43_wldev *dev, u8 spurmode)
{
if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) {
switch (spurmode) {
case 2: /* 126 Mhz */
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x2082);
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
break;
case 1: /* 123 Mhz */
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x5341);
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
break;
default: /* 120 Mhz */
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x8889);
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
break;
}
} else if (dev->phy.type == B43_PHYTYPE_LCN) {
switch (spurmode) {
case 1: /* 82 Mhz */
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0x7CE0);
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
break;
default: /* 80 Mhz */
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW, 0xCCCD);
b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0xC);
break;
}
}
}
/**************************************************
* Radio 2064.
**************************************************/
@ -609,7 +576,7 @@ static void b43_phy_lcn_txrx_spur_avoidance_mode(struct b43_wldev *dev,
b43_phy_write(dev, 0x93b, ((0 << 13) + 23));
b43_phy_write(dev, 0x93c, ((0 << 13) + 1989));
}
b43_phy_switch_macfreq(dev, enable);
b43_mac_switch_freq(dev, enable);
}
/**************************************************

File diff suppressed because it is too large Load Diff

View File

@ -366,11 +366,13 @@
#define B43_NPHY_TXF_40CO_B1S0 B43_PHY_N(0x0E5) /* TX filter 40 coeff B1 stage 0 */
#define B43_NPHY_TXF_40CO_B32S1 B43_PHY_N(0x0E6) /* TX filter 40 coeff B32 stage 1 */
#define B43_NPHY_TXF_40CO_B1S1 B43_PHY_N(0x0E7) /* TX filter 40 coeff B1 stage 1 */
#define B43_NPHY_REV3_RFCTL_OVER0 B43_PHY_N(0x0E7)
#define B43_NPHY_TXF_40CO_B32S2 B43_PHY_N(0x0E8) /* TX filter 40 coeff B32 stage 2 */
#define B43_NPHY_TXF_40CO_B1S2 B43_PHY_N(0x0E9) /* TX filter 40 coeff B1 stage 2 */
#define B43_NPHY_BIST_STAT2 B43_PHY_N(0x0EA) /* BIST status 2 */
#define B43_NPHY_BIST_STAT3 B43_PHY_N(0x0EB) /* BIST status 3 */
#define B43_NPHY_RFCTL_OVER B43_PHY_N(0x0EC) /* RF control override */
#define B43_NPHY_REV3_RFCTL_OVER1 B43_PHY_N(0x0EC)
#define B43_NPHY_MIMOCFG B43_PHY_N(0x0ED) /* MIMO config */
#define B43_NPHY_MIMOCFG_GFMIX 0x0004 /* Greenfield or mixed mode */
#define B43_NPHY_MIMOCFG_AUTO 0x0100 /* Greenfield/mixed mode auto */
@ -857,7 +859,18 @@
#define B43_NPHY_REV3_C2_CLIP2_GAIN_A B43_PHY_N(0x2AF)
#define B43_NPHY_REV3_C2_CLIP2_GAIN_B B43_PHY_N(0x2B0)
#define B43_NPHY_REV7_RF_CTL_MISC_REG3 B43_PHY_N(0x340)
#define B43_NPHY_REV7_RF_CTL_MISC_REG4 B43_PHY_N(0x341)
#define B43_NPHY_REV7_RF_CTL_OVER3 B43_PHY_N(0x342)
#define B43_NPHY_REV7_RF_CTL_OVER4 B43_PHY_N(0x343)
#define B43_NPHY_REV7_RF_CTL_MISC_REG5 B43_PHY_N(0x344)
#define B43_NPHY_REV7_RF_CTL_MISC_REG6 B43_PHY_N(0x345)
#define B43_NPHY_REV7_RF_CTL_OVER5 B43_PHY_N(0x346)
#define B43_NPHY_REV7_RF_CTL_OVER6 B43_PHY_N(0x347)
#define B43_PHY_B_BBCFG B43_PHY_N_BMODE(0x001) /* BB config */
#define B43_PHY_B_BBCFG_RSTCCA 0x4000 /* Reset CCA */
#define B43_PHY_B_BBCFG_RSTRX 0x8000 /* Reset RX */
#define B43_PHY_B_TEST B43_PHY_N_BMODE(0x00A)
struct b43_wldev;
@ -935,6 +948,8 @@ struct b43_phy_n {
bool gain_boost;
bool elna_gain_config;
bool band5g_pwrgain;
bool use_int_tx_iq_lo_cal;
bool lpf_bw_overrode_for_sample_play;
u8 mphase_cal_phase_id;
u16 mphase_txcal_cmdidx;

View File

@ -105,6 +105,27 @@ static u16 r2057_rev8_init[][2] = {
};
*/
/* Extracted from MMIO dump of 6.30.223.141 */
static u16 r2057_rev9_init[][2] = {
{ 0x27, 0x1f }, { 0x28, 0x0a }, { 0x29, 0x2f }, { 0x42, 0x1f },
{ 0x48, 0x3f }, { 0x5c, 0x41 }, { 0x63, 0x14 }, { 0x64, 0x12 },
{ 0x66, 0xff }, { 0x74, 0xa3 }, { 0x7b, 0x14 }, { 0x7c, 0x14 },
{ 0x7d, 0xee }, { 0x86, 0xc0 }, { 0xc4, 0x10 }, { 0xc9, 0x01 },
{ 0xe1, 0x41 }, { 0xe8, 0x14 }, { 0xe9, 0x12 }, { 0xeb, 0xff },
{ 0xf5, 0x0a }, { 0xf8, 0x09 }, { 0xf9, 0xa3 }, { 0x100, 0x14 },
{ 0x101, 0x10 }, { 0x102, 0xee }, { 0x10b, 0xc0 }, { 0x149, 0x10 },
{ 0x14e, 0x01 }, { 0x1b7, 0x05 }, { 0x1c2, 0xa0 },
};
/* Extracted from MMIO dump of 6.30.223.248 */
static u16 r2057_rev14_init[][2] = {
{ 0x011, 0xfc }, { 0x030, 0x24 }, { 0x040, 0x1c }, { 0x082, 0x08 },
{ 0x0b4, 0x44 }, { 0x0c8, 0x01 }, { 0x0c9, 0x01 }, { 0x107, 0x08 },
{ 0x14d, 0x01 }, { 0x14e, 0x01 }, { 0x1af, 0x40 }, { 0x1b0, 0x40 },
{ 0x1cc, 0x01 }, { 0x1cf, 0x10 }, { 0x1d0, 0x0f }, { 0x1d3, 0x10 },
{ 0x1d4, 0x0f },
};
#define RADIOREGS7(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
r20, r21, r22, r23, r24, r25, r26, r27) \
@ -137,6 +158,27 @@ static u16 r2057_rev8_init[][2] = {
.radio_lna2g_tune_core1 = r26, \
.radio_lna5g_tune_core1 = r27
#define RADIOREGS7_2G(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
r10, r11, r12, r13, r14, r15, r16, r17) \
.radio_vcocal_countval0 = r00, \
.radio_vcocal_countval1 = r01, \
.radio_rfpll_refmaster_sparextalsize = r02, \
.radio_rfpll_loopfilter_r1 = r03, \
.radio_rfpll_loopfilter_c2 = r04, \
.radio_rfpll_loopfilter_c1 = r05, \
.radio_cp_kpd_idac = r06, \
.radio_rfpll_mmd0 = r07, \
.radio_rfpll_mmd1 = r08, \
.radio_vcobuf_tune = r09, \
.radio_logen_mx2g_tune = r10, \
.radio_logen_indbuf2g_tune = r11, \
.radio_txmix2g_tune_boost_pu_core0 = r12, \
.radio_pad2g_tune_pus_core0 = r13, \
.radio_lna2g_tune_core0 = r14, \
.radio_txmix2g_tune_boost_pu_core1 = r15, \
.radio_pad2g_tune_pus_core1 = r16, \
.radio_lna2g_tune_core1 = r17
#define PHYREGS(r0, r1, r2, r3, r4, r5) \
.phy_regs.phy_bw1a = r0, \
.phy_regs.phy_bw2 = r1, \
@ -145,6 +187,353 @@ static u16 r2057_rev8_init[][2] = {
.phy_regs.phy_bw5 = r4, \
.phy_regs.phy_bw6 = r5
/* Copied from brcmsmac (5.75.11): chan_info_nphyrev8_2057_rev5 */
static const struct b43_nphy_chantabent_rev7_2g b43_nphy_chantab_phy_rev8_radio_rev5[] = {
{
.freq = 2412,
RADIOREGS7_2G(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61,
0x03, 0xff),
PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
},
{
.freq = 2417,
RADIOREGS7_2G(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61,
0x03, 0xff),
PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
},
{
.freq = 2422,
RADIOREGS7_2G(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
0x09, 0x0d, 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61,
0x03, 0xef),
PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
},
{
.freq = 2427,
RADIOREGS7_2G(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
0x09, 0x0c, 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61,
0x03, 0xdf),
PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
},
{
.freq = 2432,
RADIOREGS7_2G(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
0x09, 0x0c, 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61,
0x03, 0xcf),
PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
},
{
.freq = 2437,
RADIOREGS7_2G(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
0x09, 0x0c, 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61,
0x03, 0xbf),
PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
},
{
.freq = 2442,
RADIOREGS7_2G(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61,
0x03, 0xaf),
PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
},
{
.freq = 2447,
RADIOREGS7_2G(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61,
0x03, 0x9f),
PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
},
{
.freq = 2452,
RADIOREGS7_2G(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
0x09, 0x0b, 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61,
0x03, 0x8f),
PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
},
{
.freq = 2457,
RADIOREGS7_2G(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
0x09, 0x0b, 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61,
0x03, 0x7f),
PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
},
{
.freq = 2462,
RADIOREGS7_2G(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
0x09, 0x0b, 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61,
0x03, 0x6f),
PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
},
{
.freq = 2467,
RADIOREGS7_2G(0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3,
0x09, 0x0b, 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61,
0x03, 0x5f),
PHYREGS(0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b),
},
{
.freq = 2472,
RADIOREGS7_2G(0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8,
0x09, 0x0a, 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61,
0x03, 0x4f),
PHYREGS(0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429),
},
{
.freq = 2484,
RADIOREGS7_2G(0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4,
0x09, 0x0a, 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61,
0x03, 0x3f),
PHYREGS(0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424),
}
};
/* Extracted from MMIO dump of 6.30.223.248 */
static const struct b43_nphy_chantabent_rev7_2g b43_nphy_chantab_phy_rev17_radio_rev14[] = {
{
.freq = 2412,
RADIOREGS7_2G(0x48, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x6c,
0x09, 0x0d, 0x09, 0x03, 0x21, 0x53, 0xff, 0x21,
0x53, 0xff),
PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
},
{
.freq = 2417,
RADIOREGS7_2G(0x4b, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x71,
0x09, 0x0d, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
0x53, 0xff),
PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
},
{
.freq = 2422,
RADIOREGS7_2G(0x4e, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x76,
0x09, 0x0d, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
0x53, 0xff),
PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
},
{
.freq = 2427,
RADIOREGS7_2G(0x52, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x7b,
0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
0x53, 0xff),
PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
},
{
.freq = 2432,
RADIOREGS7_2G(0x55, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x80,
0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
0x53, 0xff),
PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
},
{
.freq = 2437,
RADIOREGS7_2G(0x58, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x85,
0x09, 0x0c, 0x08, 0x03, 0x21, 0x53, 0xff, 0x21,
0x53, 0xff),
PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
},
{
.freq = 2442,
RADIOREGS7_2G(0x5c, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x8a,
0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
0x43, 0xff),
PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
},
{
.freq = 2447,
RADIOREGS7_2G(0x5f, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x8f,
0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
0x43, 0xff),
PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
},
{
.freq = 2452,
RADIOREGS7_2G(0x62, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x94,
0x09, 0x0c, 0x08, 0x03, 0x21, 0x43, 0xff, 0x21,
0x43, 0xff),
PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
},
{
.freq = 2457,
RADIOREGS7_2G(0x66, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x99,
0x09, 0x0b, 0x07, 0x03, 0x21, 0x43, 0xff, 0x21,
0x43, 0xff),
PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
},
{
.freq = 2462,
RADIOREGS7_2G(0x69, 0x16, 0x30, 0x2b, 0x1f, 0x1f, 0x30, 0x9e,
0x09, 0x0b, 0x07, 0x03, 0x01, 0x43, 0xff, 0x01,
0x43, 0xff),
PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
},
};
/* Extracted from MMIO dump of 6.30.223.141 */
static const struct b43_nphy_chantabent_rev7 b43_nphy_chantab_phy_rev16_radio_rev9[] = {
{
.freq = 2412,
RADIOREGS7(0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c,
0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443),
},
{
.freq = 2417,
RADIOREGS7(0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71,
0x09, 0x0f, 0x0a, 0x00, 0x0a, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441),
},
{
.freq = 2422,
RADIOREGS7(0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76,
0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f),
},
{
.freq = 2427,
RADIOREGS7(0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b,
0x09, 0x0f, 0x09, 0x00, 0x09, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d),
},
{
.freq = 2432,
RADIOREGS7(0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80,
0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a),
},
{
.freq = 2437,
RADIOREGS7(0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85,
0x09, 0x0f, 0x08, 0x00, 0x08, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438),
},
{
.freq = 2442,
RADIOREGS7(0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a,
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436),
},
{
.freq = 2447,
RADIOREGS7(0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f,
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434),
},
{
.freq = 2452,
RADIOREGS7(0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94,
0x09, 0x0f, 0x07, 0x00, 0x07, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431),
},
{
.freq = 2457,
RADIOREGS7(0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99,
0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f),
},
{
.freq = 2462,
RADIOREGS7(0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e,
0x09, 0x0f, 0x06, 0x00, 0x06, 0x00, 0x41, 0x63,
0x00, 0x00, 0x00, 0xf0, 0x00, 0x41, 0x63, 0x00,
0x00, 0x00, 0xf0, 0x00),
PHYREGS(0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d),
},
{
.freq = 5180,
RADIOREGS7(0xbe, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x06,
0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
0x9f, 0x2f, 0xa3, 0x00, 0xfc, 0x00, 0x00, 0x4f,
0x3a, 0x83, 0x00, 0xfc),
PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
},
{
.freq = 5200,
RADIOREGS7(0xc5, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x08,
0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
0x7f, 0x2f, 0x83, 0x00, 0xf8, 0x00, 0x00, 0x4c,
0x4a, 0x83, 0x00, 0xf8),
PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
},
{
.freq = 5220,
RADIOREGS7(0xcc, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0a,
0x02, 0x0e, 0x00, 0x0e, 0x00, 0x9e, 0x00, 0x00,
0x6d, 0x3d, 0x83, 0x00, 0xf8, 0x00, 0x00, 0x2d,
0x2a, 0x73, 0x00, 0xf8),
PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
},
{
.freq = 5240,
RADIOREGS7(0xd2, 0x16, 0x10, 0x1f, 0x08, 0x08, 0x3f, 0x0c,
0x02, 0x0d, 0x00, 0x0d, 0x00, 0x8d, 0x00, 0x00,
0x4d, 0x1c, 0x73, 0x00, 0xf8, 0x00, 0x00, 0x4d,
0x2b, 0x73, 0x00, 0xf8),
PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
},
{
.freq = 5745,
RADIOREGS7(0x7b, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x7d,
0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
0x08, 0x03, 0x03, 0x00, 0x30, 0x00, 0x00, 0x06,
0x02, 0x03, 0x00, 0x30),
PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
},
{
.freq = 5765,
RADIOREGS7(0x81, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x81,
0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
0x06, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05,
0x02, 0x03, 0x00, 0x00),
PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
},
{
.freq = 5785,
RADIOREGS7(0x88, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x85,
0x04, 0x08, 0x00, 0x06, 0x00, 0x15, 0x00, 0x00,
0x08, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x05,
0x21, 0x03, 0x00, 0x00),
PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
},
{
.freq = 5805,
RADIOREGS7(0x8f, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x89,
0x04, 0x07, 0x00, 0x06, 0x00, 0x04, 0x00, 0x00,
0x06, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
0x00, 0x03, 0x00, 0x00),
PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
},
{
.freq = 5825,
RADIOREGS7(0x95, 0x17, 0x20, 0x1f, 0x08, 0x08, 0x3f, 0x8d,
0x04, 0x07, 0x00, 0x05, 0x00, 0x03, 0x00, 0x00,
0x05, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03,
0x00, 0x03, 0x00, 0x00),
PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
},
};
void r2057_upload_inittabs(struct b43_wldev *dev)
{
struct b43_phy *phy = &dev->phy;
@ -171,6 +560,18 @@ void r2057_upload_inittabs(struct b43_wldev *dev)
size = ARRAY_SIZE(r2057_rev5a_init);
}
break;
case 16:
if (phy->radio_rev == 9) {
table = r2057_rev9_init[0];
size = ARRAY_SIZE(r2057_rev9_init);
}
break;
case 17:
if (phy->radio_rev == 14) {
table = r2057_rev14_init[0];
size = ARRAY_SIZE(r2057_rev14_init);
}
break;
}
B43_WARN_ON(!table);
@ -193,8 +594,25 @@ void r2057_get_chantabent_rev7(struct b43_wldev *dev, u16 freq,
*tabent_r7 = NULL;
*tabent_r7_2g = NULL;
/* TODO */
switch (phy->rev) {
case 8:
if (phy->radio_rev == 5) {
e_r7_2g = b43_nphy_chantab_phy_rev8_radio_rev5;
len = ARRAY_SIZE(b43_nphy_chantab_phy_rev8_radio_rev5);
}
break;
case 16:
if (phy->radio_rev == 9) {
e_r7 = b43_nphy_chantab_phy_rev16_radio_rev9;
len = ARRAY_SIZE(b43_nphy_chantab_phy_rev16_radio_rev9);
}
break;
case 17:
if (phy->radio_rev == 14) {
e_r7_2g = b43_nphy_chantab_phy_rev17_radio_rev14;
len = ARRAY_SIZE(b43_nphy_chantab_phy_rev17_radio_rev14);
}
break;
default:
break;
}

View File

@ -84,6 +84,8 @@
#define R2057_CMOSBUF_RX_RCCR 0x04c
#define R2057_LOGEN_SEL_PKDET 0x04d
#define R2057_CMOSBUF_SHAREIQ_PTAT 0x04e
/* MISC core 0 */
#define R2057_RXTXBIAS_CONFIG_CORE0 0x04f
#define R2057_TXGM_TXRF_PUS_CORE0 0x050
#define R2057_TXGM_IDAC_BLEED_CORE0 0x051
@ -204,6 +206,8 @@
#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0x0d1
#define R2057_LPF_GAIN_CORE0 0x0d2
#define R2057_DACBUF_IDACS_BW_CORE0 0x0d3
/* MISC core 1 */
#define R2057_RXTXBIAS_CONFIG_CORE1 0x0d4
#define R2057_TXGM_TXRF_PUS_CORE1 0x0d5
#define R2057_TXGM_IDAC_BLEED_CORE1 0x0d6
@ -324,6 +328,7 @@
#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156
#define R2057_LPF_GAIN_CORE1 0x157
#define R2057_DACBUF_IDACS_BW_CORE1 0x158
#define R2057_DACBUF_VINCM_CORE1 0x159
#define R2057_RCCAL_START_R1_Q1_P1 0x15a
#define R2057_RCCAL_X1 0x15b
@ -345,6 +350,8 @@
#define R2057_RCCAL_BCAP_VAL 0x16b
#define R2057_RCCAL_HPC_VAL 0x16c
#define R2057_RCCAL_OVERRIDES 0x16d
/* TX core 0 */
#define R2057_TX0_IQCAL_GAIN_BW 0x170
#define R2057_TX0_LOFT_FINE_I 0x171
#define R2057_TX0_LOFT_FINE_Q 0x172
@ -362,6 +369,8 @@
#define R2057_TX0_TXRXCOUPLE_2G_PWRUP 0x17e
#define R2057_TX0_TXRXCOUPLE_5G_ATTEN 0x17f
#define R2057_TX0_TXRXCOUPLE_5G_PWRUP 0x180
/* TX core 1 */
#define R2057_TX1_IQCAL_GAIN_BW 0x190
#define R2057_TX1_LOFT_FINE_I 0x191
#define R2057_TX1_LOFT_FINE_Q 0x192
@ -379,6 +388,7 @@
#define R2057_TX1_TXRXCOUPLE_2G_PWRUP 0x19e
#define R2057_TX1_TXRXCOUPLE_5G_ATTEN 0x19f
#define R2057_TX1_TXRXCOUPLE_5G_PWRUP 0x1a0
#define R2057_AFE_VCM_CAL_MASTER_CORE0 0x1a1
#define R2057_AFE_SET_VCM_I_CORE0 0x1a2
#define R2057_AFE_SET_VCM_Q_CORE0 0x1a3

View File

@ -2408,6 +2408,41 @@ static const u32 b43_ntab_tx_gain_epa_rev3_2g[] = {
0x1041003c, 0x1041003b, 0x10410039, 0x10410037,
};
static const u32 b43_ntab_tx_gain_epa_rev3_hi_pwr_2g[] = {
0x0f410044, 0x0f410042, 0x0f410040, 0x0f41003e,
0x0f41003c, 0x0f41003b, 0x0f410039, 0x0f410037,
0x0e410044, 0x0e410042, 0x0e410040, 0x0e41003e,
0x0e41003c, 0x0e41003b, 0x0e410039, 0x0e410037,
0x0d410044, 0x0d410042, 0x0d410040, 0x0d41003e,
0x0d41003c, 0x0d41003b, 0x0d410039, 0x0d410037,
0x0c410044, 0x0c410042, 0x0c410040, 0x0c41003e,
0x0c41003c, 0x0c41003b, 0x0c410039, 0x0c410037,
0x0b410044, 0x0b410042, 0x0b410040, 0x0b41003e,
0x0b41003c, 0x0b41003b, 0x0b410039, 0x0b410037,
0x0a410044, 0x0a410042, 0x0a410040, 0x0a41003e,
0x0a41003c, 0x0a41003b, 0x0a410039, 0x0a410037,
0x09410044, 0x09410042, 0x09410040, 0x0941003e,
0x0941003c, 0x0941003b, 0x09410039, 0x09410037,
0x08410044, 0x08410042, 0x08410040, 0x0841003e,
0x0841003c, 0x0841003b, 0x08410039, 0x08410037,
0x07410044, 0x07410042, 0x07410040, 0x0741003e,
0x0741003c, 0x0741003b, 0x07410039, 0x07410037,
0x06410044, 0x06410042, 0x06410040, 0x0641003e,
0x0641003c, 0x0641003b, 0x06410039, 0x06410037,
0x05410044, 0x05410042, 0x05410040, 0x0541003e,
0x0541003c, 0x0541003b, 0x05410039, 0x05410037,
0x04410044, 0x04410042, 0x04410040, 0x0441003e,
0x0441003c, 0x0441003b, 0x04410039, 0x04410037,
0x03410044, 0x03410042, 0x03410040, 0x0341003e,
0x0341003c, 0x0341003b, 0x03410039, 0x03410037,
0x02410044, 0x02410042, 0x02410040, 0x0241003e,
0x0241003c, 0x0241003b, 0x02410039, 0x02410037,
0x01410044, 0x01410042, 0x01410040, 0x0141003e,
0x0141003c, 0x0141003b, 0x01410039, 0x01410037,
0x00410044, 0x00410042, 0x00410040, 0x0041003e,
0x0041003c, 0x0041003b, 0x00410039, 0x00410037
};
/* EPA 5 GHz */
static const u32 b43_ntab_tx_gain_epa_rev3_5g[] = {
@ -2480,6 +2515,41 @@ static const u32 b43_ntab_tx_gain_epa_rev4_5g[] = {
0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034,
};
static const u32 b43_ntab_tx_gain_epa_rev4_hi_pwr_5g[] = {
0x2ff10044, 0x2ff10042, 0x2ff10040, 0x2ff1003e,
0x2ff1003c, 0x2ff1003b, 0x2ff10039, 0x2ff10037,
0x2ef10044, 0x2ef10042, 0x2ef10040, 0x2ef1003e,
0x2ef1003c, 0x2ef1003b, 0x2ef10039, 0x2ef10037,
0x2df10044, 0x2df10042, 0x2df10040, 0x2df1003e,
0x2df1003c, 0x2df1003b, 0x2df10039, 0x2df10037,
0x2cf10044, 0x2cf10042, 0x2cf10040, 0x2cf1003e,
0x2cf1003c, 0x2cf1003b, 0x2cf10039, 0x2cf10037,
0x2bf10044, 0x2bf10042, 0x2bf10040, 0x2bf1003e,
0x2bf1003c, 0x2bf1003b, 0x2bf10039, 0x2bf10037,
0x2af10044, 0x2af10042, 0x2af10040, 0x2af1003e,
0x2af1003c, 0x2af1003b, 0x2af10039, 0x2af10037,
0x29f10044, 0x29f10042, 0x29f10040, 0x29f1003e,
0x29f1003c, 0x29f1003b, 0x29f10039, 0x29f10037,
0x28f10044, 0x28f10042, 0x28f10040, 0x28f1003e,
0x28f1003c, 0x28f1003b, 0x28f10039, 0x28f10037,
0x27f10044, 0x27f10042, 0x27f10040, 0x27f1003e,
0x27f1003c, 0x27f1003b, 0x27f10039, 0x27f10037,
0x26f10044, 0x26f10042, 0x26f10040, 0x26f1003e,
0x26f1003c, 0x26f1003b, 0x26f10039, 0x26f10037,
0x25f10044, 0x25f10042, 0x25f10040, 0x25f1003e,
0x25f1003c, 0x25f1003b, 0x25f10039, 0x25f10037,
0x24f10044, 0x24f10042, 0x24f10040, 0x24f1003e,
0x24f1003c, 0x24f1003b, 0x24f10039, 0x24f10038,
0x23f10041, 0x23f10040, 0x23f1003f, 0x23f1003e,
0x23f1003c, 0x23f1003b, 0x23f10039, 0x23f10037,
0x22f10044, 0x22f10042, 0x22f10040, 0x22f1003e,
0x22f1003c, 0x22f1003b, 0x22f10039, 0x22f10037,
0x21f10044, 0x21f10042, 0x21f10040, 0x21f1003e,
0x21f1003c, 0x21f1003b, 0x21f10039, 0x21f10037,
0x20d10043, 0x20d10041, 0x20d1003e, 0x20d1003c,
0x20d1003a, 0x20d10038, 0x20d10036, 0x20d10034
};
static const u32 b43_ntab_tx_gain_epa_rev5_5g[] = {
0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044,
0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c,
@ -2622,6 +2692,42 @@ static const u32 b43_ntab_tx_gain_ipa_rev6_2g[] = {
0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025,
};
/* Copied from brcmsmac (5.75.11): nphy_tpc_txgain_ipa_2g_2057rev5 */
static const u32 b43_ntab_tx_gain_ipa_2057_rev5_2g[] = {
0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e,
0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033,
0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e,
0x3067002e, 0x305f002f, 0x30570030, 0x3057002d,
0x304f002e, 0x30470031, 0x3047002e, 0x3047002c,
0x30470029, 0x303f002c, 0x303f0029, 0x3037002d,
0x3037002a, 0x30370028, 0x302f002c, 0x302f002a,
0x302f0028, 0x302f0026, 0x3027002c, 0x30270029,
0x30270027, 0x30270025, 0x30270023, 0x301f002c,
0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024,
0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b,
0x30170028, 0x30170026, 0x30170024, 0x30170022,
0x30170020, 0x3017001e, 0x3017001d, 0x3017001b,
0x3017001a, 0x30170018, 0x30170017, 0x30170015,
0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024,
0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d,
0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017,
0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215,
0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615,
0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
};
/* Extracted from MMIO dump of 6.30.223.141 */
static const u32 b43_ntab_tx_gain_ipa_2057_rev9_2g[] = {
0x60ff0031, 0x60e7002c, 0x60cf002a, 0x60c70029,
@ -2658,6 +2764,42 @@ static const u32 b43_ntab_tx_gain_ipa_2057_rev9_2g[] = {
0x600f0715, 0x600f0715, 0x600f0715, 0x600f0715,
};
/* Extracted from MMIO dump of 6.30.223.248 */
static const u32 b43_ntab_tx_gain_ipa_2057_rev14_2g[] = {
0x50df002e, 0x50cf002d, 0x50bf002c, 0x50b7002b,
0x50af002a, 0x50a70029, 0x509f0029, 0x50970028,
0x508f0027, 0x50870027, 0x507f0027, 0x50770027,
0x506f0027, 0x50670027, 0x505f0028, 0x50570029,
0x504f002b, 0x5047002e, 0x5047002b, 0x50470029,
0x503f002c, 0x503f0029, 0x5037002c, 0x5037002a,
0x50370028, 0x502f002d, 0x502f002b, 0x502f0028,
0x502f0026, 0x5027002d, 0x5027002a, 0x50270028,
0x50270026, 0x50270024, 0x501f002e, 0x501f002b,
0x501f0029, 0x501f0027, 0x501f0024, 0x501f0022,
0x501f0020, 0x501f001f, 0x5017002c, 0x50170029,
0x50170027, 0x50170024, 0x50170022, 0x50170021,
0x5017001f, 0x5017001d, 0x5017001b, 0x5017001a,
0x50170018, 0x50170017, 0x50170015, 0x500f002c,
0x500f002a, 0x500f0027, 0x500f0025, 0x500f0023,
0x500f0022, 0x500f001f, 0x500f001e, 0x500f001c,
0x500f001a, 0x500f0019, 0x500f0018, 0x500f0016,
0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
0x500f0015, 0x500f0015, 0x500f0015, 0x500f0015,
};
/* IPA 2 5Hz */
static const u32 b43_ntab_tx_gain_ipa_rev3_5g[] = {
@ -2967,11 +3109,11 @@ static const struct nphy_rf_control_override_rev7
{ 0x0010, 0x07A, 0x07D, 0x0010, 4 },
{ 0x0020, 0x07A, 0x07D, 0x0020, 5 },
{ 0x0040, 0x07A, 0x07D, 0x0040, 6 },
{ 0x0080, 0x0F8, 0x0FA, 0x0080, 7 },
{ 0x0080, 0x07A, 0x07D, 0x0080, 7 },
{ 0x0400, 0x0F8, 0x0FA, 0x0070, 4 },
{ 0x0800, 0x07B, 0x07E, 0xFFFF, 0 },
{ 0x1000, 0x07C, 0x07F, 0xFFFF, 0 },
{ 0x6000, 0x348, 0x349, 0xFFFF, 0 },
{ 0x6000, 0x348, 0x349, 0x00FF, 0 },
{ 0x2000, 0x348, 0x349, 0x000F, 0 },
};
@ -3477,9 +3619,18 @@ static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
switch (phy->rev) {
case 17:
if (phy->radio_rev == 14)
return b43_ntab_tx_gain_ipa_2057_rev14_2g;
break;
case 16:
if (phy->radio_rev == 9)
return b43_ntab_tx_gain_ipa_2057_rev9_2g;
break;
case 8:
if (phy->radio_rev == 5)
return b43_ntab_tx_gain_ipa_2057_rev5_2g;
break;
case 6:
if (dev->dev->chip_id == BCMA_CHIP_ID_BCM47162)
return b43_ntab_tx_gain_ipa_rev5_2g;
@ -3489,23 +3640,24 @@ static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
case 4:
case 3:
return b43_ntab_tx_gain_ipa_rev3_2g;
default:
b43err(dev->wl,
"No 2GHz IPA gain table available for this device\n");
return NULL;
}
b43err(dev->wl,
"No 2GHz IPA gain table available for this device\n");
return NULL;
} else {
switch (phy->rev) {
case 16:
if (phy->radio_rev == 9)
return b43_ntab_tx_gain_ipa_2057_rev9_5g;
break;
case 3 ... 6:
return b43_ntab_tx_gain_ipa_rev3_5g;
default:
b43err(dev->wl,
"No 5GHz IPA gain table available for this device\n");
return NULL;
}
b43err(dev->wl,
"No 5GHz IPA gain table available for this device\n");
return NULL;
}
}
@ -3530,7 +3682,7 @@ const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev)
case 4:
return sprom->fem.ghz5.extpa_gain == 3 ?
b43_ntab_tx_gain_epa_rev4_5g :
b43_ntab_tx_gain_epa_rev4_5g; /* FIXME */
b43_ntab_tx_gain_epa_rev4_hi_pwr_5g;
case 3:
return b43_ntab_tx_gain_epa_rev3_5g;
default:
@ -3543,7 +3695,7 @@ const u32 *b43_nphy_get_tx_gain_table(struct b43_wldev *dev)
case 6:
case 5:
if (sprom->fem.ghz5.extpa_gain == 3)
return b43_ntab_tx_gain_epa_rev3_2g; /* FIXME */
return b43_ntab_tx_gain_epa_rev3_hi_pwr_2g;
/* fall through */
case 4:
case 3:

View File

@ -80,9 +80,10 @@ static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
}
/* Extract the bitrate index out of an OFDM PLCP header. */
static int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy)
static int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool ghz5)
{
int base = aphy ? 0 : 4;
/* For 2 GHz band first OFDM rate is at index 4, see main.c */
int base = ghz5 ? 0 : 4;
switch (plcp->raw[0] & 0xF) {
case 0xB:
@ -767,7 +768,7 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
if (phystat0 & B43_RX_PHYST0_OFDM)
rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp,
phytype == B43_PHYTYPE_A);
!!(chanstat & B43_RX_CHAN_5GHZ));
else
rate_idx = b43_plcp_get_bitrate_idx_cck(plcp);
if (unlikely(rate_idx == -1)) {

View File

@ -34,6 +34,7 @@ brcmfmac-objs += \
dhd_common.o \
dhd_linux.o \
firmware.o \
feature.o \
btcoex.o \
vendor.o
brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \

View File

@ -25,7 +25,6 @@
#include <linux/mmc/sdio.h>
#include <linux/mmc/core.h>
#include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include <linux/platform_device.h>
@ -979,18 +978,20 @@ out:
return ret;
}
#define BRCMF_SDIO_DEVICE(dev_id) \
{SDIO_DEVICE(BRCM_SDIO_VENDOR_ID_BROADCOM, dev_id)}
/* devices we support, null terminated */
static const struct sdio_device_id brcmf_sdmmc_ids[] = {
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43143)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43362)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM,
SDIO_DEVICE_ID_BROADCOM_4335_4339)},
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4354)},
{ /* end: all zeroes */ },
BRCMF_SDIO_DEVICE(BRCM_SDIO_43143_DEVICE_ID),
BRCMF_SDIO_DEVICE(BRCM_SDIO_43241_DEVICE_ID),
BRCMF_SDIO_DEVICE(BRCM_SDIO_4329_DEVICE_ID),
BRCMF_SDIO_DEVICE(BRCM_SDIO_4330_DEVICE_ID),
BRCMF_SDIO_DEVICE(BRCM_SDIO_4334_DEVICE_ID),
BRCMF_SDIO_DEVICE(BRCM_SDIO_43362_DEVICE_ID),
BRCMF_SDIO_DEVICE(BRCM_SDIO_4335_4339_DEVICE_ID),
BRCMF_SDIO_DEVICE(BRCM_SDIO_4354_DEVICE_ID),
{ /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);

View File

@ -482,30 +482,30 @@ static inline int brcmf_chip_cores_check(struct brcmf_chip_priv *ci)
static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
{
switch (ci->pub.chip) {
case BCM4329_CHIP_ID:
case BRCM_CC_4329_CHIP_ID:
ci->pub.ramsize = BCM4329_RAMSIZE;
break;
case BCM43143_CHIP_ID:
case BRCM_CC_43143_CHIP_ID:
ci->pub.ramsize = BCM43143_RAMSIZE;
break;
case BCM43241_CHIP_ID:
case BRCM_CC_43241_CHIP_ID:
ci->pub.ramsize = 0x90000;
break;
case BCM4330_CHIP_ID:
case BRCM_CC_4330_CHIP_ID:
ci->pub.ramsize = 0x48000;
break;
case BCM4334_CHIP_ID:
case BRCM_CC_4334_CHIP_ID:
ci->pub.ramsize = 0x80000;
break;
case BCM4335_CHIP_ID:
case BRCM_CC_4335_CHIP_ID:
ci->pub.ramsize = 0xc0000;
ci->pub.rambase = 0x180000;
break;
case BCM43362_CHIP_ID:
case BRCM_CC_43362_CHIP_ID:
ci->pub.ramsize = 0x3c000;
break;
case BCM4339_CHIP_ID:
case BCM4354_CHIP_ID:
case BRCM_CC_4339_CHIP_ID:
case BRCM_CC_4354_CHIP_ID:
ci->pub.ramsize = 0xc0000;
ci->pub.rambase = 0x180000;
break;
@ -682,7 +682,7 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
ci->pub.chiprev);
if (socitype == SOCI_SB) {
if (ci->pub.chip != BCM4329_CHIP_ID) {
if (ci->pub.chip != BRCM_CC_4329_CHIP_ID) {
brcmf_err("SB chip is not supported\n");
return -ENODEV;
}
@ -1008,13 +1008,13 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub)
chip = container_of(pub, struct brcmf_chip_priv, pub);
switch (pub->chip) {
case BCM4354_CHIP_ID:
case BRCM_CC_4354_CHIP_ID:
/* explicitly check SR engine enable bit */
pmu_cc3_mask = BIT(2);
/* fall-through */
case BCM43241_CHIP_ID:
case BCM4335_CHIP_ID:
case BCM4339_CHIP_ID:
case BRCM_CC_43241_CHIP_ID:
case BRCM_CC_4335_CHIP_ID:
case BRCM_CC_4339_CHIP_ID:
/* read PMU chipcontrol register 3 */
addr = CORE_CC_REG(base, chipcontrol_addr);
chip->ops->write32(chip->ctx, addr, 3);

View File

@ -103,6 +103,10 @@ struct brcmf_pub {
struct brcmf_ampdu_rx_reorder
*reorder_flows[BRCMF_AMPDU_RX_REORDER_MAXFLOWS];
u32 feat_flags;
u32 chip_quirks;
#ifdef DEBUG
struct dentry *dbgfs_dir;
#endif
@ -175,7 +179,6 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
void brcmf_txflowblock_if(struct brcmf_if *ifp,
enum brcmf_netif_stop_reason reason, bool state);
u32 brcmf_get_chip_info(struct brcmf_if *ifp);
void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
bool success);

View File

@ -41,37 +41,12 @@ void brcmf_debugfs_exit(void)
root_folder = NULL;
}
static
ssize_t brcmf_debugfs_chipinfo_read(struct file *f, char __user *data,
size_t count, loff_t *ppos)
static int brcmf_debugfs_chipinfo_read(struct seq_file *seq, void *data)
{
struct brcmf_pub *drvr = f->private_data;
struct brcmf_bus *bus = drvr->bus_if;
char buf[40];
int res;
struct brcmf_bus *bus = dev_get_drvdata(seq->private);
/* only allow read from start */
if (*ppos > 0)
return 0;
res = scnprintf(buf, sizeof(buf), "chip: %x(%u) rev %u\n",
bus->chip, bus->chip, bus->chiprev);
return simple_read_from_buffer(data, count, ppos, buf, res);
}
static const struct file_operations brcmf_debugfs_chipinfo_ops = {
.owner = THIS_MODULE,
.open = simple_open,
.read = brcmf_debugfs_chipinfo_read
};
static int brcmf_debugfs_create_chipinfo(struct brcmf_pub *drvr)
{
struct dentry *dentry = drvr->dbgfs_dir;
if (!IS_ERR_OR_NULL(dentry))
debugfs_create_file("chipinfo", S_IRUGO, dentry, drvr,
&brcmf_debugfs_chipinfo_ops);
seq_printf(seq, "chip: %x(%u) rev %u\n",
bus->chip, bus->chip, bus->chiprev);
return 0;
}
@ -83,7 +58,8 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr)
return -ENODEV;
drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
brcmf_debugfs_create_chipinfo(drvr);
brcmf_debugfs_add_entry(drvr, "chipinfo", brcmf_debugfs_chipinfo_read);
return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
}
@ -98,148 +74,44 @@ struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr)
return drvr->dbgfs_dir;
}
static
ssize_t brcmf_debugfs_sdio_counter_read(struct file *f, char __user *data,
size_t count, loff_t *ppos)
{
struct brcmf_sdio_count *sdcnt = f->private_data;
char buf[750];
int res;
/* only allow read from start */
if (*ppos > 0)
return 0;
res = scnprintf(buf, sizeof(buf),
"intrcount: %u\nlastintrs: %u\n"
"pollcnt: %u\nregfails: %u\n"
"tx_sderrs: %u\nfcqueued: %u\n"
"rxrtx: %u\nrx_toolong: %u\n"
"rxc_errors: %u\nrx_hdrfail: %u\n"
"rx_badhdr: %u\nrx_badseq: %u\n"
"fc_rcvd: %u\nfc_xoff: %u\n"
"fc_xon: %u\nrxglomfail: %u\n"
"rxglomframes: %u\nrxglompkts: %u\n"
"f2rxhdrs: %u\nf2rxdata: %u\n"
"f2txdata: %u\nf1regdata: %u\n"
"tickcnt: %u\ntx_ctlerrs: %lu\n"
"tx_ctlpkts: %lu\nrx_ctlerrs: %lu\n"
"rx_ctlpkts: %lu\nrx_readahead: %lu\n",
sdcnt->intrcount, sdcnt->lastintrs,
sdcnt->pollcnt, sdcnt->regfails,
sdcnt->tx_sderrs, sdcnt->fcqueued,
sdcnt->rxrtx, sdcnt->rx_toolong,
sdcnt->rxc_errors, sdcnt->rx_hdrfail,
sdcnt->rx_badhdr, sdcnt->rx_badseq,
sdcnt->fc_rcvd, sdcnt->fc_xoff,
sdcnt->fc_xon, sdcnt->rxglomfail,
sdcnt->rxglomframes, sdcnt->rxglompkts,
sdcnt->f2rxhdrs, sdcnt->f2rxdata,
sdcnt->f2txdata, sdcnt->f1regdata,
sdcnt->tickcnt, sdcnt->tx_ctlerrs,
sdcnt->tx_ctlpkts, sdcnt->rx_ctlerrs,
sdcnt->rx_ctlpkts, sdcnt->rx_readahead_cnt);
return simple_read_from_buffer(data, count, ppos, buf, res);
}
static const struct file_operations brcmf_debugfs_sdio_counter_ops = {
.owner = THIS_MODULE,
.open = simple_open,
.read = brcmf_debugfs_sdio_counter_read
struct brcmf_debugfs_entry {
int (*read)(struct seq_file *seq, void *data);
struct brcmf_pub *drvr;
};
void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr,
struct brcmf_sdio_count *sdcnt)
static int brcmf_debugfs_entry_open(struct inode *inode, struct file *f)
{
struct dentry *dentry = drvr->dbgfs_dir;
struct brcmf_debugfs_entry *entry = inode->i_private;
if (!IS_ERR_OR_NULL(dentry))
debugfs_create_file("counters", S_IRUGO, dentry,
sdcnt, &brcmf_debugfs_sdio_counter_ops);
return single_open(f, entry->read, entry->drvr->bus_if->dev);
}
static
ssize_t brcmf_debugfs_fws_stats_read(struct file *f, char __user *data,
size_t count, loff_t *ppos)
{
struct brcmf_fws_stats *fwstats = f->private_data;
char buf[650];
int res;
/* only allow read from start */
if (*ppos > 0)
return 0;
res = scnprintf(buf, sizeof(buf),
"header_pulls: %u\n"
"header_only_pkt: %u\n"
"tlv_parse_failed: %u\n"
"tlv_invalid_type: %u\n"
"mac_update_fails: %u\n"
"ps_update_fails: %u\n"
"if_update_fails: %u\n"
"pkt2bus: %u\n"
"generic_error: %u\n"
"rollback_success: %u\n"
"rollback_failed: %u\n"
"delayq_full: %u\n"
"supprq_full: %u\n"
"txs_indicate: %u\n"
"txs_discard: %u\n"
"txs_suppr_core: %u\n"
"txs_suppr_ps: %u\n"
"txs_tossed: %u\n"
"txs_host_tossed: %u\n"
"bus_flow_block: %u\n"
"fws_flow_block: %u\n"
"send_pkts: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n"
"requested_sent: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n",
fwstats->header_pulls,
fwstats->header_only_pkt,
fwstats->tlv_parse_failed,
fwstats->tlv_invalid_type,
fwstats->mac_update_failed,
fwstats->mac_ps_update_failed,
fwstats->if_update_failed,
fwstats->pkt2bus,
fwstats->generic_error,
fwstats->rollback_success,
fwstats->rollback_failed,
fwstats->delayq_full_error,
fwstats->supprq_full_error,
fwstats->txs_indicate,
fwstats->txs_discard,
fwstats->txs_supp_core,
fwstats->txs_supp_ps,
fwstats->txs_tossed,
fwstats->txs_host_tossed,
fwstats->bus_flow_block,
fwstats->fws_flow_block,
fwstats->send_pkts[0], fwstats->send_pkts[1],
fwstats->send_pkts[2], fwstats->send_pkts[3],
fwstats->send_pkts[4],
fwstats->requested_sent[0],
fwstats->requested_sent[1],
fwstats->requested_sent[2],
fwstats->requested_sent[3],
fwstats->requested_sent[4]);
return simple_read_from_buffer(data, count, ppos, buf, res);
}
static const struct file_operations brcmf_debugfs_fws_stats_ops = {
static const struct file_operations brcmf_debugfs_def_ops = {
.owner = THIS_MODULE,
.open = simple_open,
.read = brcmf_debugfs_fws_stats_read
.open = brcmf_debugfs_entry_open,
.release = single_release,
.read = seq_read,
.llseek = seq_lseek
};
void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr,
struct brcmf_fws_stats *stats)
int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
int (*read_fn)(struct seq_file *seq, void *data))
{
struct dentry *dentry = drvr->dbgfs_dir;
struct brcmf_debugfs_entry *entry;
if (!IS_ERR_OR_NULL(dentry))
debugfs_create_file("fws_stats", S_IRUGO, dentry,
stats, &brcmf_debugfs_fws_stats_ops);
if (IS_ERR_OR_NULL(dentry))
return -ENOENT;
entry = devm_kzalloc(drvr->bus_if->dev, sizeof(*entry), GFP_KERNEL);
if (!entry)
return -ENOMEM;
entry->read = read_fn;
entry->drvr = drvr;
dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry,
&brcmf_debugfs_def_ops);
return PTR_ERR_OR_ZERO(dentry);
}

View File

@ -100,68 +100,6 @@ do { \
extern int brcmf_msg_level;
/*
* hold counter variables used in brcmfmac sdio driver.
*/
struct brcmf_sdio_count {
uint intrcount; /* Count of device interrupt callbacks */
uint lastintrs; /* Count as of last watchdog timer */
uint pollcnt; /* Count of active polls */
uint regfails; /* Count of R_REG failures */
uint tx_sderrs; /* Count of tx attempts with sd errors */
uint fcqueued; /* Tx packets that got queued */
uint rxrtx; /* Count of rtx requests (NAK to dongle) */
uint rx_toolong; /* Receive frames too long to receive */
uint rxc_errors; /* SDIO errors when reading control frames */
uint rx_hdrfail; /* SDIO errors on header reads */
uint rx_badhdr; /* Bad received headers (roosync?) */
uint rx_badseq; /* Mismatched rx sequence number */
uint fc_rcvd; /* Number of flow-control events received */
uint fc_xoff; /* Number which turned on flow-control */
uint fc_xon; /* Number which turned off flow-control */
uint rxglomfail; /* Failed deglom attempts */
uint rxglomframes; /* Number of glom frames (superframes) */
uint rxglompkts; /* Number of packets from glom frames */
uint f2rxhdrs; /* Number of header reads */
uint f2rxdata; /* Number of frame data reads */
uint f2txdata; /* Number of f2 frame writes */
uint f1regdata; /* Number of f1 register accesses */
uint tickcnt; /* Number of watchdog been schedule */
ulong tx_ctlerrs; /* Err of sending ctrl frames */
ulong tx_ctlpkts; /* Ctrl frames sent to dongle */
ulong rx_ctlerrs; /* Err of processing rx ctrl frames */
ulong rx_ctlpkts; /* Ctrl frames processed from dongle */
ulong rx_readahead_cnt; /* packets where header read-ahead was used */
};
struct brcmf_fws_stats {
u32 tlv_parse_failed;
u32 tlv_invalid_type;
u32 header_only_pkt;
u32 header_pulls;
u32 pkt2bus;
u32 send_pkts[5];
u32 requested_sent[5];
u32 generic_error;
u32 mac_update_failed;
u32 mac_ps_update_failed;
u32 if_update_failed;
u32 packet_request_failed;
u32 credit_request_failed;
u32 rollback_success;
u32 rollback_failed;
u32 delayq_full_error;
u32 supprq_full_error;
u32 txs_indicate;
u32 txs_discard;
u32 txs_supp_core;
u32 txs_supp_ps;
u32 txs_tossed;
u32 txs_host_tossed;
u32 bus_flow_block;
u32 fws_flow_block;
};
struct brcmf_pub;
#ifdef DEBUG
void brcmf_debugfs_init(void);
@ -169,10 +107,8 @@ void brcmf_debugfs_exit(void);
int brcmf_debugfs_attach(struct brcmf_pub *drvr);
void brcmf_debugfs_detach(struct brcmf_pub *drvr);
struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr);
void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr,
struct brcmf_sdio_count *sdcnt);
void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr,
struct brcmf_fws_stats *stats);
int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
int (*read_fn)(struct seq_file *seq, void *data));
#else
static inline void brcmf_debugfs_init(void)
{
@ -187,9 +123,11 @@ static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr)
static inline void brcmf_debugfs_detach(struct brcmf_pub *drvr)
{
}
static inline void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr,
struct brcmf_fws_stats *stats)
static inline
int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
int (*read_fn)(struct seq_file *seq, void *data))
{
return 0;
}
#endif

View File

@ -30,6 +30,7 @@
#include "wl_cfg80211.h"
#include "fwil.h"
#include "fwsignal.h"
#include "feature.h"
#include "proto.h"
MODULE_AUTHOR("Broadcom Corporation");
@ -937,6 +938,8 @@ int brcmf_bus_start(struct device *dev)
if (ret < 0)
goto fail;
brcmf_feat_attach(drvr);
ret = brcmf_fws_init(drvr);
if (ret < 0)
goto fail;
@ -1074,16 +1077,6 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
return !err;
}
/*
* return chip id and rev of the device encoded in u32.
*/
u32 brcmf_get_chip_info(struct brcmf_if *ifp)
{
struct brcmf_bus *bus = ifp->drvr->bus_if;
return bus->chip << 4 | bus->chiprev;
}
static void brcmf_driver_register(struct work_struct *work)
{
#ifdef CONFIG_BRCMFMAC_SDIO

View File

@ -391,6 +391,40 @@ struct brcmf_sdio_hdrinfo {
u16 tail_pad;
};
/*
* hold counter variables
*/
struct brcmf_sdio_count {
uint intrcount; /* Count of device interrupt callbacks */
uint lastintrs; /* Count as of last watchdog timer */
uint pollcnt; /* Count of active polls */
uint regfails; /* Count of R_REG failures */
uint tx_sderrs; /* Count of tx attempts with sd errors */
uint fcqueued; /* Tx packets that got queued */
uint rxrtx; /* Count of rtx requests (NAK to dongle) */
uint rx_toolong; /* Receive frames too long to receive */
uint rxc_errors; /* SDIO errors when reading control frames */
uint rx_hdrfail; /* SDIO errors on header reads */
uint rx_badhdr; /* Bad received headers (roosync?) */
uint rx_badseq; /* Mismatched rx sequence number */
uint fc_rcvd; /* Number of flow-control events received */
uint fc_xoff; /* Number which turned on flow-control */
uint fc_xon; /* Number which turned off flow-control */
uint rxglomfail; /* Failed deglom attempts */
uint rxglomframes; /* Number of glom frames (superframes) */
uint rxglompkts; /* Number of packets from glom frames */
uint f2rxhdrs; /* Number of header reads */
uint f2rxdata; /* Number of frame data reads */
uint f2txdata; /* Number of f2 frame writes */
uint f1regdata; /* Number of f1 register accesses */
uint tickcnt; /* Number of watchdog been schedule */
ulong tx_ctlerrs; /* Err of sending ctrl frames */
ulong tx_ctlpkts; /* Ctrl frames sent to dongle */
ulong rx_ctlerrs; /* Err of processing rx ctrl frames */
ulong rx_ctlpkts; /* Ctrl frames processed from dongle */
ulong rx_readahead_cnt; /* packets where header read-ahead was used */
};
/* misc chip info needed by some of the routines */
/* Private data for SDIO bus interaction */
struct brcmf_sdio {
@ -620,40 +654,46 @@ enum brcmf_firmware_type {
name ## _FIRMWARE_NAME, name ## _NVRAM_NAME
static const struct brcmf_firmware_names brcmf_fwname_data[] = {
{ BCM43143_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43143) },
{ BCM43241_CHIP_ID, 0x0000001F, BRCMF_FIRMWARE_NVRAM(BCM43241B0) },
{ BCM43241_CHIP_ID, 0xFFFFFFE0, BRCMF_FIRMWARE_NVRAM(BCM43241B4) },
{ BCM4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) },
{ BCM4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) },
{ BCM4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) },
{ BCM4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) },
{ BCM43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) },
{ BCM4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) },
{ BCM4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) }
{ BRCM_CC_43143_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM43143) },
{ BRCM_CC_43241_CHIP_ID, 0x0000001F, BRCMF_FIRMWARE_NVRAM(BCM43241B0) },
{ BRCM_CC_43241_CHIP_ID, 0xFFFFFFE0, BRCMF_FIRMWARE_NVRAM(BCM43241B4) },
{ BRCM_CC_4329_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4329) },
{ BRCM_CC_4330_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4330) },
{ BRCM_CC_4334_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4334) },
{ BRCM_CC_4335_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4335) },
{ BRCM_CC_43362_CHIP_ID, 0xFFFFFFFE, BRCMF_FIRMWARE_NVRAM(BCM43362) },
{ BRCM_CC_4339_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4339) },
{ BRCM_CC_4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) }
};
static const char *brcmf_sdio_get_fwname(struct brcmf_chip *ci,
enum brcmf_firmware_type type)
static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci,
struct brcmf_sdio_dev *sdiodev)
{
int i;
for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) {
if (brcmf_fwname_data[i].chipid == ci->chip &&
brcmf_fwname_data[i].revmsk & BIT(ci->chiprev)) {
switch (type) {
case BRCMF_FIRMWARE_BIN:
return brcmf_fwname_data[i].bin;
case BRCMF_FIRMWARE_NVRAM:
return brcmf_fwname_data[i].nv;
default:
brcmf_err("invalid firmware type (%d)\n", type);
return NULL;
}
}
brcmf_fwname_data[i].revmsk & BIT(ci->chiprev))
break;
}
brcmf_err("Unknown chipid %d [%d]\n",
ci->chip, ci->chiprev);
return NULL;
if (i == ARRAY_SIZE(brcmf_fwname_data)) {
brcmf_err("Unknown chipid %d [%d]\n", ci->chip, ci->chiprev);
return -ENODEV;
}
/* check if firmware path is provided by module parameter */
if (brcmf_firmware_path[0] != '\0') {
if (brcmf_firmware_path[strlen(brcmf_firmware_path) - 1] != '/')
strcat(brcmf_firmware_path, "/");
strcpy(sdiodev->fw_name, brcmf_firmware_path);
strcpy(sdiodev->nvram_name, brcmf_firmware_path);
}
strcat(sdiodev->fw_name, brcmf_fwname_data[i].bin);
strcat(sdiodev->nvram_name, brcmf_fwname_data[i].nv);
return 0;
}
static void pkt_align(struct sk_buff *p, int len, int align)
@ -2898,16 +2938,13 @@ brcmf_sdio_bus_txctl(struct device *dev, unsigned char *msg, uint msglen)
}
#ifdef DEBUG
static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
struct sdpcm_shared *sh, char __user *data,
size_t count)
static int brcmf_sdio_dump_console(struct seq_file *seq, struct brcmf_sdio *bus,
struct sdpcm_shared *sh)
{
u32 addr, console_ptr, console_size, console_index;
char *conbuf = NULL;
__le32 sh_val;
int rv;
loff_t pos = 0;
int nbytes = 0;
/* obtain console information from device memory */
addr = sh->console_addr + offsetof(struct rte_console, log_le);
@ -2945,33 +2982,24 @@ static int brcmf_sdio_dump_console(struct brcmf_sdio *bus,
if (rv < 0)
goto done;
rv = simple_read_from_buffer(data, count, &pos,
conbuf + console_index,
console_size - console_index);
rv = seq_write(seq, conbuf + console_index,
console_size - console_index);
if (rv < 0)
goto done;
nbytes = rv;
if (console_index > 0) {
pos = 0;
rv = simple_read_from_buffer(data+nbytes, count, &pos,
conbuf, console_index - 1);
if (rv < 0)
goto done;
rv += nbytes;
}
if (console_index > 0)
rv = seq_write(seq, conbuf, console_index - 1);
done:
vfree(conbuf);
return rv;
}
static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
char __user *data, size_t count)
static int brcmf_sdio_trap_info(struct seq_file *seq, struct brcmf_sdio *bus,
struct sdpcm_shared *sh)
{
int error, res;
char buf[350];
int error;
struct brcmf_trap_info tr;
loff_t pos = 0;
if ((sh->flags & SDPCM_SHARED_TRAP) == 0) {
brcmf_dbg(INFO, "no trap in firmware\n");
@ -2983,34 +3011,30 @@ static int brcmf_sdio_trap_info(struct brcmf_sdio *bus, struct sdpcm_shared *sh,
if (error < 0)
return error;
res = scnprintf(buf, sizeof(buf),
"dongle trap info: type 0x%x @ epc 0x%08x\n"
" cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
" lr 0x%08x pc 0x%08x offset 0x%x\n"
" r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n"
" r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n",
le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
le32_to_cpu(tr.pc), sh->trap_addr,
le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
seq_printf(seq,
"dongle trap info: type 0x%x @ epc 0x%08x\n"
" cpsr 0x%08x spsr 0x%08x sp 0x%08x\n"
" lr 0x%08x pc 0x%08x offset 0x%x\n"
" r0 0x%08x r1 0x%08x r2 0x%08x r3 0x%08x\n"
" r4 0x%08x r5 0x%08x r6 0x%08x r7 0x%08x\n",
le32_to_cpu(tr.type), le32_to_cpu(tr.epc),
le32_to_cpu(tr.cpsr), le32_to_cpu(tr.spsr),
le32_to_cpu(tr.r13), le32_to_cpu(tr.r14),
le32_to_cpu(tr.pc), sh->trap_addr,
le32_to_cpu(tr.r0), le32_to_cpu(tr.r1),
le32_to_cpu(tr.r2), le32_to_cpu(tr.r3),
le32_to_cpu(tr.r4), le32_to_cpu(tr.r5),
le32_to_cpu(tr.r6), le32_to_cpu(tr.r7));
return simple_read_from_buffer(data, count, &pos, buf, res);
return 0;
}
static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
struct sdpcm_shared *sh, char __user *data,
size_t count)
static int brcmf_sdio_assert_info(struct seq_file *seq, struct brcmf_sdio *bus,
struct sdpcm_shared *sh)
{
int error = 0;
char buf[200];
char file[80] = "?";
char expr[80] = "<???>";
int res;
loff_t pos = 0;
if ((sh->flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
brcmf_dbg(INFO, "firmware not built with -assert\n");
@ -3035,10 +3059,9 @@ static int brcmf_sdio_assert_info(struct brcmf_sdio *bus,
}
sdio_release_host(bus->sdiodev->func[1]);
res = scnprintf(buf, sizeof(buf),
"dongle assert: %s:%d: assert(%s)\n",
file, sh->assert_line, expr);
return simple_read_from_buffer(data, count, &pos, buf, res);
seq_printf(seq, "dongle assert: %s:%d: assert(%s)\n",
file, sh->assert_line, expr);
return 0;
}
static int brcmf_sdio_checkdied(struct brcmf_sdio *bus)
@ -3062,59 +3085,75 @@ static int brcmf_sdio_checkdied(struct brcmf_sdio *bus)
return 0;
}
static int brcmf_sdio_died_dump(struct brcmf_sdio *bus, char __user *data,
size_t count, loff_t *ppos)
static int brcmf_sdio_died_dump(struct seq_file *seq, struct brcmf_sdio *bus)
{
int error = 0;
struct sdpcm_shared sh;
int nbytes = 0;
loff_t pos = *ppos;
if (pos != 0)
return 0;
error = brcmf_sdio_readshared(bus, &sh);
if (error < 0)
goto done;
error = brcmf_sdio_assert_info(bus, &sh, data, count);
error = brcmf_sdio_assert_info(seq, bus, &sh);
if (error < 0)
goto done;
nbytes = error;
error = brcmf_sdio_trap_info(bus, &sh, data+nbytes, count);
error = brcmf_sdio_trap_info(seq, bus, &sh);
if (error < 0)
goto done;
nbytes += error;
error = brcmf_sdio_dump_console(bus, &sh, data+nbytes, count);
if (error < 0)
goto done;
nbytes += error;
error = brcmf_sdio_dump_console(seq, bus, &sh);
error = nbytes;
*ppos += nbytes;
done:
return error;
}
static ssize_t brcmf_sdio_forensic_read(struct file *f, char __user *data,
size_t count, loff_t *ppos)
static int brcmf_sdio_forensic_read(struct seq_file *seq, void *data)
{
struct brcmf_sdio *bus = f->private_data;
int res;
struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
struct brcmf_sdio *bus = bus_if->bus_priv.sdio->bus;
res = brcmf_sdio_died_dump(bus, data, count, ppos);
if (res > 0)
*ppos += res;
return (ssize_t)res;
return brcmf_sdio_died_dump(seq, bus);
}
static const struct file_operations brcmf_sdio_forensic_ops = {
.owner = THIS_MODULE,
.open = simple_open,
.read = brcmf_sdio_forensic_read
};
static int brcmf_debugfs_sdio_count_read(struct seq_file *seq, void *data)
{
struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
struct brcmf_sdio_count *sdcnt = &sdiodev->bus->sdcnt;
seq_printf(seq,
"intrcount: %u\nlastintrs: %u\n"
"pollcnt: %u\nregfails: %u\n"
"tx_sderrs: %u\nfcqueued: %u\n"
"rxrtx: %u\nrx_toolong: %u\n"
"rxc_errors: %u\nrx_hdrfail: %u\n"
"rx_badhdr: %u\nrx_badseq: %u\n"
"fc_rcvd: %u\nfc_xoff: %u\n"
"fc_xon: %u\nrxglomfail: %u\n"
"rxglomframes: %u\nrxglompkts: %u\n"
"f2rxhdrs: %u\nf2rxdata: %u\n"
"f2txdata: %u\nf1regdata: %u\n"
"tickcnt: %u\ntx_ctlerrs: %lu\n"
"tx_ctlpkts: %lu\nrx_ctlerrs: %lu\n"
"rx_ctlpkts: %lu\nrx_readahead: %lu\n",
sdcnt->intrcount, sdcnt->lastintrs,
sdcnt->pollcnt, sdcnt->regfails,
sdcnt->tx_sderrs, sdcnt->fcqueued,
sdcnt->rxrtx, sdcnt->rx_toolong,
sdcnt->rxc_errors, sdcnt->rx_hdrfail,
sdcnt->rx_badhdr, sdcnt->rx_badseq,
sdcnt->fc_rcvd, sdcnt->fc_xoff,
sdcnt->fc_xon, sdcnt->rxglomfail,
sdcnt->rxglomframes, sdcnt->rxglompkts,
sdcnt->f2rxhdrs, sdcnt->f2rxdata,
sdcnt->f2txdata, sdcnt->f1regdata,
sdcnt->tickcnt, sdcnt->tx_ctlerrs,
sdcnt->tx_ctlpkts, sdcnt->rx_ctlerrs,
sdcnt->rx_ctlpkts, sdcnt->rx_readahead_cnt);
return 0;
}
static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
{
@ -3124,9 +3163,9 @@ static void brcmf_sdio_debugfs_create(struct brcmf_sdio *bus)
if (IS_ERR_OR_NULL(dentry))
return;
debugfs_create_file("forensics", S_IRUGO, dentry, bus,
&brcmf_sdio_forensic_ops);
brcmf_debugfs_create_sdio_count(drvr, &bus->sdcnt);
brcmf_debugfs_add_entry(drvr, "forensics", brcmf_sdio_forensic_read);
brcmf_debugfs_add_entry(drvr, "counters",
brcmf_debugfs_sdio_count_read);
debugfs_create_u32("console_interval", 0644, dentry,
&bus->console_interval);
}
@ -3598,17 +3637,17 @@ brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
return;
switch (SDIOD_DRVSTR_KEY(ci->chip, ci->pmurev)) {
case SDIOD_DRVSTR_KEY(BCM4330_CHIP_ID, 12):
case SDIOD_DRVSTR_KEY(BRCM_CC_4330_CHIP_ID, 12):
str_tab = sdiod_drvstr_tab1_1v8;
str_mask = 0x00003800;
str_shift = 11;
break;
case SDIOD_DRVSTR_KEY(BCM4334_CHIP_ID, 17):
case SDIOD_DRVSTR_KEY(BRCM_CC_4334_CHIP_ID, 17):
str_tab = sdiod_drvstr_tab6_1v8;
str_mask = 0x00001800;
str_shift = 11;
break;
case SDIOD_DRVSTR_KEY(BCM43143_CHIP_ID, 17):
case SDIOD_DRVSTR_KEY(BRCM_CC_43143_CHIP_ID, 17):
/* note: 43143 does not support tristate */
i = ARRAY_SIZE(sdiod_drvstr_tab2_3v3) - 1;
if (drivestrength >= sdiod_drvstr_tab2_3v3[i].strength) {
@ -3619,7 +3658,7 @@ brcmf_sdio_drivestrengthinit(struct brcmf_sdio_dev *sdiodev,
brcmf_err("Invalid SDIO Drive strength for chip %s, strength=%d\n",
ci->name, drivestrength);
break;
case SDIOD_DRVSTR_KEY(BCM43362_CHIP_ID, 13):
case SDIOD_DRVSTR_KEY(BRCM_CC_43362_CHIP_ID, 13):
str_tab = sdiod_drive_strength_tab5_1v8;
str_mask = 0x00003800;
str_shift = 11;
@ -3720,12 +3759,12 @@ static u32 brcmf_sdio_buscore_read32(void *ctx, u32 addr)
u32 val, rev;
val = brcmf_sdiod_regrl(sdiodev, addr, NULL);
if (sdiodev->func[0]->device == SDIO_DEVICE_ID_BROADCOM_4335_4339 &&
if (sdiodev->func[0]->device == BRCM_SDIO_4335_4339_DEVICE_ID &&
addr == CORE_CC_REG(SI_ENUM_BASE, chipid)) {
rev = (val & CID_REV_MASK) >> CID_REV_SHIFT;
if (rev >= 2) {
val &= ~CID_ID_MASK;
val |= BCM4339_CHIP_ID;
val |= BRCM_CC_4339_CHIP_ID;
}
}
return val;
@ -4127,11 +4166,12 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
brcmf_sdio_debugfs_create(bus);
brcmf_dbg(INFO, "completed!!\n");
ret = brcmf_sdio_get_fwnames(bus->ci, sdiodev);
if (ret)
goto fail;
ret = brcmf_fw_get_firmwares(sdiodev->dev, BRCMF_FW_REQUEST_NVRAM,
brcmf_sdio_get_fwname(bus->ci,
BRCMF_FIRMWARE_BIN),
brcmf_sdio_get_fwname(bus->ci,
BRCMF_FIRMWARE_NVRAM),
sdiodev->fw_name, sdiodev->nvram_name,
brcmf_sdio_firmware_callback);
if (ret != 0) {
brcmf_err("async firmware request failed: %d\n", ret);

View File

@ -0,0 +1,136 @@
/*
* Copyright (c) 2014 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/netdevice.h>
#include <brcm_hw_ids.h>
#include "dhd.h"
#include "dhd_bus.h"
#include "dhd_dbg.h"
#include "fwil.h"
#include "feature.h"
/*
* firmware error code received if iovar is unsupported.
*/
#define EBRCMF_FEAT_UNSUPPORTED 23
/*
* expand feature list to array of feature strings.
*/
#define BRCMF_FEAT_DEF(_f) \
#_f,
static const char *brcmf_feat_names[] = {
BRCMF_FEAT_LIST
};
#undef BRCMF_FEAT_DEF
#ifdef DEBUG
/*
* expand quirk list to array of quirk strings.
*/
#define BRCMF_QUIRK_DEF(_q) \
#_q,
static const char * const brcmf_quirk_names[] = {
BRCMF_QUIRK_LIST
};
#undef BRCMF_QUIRK_DEF
/**
* brcmf_feat_debugfs_read() - expose feature info to debugfs.
*
* @seq: sequence for debugfs entry.
* @data: raw data pointer.
*/
static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data)
{
struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
u32 feats = bus_if->drvr->feat_flags;
u32 quirks = bus_if->drvr->chip_quirks;
int id;
seq_printf(seq, "Features: %08x\n", feats);
for (id = 0; id < BRCMF_FEAT_LAST; id++)
if (feats & BIT(id))
seq_printf(seq, "\t%s\n", brcmf_feat_names[id]);
seq_printf(seq, "\nQuirks: %08x\n", quirks);
for (id = 0; id < BRCMF_FEAT_QUIRK_LAST; id++)
if (quirks & BIT(id))
seq_printf(seq, "\t%s\n", brcmf_quirk_names[id]);
return 0;
}
#else
static int brcmf_feat_debugfs_read(struct seq_file *seq, void *data)
{
return 0;
}
#endif /* DEBUG */
/**
* brcmf_feat_iovar_int_get() - determine feature through iovar query.
*
* @ifp: interface to query.
* @id: feature id.
* @name: iovar name.
*/
static void brcmf_feat_iovar_int_get(struct brcmf_if *ifp,
enum brcmf_feat_id id, char *name)
{
u32 data;
int err;
err = brcmf_fil_iovar_int_get(ifp, name, &data);
if (err == 0) {
brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
ifp->drvr->feat_flags |= BIT(id);
} else {
brcmf_dbg(TRACE, "%s feature check failed: %d\n",
brcmf_feat_names[id], err);
}
}
void brcmf_feat_attach(struct brcmf_pub *drvr)
{
struct brcmf_if *ifp = drvr->iflist[0];
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan");
/* set chip related quirks */
switch (drvr->bus_if->chip) {
case BRCM_CC_43236_CHIP_ID:
drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_AUTO_AUTH);
break;
case BRCM_CC_4329_CHIP_ID:
drvr->chip_quirks |= BIT(BRCMF_FEAT_QUIRK_NEED_MPC);
break;
default:
/* no quirks */
break;
}
brcmf_debugfs_add_entry(drvr, "features", brcmf_feat_debugfs_read);
}
bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id)
{
return (ifp->drvr->feat_flags & BIT(id));
}
bool brcmf_feat_is_quirk_enabled(struct brcmf_if *ifp,
enum brcmf_feat_quirk quirk)
{
return (ifp->drvr->chip_quirks & BIT(quirk));
}

View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2014 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef _BRCMF_FEATURE_H
#define _BRCMF_FEATURE_H
/*
* Features:
*
* MCHAN: multi-channel for concurrent P2P.
*/
#define BRCMF_FEAT_LIST \
BRCMF_FEAT_DEF(MCHAN)
/*
* Quirks:
*
* AUTO_AUTH: workaround needed for automatic authentication type.
* NEED_MPC: driver needs to disable MPC during scanning operation.
*/
#define BRCMF_QUIRK_LIST \
BRCMF_QUIRK_DEF(AUTO_AUTH) \
BRCMF_QUIRK_DEF(NEED_MPC)
#define BRCMF_FEAT_DEF(_f) \
BRCMF_FEAT_ ## _f,
/*
* expand feature list to enumeration.
*/
enum brcmf_feat_id {
BRCMF_FEAT_LIST
BRCMF_FEAT_LAST
};
#undef BRCMF_FEAT_DEF
#define BRCMF_QUIRK_DEF(_q) \
BRCMF_FEAT_QUIRK_ ## _q,
/*
* expand quirk list to enumeration.
*/
enum brcmf_feat_quirk {
BRCMF_QUIRK_LIST
BRCMF_FEAT_QUIRK_LAST
};
#undef BRCMF_QUIRK_DEF
/**
* brcmf_feat_attach() - determine features and quirks.
*
* @drvr: driver instance.
*/
void brcmf_feat_attach(struct brcmf_pub *drvr);
/**
* brcmf_feat_is_enabled() - query feature.
*
* @ifp: interface instance.
* @id: feature id to check.
*
* Return: true is feature is enabled; otherwise false.
*/
bool brcmf_feat_is_enabled(struct brcmf_if *ifp, enum brcmf_feat_id id);
/**
* brcmf_feat_is_quirk_enabled() - query chip quirk.
*
* @ifp: interface instance.
* @quirk: quirk id to check.
*
* Return: true is quirk is enabled; otherwise false.
*/
bool brcmf_feat_is_quirk_enabled(struct brcmf_if *ifp,
enum brcmf_feat_quirk quirk);
#endif /* _BRCMF_FEATURE_H */

View File

@ -18,10 +18,15 @@
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/module.h>
#include "dhd_dbg.h"
#include "firmware.h"
char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
module_param_string(firmware_path, brcmf_firmware_path,
BRCMF_FW_PATH_LEN, 0440);
enum nvram_parser_state {
IDLE,
KEY,

View File

@ -21,6 +21,11 @@
#define BRCMF_FW_REQ_FLAGS 0x00F0
#define BRCMF_FW_REQ_NV_OPTIONAL 0x0010
#define BRCMF_FW_PATH_LEN 256
#define BRCMF_FW_NAME_LEN 32
extern char brcmf_firmware_path[];
void brcmf_fw_nvram_free(void *nvram);
/*
* Request firmware(s) asynchronously. When the asynchronous request

View File

@ -454,6 +454,34 @@ struct brcmf_fws_macdesc_table {
struct brcmf_fws_mac_descriptor other;
};
struct brcmf_fws_stats {
u32 tlv_parse_failed;
u32 tlv_invalid_type;
u32 header_only_pkt;
u32 header_pulls;
u32 pkt2bus;
u32 send_pkts[5];
u32 requested_sent[5];
u32 generic_error;
u32 mac_update_failed;
u32 mac_ps_update_failed;
u32 if_update_failed;
u32 packet_request_failed;
u32 credit_request_failed;
u32 rollback_success;
u32 rollback_failed;
u32 delayq_full_error;
u32 supprq_full_error;
u32 txs_indicate;
u32 txs_discard;
u32 txs_supp_core;
u32 txs_supp_ps;
u32 txs_tossed;
u32 txs_host_tossed;
u32 bus_flow_block;
u32 fws_flow_block;
};
struct brcmf_fws_info {
struct brcmf_pub *drvr;
spinlock_t spinlock;
@ -2017,6 +2045,75 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
brcmf_fws_unlock(fws);
}
#ifdef DEBUG
static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data)
{
struct brcmf_bus *bus_if = dev_get_drvdata(seq->private);
struct brcmf_fws_stats *fwstats = &bus_if->drvr->fws->stats;
seq_printf(seq,
"header_pulls: %u\n"
"header_only_pkt: %u\n"
"tlv_parse_failed: %u\n"
"tlv_invalid_type: %u\n"
"mac_update_fails: %u\n"
"ps_update_fails: %u\n"
"if_update_fails: %u\n"
"pkt2bus: %u\n"
"generic_error: %u\n"
"rollback_success: %u\n"
"rollback_failed: %u\n"
"delayq_full: %u\n"
"supprq_full: %u\n"
"txs_indicate: %u\n"
"txs_discard: %u\n"
"txs_suppr_core: %u\n"
"txs_suppr_ps: %u\n"
"txs_tossed: %u\n"
"txs_host_tossed: %u\n"
"bus_flow_block: %u\n"
"fws_flow_block: %u\n"
"send_pkts: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n"
"requested_sent: BK:%u BE:%u VO:%u VI:%u BCMC:%u\n",
fwstats->header_pulls,
fwstats->header_only_pkt,
fwstats->tlv_parse_failed,
fwstats->tlv_invalid_type,
fwstats->mac_update_failed,
fwstats->mac_ps_update_failed,
fwstats->if_update_failed,
fwstats->pkt2bus,
fwstats->generic_error,
fwstats->rollback_success,
fwstats->rollback_failed,
fwstats->delayq_full_error,
fwstats->supprq_full_error,
fwstats->txs_indicate,
fwstats->txs_discard,
fwstats->txs_supp_core,
fwstats->txs_supp_ps,
fwstats->txs_tossed,
fwstats->txs_host_tossed,
fwstats->bus_flow_block,
fwstats->fws_flow_block,
fwstats->send_pkts[0], fwstats->send_pkts[1],
fwstats->send_pkts[2], fwstats->send_pkts[3],
fwstats->send_pkts[4],
fwstats->requested_sent[0],
fwstats->requested_sent[1],
fwstats->requested_sent[2],
fwstats->requested_sent[3],
fwstats->requested_sent[4]);
return 0;
}
#else
static int brcmf_debugfs_fws_stats_read(struct seq_file *seq, void *data)
{
return 0;
}
#endif
int brcmf_fws_init(struct brcmf_pub *drvr)
{
struct brcmf_fws_info *fws;
@ -2107,7 +2204,8 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
BRCMF_FWS_PSQ_LEN);
/* create debugfs file for statistics */
brcmf_debugfs_create_fws_stats(drvr, &fws->stats);
brcmf_debugfs_add_entry(drvr, "fws_stats",
brcmf_debugfs_fws_stats_read);
brcmf_dbg(INFO, "%s bdcv2 tlv signaling [%x]\n",
fws->fw_signals ? "enabled" : "disabled", tlv);

View File

@ -18,6 +18,8 @@
#define _BRCM_SDH_H_
#include <linux/skbuff.h>
#include <linux/firmware.h>
#include "firmware.h"
#define SDIO_FUNC_0 0
#define SDIO_FUNC_1 1
@ -182,6 +184,8 @@ struct brcmf_sdio_dev {
uint max_segment_size;
uint txglomsz;
struct sg_table sgtable;
char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
};
/* sdio core registers */

View File

@ -21,6 +21,7 @@
#include <linux/vmalloc.h>
#include <brcmu_utils.h>
#include <brcm_hw_ids.h>
#include <brcmu_wifi.h>
#include <dhd_bus.h>
#include <dhd_dbg.h>
@ -913,16 +914,16 @@ static int brcmf_usb_dlrun(struct brcmf_usbdev_info *devinfo)
static bool brcmf_usb_chip_support(int chipid, int chiprev)
{
switch(chipid) {
case 43143:
case BRCM_CC_43143_CHIP_ID:
return true;
case 43235:
case 43236:
case 43238:
case BRCM_CC_43235_CHIP_ID:
case BRCM_CC_43236_CHIP_ID:
case BRCM_CC_43238_CHIP_ID:
return (chiprev == 3);
case 43242:
case BRCM_CC_43242_CHIP_ID:
return true;
case 43566:
case 43569:
case BRCM_CC_43566_CHIP_ID:
case BRCM_CC_43569_CHIP_ID:
return true;
default:
break;
@ -1016,16 +1017,16 @@ static int check_file(const u8 *headers)
static const char *brcmf_usb_get_fwname(struct brcmf_usbdev_info *devinfo)
{
switch (devinfo->bus_pub.devid) {
case 43143:
case BRCM_CC_43143_CHIP_ID:
return BRCMF_USB_43143_FW_NAME;
case 43235:
case 43236:
case 43238:
case BRCM_CC_43235_CHIP_ID:
case BRCM_CC_43236_CHIP_ID:
case BRCM_CC_43238_CHIP_ID:
return BRCMF_USB_43236_FW_NAME;
case 43242:
case BRCM_CC_43242_CHIP_ID:
return BRCMF_USB_43242_FW_NAME;
case 43566:
case 43569:
case BRCM_CC_43566_CHIP_ID:
case BRCM_CC_43569_CHIP_ID:
return BRCMF_USB_43569_FW_NAME;
default:
return NULL;
@ -1366,21 +1367,17 @@ static int brcmf_usb_reset_resume(struct usb_interface *intf)
brcmf_usb_probe_phase2);
}
#define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c
#define BRCMF_USB_DEVICE_ID_43143 0xbd1e
#define BRCMF_USB_DEVICE_ID_43236 0xbd17
#define BRCMF_USB_DEVICE_ID_43242 0xbd1f
#define BRCMF_USB_DEVICE_ID_43569 0xbd27
#define BRCMF_USB_DEVICE_ID_BCMFW 0x0bdc
#define BRCMF_USB_DEVICE(dev_id) \
{ USB_DEVICE(BRCM_USB_VENDOR_ID_BROADCOM, dev_id) }
static struct usb_device_id brcmf_usb_devid_table[] = {
{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43143) },
{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43236) },
{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43242) },
{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_43569) },
BRCMF_USB_DEVICE(BRCM_USB_43143_DEVICE_ID),
BRCMF_USB_DEVICE(BRCM_USB_43236_DEVICE_ID),
BRCMF_USB_DEVICE(BRCM_USB_43242_DEVICE_ID),
BRCMF_USB_DEVICE(BRCM_USB_43569_DEVICE_ID),
/* special entry for device with firmware loaded and running */
{ USB_DEVICE(BRCMF_USB_VENDOR_ID_BROADCOM, BRCMF_USB_DEVICE_ID_BCMFW) },
{ }
BRCMF_USB_DEVICE(BRCM_USB_BCMFW_DEVICE_ID),
{ /* end: all zeroes */ }
};
MODULE_DEVICE_TABLE(usb, brcmf_usb_devid_table);

File diff suppressed because it is too large Load Diff

View File

@ -4707,41 +4707,6 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core,
return err;
}
static void brcms_c_attach_antgain_init(struct brcms_c_info *wlc)
{
uint unit;
unit = wlc->pub->unit;
if ((wlc->band->antgain == -1) && (wlc->pub->sromrev == 1)) {
/* default antenna gain for srom rev 1 is 2 dBm (8 qdbm) */
wlc->band->antgain = 8;
} else if (wlc->band->antgain == -1) {
wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in"
" srom, using 2dB\n", unit, __func__);
wlc->band->antgain = 8;
} else {
s8 gain, fract;
/* Older sroms specified gain in whole dbm only. In order
* be able to specify qdbm granularity and remain backward
* compatible the whole dbms are now encoded in only
* low 6 bits and remaining qdbms are encoded in the hi 2 bits.
* 6 bit signed number ranges from -32 - 31.
*
* Examples:
* 0x1 = 1 db,
* 0xc1 = 1.75 db (1 + 3 quarters),
* 0x3f = -1 (-1 + 0 quarters),
* 0x7f = -.75 (-1 + 1 quarters) = -3 qdbm.
* 0xbf = -.50 (-1 + 2 quarters) = -2 qdbm.
*/
gain = wlc->band->antgain & 0x3f;
gain <<= 2; /* Sign extend */
gain >>= 2;
fract = (wlc->band->antgain & 0xc0) >> 6;
wlc->band->antgain = 4 * gain + fract;
}
}
static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc)
{
int aa;
@ -4780,8 +4745,6 @@ static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc)
else
wlc->band->antgain = sprom->antenna_gain.a0;
brcms_c_attach_antgain_init(wlc);
return true;
}

View File

@ -17,32 +17,56 @@
#ifndef _BRCM_HW_IDS_H_
#define _BRCM_HW_IDS_H_
#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */
#include <linux/pci_ids.h>
#include <linux/mmc/sdio_ids.h>
#define BRCM_USB_VENDOR_ID_BROADCOM 0x0a5c
#define BRCM_PCIE_VENDOR_ID_BROADCOM PCI_VENDOR_ID_BROADCOM
#define BRCM_SDIO_VENDOR_ID_BROADCOM SDIO_VENDOR_ID_BROADCOM
/* Chipcommon Core Chip IDs */
#define BRCM_CC_43143_CHIP_ID 43143
#define BRCM_CC_43235_CHIP_ID 43235
#define BRCM_CC_43236_CHIP_ID 43236
#define BRCM_CC_43238_CHIP_ID 43238
#define BRCM_CC_43241_CHIP_ID 0x4324
#define BRCM_CC_43242_CHIP_ID 43242
#define BRCM_CC_4329_CHIP_ID 0x4329
#define BRCM_CC_4330_CHIP_ID 0x4330
#define BRCM_CC_4334_CHIP_ID 0x4334
#define BRCM_CC_43362_CHIP_ID 43362
#define BRCM_CC_4335_CHIP_ID 0x4335
#define BRCM_CC_4339_CHIP_ID 0x4339
#define BRCM_CC_4354_CHIP_ID 0x4354
#define BRCM_CC_43566_CHIP_ID 43566
#define BRCM_CC_43569_CHIP_ID 43569
/* SDIO Device IDs */
#define BRCM_SDIO_43143_DEVICE_ID BRCM_CC_43143_CHIP_ID
#define BRCM_SDIO_43241_DEVICE_ID BRCM_CC_43241_CHIP_ID
#define BRCM_SDIO_4329_DEVICE_ID BRCM_CC_4329_CHIP_ID
#define BRCM_SDIO_4330_DEVICE_ID BRCM_CC_4330_CHIP_ID
#define BRCM_SDIO_4334_DEVICE_ID BRCM_CC_4334_CHIP_ID
#define BRCM_SDIO_43362_DEVICE_ID BRCM_CC_43362_CHIP_ID
#define BRCM_SDIO_4335_4339_DEVICE_ID BRCM_CC_4335_CHIP_ID
#define BRCM_SDIO_4354_DEVICE_ID BRCM_CC_4354_CHIP_ID
/* USB Device IDs */
#define BRCM_USB_43143_DEVICE_ID 0xbd1e
#define BRCM_USB_43236_DEVICE_ID 0xbd17
#define BRCM_USB_43242_DEVICE_ID 0xbd1f
#define BRCM_USB_43569_DEVICE_ID 0xbd27
#define BRCM_USB_BCMFW_DEVICE_ID 0x0bdc
/* brcmsmac IDs */
#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */
#define BCM43224_D11N_ID 0x4353 /* 43224 802.11n dualband device */
#define BCM43224_D11N_ID_VEN1 0x0576 /* Vendor specific 43224 802.11n db */
#define BCM43225_D11N2G_ID 0x4357 /* 43225 802.11n 2.4GHz device */
#define BCM43236_D11N_ID 0x4346 /* 43236 802.11n dualband device */
#define BCM43236_D11N2G_ID 0x4347 /* 43236 802.11n 2.4GHz device */
/* Chipcommon Core Chip IDs */
#define BCM4313_CHIP_ID 0x4313
#define BCM43143_CHIP_ID 43143
#define BCM43224_CHIP_ID 43224
#define BCM43225_CHIP_ID 43225
#define BCM43235_CHIP_ID 43235
#define BCM43236_CHIP_ID 43236
#define BCM43238_CHIP_ID 43238
#define BCM43241_CHIP_ID 0x4324
#define BCM4329_CHIP_ID 0x4329
#define BCM4330_CHIP_ID 0x4330
#define BCM4331_CHIP_ID 0x4331
#define BCM4334_CHIP_ID 0x4334
#define BCM4335_CHIP_ID 0x4335
#define BCM43362_CHIP_ID 43362
#define BCM4339_CHIP_ID 0x4339
#define BCM4354_CHIP_ID 0x4354
#endif /* _BRCM_HW_IDS_H_ */

View File

@ -20,16 +20,17 @@ config IWLWIFI
Intel 2000 Series Wi-Fi Adapters
Intel 7260 Wi-Fi Adapter
Intel 3160 Wi-Fi Adapter
Intel 7265 Wi-Fi Adapter
This driver uses the kernel's mac80211 subsystem.
In order to use this driver, you will need a microcode (uCode)
In order to use this driver, you will need a firmware
image for it. You can obtain the microcode from:
<http://intellinuxwireless.org/>.
<http://wireless.kernel.org/en/users/Drivers/iwlwifi>.
The microcode is typically installed in /lib/firmware. You can
The firmware is typically installed in /lib/firmware. You can
look in the hotplug script /etc/hotplug/firmware.agent to
determine which directory FIRMWARE_DIR is set to when the script
runs.
@ -39,9 +40,10 @@ config IWLWIFI
say M here and read <file:Documentation/kbuild/modules.txt>. The
module will be called iwlwifi.
if IWLWIFI
config IWLWIFI_LEDS
bool
depends on IWLWIFI
depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI
select LEDS_TRIGGERS
select MAC80211_LEDS
@ -49,7 +51,7 @@ config IWLWIFI_LEDS
config IWLDVM
tristate "Intel Wireless WiFi DVM Firmware support"
depends on IWLWIFI
depends on m
default IWLWIFI
help
This is the driver that supports the DVM firmware which is
@ -58,7 +60,7 @@ config IWLDVM
config IWLMVM
tristate "Intel Wireless WiFi MVM Firmware support"
depends on IWLWIFI
depends on m
help
This is the driver that supports the MVM firmware which is
currently only available for 7260 and 3160 devices.
@ -70,7 +72,7 @@ config IWLWIFI_OPMODE_MODULAR
default y if IWLMVM=m
comment "WARNING: iwlwifi is useless without IWLDVM or IWLMVM"
depends on IWLWIFI && IWLDVM=n && IWLMVM=n
depends on IWLDVM=n && IWLMVM=n
config IWLWIFI_BCAST_FILTERING
bool "Enable broadcast filtering"
@ -86,11 +88,9 @@ config IWLWIFI_BCAST_FILTERING
expect incoming broadcasts for their normal operations.
menu "Debugging Options"
depends on IWLWIFI
config IWLWIFI_DEBUG
bool "Enable full debugging output in the iwlwifi driver"
depends on IWLWIFI
---help---
This option will enable debug tracing output for the iwlwifi drivers
@ -115,7 +115,7 @@ config IWLWIFI_DEBUG
config IWLWIFI_DEBUGFS
bool "iwlwifi debugfs support"
depends on IWLWIFI && MAC80211_DEBUGFS
depends on MAC80211_DEBUGFS
---help---
Enable creation of debugfs files for the iwlwifi drivers. This
is a low-impact option that allows getting insight into the
@ -123,13 +123,12 @@ config IWLWIFI_DEBUGFS
config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
bool "Experimental uCode support"
depends on IWLWIFI && IWLWIFI_DEBUG
depends on IWLWIFI_DEBUG
---help---
Enable use of experimental ucode for testing and debugging.
config IWLWIFI_DEVICE_TRACING
bool "iwlwifi device access tracing"
depends on IWLWIFI
depends on EVENT_TRACING
help
Say Y here to trace all commands, including TX frames and IO
@ -145,3 +144,5 @@ config IWLWIFI_DEVICE_TRACING
If unsure, say Y so we can help you better when problems
occur.
endmenu
endif

View File

@ -85,6 +85,9 @@
#define NVM_HW_SECTION_NUM_FAMILY_8000 10
#define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000.bin"
/* Max SDIO RX aggregation size of the ADDBA request/response */
#define MAX_RX_AGG_SIZE_8260_SDIO 28
static const struct iwl_base_params iwl8000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000,
.num_of_queues = IWLAGN_NUM_QUEUES,
@ -129,6 +132,7 @@ const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
.nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
.default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
.max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
};
MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK));

View File

@ -240,6 +240,7 @@ struct iwl_pwr_tx_backoff {
* @d0i3: device uses d0i3 instead of d3
* @nvm_hw_section_num: the ID of the HW NVM section
* @pwr_tx_backoffs: translation table between power limits and backoffs
* @max_rx_agg_size: max RX aggregation size of the ADDBA request/response
*
* We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs
@ -276,6 +277,7 @@ struct iwl_cfg {
const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
bool no_power_up_nic_in_init;
const char *default_nvm_file;
unsigned int max_rx_agg_size;
};
/*

View File

@ -70,21 +70,24 @@
/**
* enum iwl_fw_error_dump_type - types of data in the dump file
* @IWL_FW_ERROR_DUMP_SRAM:
* @IWL_FW_ERROR_DUMP_REG:
* @IWL_FW_ERROR_DUMP_CSR: Control Status Registers - from offset 0
* @IWL_FW_ERROR_DUMP_RXF:
* @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as
* &struct iwl_fw_error_dump_txcmd packets
* @IWL_FW_ERROR_DUMP_DEV_FW_INFO: struct %iwl_fw_error_dump_info
* info on the device / firmware.
* @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor
* @IWL_FW_ERROR_DUMP_PRPH: range of periphery registers - there can be several
* sections like this in a single file.
*/
enum iwl_fw_error_dump_type {
IWL_FW_ERROR_DUMP_SRAM = 0,
IWL_FW_ERROR_DUMP_REG = 1,
IWL_FW_ERROR_DUMP_CSR = 1,
IWL_FW_ERROR_DUMP_RXF = 2,
IWL_FW_ERROR_DUMP_TXCMD = 3,
IWL_FW_ERROR_DUMP_DEV_FW_INFO = 4,
IWL_FW_ERROR_DUMP_FW_MONITOR = 5,
IWL_FW_ERROR_DUMP_PRPH = 6,
IWL_FW_ERROR_DUMP_MAX,
};
@ -162,6 +165,16 @@ struct iwl_fw_error_dump_fw_mon {
u8 data[];
} __packed;
/**
* struct iwl_fw_error_dump_prph - periphery registers data
* @prph_start: address of the first register in this chunk
* @data: the content of the registers
*/
struct iwl_fw_error_dump_prph {
__le32 prph_start;
__le32 data[];
};
/**
* iwl_fw_error_next_data - advance fw error dump data pointer
* @data: previous data block

View File

@ -99,7 +99,7 @@ enum iwl_disable_11n {
* @wd_disable: disable stuck queue check, default = 1
* @bt_coex_active: enable bt coex, default = true
* @led_mode: system default, default = 0
* @power_save: disable power save, default = false
* @power_save: enable power save, default = false
* @power_level: power level, default = 1
* @debug_level: levels are IWL_DL_*
* @ant_coupling: antenna coupling in dB, default = 0

View File

@ -394,6 +394,11 @@ struct iwl_trans_config {
const char *const *command_names;
};
struct iwl_trans_dump_data {
u32 len;
u8 data[];
};
struct iwl_trans;
/**
@ -461,10 +466,8 @@ struct iwl_trans;
* @unref: release a reference previously taken with @ref. Note that
* initially the reference count is 1, making an initial @unref
* necessary to allow low power states.
* @dump_data: fill a data dump with debug data, maybe containing last
* TX'ed commands and similar. When called with a NULL buffer and
* zero buffer length, provide only the (estimated) required buffer
* length. Return the used buffer length.
* @dump_data: return a vmalloc'ed buffer with debug data, maybe containing last
* TX'ed commands and similar. The buffer will be vfree'd by the caller.
* Note that the transport must fill in the proper file headers.
*/
struct iwl_trans_ops {
@ -518,7 +521,7 @@ struct iwl_trans_ops {
void (*unref)(struct iwl_trans *trans);
#ifdef CONFIG_IWLWIFI_DEBUGFS
u32 (*dump_data)(struct iwl_trans *trans, void *buf, u32 buflen);
struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans);
#endif
};
@ -685,12 +688,12 @@ static inline void iwl_trans_unref(struct iwl_trans *trans)
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
static inline u32 iwl_trans_dump_data(struct iwl_trans *trans,
void *buf, u32 buflen)
static inline struct iwl_trans_dump_data *
iwl_trans_dump_data(struct iwl_trans *trans)
{
if (!trans->ops->dump_data)
return 0;
return trans->ops->dump_data(trans, buf, buflen);
return NULL;
return trans->ops->dump_data(trans);
}
#endif

View File

@ -72,16 +72,56 @@
#define BT_ANTENNA_COUPLING_THRESHOLD (30)
const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = {
[BT_KILL_MSK_DEFAULT] = 0xffff0000,
[BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
[BT_KILL_MSK_REDUCED_TXPOW] = 0,
const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = {
[BT_KILL_MSK_DEFAULT] = 0xfffffc00,
[BT_KILL_MSK_NEVER] = 0xffffffff,
[BT_KILL_MSK_ALWAYS] = 0,
};
const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = {
[BT_KILL_MSK_DEFAULT] = 0xffff0000,
[BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
[BT_KILL_MSK_REDUCED_TXPOW] = 0,
const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = {
{
BT_KILL_MSK_ALWAYS,
BT_KILL_MSK_ALWAYS,
BT_KILL_MSK_ALWAYS,
},
{
BT_KILL_MSK_NEVER,
BT_KILL_MSK_NEVER,
BT_KILL_MSK_NEVER,
},
{
BT_KILL_MSK_NEVER,
BT_KILL_MSK_NEVER,
BT_KILL_MSK_NEVER,
},
{
BT_KILL_MSK_DEFAULT,
BT_KILL_MSK_NEVER,
BT_KILL_MSK_DEFAULT,
},
};
const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT] = {
{
BT_KILL_MSK_ALWAYS,
BT_KILL_MSK_ALWAYS,
BT_KILL_MSK_ALWAYS,
},
{
BT_KILL_MSK_ALWAYS,
BT_KILL_MSK_ALWAYS,
BT_KILL_MSK_ALWAYS,
},
{
BT_KILL_MSK_ALWAYS,
BT_KILL_MSK_ALWAYS,
BT_KILL_MSK_ALWAYS,
},
{
BT_KILL_MSK_DEFAULT,
BT_KILL_MSK_ALWAYS,
BT_KILL_MSK_DEFAULT,
},
};
static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = {
@ -611,54 +651,43 @@ send_cmd:
return ret;
}
static int iwl_mvm_bt_udpate_sw_boost(struct iwl_mvm *mvm,
bool reduced_tx_power)
static int iwl_mvm_bt_udpate_sw_boost(struct iwl_mvm *mvm)
{
enum iwl_bt_kill_msk bt_kill_msk;
struct iwl_bt_coex_sw_boost_update_cmd cmd = {};
struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
u32 primary_lut = le32_to_cpu(notif->primary_ch_lut);
u32 secondary_lut = le32_to_cpu(notif->secondary_ch_lut);
u32 ag = le32_to_cpu(notif->bt_activity_grading);
struct iwl_bt_coex_sw_boost_update_cmd cmd = {};
u8 ack_kill_msk[NUM_PHY_CTX] = {};
u8 cts_kill_msk[NUM_PHY_CTX] = {};
int i;
lockdep_assert_held(&mvm->mutex);
if (reduced_tx_power) {
/* Reduced Tx power has precedence on the type of the profile */
bt_kill_msk = BT_KILL_MSK_REDUCED_TXPOW;
} else {
/* Low latency BT profile is active: give higher prio to BT */
if (BT_MBOX_MSG(notif, 3, SCO_STATE) ||
BT_MBOX_MSG(notif, 3, A2DP_STATE) ||
BT_MBOX_MSG(notif, 3, SNIFF_STATE))
bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP;
else
bt_kill_msk = BT_KILL_MSK_DEFAULT;
}
ack_kill_msk[0] = iwl_bt_ack_kill_msk[ag][primary_lut];
cts_kill_msk[0] = iwl_bt_cts_kill_msk[ag][primary_lut];
IWL_DEBUG_COEX(mvm,
"Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n",
bt_kill_msk,
BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in");
ack_kill_msk[1] = iwl_bt_ack_kill_msk[ag][secondary_lut];
cts_kill_msk[1] = iwl_bt_cts_kill_msk[ag][secondary_lut];
/* Don't send HCMD if there is no update */
if (bt_kill_msk == mvm->bt_kill_msk)
if (!memcmp(ack_kill_msk, mvm->bt_ack_kill_msk, sizeof(ack_kill_msk)) ||
!memcmp(cts_kill_msk, mvm->bt_cts_kill_msk, sizeof(cts_kill_msk)))
return 0;
mvm->bt_kill_msk = bt_kill_msk;
memcpy(mvm->bt_ack_kill_msk, ack_kill_msk,
sizeof(mvm->bt_ack_kill_msk));
memcpy(mvm->bt_cts_kill_msk, cts_kill_msk,
sizeof(mvm->bt_cts_kill_msk));
cmd.boost_values[0].kill_ack_msk =
cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
cmd.boost_values[0].kill_cts_msk =
cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
BUILD_BUG_ON(ARRAY_SIZE(ack_kill_msk) < ARRAY_SIZE(cmd.boost_values));
cmd.boost_values[1].kill_ack_msk = cmd.boost_values[0].kill_ack_msk;
cmd.boost_values[2].kill_cts_msk = cmd.boost_values[0].kill_cts_msk;
cmd.boost_values[1].kill_ack_msk = cmd.boost_values[0].kill_ack_msk;
cmd.boost_values[2].kill_cts_msk = cmd.boost_values[0].kill_cts_msk;
IWL_DEBUG_COEX(mvm, "ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x\n",
iwl_bt_ack_kill_msk[bt_kill_msk],
iwl_bt_cts_kill_msk[bt_kill_msk]);
for (i = 0; i < ARRAY_SIZE(cmd.boost_values); i++) {
cmd.boost_values[i].kill_ack_msk =
cpu_to_le32(iwl_bt_ctl_kill_msk[ack_kill_msk[i]]);
cmd.boost_values[i].kill_cts_msk =
cpu_to_le32(iwl_bt_ctl_kill_msk[cts_kill_msk[i]]);
}
return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_SW_BOOST, 0,
sizeof(cmd), &cmd);
@ -700,8 +729,6 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
struct iwl_bt_iterator_data {
struct iwl_bt_coex_profile_notif *notif;
struct iwl_mvm *mvm;
u32 num_bss_ifaces;
bool reduced_tx_power;
struct ieee80211_chanctx_conf *primary;
struct ieee80211_chanctx_conf *secondary;
bool primary_ll;
@ -737,22 +764,12 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
switch (vif->type) {
case NL80211_IFTYPE_STATION:
/* Count BSSes vifs */
data->num_bss_ifaces++;
/* default smps_mode for BSS / P2P client is AUTOMATIC */
smps_mode = IEEE80211_SMPS_AUTOMATIC;
break;
case NL80211_IFTYPE_AP:
/* default smps_mode for AP / GO is OFF */
smps_mode = IEEE80211_SMPS_OFF;
if (!mvmvif->ap_ibss_active) {
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
smps_mode);
if (!mvmvif->ap_ibss_active)
return;
}
/* the Ack / Cts kill mask must be default if AP / GO */
data->reduced_tx_power = false;
break;
default:
return;
@ -763,11 +780,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
/* If channel context is invalid or not on 2.4GHz .. */
if ((!chanctx_conf ||
chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) {
/* ... relax constraints and disable rssi events */
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
smps_mode);
data->reduced_tx_power = false;
if (vif->type == NL80211_IFTYPE_STATION) {
/* ... relax constraints and disable rssi events */
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
smps_mode);
iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
false);
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
@ -779,9 +795,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if (bt_activity_grading >= BT_HIGH_TRAFFIC)
smps_mode = IEEE80211_SMPS_STATIC;
else if (bt_activity_grading >= BT_LOW_TRAFFIC)
smps_mode = vif->type == NL80211_IFTYPE_AP ?
IEEE80211_SMPS_OFF :
IEEE80211_SMPS_DYNAMIC;
smps_mode = IEEE80211_SMPS_DYNAMIC;
/* relax SMPS contraints for next association */
if (!vif->bss_conf.assoc)
@ -795,7 +809,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
"mac %d: bt_activity_grading %d smps_req %d\n",
mvmvif->id, bt_activity_grading, smps_mode);
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode);
if (vif->type == NL80211_IFTYPE_STATION)
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
smps_mode);
/* low latency is always primary */
if (iwl_mvm_vif_low_latency(mvmvif)) {
@ -846,7 +862,6 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc ||
le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF) {
data->reduced_tx_power = false;
iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false);
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
return;
@ -861,23 +876,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) {
if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
/*
* bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the
* BSS / P2P clients have rssi above threshold.
* We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before
* the iteration, if one interface's rssi isn't good enough,
* bt_kill_msk will be set to default values.
*/
} else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) {
if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
/*
* One interface hasn't rssi above threshold, bt_kill_msk must
* be set to default values.
*/
data->reduced_tx_power = false;
}
/* Begin to monitor the RSSI: it may influence the reduced Tx power */
@ -889,7 +890,6 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
struct iwl_bt_iterator_data data = {
.mvm = mvm,
.notif = &mvm->last_bt_notif,
.reduced_tx_power = true,
};
struct iwl_bt_coex_ci_cmd cmd = {};
u8 ci_bw_idx;
@ -959,14 +959,7 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd));
}
/*
* If there are no BSS / P2P client interfaces, reduced Tx Power is
* irrelevant since it is based on the RSSI coming from the beacon.
* Use BT_KILL_MSK_DEFAULT in that case.
*/
data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
if (iwl_mvm_bt_udpate_sw_boost(mvm, data.reduced_tx_power))
if (iwl_mvm_bt_udpate_sw_boost(mvm))
IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
}
@ -1035,16 +1028,6 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
return;
mvmsta = iwl_mvm_sta_from_mac80211(sta);
data->num_bss_ifaces++;
/*
* This interface doesn't support reduced Tx power (because of low
* RSSI probably), then set bt_kill_msk to default values.
*/
if (!mvmsta->bt_reduced_txpower)
data->reduced_tx_power = false;
/* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */
}
void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@ -1053,7 +1036,6 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
struct iwl_bt_iterator_data data = {
.mvm = mvm,
.reduced_tx_power = true,
};
int ret;
@ -1100,14 +1082,7 @@ void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_bt_rssi_iterator, &data);
/*
* If there are no BSS / P2P client interfaces, reduced Tx Power is
* irrelevant since it is based on the RSSI coming from the beacon.
* Use BT_KILL_MSK_DEFAULT in that case.
*/
data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
if (iwl_mvm_bt_udpate_sw_boost(mvm, data.reduced_tx_power))
if (iwl_mvm_bt_udpate_sw_boost(mvm))
IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
}
@ -1150,7 +1125,7 @@ bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
enum iwl_bt_coex_lut_type lut_type;
if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
return iwl_mvm_coex_agg_time_limit_old(mvm, sta);
return iwl_mvm_bt_coex_is_mimo_allowed_old(mvm, sta);
if (IWL_COEX_IS_TTC_ON(mvm->last_bt_notif.ttc_rrc_status, phy_ctxt->id))
return true;

View File

@ -649,10 +649,6 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm)
sizeof(iwl_bt_prio_boost));
memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut,
sizeof(iwl_bt_mprio_lut));
bt_cmd->kill_ack_msk =
cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]);
bt_cmd->kill_cts_msk =
cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]);
send_cmd:
memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
@ -664,12 +660,13 @@ send_cmd:
return ret;
}
static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
bool reduced_tx_power)
static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm)
{
enum iwl_bt_kill_msk bt_kill_msk;
struct iwl_bt_coex_cmd_old *bt_cmd;
struct iwl_bt_coex_profile_notif_old *notif = &mvm->last_bt_notif_old;
u32 primary_lut = le32_to_cpu(notif->primary_ch_lut);
u32 ag = le32_to_cpu(notif->bt_activity_grading);
struct iwl_bt_coex_cmd_old *bt_cmd;
u8 ack_kill_msk, cts_kill_msk;
struct iwl_host_cmd cmd = {
.id = BT_CONFIG,
.data[0] = &bt_cmd,
@ -680,31 +677,15 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
lockdep_assert_held(&mvm->mutex);
if (reduced_tx_power) {
/* Reduced Tx power has precedence on the type of the profile */
bt_kill_msk = BT_KILL_MSK_REDUCED_TXPOW;
} else {
/* Low latency BT profile is active: give higher prio to BT */
if (BT_MBOX_MSG(notif, 3, SCO_STATE) ||
BT_MBOX_MSG(notif, 3, A2DP_STATE) ||
BT_MBOX_MSG(notif, 3, SNIFF_STATE))
bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP;
else
bt_kill_msk = BT_KILL_MSK_DEFAULT;
}
ack_kill_msk = iwl_bt_ack_kill_msk[ag][primary_lut];
cts_kill_msk = iwl_bt_cts_kill_msk[ag][primary_lut];
IWL_DEBUG_COEX(mvm,
"Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n",
bt_kill_msk,
BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in");
/* Don't send HCMD if there is no update */
if (bt_kill_msk == mvm->bt_kill_msk)
if (mvm->bt_ack_kill_msk[0] == ack_kill_msk &&
mvm->bt_cts_kill_msk[0] == cts_kill_msk)
return 0;
mvm->bt_kill_msk = bt_kill_msk;
mvm->bt_ack_kill_msk[0] = ack_kill_msk;
mvm->bt_cts_kill_msk[0] = cts_kill_msk;
bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
if (!bt_cmd)
@ -712,16 +693,12 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
cmd.data[0] = bt_cmd;
bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD);
bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ctl_kill_msk[ack_kill_msk]);
bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_ctl_kill_msk[cts_kill_msk]);
bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE |
BT_VALID_KILL_ACK |
BT_VALID_KILL_CTS);
IWL_DEBUG_COEX(mvm, "ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x\n",
iwl_bt_ack_kill_msk[bt_kill_msk],
iwl_bt_cts_kill_msk[bt_kill_msk]);
ret = iwl_mvm_send_cmd(mvm, &cmd);
kfree(bt_cmd);
@ -777,8 +754,6 @@ static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
struct iwl_bt_iterator_data {
struct iwl_bt_coex_profile_notif_old *notif;
struct iwl_mvm *mvm;
u32 num_bss_ifaces;
bool reduced_tx_power;
struct ieee80211_chanctx_conf *primary;
struct ieee80211_chanctx_conf *secondary;
bool primary_ll;
@ -814,22 +789,12 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
switch (vif->type) {
case NL80211_IFTYPE_STATION:
/* Count BSSes vifs */
data->num_bss_ifaces++;
/* default smps_mode for BSS / P2P client is AUTOMATIC */
smps_mode = IEEE80211_SMPS_AUTOMATIC;
break;
case NL80211_IFTYPE_AP:
/* default smps_mode for AP / GO is OFF */
smps_mode = IEEE80211_SMPS_OFF;
if (!mvmvif->ap_ibss_active) {
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
smps_mode);
if (!mvmvif->ap_ibss_active)
return;
}
/* the Ack / Cts kill mask must be default if AP / GO */
data->reduced_tx_power = false;
break;
default:
return;
@ -840,11 +805,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
/* If channel context is invalid or not on 2.4GHz .. */
if ((!chanctx_conf ||
chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) {
/* ... relax constraints and disable rssi events */
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
smps_mode);
data->reduced_tx_power = false;
if (vif->type == NL80211_IFTYPE_STATION) {
/* ... relax constraints and disable rssi events */
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
smps_mode);
iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
false);
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
@ -869,7 +833,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
mvmvif->id, data->notif->bt_status, bt_activity_grading,
smps_mode);
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode);
if (vif->type == NL80211_IFTYPE_STATION)
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
smps_mode);
/* low latency is always primary */
if (iwl_mvm_vif_low_latency(mvmvif)) {
@ -920,7 +886,6 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc ||
!data->notif->bt_status) {
data->reduced_tx_power = false;
iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false);
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
return;
@ -935,23 +900,9 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) {
if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
/*
* bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the
* BSS / P2P clients have rssi above threshold.
* We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before
* the iteration, if one interface's rssi isn't good enough,
* bt_kill_msk will be set to default values.
*/
} else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) {
if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
/*
* One interface hasn't rssi above threshold, bt_kill_msk must
* be set to default values.
*/
data->reduced_tx_power = false;
}
/* Begin to monitor the RSSI: it may influence the reduced Tx power */
@ -963,7 +914,6 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
struct iwl_bt_iterator_data data = {
.mvm = mvm,
.notif = &mvm->last_bt_notif_old,
.reduced_tx_power = true,
};
struct iwl_bt_coex_ci_cmd_old cmd = {};
u8 ci_bw_idx;
@ -1037,14 +987,7 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
memcpy(&mvm->last_bt_ci_cmd_old, &cmd, sizeof(cmd));
}
/*
* If there are no BSS / P2P client interfaces, reduced Tx Power is
* irrelevant since it is based on the RSSI coming from the beacon.
* Use BT_KILL_MSK_DEFAULT in that case.
*/
data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power))
if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm))
IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
}
@ -1115,16 +1058,6 @@ static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
return;
mvmsta = iwl_mvm_sta_from_mac80211(sta);
data->num_bss_ifaces++;
/*
* This interface doesn't support reduced Tx power (because of low
* RSSI probably), then set bt_kill_msk to default values.
*/
if (!mvmsta->bt_reduced_txpower)
data->reduced_tx_power = false;
/* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */
}
void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@ -1133,7 +1066,6 @@ void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
struct iwl_bt_iterator_data data = {
.mvm = mvm,
.reduced_tx_power = true,
};
int ret;
@ -1175,14 +1107,7 @@ void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_bt_rssi_iterator, &data);
/*
* If there are no BSS / P2P client interfaces, reduced Tx Power is
* irrelevant since it is based on the RSSI coming from the beacon.
* Use BT_KILL_MSK_DEFAULT in that case.
*/
data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power))
if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm))
IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
}

View File

@ -146,17 +146,47 @@ static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct iwl_fw_error_dump_file *dump_file = file->private_data;
struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
ssize_t bytes_read = 0;
ssize_t bytes_read_trans = 0;
if (*ppos < dump_ptrs->op_mode_len)
bytes_read +=
simple_read_from_buffer(user_buf, count, ppos,
dump_ptrs->op_mode_ptr,
dump_ptrs->op_mode_len);
if (bytes_read < 0 || *ppos < dump_ptrs->op_mode_len)
return bytes_read;
if (dump_ptrs->trans_ptr) {
*ppos -= dump_ptrs->op_mode_len;
bytes_read_trans =
simple_read_from_buffer(user_buf + bytes_read,
count - bytes_read, ppos,
dump_ptrs->trans_ptr->data,
dump_ptrs->trans_ptr->len);
*ppos += dump_ptrs->op_mode_len;
if (bytes_read_trans >= 0)
bytes_read += bytes_read_trans;
else if (!bytes_read)
/* propagate the failure */
return bytes_read_trans;
}
return bytes_read;
return simple_read_from_buffer(user_buf, count, ppos,
dump_file,
le32_to_cpu(dump_file->file_len));
}
static int iwl_dbgfs_fw_error_dump_release(struct inode *inode,
struct file *file)
{
vfree(file->private_data);
struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
vfree(dump_ptrs->op_mode_ptr);
vfree(dump_ptrs->trans_ptr);
kfree(dump_ptrs);
return 0;
}
@ -514,9 +544,9 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n");
pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n",
iwl_bt_ack_kill_msk[mvm->bt_kill_msk]);
iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[0]]);
pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n",
iwl_bt_cts_kill_msk[mvm->bt_kill_msk]);
iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[0]]);
} else {
struct iwl_bt_coex_ci_cmd *cmd = &mvm->last_bt_ci_cmd;
@ -531,10 +561,19 @@ static ssize_t iwl_dbgfs_bt_cmd_read(struct file *file, char __user *user_buf,
le64_to_cpu(cmd->bt_secondary_ci));
pos += scnprintf(buf+pos, bufsz-pos, "BT Configuration CMD\n");
pos += scnprintf(buf+pos, bufsz-pos, "\tACK Kill Mask 0x%08x\n",
iwl_bt_ack_kill_msk[mvm->bt_kill_msk]);
pos += scnprintf(buf+pos, bufsz-pos, "\tCTS Kill Mask 0x%08x\n",
iwl_bt_cts_kill_msk[mvm->bt_kill_msk]);
pos += scnprintf(buf+pos, bufsz-pos,
"\tPrimary: ACK Kill Mask 0x%08x\n",
iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[0]]);
pos += scnprintf(buf+pos, bufsz-pos,
"\tPrimary: CTS Kill Mask 0x%08x\n",
iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[0]]);
pos += scnprintf(buf+pos, bufsz-pos,
"\tSecondary: ACK Kill Mask 0x%08x\n",
iwl_bt_ctl_kill_msk[mvm->bt_ack_kill_msk[1]]);
pos += scnprintf(buf+pos, bufsz-pos,
"\tSecondary: CTS Kill Mask 0x%08x\n",
iwl_bt_ctl_kill_msk[mvm->bt_cts_kill_msk[1]]);
}
mutex_unlock(&mvm->mutex);
@ -830,8 +869,14 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos)
{
int ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_NMI);
if (ret)
return ret;
iwl_force_nmi(mvm->trans);
iwl_mvm_unref(mvm, IWL_MVM_REF_NMI);
return count;
}
@ -1115,11 +1160,11 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf,
}
#endif
#define PRINT_MVM_REF(ref) do { \
if (test_bit(ref, mvm->ref_bitmap)) \
pos += scnprintf(buf + pos, bufsz - pos, \
"\t(0x%lx) %s\n", \
BIT(ref), #ref); \
#define PRINT_MVM_REF(ref) do { \
if (mvm->refs[ref]) \
pos += scnprintf(buf + pos, bufsz - pos, \
"\t(0x%lx): %d %s\n", \
BIT(ref), mvm->refs[ref], #ref); \
} while (0)
static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
@ -1127,12 +1172,17 @@ static ssize_t iwl_dbgfs_d0i3_refs_read(struct file *file,
size_t count, loff_t *ppos)
{
struct iwl_mvm *mvm = file->private_data;
int pos = 0;
int i, pos = 0;
char buf[256];
const size_t bufsz = sizeof(buf);
u32 refs = 0;
pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%lx\n",
mvm->ref_bitmap[0]);
for (i = 0; i < IWL_MVM_REF_COUNT; i++)
if (mvm->refs[i])
refs |= BIT(i);
pos += scnprintf(buf + pos, bufsz - pos, "taken mvm refs: 0x%x\n",
refs);
PRINT_MVM_REF(IWL_MVM_REF_UCODE_DOWN);
PRINT_MVM_REF(IWL_MVM_REF_SCAN);
@ -1158,7 +1208,7 @@ static ssize_t iwl_dbgfs_d0i3_refs_write(struct iwl_mvm *mvm, char *buf,
mutex_lock(&mvm->mutex);
taken = test_bit(IWL_MVM_REF_USER, mvm->ref_bitmap);
taken = mvm->refs[IWL_MVM_REF_USER];
if (value == 1 && !taken)
iwl_mvm_ref(mvm, IWL_MVM_REF_USER);
else if (value == 0 && taken)
@ -1194,14 +1244,21 @@ iwl_dbgfs_prph_reg_read(struct file *file,
int pos = 0;
char buf[32];
const size_t bufsz = sizeof(buf);
int ret;
if (!mvm->dbgfs_prph_reg_addr)
return -EINVAL;
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_READ);
if (ret)
return ret;
pos += scnprintf(buf + pos, bufsz - pos, "Reg 0x%x: (0x%x)\n",
mvm->dbgfs_prph_reg_addr,
iwl_read_prph(mvm->trans, mvm->dbgfs_prph_reg_addr));
iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_READ);
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
@ -1211,6 +1268,7 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
{
u8 args;
u32 value;
int ret;
args = sscanf(buf, "%i %i", &mvm->dbgfs_prph_reg_addr, &value);
/* if we only want to set the reg address - nothing more to do */
@ -1221,7 +1279,13 @@ iwl_dbgfs_prph_reg_write(struct iwl_mvm *mvm, char *buf,
if (args != 2)
return -EINVAL;
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PRPH_WRITE);
if (ret)
return ret;
iwl_write_prph(mvm->trans, mvm->dbgfs_prph_reg_addr, value);
iwl_mvm_unref(mvm, IWL_MVM_REF_PRPH_WRITE);
out:
return count;
}

View File

@ -385,6 +385,8 @@ enum iwl_bt_activity_grading {
BT_ON_NO_CONNECTION = 1,
BT_LOW_TRAFFIC = 2,
BT_HIGH_TRAFFIC = 3,
BT_MAX_AG,
}; /* BT_COEX_BT_ACTIVITY_GRADING_API_E_VER_1 */
enum iwl_bt_ci_compliance {

View File

@ -133,6 +133,7 @@ enum {
/* Scan offload */
SCAN_OFFLOAD_REQUEST_CMD = 0x51,
SCAN_OFFLOAD_ABORT_CMD = 0x52,
HOT_SPOT_CMD = 0x53,
SCAN_OFFLOAD_COMPLETE = 0x6D,
SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E,
SCAN_OFFLOAD_CONFIG_CMD = 0x6f,
@ -910,6 +911,72 @@ struct iwl_phy_context_cmd {
__le32 dsp_cfg_flags;
} __packed; /* PHY_CONTEXT_CMD_API_VER_1 */
/*
* Aux ROC command
*
* Command requests the firmware to create a time event for a certain duration
* and remain on the given channel. This is done by using the Aux framework in
* the FW.
* The command was first used for Hot Spot issues - but can be used regardless
* to Hot Spot.
*
* ( HOT_SPOT_CMD 0x53 )
*
* @id_and_color: ID and color of the MAC
* @action: action to perform, one of FW_CTXT_ACTION_*
* @event_unique_id: If the action FW_CTXT_ACTION_REMOVE then the
* event_unique_id should be the id of the time event assigned by ucode.
* Otherwise ignore the event_unique_id.
* @sta_id_and_color: station id and color, resumed during "Remain On Channel"
* activity.
* @channel_info: channel info
* @node_addr: Our MAC Address
* @reserved: reserved for alignment
* @apply_time: GP2 value to start (should always be the current GP2 value)
* @apply_time_max_delay: Maximum apply time delay value in TU. Defines max
* time by which start of the event is allowed to be postponed.
* @duration: event duration in TU To calculate event duration:
* timeEventDuration = min(duration, remainingQuota)
*/
struct iwl_hs20_roc_req {
/* COMMON_INDEX_HDR_API_S_VER_1 hdr */
__le32 id_and_color;
__le32 action;
__le32 event_unique_id;
__le32 sta_id_and_color;
struct iwl_fw_channel_info channel_info;
u8 node_addr[ETH_ALEN];
__le16 reserved;
__le32 apply_time;
__le32 apply_time_max_delay;
__le32 duration;
} __packed; /* HOT_SPOT_CMD_API_S_VER_1 */
/*
* values for AUX ROC result values
*/
enum iwl_mvm_hot_spot {
HOT_SPOT_RSP_STATUS_OK,
HOT_SPOT_RSP_STATUS_TOO_MANY_EVENTS,
HOT_SPOT_MAX_NUM_OF_SESSIONS,
};
/*
* Aux ROC command response
*
* In response to iwl_hs20_roc_req the FW sends this command to notify the
* driver the uid of the timevent.
*
* ( HOT_SPOT_CMD 0x53 )
*
* @event_unique_id: Unique ID of time event assigned by ucode
* @status: Return status 0 is success, all the rest used for specific errors
*/
struct iwl_hs20_roc_res {
__le32 event_unique_id;
__le32 status;
} __packed; /* HOT_SPOT_RSP_API_S_VER_1 */
#define IWL_RX_INFO_PHY_CNT 8
#define IWL_RX_INFO_ENERGY_ANT_ABC_IDX 1
#define IWL_RX_INFO_ENERGY_ANT_A_MSK 0x000000ff

View File

@ -1074,8 +1074,12 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
/* Fill the common data for all mac context types */
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
/* Also enable probe requests to pass */
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
/*
* pass probe requests and beacons from other APs (needed
* for ht protection)
*/
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST |
MAC_FILTER_IN_BEACON);
/* Fill the data specific for ap mode */
iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap,
@ -1096,6 +1100,13 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
/* Fill the common data for all mac context types */
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
/*
* pass probe requests and beacons from other APs (needed
* for ht protection)
*/
cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST |
MAC_FILTER_IN_BEACON);
/* Fill the data specific for GO mode */
iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap,
action == FW_CTXT_ACTION_ADD);

View File

@ -211,7 +211,9 @@ void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
return;
IWL_DEBUG_RPM(mvm, "Take mvm reference - type %d\n", ref_type);
WARN_ON(test_and_set_bit(ref_type, mvm->ref_bitmap));
spin_lock_bh(&mvm->refs_lock);
mvm->refs[ref_type]++;
spin_unlock_bh(&mvm->refs_lock);
iwl_trans_ref(mvm->trans);
}
@ -221,29 +223,35 @@ void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
return;
IWL_DEBUG_RPM(mvm, "Leave mvm reference - type %d\n", ref_type);
WARN_ON(!test_and_clear_bit(ref_type, mvm->ref_bitmap));
spin_lock_bh(&mvm->refs_lock);
WARN_ON(!mvm->refs[ref_type]--);
spin_unlock_bh(&mvm->refs_lock);
iwl_trans_unref(mvm->trans);
}
static void
iwl_mvm_unref_all_except(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref)
static void iwl_mvm_unref_all_except(struct iwl_mvm *mvm,
enum iwl_mvm_ref_type except_ref)
{
int i;
int i, j;
if (!iwl_mvm_is_d0i3_supported(mvm))
return;
for_each_set_bit(i, mvm->ref_bitmap, IWL_MVM_REF_COUNT) {
if (ref == i)
spin_lock_bh(&mvm->refs_lock);
for (i = 0; i < IWL_MVM_REF_COUNT; i++) {
if (except_ref == i || !mvm->refs[i])
continue;
IWL_DEBUG_RPM(mvm, "Cleanup: remove mvm ref type %d\n", i);
clear_bit(i, mvm->ref_bitmap);
iwl_trans_unref(mvm->trans);
IWL_DEBUG_RPM(mvm, "Cleanup: remove mvm ref type %d (%d)\n",
i, mvm->refs[i]);
for (j = 0; j < mvm->refs[i]; j++)
iwl_trans_unref(mvm->trans);
mvm->refs[i] = 0;
}
spin_unlock_bh(&mvm->refs_lock);
}
static int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
{
iwl_mvm_ref(mvm, ref_type);
@ -321,13 +329,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
}
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT &&
!iwlwifi_mod_params.uapsd_disable) {
hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD;
hw->uapsd_queues = IWL_UAPSD_AC_INFO;
hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
}
if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS;
@ -660,6 +661,7 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac,
spin_unlock_bh(&mvm->time_event_lock);
mvmvif->phy_ctxt = NULL;
memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
}
#ifdef CONFIG_IWLWIFI_DEBUGFS
@ -668,11 +670,11 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
struct iwl_fw_error_dump_file *dump_file;
struct iwl_fw_error_dump_data *dump_data;
struct iwl_fw_error_dump_info *dump_info;
struct iwl_mvm_dump_ptrs *fw_error_dump;
const struct fw_img *img;
u32 sram_len, sram_ofs;
u32 file_len, rxf_len;
unsigned long flags;
u32 trans_len;
int reg_val;
lockdep_assert_held(&mvm->mutex);
@ -680,6 +682,10 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
if (mvm->fw_error_dump)
return;
fw_error_dump = kzalloc(sizeof(*mvm->fw_error_dump), GFP_KERNEL);
if (!fw_error_dump)
return;
img = &mvm->fw->img[mvm->cur_ucode];
sram_ofs = img->sec[IWL_UCODE_SECTION_DATA].offset;
sram_len = img->sec[IWL_UCODE_SECTION_DATA].len;
@ -697,18 +703,15 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
rxf_len +
sizeof(*dump_info);
trans_len = iwl_trans_dump_data(mvm->trans, NULL, 0);
if (trans_len)
file_len += trans_len;
dump_file = vzalloc(file_len);
if (!dump_file)
if (!dump_file) {
kfree(fw_error_dump);
return;
}
mvm->fw_error_dump = dump_file;
fw_error_dump->op_mode_ptr = dump_file;
dump_file->barker = cpu_to_le32(IWL_FW_ERROR_DUMP_BARKER);
dump_file->file_len = cpu_to_le32(file_len);
dump_data = (void *)dump_file->data;
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_DEV_FW_INFO);
@ -749,14 +752,12 @@ static void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
iwl_trans_read_mem_bytes(mvm->trans, sram_ofs, dump_data->data,
sram_len);
if (trans_len) {
void *buf = iwl_fw_error_next_data(dump_data);
u32 real_trans_len = iwl_trans_dump_data(mvm->trans, buf,
trans_len);
dump_data = (void *)((u8 *)buf + real_trans_len);
dump_file->file_len =
cpu_to_le32(file_len - trans_len + real_trans_len);
}
fw_error_dump->trans_ptr = iwl_trans_dump_data(mvm->trans);
fw_error_dump->op_mode_len = file_len;
if (fw_error_dump->trans_ptr)
file_len += fw_error_dump->trans_ptr->len;
dump_file->file_len = cpu_to_le32(file_len);
mvm->fw_error_dump = fw_error_dump;
}
#endif
@ -788,6 +789,12 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
iwl_mvm_reset_phy_ctxts(mvm);
memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained));
memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
memset(&mvm->last_bt_ci_cmd_old, 0, sizeof(mvm->last_bt_ci_cmd_old));
memset(&mvm->bt_ack_kill_msk, 0, sizeof(mvm->bt_ack_kill_msk));
memset(&mvm->bt_cts_kill_msk, 0, sizeof(mvm->bt_cts_kill_msk));
ieee80211_wake_queues(mvm->hw);
@ -1399,6 +1406,28 @@ static inline int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm,
}
#endif
static void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm)
{
struct ieee80211_sta *sta;
struct iwl_mvm_sta *mvmsta;
int i;
lockdep_assert_held(&mvm->mutex);
for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
lockdep_is_held(&mvm->mutex));
if (!sta || IS_ERR(sta) || !sta->tdls)
continue;
mvmsta = iwl_mvm_sta_from_mac80211(sta);
ieee80211_tdls_oper_request(mvmsta->vif, sta->addr,
NL80211_TDLS_TEARDOWN,
WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED,
GFP_KERNEL);
}
}
static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_bss_conf *bss_conf,
@ -1494,14 +1523,18 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
*/
iwl_mvm_remove_time_event(mvm, mvmvif,
&mvmvif->time_event_data);
iwl_mvm_sf_update(mvm, vif, false);
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
} else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS |
BSS_CHANGED_QOS)) {
ret = iwl_mvm_power_update_mac(mvm);
if (ret)
IWL_ERR(mvm, "failed to update power mode\n");
}
if (changes & BSS_CHANGED_BEACON_INFO) {
iwl_mvm_sf_update(mvm, vif, false);
WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
}
if (changes & BSS_CHANGED_TXPOWER) {
IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n",
bss_conf->txpower);
@ -1533,6 +1566,14 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
/*
* iwl_mvm_mac_ctxt_add() might read directly from the device
* (the system time), so make sure it is available.
*/
ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_START_AP);
if (ret)
return ret;
mutex_lock(&mvm->mutex);
/* Send the beacon template */
@ -1581,6 +1622,10 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
iwl_mvm_bt_coex_vif_change(mvm);
/* we don't support TDLS during DCM */
if (iwl_mvm_phy_ctx_count(mvm) > 1)
iwl_mvm_teardown_tdls_peers(mvm);
mutex_unlock(&mvm->mutex);
return 0;
@ -1594,6 +1639,7 @@ out_remove:
iwl_mvm_mac_ctxt_remove(mvm, vif);
out_unlock:
mutex_unlock(&mvm->mutex);
iwl_mvm_unref(mvm, IWL_MVM_REF_START_AP);
return ret;
}
@ -1671,6 +1717,14 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
/*
* iwl_mvm_bss_info_changed_station() might call
* iwl_mvm_protect_session(), which reads directly from
* the device (the system time), so make sure it is available.
*/
if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_BSS_CHANGED))
return;
mutex_lock(&mvm->mutex);
if (changes & BSS_CHANGED_IDLE && !bss_conf->idle)
@ -1690,8 +1744,50 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
}
mutex_unlock(&mvm->mutex);
iwl_mvm_unref(mvm, IWL_MVM_REF_BSS_CHANGED);
}
static int iwl_mvm_cancel_scan_wait_notif(struct iwl_mvm *mvm,
enum iwl_scan_status scan_type)
{
int ret;
bool wait_for_handlers = false;
mutex_lock(&mvm->mutex);
if (mvm->scan_status != scan_type) {
ret = 0;
/* make sure there are no pending notifications */
wait_for_handlers = true;
goto out;
}
switch (scan_type) {
case IWL_MVM_SCAN_SCHED:
ret = iwl_mvm_scan_offload_stop(mvm, true);
break;
case IWL_MVM_SCAN_OS:
ret = iwl_mvm_cancel_scan(mvm);
break;
case IWL_MVM_SCAN_NONE:
default:
WARN_ON_ONCE(1);
ret = -EINVAL;
break;
}
if (ret)
goto out;
wait_for_handlers = true;
out:
mutex_unlock(&mvm->mutex);
/* make sure we consume the completion notification */
if (wait_for_handlers)
iwl_mvm_wait_for_async_handlers(mvm);
return ret;
}
static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_scan_request *hw_req)
@ -1704,19 +1800,13 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
req->n_channels > mvm->fw->ucode_capa.n_scan_channels)
return -EINVAL;
ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_SCHED);
if (ret)
return ret;
mutex_lock(&mvm->mutex);
switch (mvm->scan_status) {
case IWL_MVM_SCAN_SCHED:
ret = iwl_mvm_scan_offload_stop(mvm, true);
if (ret) {
ret = -EBUSY;
goto out;
}
break;
case IWL_MVM_SCAN_NONE:
break;
default:
if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
ret = -EBUSY;
goto out;
}
@ -1732,8 +1822,6 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
out:
mutex_unlock(&mvm->mutex);
/* make sure to flush the Rx handler before the next scan arrives */
iwl_mvm_wait_for_async_handlers(mvm);
return ret;
}
@ -1885,28 +1973,6 @@ static void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm,
iwl_mvm_power_update_mac(mvm);
}
static void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm)
{
struct ieee80211_sta *sta;
struct iwl_mvm_sta *mvmsta;
int i;
lockdep_assert_held(&mvm->mutex);
for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
lockdep_is_held(&mvm->mutex));
if (!sta || IS_ERR(sta) || !sta->tdls)
continue;
mvmsta = iwl_mvm_sta_from_mac80211(sta);
ieee80211_tdls_oper_request(mvmsta->vif, sta->addr,
NL80211_TDLS_TEARDOWN,
WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED,
GFP_KERNEL);
}
}
static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@ -2065,10 +2131,19 @@ static void iwl_mvm_mac_mgd_prepare_tx(struct ieee80211_hw *hw,
if (WARN_ON_ONCE(vif->bss_conf.assoc))
return;
/*
* iwl_mvm_protect_session() reads directly from the device
* (the system time), so make sure it is available.
*/
if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PREPARE_TX))
return;
mutex_lock(&mvm->mutex);
/* Try really hard to protect the session and hear a beacon */
iwl_mvm_protect_session(mvm, vif, duration, min_duration, 500);
mutex_unlock(&mvm->mutex);
iwl_mvm_unref(mvm, IWL_MVM_REF_PREPARE_TX);
}
static void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
@ -2077,10 +2152,19 @@ static void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
u32 duration = 2 * vif->bss_conf.dtim_period * vif->bss_conf.beacon_int;
/*
* iwl_mvm_protect_session() reads directly from the device
* (the system time), so make sure it is available.
*/
if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_TDLS))
return;
mutex_lock(&mvm->mutex);
/* Protect the session to hear the TDLS setup response on the channel */
iwl_mvm_protect_session(mvm, vif, duration, duration, 100);
mutex_unlock(&mvm->mutex);
iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_TDLS);
}
static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
@ -2091,6 +2175,10 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_OS);
if (ret)
return ret;
mutex_lock(&mvm->mutex);
if (!iwl_mvm_is_idle(mvm)) {
@ -2098,26 +2186,7 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
goto out;
}
switch (mvm->scan_status) {
case IWL_MVM_SCAN_OS:
IWL_DEBUG_SCAN(mvm, "Stopping previous scan for sched_scan\n");
ret = iwl_mvm_cancel_scan(mvm);
if (ret) {
ret = -EBUSY;
goto out;
}
/*
* iwl_mvm_rx_scan_complete() will be called soon but will
* not reset the scan status as it won't be IWL_MVM_SCAN_OS
* any more since we queue the next scan immediately (below).
* We make sure it is called before the next scan starts by
* flushing the async-handlers work.
*/
break;
case IWL_MVM_SCAN_NONE:
break;
default:
if (mvm->scan_status != IWL_MVM_SCAN_NONE) {
ret = -EBUSY;
goto out;
}
@ -2145,8 +2214,6 @@ err:
mvm->scan_status = IWL_MVM_SCAN_NONE;
out:
mutex_unlock(&mvm->mutex);
/* make sure to flush the Rx handler before the next scan arrives */
iwl_mvm_wait_for_async_handlers(mvm);
return ret;
}
@ -2266,6 +2333,119 @@ static void iwl_mvm_mac_update_tkip_key(struct ieee80211_hw *hw,
}
static bool iwl_mvm_rx_aux_roc(struct iwl_notif_wait_data *notif_wait,
struct iwl_rx_packet *pkt, void *data)
{
struct iwl_mvm *mvm =
container_of(notif_wait, struct iwl_mvm, notif_wait);
struct iwl_hs20_roc_res *resp;
int resp_len = iwl_rx_packet_payload_len(pkt);
struct iwl_mvm_time_event_data *te_data = data;
if (WARN_ON(pkt->hdr.cmd != HOT_SPOT_CMD))
return true;
if (WARN_ON_ONCE(resp_len != sizeof(*resp))) {
IWL_ERR(mvm, "Invalid HOT_SPOT_CMD response\n");
return true;
}
resp = (void *)pkt->data;
IWL_DEBUG_TE(mvm,
"Aux ROC: Recieved response from ucode: status=%d uid=%d\n",
resp->status, resp->event_unique_id);
te_data->uid = le32_to_cpu(resp->event_unique_id);
IWL_DEBUG_TE(mvm, "TIME_EVENT_CMD response - UID = 0x%x\n",
te_data->uid);
spin_lock_bh(&mvm->time_event_lock);
list_add_tail(&te_data->list, &mvm->aux_roc_te_list);
spin_unlock_bh(&mvm->time_event_lock);
return true;
}
#define AUX_ROC_MAX_DELAY_ON_CHANNEL 5000
static int iwl_mvm_send_aux_roc_cmd(struct iwl_mvm *mvm,
struct ieee80211_channel *channel,
struct ieee80211_vif *vif,
int duration)
{
int res, time_reg = DEVICE_SYSTEM_TIME_REG;
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct iwl_mvm_time_event_data *te_data = &mvmvif->hs_time_event_data;
static const u8 time_event_response[] = { HOT_SPOT_CMD };
struct iwl_notification_wait wait_time_event;
struct iwl_hs20_roc_req aux_roc_req = {
.action = cpu_to_le32(FW_CTXT_ACTION_ADD),
.id_and_color =
cpu_to_le32(FW_CMD_ID_AND_COLOR(MAC_INDEX_AUX, 0)),
.sta_id_and_color = cpu_to_le32(mvm->aux_sta.sta_id),
/* Set the channel info data */
.channel_info.band = (channel->band == IEEE80211_BAND_2GHZ) ?
PHY_BAND_24 : PHY_BAND_5,
.channel_info.channel = channel->hw_value,
.channel_info.width = PHY_VHT_CHANNEL_MODE20,
/* Set the time and duration */
.apply_time = cpu_to_le32(iwl_read_prph(mvm->trans, time_reg)),
.apply_time_max_delay =
cpu_to_le32(MSEC_TO_TU(AUX_ROC_MAX_DELAY_ON_CHANNEL)),
.duration = cpu_to_le32(MSEC_TO_TU(duration)),
};
/* Set the node address */
memcpy(aux_roc_req.node_addr, vif->addr, ETH_ALEN);
te_data->vif = vif;
te_data->duration = duration;
te_data->id = HOT_SPOT_CMD;
lockdep_assert_held(&mvm->mutex);
spin_lock_bh(&mvm->time_event_lock);
list_add_tail(&te_data->list, &mvm->time_event_list);
spin_unlock_bh(&mvm->time_event_lock);
/*
* Use a notification wait, which really just processes the
* command response and doesn't wait for anything, in order
* to be able to process the response and get the UID inside
* the RX path. Using CMD_WANT_SKB doesn't work because it
* stores the buffer and then wakes up this thread, by which
* time another notification (that the time event started)
* might already be processed unsuccessfully.
*/
iwl_init_notification_wait(&mvm->notif_wait, &wait_time_event,
time_event_response,
ARRAY_SIZE(time_event_response),
iwl_mvm_rx_aux_roc, te_data);
res = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0, sizeof(aux_roc_req),
&aux_roc_req);
if (res) {
IWL_ERR(mvm, "Couldn't send HOT_SPOT_CMD: %d\n", res);
iwl_remove_notification(&mvm->notif_wait, &wait_time_event);
goto out_clear_te;
}
/* No need to wait for anything, so just pass 1 (0 isn't valid) */
res = iwl_wait_notification(&mvm->notif_wait, &wait_time_event, 1);
/* should never fail */
WARN_ON_ONCE(res);
if (res) {
out_clear_te:
spin_lock_bh(&mvm->time_event_lock);
iwl_mvm_te_clear_data(mvm, te_data);
spin_unlock_bh(&mvm->time_event_lock);
}
return res;
}
static int iwl_mvm_roc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_channel *channel,
@ -2281,8 +2461,17 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw,
IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
duration, type);
if (vif->type != NL80211_IFTYPE_P2P_DEVICE) {
IWL_ERR(mvm, "vif isn't a P2P_DEVICE: %d\n", vif->type);
switch (vif->type) {
case NL80211_IFTYPE_STATION:
/* Use aux roc framework (HS20) */
ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
vif, duration);
return ret;
case NL80211_IFTYPE_P2P_DEVICE:
/* handle below */
break;
default:
IWL_ERR(mvm, "vif isn't P2P_DEVICE: %d\n", vif->type);
return -EINVAL;
}
@ -2661,6 +2850,10 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
goto out_remove;
}
/* we don't support TDLS during DCM - can be caused by channel switch */
if (iwl_mvm_phy_ctx_count(mvm) > 1)
iwl_mvm_teardown_tdls_peers(mvm);
goto out;
out_remove:

View File

@ -82,6 +82,8 @@
/* RSSI offset for WkP */
#define IWL_RSSI_OFFSET 50
#define IWL_MVM_MISSED_BEACONS_THRESHOLD 8
/* A TimeUnit is 1024 microsecond */
#define MSEC_TO_TU(_msec) (_msec*1000/1024)
/*
* The CSA NoA is scheduled IWL_MVM_CHANNEL_SWITCH_TIME TUs before "beacon 0"
@ -126,6 +128,21 @@ struct iwl_mvm_mod_params {
};
extern struct iwl_mvm_mod_params iwlmvm_mod_params;
/**
* struct iwl_mvm_dump_ptrs - set of pointers needed for the fw-error-dump
*
* @op_mode_ptr: pointer to the buffer coming from the mvm op_mode
* @trans_ptr: pointer to struct %iwl_trans_dump_data which contains the
* transport's data.
* @trans_len: length of the valid data in trans_ptr
* @op_mode_len: length of the valid data in op_mode_ptr
*/
struct iwl_mvm_dump_ptrs {
struct iwl_trans_dump_data *trans_ptr;
void *op_mode_ptr;
u32 op_mode_len;
};
struct iwl_mvm_phy_ctxt {
u16 id;
u16 color;
@ -249,6 +266,15 @@ enum iwl_mvm_ref_type {
IWL_MVM_REF_TX,
IWL_MVM_REF_TX_AGG,
IWL_MVM_REF_ADD_IF,
IWL_MVM_REF_START_AP,
IWL_MVM_REF_BSS_CHANGED,
IWL_MVM_REF_PREPARE_TX,
IWL_MVM_REF_PROTECT_TDLS,
IWL_MVM_REF_CHECK_CTKILL,
IWL_MVM_REF_PRPH_READ,
IWL_MVM_REF_PRPH_WRITE,
IWL_MVM_REF_NMI,
IWL_MVM_REF_TM_CMD,
IWL_MVM_REF_EXIT_WORK,
IWL_MVM_REF_COUNT,
@ -327,6 +353,7 @@ struct iwl_mvm_vif {
*/
struct ieee80211_tx_queue_params queue_params[IEEE80211_NUM_ACS];
struct iwl_mvm_time_event_data time_event_data;
struct iwl_mvm_time_event_data hs_time_event_data;
struct iwl_mvm_int_sta bcast_sta;
@ -606,14 +633,15 @@ struct iwl_mvm {
*/
unsigned long fw_key_table[BITS_TO_LONGS(STA_KEY_MAX_NUM)];
/* A bitmap of reference types taken by the driver. */
unsigned long ref_bitmap[BITS_TO_LONGS(IWL_MVM_REF_COUNT)];
/* references taken by the driver and spinlock protecting them */
spinlock_t refs_lock;
u8 refs[IWL_MVM_REF_COUNT];
u8 vif_count;
/* -1 for always, 0 for never, >0 for that many times */
s8 restart_fw;
void *fw_error_dump;
struct iwl_mvm_dump_ptrs *fw_error_dump;
#ifdef CONFIG_IWLWIFI_LEDS
struct led_classdev led;
@ -647,7 +675,8 @@ struct iwl_mvm {
wait_queue_head_t d0i3_exit_waitq;
/* BT-Coex */
u8 bt_kill_msk;
u8 bt_ack_kill_msk[NUM_PHY_CTX];
u8 bt_cts_kill_msk[NUM_PHY_CTX];
struct iwl_bt_coex_profile_notif_old last_bt_notif_old;
struct iwl_bt_coex_ci_cmd_old last_bt_ci_cmd_old;
@ -659,6 +688,9 @@ struct iwl_mvm {
u8 bt_tx_prio;
enum iwl_bt_force_ant_mode bt_force_ant_mode;
/* Aux ROC */
struct list_head aux_roc_te_list;
/* Thermal Throttling and CTkill */
struct iwl_mvm_tt_mgmt thermal_throttle;
s32 temperature; /* Celsius */
@ -697,6 +729,7 @@ enum iwl_mvm_status {
IWL_MVM_STATUS_ROC_RUNNING,
IWL_MVM_STATUS_IN_HW_RESTART,
IWL_MVM_STATUS_IN_D0I3,
IWL_MVM_STATUS_ROC_AUX_RUNNING,
};
static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm)
@ -988,6 +1021,7 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
/* D0i3 */
void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq);
int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm);
@ -1029,12 +1063,14 @@ int iwl_mvm_rx_ant_coupling_notif_old(struct iwl_mvm *mvm,
enum iwl_bt_kill_msk {
BT_KILL_MSK_DEFAULT,
BT_KILL_MSK_SCO_HID_A2DP,
BT_KILL_MSK_REDUCED_TXPOW,
BT_KILL_MSK_NEVER,
BT_KILL_MSK_ALWAYS,
BT_KILL_MSK_MAX,
};
extern const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX];
extern const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX];
extern const u8 iwl_bt_ack_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT];
extern const u8 iwl_bt_cts_kill_msk[BT_MAX_AG][BT_COEX_MAX_LUT];
extern const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX];
/* beacon filtering */
#ifdef CONFIG_IWLWIFI_DEBUGFS

View File

@ -265,7 +265,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
!mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) {
IWL_ERR(mvm, "Can't parse empty NVM sections\n");
IWL_ERR(mvm, "Can't parse empty OTP/NVM sections\n");
return NULL;
}
} else {
@ -273,7 +273,7 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
!mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) {
IWL_ERR(mvm,
"Can't parse empty family 8000 NVM sections\n");
"Can't parse empty family 8000 OTP/NVM sections\n");
return NULL;
}
/* MAC_OVERRIDE or at least HW section must exist */

View File

@ -289,6 +289,7 @@ static const char *const iwl_mvm_cmd_strings[REPLY_MAX] = {
CMD(MATCH_FOUND_NOTIFICATION),
CMD(SCAN_OFFLOAD_REQUEST_CMD),
CMD(SCAN_OFFLOAD_ABORT_CMD),
CMD(HOT_SPOT_CMD),
CMD(SCAN_OFFLOAD_COMPLETE),
CMD(SCAN_OFFLOAD_UPDATE_PROFILES_CMD),
CMD(SCAN_ITERATION_COMPLETE),
@ -391,6 +392,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
if (!hw)
return NULL;
if (cfg->max_rx_agg_size)
hw->max_rx_aggregation_subframes = cfg->max_rx_agg_size;
op_mode = hw->priv;
op_mode->ops = &iwl_mvm_ops;
@ -416,6 +420,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
mutex_init(&mvm->d0i3_suspend_mutex);
spin_lock_init(&mvm->async_handlers_lock);
INIT_LIST_HEAD(&mvm->time_event_list);
INIT_LIST_HEAD(&mvm->aux_roc_te_list);
INIT_LIST_HEAD(&mvm->async_handlers_list);
spin_lock_init(&mvm->time_event_lock);
@ -425,6 +430,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work);
spin_lock_init(&mvm->d0i3_tx_lock);
spin_lock_init(&mvm->refs_lock);
skb_queue_head_init(&mvm->d0i3_tx);
init_waitqueue_head(&mvm->d0i3_exit_waitq);
@ -539,7 +545,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
memset(&mvm->rx_stats, 0, sizeof(struct mvm_statistics_rx));
/* rpm starts with a taken ref. only set the appropriate bit here. */
set_bit(IWL_MVM_REF_UCODE_DOWN, mvm->ref_bitmap);
mvm->refs[IWL_MVM_REF_UCODE_DOWN] = 1;
return op_mode;
@ -567,7 +573,11 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)
ieee80211_unregister_hw(mvm->hw);
kfree(mvm->scan_cmd);
vfree(mvm->fw_error_dump);
if (mvm->fw_error_dump) {
vfree(mvm->fw_error_dump->op_mode_ptr);
vfree(mvm->fw_error_dump->trans_ptr);
kfree(mvm->fw_error_dump);
}
kfree(mvm->mcast_filter_cmd);
mvm->mcast_filter_cmd = NULL;

View File

@ -98,23 +98,21 @@ int iwl_mvm_sta_send_to_fw(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
bool update)
{
struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
struct iwl_mvm_add_sta_cmd add_sta_cmd;
struct iwl_mvm_add_sta_cmd add_sta_cmd = {
.sta_id = mvm_sta->sta_id,
.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color),
.add_modify = update ? 1 : 0,
.station_flags_msk = cpu_to_le32(STA_FLG_FAT_EN_MSK |
STA_FLG_MIMO_EN_MSK),
};
int ret;
u32 status;
u32 agg_size = 0, mpdu_dens = 0;
memset(&add_sta_cmd, 0, sizeof(add_sta_cmd));
add_sta_cmd.sta_id = mvm_sta->sta_id;
add_sta_cmd.mac_id_n_color = cpu_to_le32(mvm_sta->mac_id_n_color);
if (!update) {
add_sta_cmd.tfd_queue_msk = cpu_to_le32(mvm_sta->tfd_queue_msk);
memcpy(&add_sta_cmd.addr, sta->addr, ETH_ALEN);
}
add_sta_cmd.add_modify = update ? 1 : 0;
add_sta_cmd.station_flags_msk |= cpu_to_le32(STA_FLG_FAT_EN_MSK |
STA_FLG_MIMO_EN_MSK);
switch (sta->bandwidth) {
case IEEE80211_STA_RX_BW_160:
@ -528,8 +526,12 @@ int iwl_mvm_add_aux_sta(struct iwl_mvm *mvm)
lockdep_assert_held(&mvm->mutex);
/* Add the aux station, but without any queues */
ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, 0,
/* Map Aux queue to fifo - needs to happen before adding Aux station */
iwl_trans_ac_txq_enable(mvm->trans, mvm->aux_queue,
IWL_MVM_TX_FIFO_MCAST);
/* Allocate aux station and assign to it the aux queue */
ret = iwl_mvm_allocate_int_sta(mvm, &mvm->aux_sta, BIT(mvm->aux_queue),
NL80211_IFTYPE_UNSPECIFIED);
if (ret)
return ret;

View File

@ -72,9 +72,6 @@
#include "iwl-io.h"
#include "iwl-prph.h"
/* A TimeUnit is 1024 microsecond */
#define MSEC_TO_TU(_msec) (_msec*1000/1024)
/*
* For the high priority TE use a time event type that has similar priority to
* the FW's action scan priority.
@ -100,6 +97,21 @@ void iwl_mvm_te_clear_data(struct iwl_mvm *mvm,
void iwl_mvm_roc_done_wk(struct work_struct *wk)
{
struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, roc_done_wk);
u32 queues = 0;
/*
* Clear the ROC_RUNNING /ROC_AUX_RUNNING status bit.
* This will cause the TX path to drop offchannel transmissions.
* That would also be done by mac80211, but it is racy, in particular
* in the case that the time event actually completed in the firmware
* (which is handled in iwl_mvm_te_handle_notif).
*/
if (test_and_clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
queues |= BIT(IWL_MVM_OFFCHANNEL_QUEUE);
if (test_and_clear_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status))
queues |= BIT(mvm->aux_queue);
iwl_mvm_unref(mvm, IWL_MVM_REF_ROC);
synchronize_net();
@ -113,21 +125,11 @@ void iwl_mvm_roc_done_wk(struct work_struct *wk)
* issue as it will have to complete before the next command is
* executed, and a new time event means a new command.
*/
iwl_mvm_flush_tx_path(mvm, BIT(IWL_MVM_OFFCHANNEL_QUEUE), false);
iwl_mvm_flush_tx_path(mvm, queues, false);
}
static void iwl_mvm_roc_finished(struct iwl_mvm *mvm)
{
/*
* First, clear the ROC_RUNNING status bit. This will cause the TX
* path to drop offchannel transmissions. That would also be done
* by mac80211, but it is racy, in particular in the case that the
* time event actually completed in the firmware (which is handled
* in iwl_mvm_te_handle_notif).
*/
clear_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
iwl_mvm_unref(mvm, IWL_MVM_REF_ROC);
/*
* Of course, our status bit is just as racy as mac80211, so in
* addition, fire off the work struct which will drop all frames
@ -262,6 +264,60 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm,
}
}
/*
* Handle A Aux ROC time event
*/
static int iwl_mvm_aux_roc_te_handle_notif(struct iwl_mvm *mvm,
struct iwl_time_event_notif *notif)
{
struct iwl_mvm_time_event_data *te_data, *tmp;
bool aux_roc_te = false;
list_for_each_entry_safe(te_data, tmp, &mvm->aux_roc_te_list, list) {
if (le32_to_cpu(notif->unique_id) == te_data->uid) {
aux_roc_te = true;
break;
}
}
if (!aux_roc_te) /* Not a Aux ROC time event */
return -EINVAL;
if (!le32_to_cpu(notif->status)) {
IWL_DEBUG_TE(mvm,
"ERROR: Aux ROC Time Event %s notification failure\n",
(le32_to_cpu(notif->action) &
TE_V2_NOTIF_HOST_EVENT_START) ? "start" : "end");
return -EINVAL;
}
IWL_DEBUG_TE(mvm,
"Aux ROC time event notification - UID = 0x%x action %d\n",
le32_to_cpu(notif->unique_id),
le32_to_cpu(notif->action));
if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_END) {
/* End TE, notify mac80211 */
ieee80211_remain_on_channel_expired(mvm->hw);
iwl_mvm_roc_finished(mvm); /* flush aux queue */
list_del(&te_data->list); /* remove from list */
te_data->running = false;
te_data->vif = NULL;
te_data->uid = 0;
} else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) {
set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
te_data->running = true;
ieee80211_ready_on_channel(mvm->hw); /* Start TE */
} else {
IWL_DEBUG_TE(mvm,
"ERROR: Unknown Aux ROC Time Event (action = %d)\n",
le32_to_cpu(notif->action));
return -EINVAL;
}
return 0;
}
/*
* The Rx handler for time event notifications
*/
@ -278,10 +334,15 @@ int iwl_mvm_rx_time_event_notif(struct iwl_mvm *mvm,
le32_to_cpu(notif->action));
spin_lock_bh(&mvm->time_event_lock);
/* This time event is triggered for Aux ROC request */
if (!iwl_mvm_aux_roc_te_handle_notif(mvm, notif))
goto unlock;
list_for_each_entry_safe(te_data, tmp, &mvm->time_event_list, list) {
if (le32_to_cpu(notif->unique_id) == te_data->uid)
iwl_mvm_te_handle_notif(mvm, te_data, notif);
}
unlock:
spin_unlock_bh(&mvm->time_event_lock);
return 0;

View File

@ -140,9 +140,9 @@ static u16 iwl_mvm_dts_get_ptat_deviation_offset(struct iwl_mvm *mvm)
/* TODO: move parsing to NVM code */
calib = mvm->nvm_sections[NVM_SECTION_TYPE_CALIBRATION].data;
ptat = calib[OTP_DTS_DIODE_DEVIATION];
pa1 = calib[OTP_DTS_DIODE_DEVIATION + 1];
pa2 = calib[OTP_DTS_DIODE_DEVIATION + 2];
ptat = calib[OTP_DTS_DIODE_DEVIATION * 2];
pa1 = calib[OTP_DTS_DIODE_DEVIATION * 2 + 1];
pa2 = calib[OTP_DTS_DIODE_DEVIATION * 2 + 2];
/* get the median: */
if (ptat > pa1) {
@ -338,10 +338,16 @@ static void check_exit_ctkill(struct work_struct *work)
duration = tt->params->ct_kill_duration;
/* make sure the device is available for direct read/writes */
if (iwl_mvm_ref_sync(mvm, IWL_MVM_REF_CHECK_CTKILL))
goto reschedule;
iwl_trans_start_hw(mvm->trans);
temp = check_nic_temperature(mvm);
iwl_trans_stop_device(mvm->trans);
iwl_mvm_unref(mvm, IWL_MVM_REF_CHECK_CTKILL);
if (temp < MIN_TEMPERATURE || temp > MAX_TEMPERATURE) {
IWL_DEBUG_TEMP(mvm, "Failed to measure NIC temperature\n");
goto reschedule;

View File

@ -310,6 +310,16 @@ int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb)
info->hw_queue != info->control.vif->cab_queue)))
return -1;
/*
* IWL_MVM_OFFCHANNEL_QUEUE is used for ROC packets that can be used
* in 2 different types of vifs, P2P & STATION. P2P uses the offchannel
* queue. STATION (HS2.0) uses the auxiliary context of the FW,
* and hence needs to be sent on the aux queue
*/
if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
info->control.vif->type == NL80211_IFTYPE_STATION)
IEEE80211_SKB_CB(skb)->hw_queue = mvm->aux_queue;
/*
* If the interface on which frame is sent is the P2P_DEVICE
* or an AP/GO interface use the broadcast station associated

View File

@ -67,6 +67,7 @@
#include <linux/sched.h>
#include <linux/bitops.h>
#include <linux/gfp.h>
#include <linux/vmalloc.h>
#include "iwl-drv.h"
#include "iwl-trans.h"
@ -1773,28 +1774,207 @@ static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd)
return cmdlen;
}
static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans,
void *buf, u32 buflen)
static const struct {
u32 start, end;
} iwl_prph_dump_addr[] = {
{ .start = 0x00a00000, .end = 0x00a00000 },
{ .start = 0x00a0000c, .end = 0x00a00024 },
{ .start = 0x00a0002c, .end = 0x00a0003c },
{ .start = 0x00a00410, .end = 0x00a00418 },
{ .start = 0x00a00420, .end = 0x00a00420 },
{ .start = 0x00a00428, .end = 0x00a00428 },
{ .start = 0x00a00430, .end = 0x00a0043c },
{ .start = 0x00a00444, .end = 0x00a00444 },
{ .start = 0x00a004c0, .end = 0x00a004cc },
{ .start = 0x00a004d8, .end = 0x00a004d8 },
{ .start = 0x00a004e0, .end = 0x00a004f0 },
{ .start = 0x00a00840, .end = 0x00a00840 },
{ .start = 0x00a00850, .end = 0x00a00858 },
{ .start = 0x00a01004, .end = 0x00a01008 },
{ .start = 0x00a01010, .end = 0x00a01010 },
{ .start = 0x00a01018, .end = 0x00a01018 },
{ .start = 0x00a01024, .end = 0x00a01024 },
{ .start = 0x00a0102c, .end = 0x00a01034 },
{ .start = 0x00a0103c, .end = 0x00a01040 },
{ .start = 0x00a01048, .end = 0x00a01094 },
{ .start = 0x00a01c00, .end = 0x00a01c20 },
{ .start = 0x00a01c58, .end = 0x00a01c58 },
{ .start = 0x00a01c7c, .end = 0x00a01c7c },
{ .start = 0x00a01c28, .end = 0x00a01c54 },
{ .start = 0x00a01c5c, .end = 0x00a01c5c },
{ .start = 0x00a01c84, .end = 0x00a01c84 },
{ .start = 0x00a01ce0, .end = 0x00a01d0c },
{ .start = 0x00a01d18, .end = 0x00a01d20 },
{ .start = 0x00a01d2c, .end = 0x00a01d30 },
{ .start = 0x00a01d40, .end = 0x00a01d5c },
{ .start = 0x00a01d80, .end = 0x00a01d80 },
{ .start = 0x00a01d98, .end = 0x00a01d98 },
{ .start = 0x00a01dc0, .end = 0x00a01dfc },
{ .start = 0x00a01e00, .end = 0x00a01e2c },
{ .start = 0x00a01e40, .end = 0x00a01e60 },
{ .start = 0x00a01e84, .end = 0x00a01e90 },
{ .start = 0x00a01e9c, .end = 0x00a01ec4 },
{ .start = 0x00a01ed0, .end = 0x00a01ed0 },
{ .start = 0x00a01f00, .end = 0x00a01f14 },
{ .start = 0x00a01f44, .end = 0x00a01f58 },
{ .start = 0x00a01f80, .end = 0x00a01fa8 },
{ .start = 0x00a01fb0, .end = 0x00a01fbc },
{ .start = 0x00a01ff8, .end = 0x00a01ffc },
{ .start = 0x00a02000, .end = 0x00a02048 },
{ .start = 0x00a02068, .end = 0x00a020f0 },
{ .start = 0x00a02100, .end = 0x00a02118 },
{ .start = 0x00a02140, .end = 0x00a0214c },
{ .start = 0x00a02168, .end = 0x00a0218c },
{ .start = 0x00a021c0, .end = 0x00a021c0 },
{ .start = 0x00a02400, .end = 0x00a02410 },
{ .start = 0x00a02418, .end = 0x00a02420 },
{ .start = 0x00a02428, .end = 0x00a0242c },
{ .start = 0x00a02434, .end = 0x00a02434 },
{ .start = 0x00a02440, .end = 0x00a02460 },
{ .start = 0x00a02468, .end = 0x00a024b0 },
{ .start = 0x00a024c8, .end = 0x00a024cc },
{ .start = 0x00a02500, .end = 0x00a02504 },
{ .start = 0x00a0250c, .end = 0x00a02510 },
{ .start = 0x00a02540, .end = 0x00a02554 },
{ .start = 0x00a02580, .end = 0x00a025f4 },
{ .start = 0x00a02600, .end = 0x00a0260c },
{ .start = 0x00a02648, .end = 0x00a02650 },
{ .start = 0x00a02680, .end = 0x00a02680 },
{ .start = 0x00a026c0, .end = 0x00a026d0 },
{ .start = 0x00a02700, .end = 0x00a0270c },
{ .start = 0x00a02804, .end = 0x00a02804 },
{ .start = 0x00a02818, .end = 0x00a0281c },
{ .start = 0x00a02c00, .end = 0x00a02db4 },
{ .start = 0x00a02df4, .end = 0x00a02fb0 },
{ .start = 0x00a03000, .end = 0x00a03014 },
{ .start = 0x00a0301c, .end = 0x00a0302c },
{ .start = 0x00a03034, .end = 0x00a03038 },
{ .start = 0x00a03040, .end = 0x00a03048 },
{ .start = 0x00a03060, .end = 0x00a03068 },
{ .start = 0x00a03070, .end = 0x00a03074 },
{ .start = 0x00a0307c, .end = 0x00a0307c },
{ .start = 0x00a03080, .end = 0x00a03084 },
{ .start = 0x00a0308c, .end = 0x00a03090 },
{ .start = 0x00a03098, .end = 0x00a03098 },
{ .start = 0x00a030a0, .end = 0x00a030a0 },
{ .start = 0x00a030a8, .end = 0x00a030b4 },
{ .start = 0x00a030bc, .end = 0x00a030bc },
{ .start = 0x00a030c0, .end = 0x00a0312c },
{ .start = 0x00a03c00, .end = 0x00a03c5c },
{ .start = 0x00a04400, .end = 0x00a04454 },
{ .start = 0x00a04460, .end = 0x00a04474 },
{ .start = 0x00a044c0, .end = 0x00a044ec },
{ .start = 0x00a04500, .end = 0x00a04504 },
{ .start = 0x00a04510, .end = 0x00a04538 },
{ .start = 0x00a04540, .end = 0x00a04548 },
{ .start = 0x00a04560, .end = 0x00a0457c },
{ .start = 0x00a04590, .end = 0x00a04598 },
{ .start = 0x00a045c0, .end = 0x00a045f4 },
};
static u32 iwl_trans_pcie_dump_prph(struct iwl_trans *trans,
struct iwl_fw_error_dump_data **data)
{
struct iwl_fw_error_dump_prph *prph;
unsigned long flags;
u32 prph_len = 0, i;
if (!iwl_trans_grab_nic_access(trans, false, &flags))
return 0;
for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
/* The range includes both boundaries */
int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
iwl_prph_dump_addr[i].start + 4;
int reg;
__le32 *val;
prph_len += sizeof(*data) + sizeof(*prph) +
num_bytes_in_chunk;
(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
(*data)->len = cpu_to_le32(sizeof(*prph) +
num_bytes_in_chunk);
prph = (void *)(*data)->data;
prph->prph_start = cpu_to_le32(iwl_prph_dump_addr[i].start);
val = (void *)prph->data;
for (reg = iwl_prph_dump_addr[i].start;
reg <= iwl_prph_dump_addr[i].end;
reg += 4)
*val++ = cpu_to_le32(iwl_trans_pcie_read_prph(trans,
reg));
*data = iwl_fw_error_next_data(*data);
}
iwl_trans_release_nic_access(trans, &flags);
return prph_len;
}
#define IWL_CSR_TO_DUMP (0x250)
static u32 iwl_trans_pcie_dump_csr(struct iwl_trans *trans,
struct iwl_fw_error_dump_data **data)
{
u32 csr_len = sizeof(**data) + IWL_CSR_TO_DUMP;
__le32 *val;
int i;
(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_CSR);
(*data)->len = cpu_to_le32(IWL_CSR_TO_DUMP);
val = (void *)(*data)->data;
for (i = 0; i < IWL_CSR_TO_DUMP; i += 4)
*val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i));
*data = iwl_fw_error_next_data(*data);
return csr_len;
}
static
struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_fw_error_dump_data *data;
struct iwl_txq *cmdq = &trans_pcie->txq[trans_pcie->cmd_queue];
struct iwl_fw_error_dump_txcmd *txcmd;
struct iwl_trans_dump_data *dump_data;
u32 len;
int i, ptr;
len = sizeof(*data) +
/* transport dump header */
len = sizeof(*dump_data);
/* host commands */
len += sizeof(*data) +
cmdq->q.n_window * (sizeof(*txcmd) + TFD_MAX_PAYLOAD_SIZE);
/* CSR registers */
len += sizeof(*data) + IWL_CSR_TO_DUMP;
/* PRPH registers */
for (i = 0; i < ARRAY_SIZE(iwl_prph_dump_addr); i++) {
/* The range includes both boundaries */
int num_bytes_in_chunk = iwl_prph_dump_addr[i].end -
iwl_prph_dump_addr[i].start + 4;
len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_prph) +
num_bytes_in_chunk;
}
/* FW monitor */
if (trans_pcie->fw_mon_page)
len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_fw_mon) +
trans_pcie->fw_mon_size;
if (!buf)
return len;
dump_data = vzalloc(len);
if (!dump_data)
return NULL;
len = 0;
data = buf;
data = (void *)dump_data->data;
data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD);
txcmd = (void *)data->data;
spin_lock_bh(&cmdq->lock);
@ -1820,11 +2000,15 @@ static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans,
data->len = cpu_to_le32(len);
len += sizeof(*data);
data = iwl_fw_error_next_data(data);
len += iwl_trans_pcie_dump_prph(trans, &data);
len += iwl_trans_pcie_dump_csr(trans, &data);
/* data is already pointing to the next section */
if (trans_pcie->fw_mon_page) {
struct iwl_fw_error_dump_fw_mon *fw_mon_data;
data = iwl_fw_error_next_data(data);
data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR);
data->len = cpu_to_le32(trans_pcie->fw_mon_size +
sizeof(*fw_mon_data));
@ -1852,7 +2036,9 @@ static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans,
trans_pcie->fw_mon_size;
}
return len;
dump_data->len = len;
return dump_data;
}
#else
static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,

View File

@ -685,11 +685,16 @@ static void mac80211_hwsim_set_tsf(struct ieee80211_hw *hw,
struct mac80211_hwsim_data *data = hw->priv;
u64 now = mac80211_hwsim_get_tsf(hw, vif);
u32 bcn_int = data->beacon_int;
s64 delta = tsf - now;
u64 delta = abs64(tsf - now);
data->tsf_offset += delta;
/* adjust after beaconing with new timestamp at old TBTT */
data->bcn_delta = do_div(delta, bcn_int);
if (tsf > now) {
data->tsf_offset += delta;
data->bcn_delta = do_div(delta, bcn_int);
} else {
data->tsf_offset -= delta;
data->bcn_delta = -do_div(delta, bcn_int);
}
}
static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,

View File

@ -541,7 +541,6 @@ void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid,
int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
{
struct host_cmd_ds_11n_addba_req add_ba_req;
struct mwifiex_sta_node *sta_ptr;
u32 tx_win_size = priv->add_ba_param.tx_win_size;
static u8 dialog_tok;
int ret;
@ -553,6 +552,8 @@ int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac)
ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
priv->adapter->is_hw_11ac_capable &&
memcmp(priv->cfg_bssid, peer_mac, ETH_ALEN)) {
struct mwifiex_sta_node *sta_ptr;
sta_ptr = mwifiex_get_sta_entry(priv, peer_mac);
if (!sta_ptr) {
dev_warn(priv->adapter->dev,

View File

@ -249,13 +249,22 @@ void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta)
* buffered in Rx reordering table.
*/
static int
mwifiex_11n_find_last_seq_num(struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr)
mwifiex_11n_find_last_seq_num(struct reorder_tmr_cnxt *ctx)
{
struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr = ctx->ptr;
struct mwifiex_private *priv = ctx->priv;
unsigned long flags;
int i;
for (i = (rx_reorder_tbl_ptr->win_size - 1); i >= 0; --i)
if (rx_reorder_tbl_ptr->rx_reorder_ptr[i])
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
for (i = rx_reorder_tbl_ptr->win_size - 1; i >= 0; --i) {
if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) {
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
flags);
return i;
}
}
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
return -1;
}
@ -274,7 +283,7 @@ mwifiex_flush_data(unsigned long context)
(struct reorder_tmr_cnxt *) context;
int start_win, seq_num;
seq_num = mwifiex_11n_find_last_seq_num(ctx->ptr);
seq_num = mwifiex_11n_find_last_seq_num(ctx);
if (seq_num < 0)
return;
@ -729,9 +738,9 @@ void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv)
mwifiex_del_rx_reorder_entry(priv, del_tbl_ptr);
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
}
INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
mwifiex_reset_11n_rx_seq_num(priv);
}
@ -749,10 +758,14 @@ void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags)
priv = adapter->priv[i];
if (!priv)
continue;
if (list_empty(&priv->rx_reorder_tbl_ptr))
continue;
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, lock_flags);
if (list_empty(&priv->rx_reorder_tbl_ptr)) {
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
lock_flags);
continue;
}
list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list)
tbl->flags = flags;
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, lock_flags);

View File

@ -1604,9 +1604,6 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len,
return -EINVAL;
}
/* disconnect before try to associate */
mwifiex_deauthenticate(priv, NULL);
/* As this is new association, clear locally stored
* keys and security related flags */
priv->sec_info.wpa_enabled = false;
@ -1744,6 +1741,11 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
return -EINVAL;
}
if (priv->wdev && priv->wdev->current_bss) {
wiphy_warn(wiphy, "%s: already connected\n", dev->name);
return -EALREADY;
}
wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n",
(char *) sme->ssid, sme->bssid);

View File

@ -137,7 +137,6 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
struct host_cmd_ds_command *host_cmd;
uint16_t cmd_code;
uint16_t cmd_size;
struct timeval tstamp;
unsigned long flags;
__le32 tmp;
@ -198,10 +197,8 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
*/
skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len);
do_gettimeofday(&tstamp);
dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d,"
" seqno %#x\n",
tstamp.tv_sec, tstamp.tv_usec, cmd_code,
dev_dbg(adapter->dev,
"cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n", cmd_code,
le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)), cmd_size,
le16_to_cpu(host_cmd->seq_num));
@ -273,7 +270,6 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
(struct mwifiex_opt_sleep_confirm *)
adapter->sleep_cfm->data;
struct sk_buff *sleep_cfm_tmp;
struct timeval ts;
__le32 tmp;
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
@ -284,10 +280,9 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter)
(adapter->seq_num, priv->bss_num,
priv->bss_type)));
do_gettimeofday(&ts);
dev_dbg(adapter->dev,
"cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d, seqno %#x\n",
ts.tv_sec, ts.tv_usec, le16_to_cpu(sleep_cfm_buf->command),
"cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n",
le16_to_cpu(sleep_cfm_buf->command),
le16_to_cpu(sleep_cfm_buf->action),
le16_to_cpu(sleep_cfm_buf->size),
le16_to_cpu(sleep_cfm_buf->seq_num));
@ -442,7 +437,6 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
struct sk_buff *skb = adapter->event_skb;
u32 eventcause = adapter->event_cause;
struct timeval tstamp;
struct mwifiex_rxinfo *rx_info;
/* Save the last event to debug log */
@ -467,9 +461,7 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
rx_info->bss_type = priv->bss_type;
}
do_gettimeofday(&tstamp);
dev_dbg(adapter->dev, "EVENT: %lu.%lu: cause: %#x\n",
tstamp.tv_sec, tstamp.tv_usec, eventcause);
dev_dbg(adapter->dev, "EVENT: cause: %#x\n", eventcause);
if (eventcause == EVENT_PS_SLEEP || eventcause == EVENT_PS_AWAKE) {
/* Handle PS_SLEEP/AWAKE events on STA */
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA);
@ -781,7 +773,6 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
uint16_t orig_cmdresp_no;
uint16_t cmdresp_no;
uint16_t cmdresp_result;
struct timeval tstamp;
unsigned long flags;
/* Now we got response from FW, cancel the command timer */
@ -839,11 +830,10 @@ int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter)
adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] =
orig_cmdresp_no;
do_gettimeofday(&tstamp);
dev_dbg(adapter->dev, "cmd: CMD_RESP: (%lu.%lu): 0x%x, result %d,"
" len %d, seqno 0x%x\n",
tstamp.tv_sec, tstamp.tv_usec, orig_cmdresp_no, cmdresp_result,
le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num));
dev_dbg(adapter->dev,
"cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
orig_cmdresp_no, cmdresp_result,
le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num));
if (!(orig_cmdresp_no & HostCmd_RET_BIT)) {
dev_err(adapter->dev, "CMD_RESP: invalid cmd resp\n");
@ -903,7 +893,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
struct mwifiex_adapter *adapter =
(struct mwifiex_adapter *) function_context;
struct cmd_ctrl_node *cmd_node;
struct timeval tstamp;
adapter->is_cmd_timedout = 1;
if (!adapter->curr_cmd) {
@ -916,10 +905,8 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index];
adapter->dbg.timeout_cmd_act =
adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index];
do_gettimeofday(&tstamp);
dev_err(adapter->dev,
"%s: Timeout cmd id (%lu.%lu) = %#x, act = %#x\n",
__func__, tstamp.tv_sec, tstamp.tv_usec,
"%s: Timeout cmd id = %#x, act = %#x\n", __func__,
adapter->dbg.timeout_cmd_id,
adapter->dbg.timeout_cmd_act);
@ -1237,18 +1224,15 @@ mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *adapter,
uint16_t result = le16_to_cpu(cmd->result);
uint16_t command = le16_to_cpu(cmd->command);
uint16_t seq_num = le16_to_cpu(cmd->seq_num);
struct timeval ts;
if (!upld_len) {
dev_err(adapter->dev, "%s: cmd size is 0\n", __func__);
return;
}
do_gettimeofday(&ts);
dev_dbg(adapter->dev,
"cmd: CMD_RESP: (%lu.%lu): 0x%x, result %d, len %d, seqno 0x%x\n",
ts.tv_sec, ts.tv_usec, command, result, le16_to_cpu(cmd->size),
seq_num);
"cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n",
command, result, le16_to_cpu(cmd->size), seq_num);
/* Get BSS number and corresponding priv */
priv = mwifiex_get_priv_by_id(adapter, HostCmd_GET_BSS_NO(seq_num),

View File

@ -713,7 +713,7 @@ struct mwifiex_ie_types_vendor_param_set {
u8 ie[MWIFIEX_MAX_VSIE_LEN];
};
#define MWIFIEX_TDLS_IDLE_TIMEOUT 60
#define MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC 60
struct mwifiex_ie_types_tdls_idle_timeout {
struct mwifiex_ie_types_header header;

View File

@ -949,7 +949,7 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv,
chan_tlv->chan_scan_param[0].radio_type |=
(IEEE80211_HT_PARAM_CHA_SEC_ABOVE << 4);
else if (adapter->sec_chan_offset ==
IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
IEEE80211_HT_PARAM_CHA_SEC_BELOW)
chan_tlv->chan_scan_param[0].radio_type |=
(IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4);
}
@ -1288,8 +1288,6 @@ done:
int mwifiex_associate(struct mwifiex_private *priv,
struct mwifiex_bssdescriptor *bss_desc)
{
u8 current_bssid[ETH_ALEN];
/* Return error if the adapter is not STA role or table entry
* is not marked as infra.
*/
@ -1304,10 +1302,6 @@ int mwifiex_associate(struct mwifiex_private *priv,
else
mwifiex_set_ba_params(priv);
memcpy(&current_bssid,
&priv->curr_bss_params.bss_descriptor.mac_address,
sizeof(current_bssid));
/* Clear any past association response stored for application
retrieval */
priv->assoc_rsp_size = 0;

View File

@ -33,6 +33,7 @@ static void scan_delay_timer_fn(unsigned long data)
struct mwifiex_private *priv = (struct mwifiex_private *)data;
struct mwifiex_adapter *adapter = priv->adapter;
struct cmd_ctrl_node *cmd_node, *tmp_node;
spinlock_t *scan_q_lock = &adapter->scan_pending_q_lock;
unsigned long flags;
if (adapter->surprise_removed)
@ -44,13 +45,13 @@ static void scan_delay_timer_fn(unsigned long data)
* Abort scan operation by cancelling all pending scan
* commands
*/
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
spin_lock_irqsave(scan_q_lock, flags);
list_for_each_entry_safe(cmd_node, tmp_node,
&adapter->scan_pending_q, list) {
list_del(&cmd_node->list);
mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
}
spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
spin_unlock_irqrestore(scan_q_lock, flags);
spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
adapter->scan_processing = false;
@ -79,12 +80,17 @@ static void scan_delay_timer_fn(unsigned long data)
*/
adapter->scan_delay_cnt = 0;
adapter->empty_tx_q_cnt = 0;
spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
spin_lock_irqsave(scan_q_lock, flags);
if (list_empty(&adapter->scan_pending_q)) {
spin_unlock_irqrestore(scan_q_lock, flags);
goto done;
}
cmd_node = list_first_entry(&adapter->scan_pending_q,
struct cmd_ctrl_node, list);
list_del(&cmd_node->list);
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
flags);
spin_unlock_irqrestore(scan_q_lock, flags);
mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
true);

View File

@ -2238,7 +2238,6 @@ static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter)
struct pcie_service_card *card = adapter->card;
const struct mwifiex_pcie_card_reg *creg = card->pcie.reg;
unsigned int reg, reg_start, reg_end;
struct timeval t;
u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0;
enum rdwr_status stat;
u32 memory_size;
@ -2257,9 +2256,7 @@ static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter)
entry->mem_size = 0;
}
do_gettimeofday(&t);
dev_info(adapter->dev, "== mwifiex firmware dump start: %u.%06u ==\n",
(u32)t.tv_sec, (u32)t.tv_usec);
dev_info(adapter->dev, "== mwifiex firmware dump start ==\n");
/* Read the number of the memories which will dump */
stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
@ -2303,9 +2300,8 @@ static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter)
end_ptr = dbg_ptr + memory_size;
doneflag = entry->done_flag;
do_gettimeofday(&t);
dev_info(adapter->dev, "Start %s output %u.%06u, please wait...\n",
entry->mem_name, (u32)t.tv_sec, (u32)t.tv_usec);
dev_info(adapter->dev, "Start %s output, please wait...\n",
entry->mem_name);
do {
stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag);
@ -2331,9 +2327,7 @@ static void mwifiex_pcie_fw_dump_work(struct mwifiex_adapter *adapter)
break;
} while (true);
}
do_gettimeofday(&t);
dev_info(adapter->dev, "== mwifiex firmware dump end: %u.%06u ==\n",
(u32)t.tv_sec, (u32)t.tv_usec);
dev_info(adapter->dev, "== mwifiex firmware dump end ==\n");
kobject_uevent_env(&adapter->wiphy->dev.kobj, KOBJ_CHANGE, env);

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