提交 ae0008c7 编写于 作者: E Emmanuel Grumbach

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

...@@ -148,6 +148,13 @@ L: linux-scsi@vger.kernel.org ...@@ -148,6 +148,13 @@ L: linux-scsi@vger.kernel.org
S: Maintained S: Maintained
F: drivers/scsi/53c700* 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 6PACK NETWORK DRIVER FOR AX.25
M: Andreas Koensgen <ajk@comnets.uni-bremen.de> M: Andreas Koensgen <ajk@comnets.uni-bremen.de>
L: linux-hams@vger.kernel.org L: linux-hams@vger.kernel.org
......
...@@ -3,6 +3,7 @@ bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o ...@@ -3,6 +3,7 @@ bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o
bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o bcma-$(CONFIG_BCMA_SFLASH) += driver_chipcommon_sflash.o
bcma-$(CONFIG_BCMA_NFLASH) += driver_chipcommon_nflash.o bcma-$(CONFIG_BCMA_NFLASH) += driver_chipcommon_nflash.o
bcma-y += driver_pci.o bcma-y += driver_pci.o
bcma-y += driver_pcie2.o
bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o bcma-$(CONFIG_BCMA_DRIVER_PCI_HOSTMODE) += driver_pci_host.o
bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o bcma-$(CONFIG_BCMA_DRIVER_MIPS) += driver_mips.o
bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o bcma-$(CONFIG_BCMA_DRIVER_GMAC_CMN) += driver_gmac_cmn.o
......
...@@ -603,6 +603,7 @@ void bcma_pmu_spuravoid_pllupdate(struct bcma_drv_cc *cc, int spuravoid) ...@@ -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; tmp = BCMA_CC_PMU_CTL_PLL_UPD | BCMA_CC_PMU_CTL_NOILPONW;
break; break;
case BCMA_CHIP_ID_BCM43217:
case BCMA_CHIP_ID_BCM43227: case BCMA_CHIP_ID_BCM43227:
case BCMA_CHIP_ID_BCM43228: case BCMA_CHIP_ID_BCM43228:
case BCMA_CHIP_ID_BCM43428: case BCMA_CHIP_ID_BCM43428:
......
/*
* Broadcom specific AMBA
* PCIe Gen 2 Core
*
* Copyright 2014, Broadcom Corporation
* Copyright 2014, Rafał Miłecki <zajec5@gmail.com>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/
#include "bcma_private.h"
#include <linux/bcma/bcma.h>
/**************************************************
* R/W ops.
**************************************************/
#if 0
static u32 bcma_core_pcie2_cfg_read(struct bcma_drv_pcie2 *pcie2, u32 addr)
{
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr);
pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR);
return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA);
}
#endif
static void bcma_core_pcie2_cfg_write(struct bcma_drv_pcie2 *pcie2, u32 addr,
u32 val)
{
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, addr);
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, val);
}
/**************************************************
* Init.
**************************************************/
static u32 bcma_core_pcie2_war_delay_perst_enab(struct bcma_drv_pcie2 *pcie2,
bool enable)
{
u32 val;
/* restore back to default */
val = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL);
val |= PCIE2_CLKC_DLYPERST;
val &= ~PCIE2_CLKC_DISSPROMLD;
if (enable) {
val &= ~PCIE2_CLKC_DLYPERST;
val |= PCIE2_CLKC_DISSPROMLD;
}
pcie2_write32(pcie2, (BCMA_CORE_PCIE2_CLK_CONTROL), val);
/* flush */
return pcie2_read32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL);
}
static void bcma_core_pcie2_set_ltr_vals(struct bcma_drv_pcie2 *pcie2)
{
/* LTR0 */
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x844);
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x883c883c);
/* LTR1 */
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x848);
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x88648864);
/* LTR2 */
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, 0x84C);
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x90039003);
}
static void bcma_core_pcie2_hw_ltr_war(struct bcma_drv_pcie2 *pcie2)
{
u8 core_rev = pcie2->core->id.rev;
u32 devstsctr2;
if (core_rev < 2 || core_rev == 10 || core_rev > 13)
return;
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR,
PCIE2_CAP_DEVSTSCTRL2_OFFSET);
devstsctr2 = pcie2_read32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA);
if (devstsctr2 & PCIE2_CAP_DEVSTSCTRL2_LTRENAB) {
/* force the right LTR values */
bcma_core_pcie2_set_ltr_vals(pcie2);
/* TODO:
si_core_wrapperreg(pcie2, 3, 0x60, 0x8080, 0); */
/* enable the LTR */
devstsctr2 |= PCIE2_CAP_DEVSTSCTRL2_LTRENAB;
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR,
PCIE2_CAP_DEVSTSCTRL2_OFFSET);
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, devstsctr2);
/* set the LTR state to be active */
pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE,
PCIE2_LTR_ACTIVE);
usleep_range(1000, 2000);
/* set the LTR state to be sleep */
pcie2_write32(pcie2, BCMA_CORE_PCIE2_LTR_STATE,
PCIE2_LTR_SLEEP);
usleep_range(1000, 2000);
}
}
static void pciedev_crwlpciegen2(struct bcma_drv_pcie2 *pcie2)
{
u8 core_rev = pcie2->core->id.rev;
bool pciewar160, pciewar162;
pciewar160 = core_rev == 7 || core_rev == 9 || core_rev == 11;
pciewar162 = core_rev == 5 || core_rev == 7 || core_rev == 8 ||
core_rev == 9 || core_rev == 11;
if (!pciewar160 && !pciewar162)
return;
/* TODO */
#if 0
pcie2_set32(pcie2, BCMA_CORE_PCIE2_CLK_CONTROL,
PCIE_DISABLE_L1CLK_GATING);
#if 0
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR,
PCIEGEN2_COE_PVT_TL_CTRL_0);
pcie2_mask32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA,
~(1 << COE_PVT_TL_CTRL_0_PM_DIS_L1_REENTRY_BIT));
#endif
#endif
}
static void pciedev_crwlpciegen2_180(struct bcma_drv_pcie2 *pcie2)
{
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_PMCR_REFUP);
pcie2_set32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 0x1f);
}
static void pciedev_crwlpciegen2_182(struct bcma_drv_pcie2 *pcie2)
{
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR, PCIE2_SBMBX);
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, 1 << 0);
}
static void pciedev_reg_pm_clk_period(struct bcma_drv_pcie2 *pcie2)
{
struct bcma_drv_cc *drv_cc = &pcie2->core->bus->drv_cc;
u8 core_rev = pcie2->core->id.rev;
u32 alp_khz, pm_value;
if (core_rev <= 13) {
alp_khz = bcma_pmu_get_alp_clock(drv_cc) / 1000;
pm_value = (1000000 * 2) / alp_khz;
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDADDR,
PCIE2_PVT_REG_PM_CLK_PERIOD);
pcie2_write32(pcie2, BCMA_CORE_PCIE2_CONFIGINDDATA, pm_value);
}
}
void bcma_core_pcie2_init(struct bcma_drv_pcie2 *pcie2)
{
struct bcma_chipinfo *ci = &pcie2->core->bus->chipinfo;
u32 tmp;
tmp = pcie2_read32(pcie2, BCMA_CORE_PCIE2_SPROM(54));
if ((tmp & 0xe) >> 1 == 2)
bcma_core_pcie2_cfg_write(pcie2, 0x4e0, 0x17);
/* TODO: Do we need pcie_reqsize? */
if (ci->id == BCMA_CHIP_ID_BCM4360 && ci->rev > 3)
bcma_core_pcie2_war_delay_perst_enab(pcie2, true);
bcma_core_pcie2_hw_ltr_war(pcie2);
pciedev_crwlpciegen2(pcie2);
pciedev_reg_pm_clk_period(pcie2);
pciedev_crwlpciegen2_180(pcie2);
pciedev_crwlpciegen2_182(pcie2);
}
...@@ -279,6 +279,7 @@ static const struct pci_device_id bcma_pci_bridge_tbl[] = { ...@@ -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, 0x4358) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4359) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4365) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
{ 0, }, { 0, },
}; };
......
...@@ -132,6 +132,7 @@ static int bcma_register_cores(struct bcma_bus *bus) ...@@ -132,6 +132,7 @@ static int bcma_register_cores(struct bcma_bus *bus)
case BCMA_CORE_CHIPCOMMON: case BCMA_CORE_CHIPCOMMON:
case BCMA_CORE_PCI: case BCMA_CORE_PCI:
case BCMA_CORE_PCIE: case BCMA_CORE_PCIE:
case BCMA_CORE_PCIE2:
case BCMA_CORE_MIPS_74K: case BCMA_CORE_MIPS_74K:
case BCMA_CORE_4706_MAC_GBIT_COMMON: case BCMA_CORE_4706_MAC_GBIT_COMMON:
continue; continue;
...@@ -281,6 +282,13 @@ int bcma_bus_register(struct bcma_bus *bus) ...@@ -281,6 +282,13 @@ int bcma_bus_register(struct bcma_bus *bus)
bcma_core_pci_init(&bus->drv_pci[1]); bcma_core_pci_init(&bus->drv_pci[1]);
} }
/* Init PCIe Gen 2 core */
core = bcma_find_core_unit(bus, BCMA_CORE_PCIE2, 0);
if (core) {
bus->drv_pcie2.core = core;
bcma_core_pcie2_init(&bus->drv_pcie2);
}
/* Init GBIT MAC COMMON core */ /* Init GBIT MAC COMMON core */
core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON); core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON);
if (core) { if (core) {
......
...@@ -201,6 +201,23 @@ static int bcma_sprom_valid(struct bcma_bus *bus, const u16 *sprom, ...@@ -201,6 +201,23 @@ static int bcma_sprom_valid(struct bcma_bus *bus, const u16 *sprom,
SPEX(_field[7], _offset + 14, _mask, _shift); \ SPEX(_field[7], _offset + 14, _mask, _shift); \
} while (0) } 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) static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
{ {
u16 v, o; u16 v, o;
...@@ -381,14 +398,22 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) ...@@ -381,14 +398,22 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom)
SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0); SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0);
/* Extract the antenna gain values. */ /* Extract the antenna gain values. */
SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01, bus->sprom.antenna_gain.a0 = sprom_extract_antgain(sprom,
SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT); SSB_SPROM8_AGAIN01,
SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01, SSB_SPROM8_AGAIN0,
SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT); SSB_SPROM8_AGAIN0_SHIFT);
SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23, bus->sprom.antenna_gain.a1 = sprom_extract_antgain(sprom,
SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT); SSB_SPROM8_AGAIN01,
SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23, SSB_SPROM8_AGAIN1,
SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT); 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, SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON,
SSB_SPROM8_LEDDC_ON_SHIFT); SSB_SPROM8_LEDDC_ON_SHIFT);
...@@ -509,6 +534,7 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus) ...@@ -509,6 +534,7 @@ static bool bcma_sprom_onchip_available(struct bcma_bus *bus)
/* for these chips OTP is always available */ /* for these chips OTP is always available */
present = true; present = true;
break; break;
case BCMA_CHIP_ID_BCM43217:
case BCMA_CHIP_ID_BCM43227: case BCMA_CHIP_ID_BCM43227:
case BCMA_CHIP_ID_BCM43228: case BCMA_CHIP_ID_BCM43228:
case BCMA_CHIP_ID_BCM43428: case BCMA_CHIP_ID_BCM43428:
......
...@@ -30,8 +30,8 @@ config BT_HCIUART ...@@ -30,8 +30,8 @@ config BT_HCIUART
help help
Bluetooth HCI UART driver. Bluetooth HCI UART driver.
This driver is required if you want to use Bluetooth devices with This driver is required if you want to use Bluetooth devices with
serial port interface. You will also need this driver if you have serial port interface. You will also need this driver if you have
UART based Bluetooth PCMCIA and CF devices like Xircom Credit Card UART based Bluetooth PCMCIA and CF devices like Xircom Credit Card
adapter and BrainBoxes Bluetooth PC Card. adapter and BrainBoxes Bluetooth PC Card.
Say Y here to compile support for Bluetooth UART devices into the Say Y here to compile support for Bluetooth UART devices into the
...@@ -41,9 +41,9 @@ config BT_HCIUART_H4 ...@@ -41,9 +41,9 @@ config BT_HCIUART_H4
bool "UART (H4) protocol support" bool "UART (H4) protocol support"
depends on BT_HCIUART depends on BT_HCIUART
help help
UART (H4) is serial protocol for communication between Bluetooth UART (H4) is serial protocol for communication between Bluetooth
device and host. This protocol is required for most Bluetooth devices device and host. This protocol is required for most Bluetooth devices
with UART interface, including PCMCIA and CF cards. with UART interface, including PCMCIA and CF cards.
Say Y here to compile support for HCI UART (H4) protocol. Say Y here to compile support for HCI UART (H4) protocol.
...@@ -52,7 +52,7 @@ config BT_HCIUART_BCSP ...@@ -52,7 +52,7 @@ config BT_HCIUART_BCSP
depends on BT_HCIUART depends on BT_HCIUART
select BITREVERSE select BITREVERSE
help help
BCSP (BlueCore Serial Protocol) is serial protocol for communication BCSP (BlueCore Serial Protocol) is serial protocol for communication
between Bluetooth device and host. This protocol is required for non between Bluetooth device and host. This protocol is required for non
USB Bluetooth devices based on CSR BlueCore chip, including PCMCIA and USB Bluetooth devices based on CSR BlueCore chip, including PCMCIA and
CF cards. CF cards.
......
...@@ -90,7 +90,6 @@ static const struct usb_device_id ath3k_table[] = { ...@@ -90,7 +90,6 @@ static const struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x0b05, 0x17d0) }, { USB_DEVICE(0x0b05, 0x17d0) },
{ USB_DEVICE(0x0CF3, 0x0036) }, { USB_DEVICE(0x0CF3, 0x0036) },
{ USB_DEVICE(0x0CF3, 0x3004) }, { USB_DEVICE(0x0CF3, 0x3004) },
{ USB_DEVICE(0x0CF3, 0x3005) },
{ USB_DEVICE(0x0CF3, 0x3008) }, { USB_DEVICE(0x0CF3, 0x3008) },
{ USB_DEVICE(0x0CF3, 0x311D) }, { USB_DEVICE(0x0CF3, 0x311D) },
{ USB_DEVICE(0x0CF3, 0x311E) }, { USB_DEVICE(0x0CF3, 0x311E) },
...@@ -104,6 +103,7 @@ static const struct usb_device_id ath3k_table[] = { ...@@ -104,6 +103,7 @@ static const struct usb_device_id ath3k_table[] = {
{ USB_DEVICE(0x13d3, 0x3375) }, { USB_DEVICE(0x13d3, 0x3375) },
{ USB_DEVICE(0x13d3, 0x3393) }, { USB_DEVICE(0x13d3, 0x3393) },
{ USB_DEVICE(0x13d3, 0x3402) }, { USB_DEVICE(0x13d3, 0x3402) },
{ USB_DEVICE(0x13d3, 0x3432) },
/* Atheros AR5BBU12 with sflash firmware */ /* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE02C) }, { USB_DEVICE(0x0489, 0xE02C) },
...@@ -140,7 +140,6 @@ static const struct usb_device_id ath3k_blist_tbl[] = { ...@@ -140,7 +140,6 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x311E), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311E), .driver_info = BTUSB_ATH3012 },
...@@ -154,6 +153,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = { ...@@ -154,6 +153,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU22 with sflash firmware */ /* Atheros AR5BBU22 with sflash firmware */
{ USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 },
...@@ -290,10 +290,10 @@ static int ath3k_load_fwfile(struct usb_device *udev, ...@@ -290,10 +290,10 @@ static int ath3k_load_fwfile(struct usb_device *udev,
sent += size; sent += size;
count -= size; count -= size;
pipe = usb_sndbulkpipe(udev, 0x02);
while (count) { while (count) {
size = min_t(uint, count, BULK_SIZE); size = min_t(uint, count, BULK_SIZE);
pipe = usb_sndbulkpipe(udev, 0x02);
memcpy(send_buf, firmware->data + sent, size); memcpy(send_buf, firmware->data + sent, size);
err = usb_bulk_msg(udev, pipe, send_buf, size, err = usb_bulk_msg(udev, pipe, send_buf, size,
......
...@@ -68,6 +68,7 @@ struct btmrvl_adapter { ...@@ -68,6 +68,7 @@ struct btmrvl_adapter {
u8 hs_state; u8 hs_state;
u8 wakeup_tries; u8 wakeup_tries;
wait_queue_head_t cmd_wait_q; wait_queue_head_t cmd_wait_q;
wait_queue_head_t event_hs_wait_q;
u8 cmd_complete; u8 cmd_complete;
bool is_suspended; bool is_suspended;
}; };
...@@ -89,6 +90,7 @@ struct btmrvl_private { ...@@ -89,6 +90,7 @@ struct btmrvl_private {
#define MRVL_VENDOR_PKT 0xFE #define MRVL_VENDOR_PKT 0xFE
/* Vendor specific Bluetooth commands */ /* Vendor specific Bluetooth commands */
#define BT_CMD_PSCAN_WIN_REPORT_ENABLE 0xFC03
#define BT_CMD_AUTO_SLEEP_MODE 0xFC23 #define BT_CMD_AUTO_SLEEP_MODE 0xFC23
#define BT_CMD_HOST_SLEEP_CONFIG 0xFC59 #define BT_CMD_HOST_SLEEP_CONFIG 0xFC59
#define BT_CMD_HOST_SLEEP_ENABLE 0xFC5A #define BT_CMD_HOST_SLEEP_ENABLE 0xFC5A
...@@ -143,6 +145,7 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb); ...@@ -143,6 +145,7 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb);
int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb); int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb);
int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, u8 subcmd); int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, u8 subcmd);
int btmrvl_pscan_window_reporting(struct btmrvl_private *priv, u8 subcmd);
int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv); int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv);
int btmrvl_enable_ps(struct btmrvl_private *priv); int btmrvl_enable_ps(struct btmrvl_private *priv);
int btmrvl_prepare_command(struct btmrvl_private *priv); int btmrvl_prepare_command(struct btmrvl_private *priv);
......
...@@ -114,6 +114,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb) ...@@ -114,6 +114,7 @@ int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb)
adapter->hs_state = HS_ACTIVATED; adapter->hs_state = HS_ACTIVATED;
if (adapter->psmode) if (adapter->psmode)
adapter->ps_state = PS_SLEEP; adapter->ps_state = PS_SLEEP;
wake_up_interruptible(&adapter->event_hs_wait_q);
BT_DBG("HS ACTIVATED!"); BT_DBG("HS ACTIVATED!");
} else { } else {
BT_DBG("HS Enable failed"); BT_DBG("HS Enable failed");
...@@ -214,6 +215,23 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, u8 subcmd) ...@@ -214,6 +215,23 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, u8 subcmd)
} }
EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd); EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd);
int btmrvl_pscan_window_reporting(struct btmrvl_private *priv, u8 subcmd)
{
struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
int ret;
if (!card->support_pscan_win_report)
return 0;
ret = btmrvl_send_sync_cmd(priv, BT_CMD_PSCAN_WIN_REPORT_ENABLE,
&subcmd, 1);
if (ret)
BT_ERR("PSCAN_WIN_REPORT_ENABLE command failed: %#x", ret);
return ret;
}
EXPORT_SYMBOL_GPL(btmrvl_pscan_window_reporting);
int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv) int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv)
{ {
int ret; int ret;
...@@ -253,11 +271,31 @@ EXPORT_SYMBOL_GPL(btmrvl_enable_ps); ...@@ -253,11 +271,31 @@ EXPORT_SYMBOL_GPL(btmrvl_enable_ps);
int btmrvl_enable_hs(struct btmrvl_private *priv) int btmrvl_enable_hs(struct btmrvl_private *priv)
{ {
struct btmrvl_adapter *adapter = priv->adapter;
int ret; int ret;
ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_ENABLE, NULL, 0); ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_ENABLE, NULL, 0);
if (ret) if (ret) {
BT_ERR("Host sleep enable command failed\n"); BT_ERR("Host sleep enable command failed\n");
return ret;
}
ret = wait_event_interruptible_timeout(adapter->event_hs_wait_q,
adapter->hs_state,
msecs_to_jiffies(WAIT_UNTIL_HS_STATE_CHANGED));
if (ret < 0) {
BT_ERR("event_hs_wait_q terminated (%d): %d,%d,%d",
ret, adapter->hs_state, adapter->ps_state,
adapter->wakeup_tries);
} else if (!ret) {
BT_ERR("hs_enable timeout: %d,%d,%d", adapter->hs_state,
adapter->ps_state, adapter->wakeup_tries);
ret = -ETIMEDOUT;
} else {
BT_DBG("host sleep enabled: %d,%d,%d", adapter->hs_state,
adapter->ps_state, adapter->wakeup_tries);
ret = 0;
}
return ret; return ret;
} }
...@@ -358,6 +396,7 @@ static void btmrvl_init_adapter(struct btmrvl_private *priv) ...@@ -358,6 +396,7 @@ static void btmrvl_init_adapter(struct btmrvl_private *priv)
} }
init_waitqueue_head(&priv->adapter->cmd_wait_q); init_waitqueue_head(&priv->adapter->cmd_wait_q);
init_waitqueue_head(&priv->adapter->event_hs_wait_q);
} }
static void btmrvl_free_adapter(struct btmrvl_private *priv) static void btmrvl_free_adapter(struct btmrvl_private *priv)
...@@ -489,6 +528,8 @@ static int btmrvl_setup(struct hci_dev *hdev) ...@@ -489,6 +528,8 @@ static int btmrvl_setup(struct hci_dev *hdev)
btmrvl_cal_data_dt(priv); btmrvl_cal_data_dt(priv);
btmrvl_pscan_window_reporting(priv, 0x01);
priv->btmrvl_dev.psmode = 1; priv->btmrvl_dev.psmode = 1;
btmrvl_enable_ps(priv); btmrvl_enable_ps(priv);
...@@ -666,6 +707,7 @@ int btmrvl_remove_card(struct btmrvl_private *priv) ...@@ -666,6 +707,7 @@ int btmrvl_remove_card(struct btmrvl_private *priv)
hdev = priv->btmrvl_dev.hcidev; hdev = priv->btmrvl_dev.hcidev;
wake_up_interruptible(&priv->adapter->cmd_wait_q); wake_up_interruptible(&priv->adapter->cmd_wait_q);
wake_up_interruptible(&priv->adapter->event_hs_wait_q);
kthread_stop(priv->main_thread.task); kthread_stop(priv->main_thread.task);
......
...@@ -108,6 +108,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = { ...@@ -108,6 +108,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
.helper = "mrvl/sd8688_helper.bin", .helper = "mrvl/sd8688_helper.bin",
.firmware = "mrvl/sd8688.bin", .firmware = "mrvl/sd8688.bin",
.reg = &btmrvl_reg_8688, .reg = &btmrvl_reg_8688,
.support_pscan_win_report = false,
.sd_blksz_fw_dl = 64, .sd_blksz_fw_dl = 64,
}; };
...@@ -115,6 +116,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = { ...@@ -115,6 +116,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
.helper = NULL, .helper = NULL,
.firmware = "mrvl/sd8787_uapsta.bin", .firmware = "mrvl/sd8787_uapsta.bin",
.reg = &btmrvl_reg_87xx, .reg = &btmrvl_reg_87xx,
.support_pscan_win_report = false,
.sd_blksz_fw_dl = 256, .sd_blksz_fw_dl = 256,
}; };
...@@ -122,6 +124,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = { ...@@ -122,6 +124,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
.helper = NULL, .helper = NULL,
.firmware = "mrvl/sd8797_uapsta.bin", .firmware = "mrvl/sd8797_uapsta.bin",
.reg = &btmrvl_reg_87xx, .reg = &btmrvl_reg_87xx,
.support_pscan_win_report = false,
.sd_blksz_fw_dl = 256, .sd_blksz_fw_dl = 256,
}; };
...@@ -129,6 +132,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = { ...@@ -129,6 +132,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
.helper = NULL, .helper = NULL,
.firmware = "mrvl/sd8897_uapsta.bin", .firmware = "mrvl/sd8897_uapsta.bin",
.reg = &btmrvl_reg_88xx, .reg = &btmrvl_reg_88xx,
.support_pscan_win_report = true,
.sd_blksz_fw_dl = 256, .sd_blksz_fw_dl = 256,
}; };
...@@ -1067,6 +1071,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func, ...@@ -1067,6 +1071,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
card->firmware = data->firmware; card->firmware = data->firmware;
card->reg = data->reg; card->reg = data->reg;
card->sd_blksz_fw_dl = data->sd_blksz_fw_dl; card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
card->support_pscan_win_report = data->support_pscan_win_report;
} }
if (btmrvl_sdio_register_dev(card) < 0) { if (btmrvl_sdio_register_dev(card) < 0) {
......
...@@ -89,6 +89,7 @@ struct btmrvl_sdio_card { ...@@ -89,6 +89,7 @@ struct btmrvl_sdio_card {
const char *helper; const char *helper;
const char *firmware; const char *firmware;
const struct btmrvl_sdio_card_reg *reg; const struct btmrvl_sdio_card_reg *reg;
bool support_pscan_win_report;
u16 sd_blksz_fw_dl; u16 sd_blksz_fw_dl;
u8 rx_unit; u8 rx_unit;
struct btmrvl_private *priv; struct btmrvl_private *priv;
...@@ -98,6 +99,7 @@ struct btmrvl_sdio_device { ...@@ -98,6 +99,7 @@ struct btmrvl_sdio_device {
const char *helper; const char *helper;
const char *firmware; const char *firmware;
const struct btmrvl_sdio_card_reg *reg; const struct btmrvl_sdio_card_reg *reg;
const bool support_pscan_win_report;
u16 sd_blksz_fw_dl; u16 sd_blksz_fw_dl;
}; };
......
...@@ -30,9 +30,6 @@ ...@@ -30,9 +30,6 @@
#define VERSION "0.6" #define VERSION "0.6"
static bool ignore_dga;
static bool ignore_csr;
static bool ignore_sniffer;
static bool disable_scofix; static bool disable_scofix;
static bool force_scofix; static bool force_scofix;
...@@ -49,7 +46,8 @@ static struct usb_driver btusb_driver; ...@@ -49,7 +46,8 @@ static struct usb_driver btusb_driver;
#define BTUSB_WRONG_SCO_MTU 0x40 #define BTUSB_WRONG_SCO_MTU 0x40
#define BTUSB_ATH3012 0x80 #define BTUSB_ATH3012 0x80
#define BTUSB_INTEL 0x100 #define BTUSB_INTEL 0x100
#define BTUSB_BCM_PATCHRAM 0x200 #define BTUSB_INTEL_BOOT 0x200
#define BTUSB_BCM_PATCHRAM 0x400
static const struct usb_device_id btusb_table[] = { static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */ /* Generic Bluetooth USB device */
...@@ -121,6 +119,10 @@ static const struct usb_device_id btusb_table[] = { ...@@ -121,6 +119,10 @@ static const struct usb_device_id btusb_table[] = {
/* IMC Networks - Broadcom based */ /* IMC Networks - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01) }, { USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01) },
/* Intel Bluetooth USB Bootloader (RAM module) */
{ USB_DEVICE(0x8087, 0x0a5a),
.driver_info = BTUSB_INTEL_BOOT | BTUSB_BROKEN_ISOC },
{ } /* Terminating entry */ { } /* Terminating entry */
}; };
...@@ -162,7 +164,6 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -162,7 +164,6 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0b05, 0x17d0), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3005), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x311e), .driver_info = BTUSB_ATH3012 },
...@@ -176,6 +177,7 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -176,6 +177,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU12 with sflash firmware */ /* Atheros AR5BBU12 with sflash firmware */
{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
...@@ -229,10 +231,12 @@ static const struct usb_device_id blacklist_table[] = { ...@@ -229,10 +231,12 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE }, { USB_DEVICE(0x08fd, 0x0002), .driver_info = BTUSB_IGNORE },
/* CSR BlueCore Bluetooth Sniffer */ /* CSR BlueCore Bluetooth Sniffer */
{ USB_DEVICE(0x0a12, 0x0002), .driver_info = BTUSB_SNIFFER }, { USB_DEVICE(0x0a12, 0x0002),
.driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC },
/* Frontline ComProbe Bluetooth Sniffer */ /* Frontline ComProbe Bluetooth Sniffer */
{ USB_DEVICE(0x16d3, 0x0002), .driver_info = BTUSB_SNIFFER }, { USB_DEVICE(0x16d3, 0x0002),
.driver_info = BTUSB_SNIFFER | BTUSB_BROKEN_ISOC },
/* Intel Bluetooth device */ /* Intel Bluetooth device */
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL }, { USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
...@@ -1183,6 +1187,51 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev, ...@@ -1183,6 +1187,51 @@ static int btusb_setup_intel_patching(struct hci_dev *hdev,
return 0; return 0;
} }
#define BDADDR_INTEL (&(bdaddr_t) {{0x00, 0x8b, 0x9e, 0x19, 0x03, 0x00}})
static int btusb_check_bdaddr_intel(struct hci_dev *hdev)
{
struct sk_buff *skb;
struct hci_rp_read_bd_addr *rp;
skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
BT_ERR("%s reading Intel device address failed (%ld)",
hdev->name, PTR_ERR(skb));
return PTR_ERR(skb);
}
if (skb->len != sizeof(*rp)) {
BT_ERR("%s Intel device address length mismatch", hdev->name);
kfree_skb(skb);
return -EIO;
}
rp = (struct hci_rp_read_bd_addr *) skb->data;
if (rp->status) {
BT_ERR("%s Intel device address result failed (%02x)",
hdev->name, rp->status);
kfree_skb(skb);
return -bt_to_errno(rp->status);
}
/* For some Intel based controllers, the default Bluetooth device
* address 00:03:19:9E:8B:00 can be found. These controllers are
* fully operational, but have the danger of duplicate addresses
* and that in turn can cause problems with Bluetooth operation.
*/
if (!bacmp(&rp->bdaddr, BDADDR_INTEL)) {
BT_ERR("%s found Intel default device address (%pMR)",
hdev->name, &rp->bdaddr);
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
}
kfree_skb(skb);
return 0;
}
static int btusb_setup_intel(struct hci_dev *hdev) static int btusb_setup_intel(struct hci_dev *hdev)
{ {
struct sk_buff *skb; struct sk_buff *skb;
...@@ -1255,6 +1304,7 @@ static int btusb_setup_intel(struct hci_dev *hdev) ...@@ -1255,6 +1304,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
BT_INFO("%s: Intel device is already patched. patch num: %02x", BT_INFO("%s: Intel device is already patched. patch num: %02x",
hdev->name, ver->fw_patch_num); hdev->name, ver->fw_patch_num);
kfree_skb(skb); kfree_skb(skb);
btusb_check_bdaddr_intel(hdev);
return 0; return 0;
} }
...@@ -1267,6 +1317,7 @@ static int btusb_setup_intel(struct hci_dev *hdev) ...@@ -1267,6 +1317,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
fw = btusb_setup_intel_get_fw(hdev, ver); fw = btusb_setup_intel_get_fw(hdev, ver);
if (!fw) { if (!fw) {
kfree_skb(skb); kfree_skb(skb);
btusb_check_bdaddr_intel(hdev);
return 0; return 0;
} }
fw_ptr = fw->data; fw_ptr = fw->data;
...@@ -1346,6 +1397,7 @@ static int btusb_setup_intel(struct hci_dev *hdev) ...@@ -1346,6 +1397,7 @@ static int btusb_setup_intel(struct hci_dev *hdev)
BT_INFO("%s: Intel Bluetooth firmware patch completed and activated", BT_INFO("%s: Intel Bluetooth firmware patch completed and activated",
hdev->name); hdev->name);
btusb_check_bdaddr_intel(hdev);
return 0; return 0;
exit_mfg_disable: exit_mfg_disable:
...@@ -1360,6 +1412,8 @@ static int btusb_setup_intel(struct hci_dev *hdev) ...@@ -1360,6 +1412,8 @@ static int btusb_setup_intel(struct hci_dev *hdev)
kfree_skb(skb); kfree_skb(skb);
BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name); BT_INFO("%s: Intel Bluetooth firmware patch completed", hdev->name);
btusb_check_bdaddr_intel(hdev);
return 0; return 0;
exit_mfg_deactivate: exit_mfg_deactivate:
...@@ -1380,9 +1434,29 @@ static int btusb_setup_intel(struct hci_dev *hdev) ...@@ -1380,9 +1434,29 @@ static int btusb_setup_intel(struct hci_dev *hdev)
BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated", BT_INFO("%s: Intel Bluetooth firmware patch completed and deactivated",
hdev->name); hdev->name);
btusb_check_bdaddr_intel(hdev);
return 0;
}
static int btusb_set_bdaddr_intel(struct hci_dev *hdev, const bdaddr_t *bdaddr)
{
struct sk_buff *skb;
long ret;
skb = __hci_cmd_sync(hdev, 0xfc31, 6, bdaddr, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
ret = PTR_ERR(skb);
BT_ERR("%s: changing Intel device address failed (%ld)",
hdev->name, ret);
return ret;
}
kfree_skb(skb);
return 0; return 0;
} }
#define BDADDR_BCM20702A0 (&(bdaddr_t) {{0x00, 0xa0, 0x02, 0x70, 0x20, 0x00}})
static int btusb_setup_bcm_patchram(struct hci_dev *hdev) static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
{ {
struct btusb_data *data = hci_get_drvdata(hdev); struct btusb_data *data = hci_get_drvdata(hdev);
...@@ -1396,6 +1470,7 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev) ...@@ -1396,6 +1470,7 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
u16 opcode; u16 opcode;
struct sk_buff *skb; struct sk_buff *skb;
struct hci_rp_read_local_version *ver; struct hci_rp_read_local_version *ver;
struct hci_rp_read_bd_addr *bda;
long ret; long ret;
snprintf(fw_name, sizeof(fw_name), "brcm/%s-%04x-%04x.hcd", snprintf(fw_name, sizeof(fw_name), "brcm/%s-%04x-%04x.hcd",
...@@ -1405,8 +1480,7 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev) ...@@ -1405,8 +1480,7 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
ret = request_firmware(&fw, fw_name, &hdev->dev); ret = request_firmware(&fw, fw_name, &hdev->dev);
if (ret < 0) { if (ret < 0) {
BT_INFO("%s: BCM: patch %s not found", hdev->name, BT_INFO("%s: BCM: patch %s not found", hdev->name, fw_name);
fw_name);
return 0; return 0;
} }
...@@ -1525,12 +1599,67 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev) ...@@ -1525,12 +1599,67 @@ static int btusb_setup_bcm_patchram(struct hci_dev *hdev)
ver->lmp_ver, ver->lmp_subver); ver->lmp_ver, ver->lmp_subver);
kfree_skb(skb); kfree_skb(skb);
/* Read BD Address */
skb = __hci_cmd_sync(hdev, HCI_OP_READ_BD_ADDR, 0, NULL,
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
ret = PTR_ERR(skb);
BT_ERR("%s: HCI_OP_READ_BD_ADDR failed (%ld)",
hdev->name, ret);
goto done;
}
if (skb->len != sizeof(*bda)) {
BT_ERR("%s: HCI_OP_READ_BD_ADDR event length mismatch",
hdev->name);
kfree_skb(skb);
ret = -EIO;
goto done;
}
bda = (struct hci_rp_read_bd_addr *) skb->data;
if (bda->status) {
BT_ERR("%s: HCI_OP_READ_BD_ADDR error status (%02x)",
hdev->name, bda->status);
kfree_skb(skb);
ret = -bt_to_errno(bda->status);
goto done;
}
/* The address 00:20:70:02:A0:00 indicates a BCM20702A0 controller
* with no configured address.
*/
if (!bacmp(&bda->bdaddr, BDADDR_BCM20702A0)) {
BT_INFO("%s: BCM: using default device address (%pMR)",
hdev->name, &bda->bdaddr);
set_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks);
}
kfree_skb(skb);
done: done:
release_firmware(fw); release_firmware(fw);
return ret; return ret;
} }
static int btusb_set_bdaddr_bcm(struct hci_dev *hdev, const bdaddr_t *bdaddr)
{
struct sk_buff *skb;
long ret;
skb = __hci_cmd_sync(hdev, 0xfc01, 6, bdaddr, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
ret = PTR_ERR(skb);
BT_ERR("%s: BCM: Change address command failed (%ld)",
hdev->name, ret);
return ret;
}
kfree_skb(skb);
return 0;
}
static int btusb_probe(struct usb_interface *intf, static int btusb_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
...@@ -1555,15 +1684,6 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -1555,15 +1684,6 @@ static int btusb_probe(struct usb_interface *intf,
if (id->driver_info == BTUSB_IGNORE) if (id->driver_info == BTUSB_IGNORE)
return -ENODEV; return -ENODEV;
if (ignore_dga && id->driver_info & BTUSB_DIGIANSWER)
return -ENODEV;
if (ignore_csr && id->driver_info & BTUSB_CSR)
return -ENODEV;
if (ignore_sniffer && id->driver_info & BTUSB_SNIFFER)
return -ENODEV;
if (id->driver_info & BTUSB_ATH3012) { if (id->driver_info & BTUSB_ATH3012) {
struct usb_device *udev = interface_to_usbdev(intf); struct usb_device *udev = interface_to_usbdev(intf);
...@@ -1636,11 +1756,18 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -1636,11 +1756,18 @@ static int btusb_probe(struct usb_interface *intf,
if (id->driver_info & BTUSB_BCM92035) if (id->driver_info & BTUSB_BCM92035)
hdev->setup = btusb_setup_bcm92035; hdev->setup = btusb_setup_bcm92035;
if (id->driver_info & BTUSB_BCM_PATCHRAM) if (id->driver_info & BTUSB_BCM_PATCHRAM) {
hdev->setup = btusb_setup_bcm_patchram; hdev->setup = btusb_setup_bcm_patchram;
hdev->set_bdaddr = btusb_set_bdaddr_bcm;
}
if (id->driver_info & BTUSB_INTEL) if (id->driver_info & BTUSB_INTEL) {
hdev->setup = btusb_setup_intel; hdev->setup = btusb_setup_intel;
hdev->set_bdaddr = btusb_set_bdaddr_intel;
}
if (id->driver_info & BTUSB_INTEL_BOOT)
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
/* Interface numbers are hardcoded in the specification */ /* Interface numbers are hardcoded in the specification */
data->isoc = usb_ifnum_to_if(data->udev, 1); data->isoc = usb_ifnum_to_if(data->udev, 1);
...@@ -1680,8 +1807,18 @@ static int btusb_probe(struct usb_interface *intf, ...@@ -1680,8 +1807,18 @@ static int btusb_probe(struct usb_interface *intf,
/* New sniffer firmware has crippled HCI interface */ /* New sniffer firmware has crippled HCI interface */
if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997) if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997)
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
}
data->isoc = NULL; if (id->driver_info & BTUSB_INTEL_BOOT) {
/* A bug in the bootloader causes that interrupt interface is
* only enabled after receiving SetInterface(0, AltSetting=0).
*/
err = usb_set_interface(data->udev, 0, 0);
if (err < 0) {
BT_ERR("failed to set interface 0, alt 0 %d", err);
hci_free_dev(hdev);
return err;
}
} }
if (data->isoc) { if (data->isoc) {
...@@ -1846,15 +1983,6 @@ static struct usb_driver btusb_driver = { ...@@ -1846,15 +1983,6 @@ static struct usb_driver btusb_driver = {
module_usb_driver(btusb_driver); module_usb_driver(btusb_driver);
module_param(ignore_dga, bool, 0644);
MODULE_PARM_DESC(ignore_dga, "Ignore devices with id 08fd:0001");
module_param(ignore_csr, bool, 0644);
MODULE_PARM_DESC(ignore_csr, "Ignore devices with id 0a12:0001");
module_param(ignore_sniffer, bool, 0644);
MODULE_PARM_DESC(ignore_sniffer, "Ignore devices with id 0a12:0002");
module_param(disable_scofix, bool, 0644); module_param(disable_scofix, bool, 0644);
MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size"); MODULE_PARM_DESC(disable_scofix, "Disable fixup of wrong SCO buffer size");
......
...@@ -355,10 +355,7 @@ static void h5_complete_rx_pkt(struct hci_uart *hu) ...@@ -355,10 +355,7 @@ static void h5_complete_rx_pkt(struct hci_uart *hu)
static int h5_rx_crc(struct hci_uart *hu, unsigned char c) static int h5_rx_crc(struct hci_uart *hu, unsigned char c)
{ {
struct h5 *h5 = hu->priv;
h5_complete_rx_pkt(hu); h5_complete_rx_pkt(hu);
h5_reset_rx(h5);
return 0; return 0;
} }
...@@ -373,7 +370,6 @@ static int h5_rx_payload(struct hci_uart *hu, unsigned char c) ...@@ -373,7 +370,6 @@ static int h5_rx_payload(struct hci_uart *hu, unsigned char c)
h5->rx_pending = 2; h5->rx_pending = 2;
} else { } else {
h5_complete_rx_pkt(hu); h5_complete_rx_pkt(hu);
h5_reset_rx(h5);
} }
return 0; return 0;
...@@ -406,6 +402,7 @@ static int h5_rx_3wire_hdr(struct hci_uart *hu, unsigned char c) ...@@ -406,6 +402,7 @@ static int h5_rx_3wire_hdr(struct hci_uart *hu, unsigned char c)
H5_HDR_PKT_TYPE(hdr) != HCI_3WIRE_LINK_PKT) { H5_HDR_PKT_TYPE(hdr) != HCI_3WIRE_LINK_PKT) {
BT_ERR("Non-link packet received in non-active state"); BT_ERR("Non-link packet received in non-active state");
h5_reset_rx(h5); h5_reset_rx(h5);
return 0;
} }
h5->rx_func = h5_rx_payload; h5->rx_func = h5_rx_payload;
......
...@@ -431,6 +431,9 @@ static int hci_uart_register_dev(struct hci_uart *hu) ...@@ -431,6 +431,9 @@ static int hci_uart_register_dev(struct hci_uart *hu)
if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags)) if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags))
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); 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)) if (!test_bit(HCI_UART_RESET_ON_INIT, &hu->hdev_flags))
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks); 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) ...@@ -477,6 +480,22 @@ static int hci_uart_set_proto(struct hci_uart *hu, int id)
return 0; 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() /* hci_uart_tty_ioctl()
* *
* Process IOCTL system call for the tty device. * 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, ...@@ -520,14 +539,16 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file,
return -EUNATCH; return -EUNATCH;
case HCIUARTGETDEVICE: case HCIUARTGETDEVICE:
if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) if (test_bit(HCI_UART_REGISTERED, &hu->flags))
return hu->hdev->id; return hu->hdev->id;
return -EUNATCH; return -EUNATCH;
case HCIUARTSETFLAGS: case HCIUARTSETFLAGS:
if (test_bit(HCI_UART_PROTO_SET, &hu->flags)) if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
return -EBUSY; return -EBUSY;
hu->hdev_flags = arg; err = hci_uart_set_flags(hu, arg);
if (err)
return err;
break; break;
case HCIUARTGETFLAGS: case HCIUARTGETFLAGS:
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#define HCI_UART_RESET_ON_INIT 1 #define HCI_UART_RESET_ON_INIT 1
#define HCI_UART_CREATE_AMP 2 #define HCI_UART_CREATE_AMP 2
#define HCI_UART_INIT_PENDING 3 #define HCI_UART_INIT_PENDING 3
#define HCI_UART_EXT_CONFIG 4
struct hci_uart; struct hci_uart;
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
#define VERSION "1.4" #define VERSION "1.5"
static bool amp; static bool amp;
...@@ -95,10 +95,21 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -95,10 +95,21 @@ static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
return 0; return 0;
} }
static int vhci_create_device(struct vhci_data *data, __u8 dev_type) static int vhci_create_device(struct vhci_data *data, __u8 opcode)
{ {
struct hci_dev *hdev; struct hci_dev *hdev;
struct sk_buff *skb; struct sk_buff *skb;
__u8 dev_type;
/* bits 0-1 are dev_type (BR/EDR or AMP) */
dev_type = opcode & 0x03;
if (dev_type != HCI_BREDR && dev_type != HCI_AMP)
return -EINVAL;
/* bits 2-5 are reserved (must be zero) */
if (opcode & 0x3c)
return -EINVAL;
skb = bt_skb_alloc(4, GFP_KERNEL); skb = bt_skb_alloc(4, GFP_KERNEL);
if (!skb) if (!skb)
...@@ -121,6 +132,14 @@ static int vhci_create_device(struct vhci_data *data, __u8 dev_type) ...@@ -121,6 +132,14 @@ static int vhci_create_device(struct vhci_data *data, __u8 dev_type)
hdev->flush = vhci_flush; hdev->flush = vhci_flush;
hdev->send = vhci_send_frame; hdev->send = vhci_send_frame;
/* bit 6 is for external configuration */
if (opcode & 0x40)
set_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks);
/* bit 7 is for raw device */
if (opcode & 0x80)
set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks);
if (hci_register_dev(hdev) < 0) { if (hci_register_dev(hdev) < 0) {
BT_ERR("Can't register HCI device"); BT_ERR("Can't register HCI device");
hci_free_dev(hdev); hci_free_dev(hdev);
...@@ -132,7 +151,7 @@ static int vhci_create_device(struct vhci_data *data, __u8 dev_type) ...@@ -132,7 +151,7 @@ static int vhci_create_device(struct vhci_data *data, __u8 dev_type)
bt_cb(skb)->pkt_type = HCI_VENDOR_PKT; bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
*skb_put(skb, 1) = 0xff; *skb_put(skb, 1) = 0xff;
*skb_put(skb, 1) = dev_type; *skb_put(skb, 1) = opcode;
put_unaligned_le16(hdev->id, skb_put(skb, 2)); put_unaligned_le16(hdev->id, skb_put(skb, 2));
skb_queue_tail(&data->readq, skb); skb_queue_tail(&data->readq, skb);
...@@ -146,7 +165,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data, ...@@ -146,7 +165,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
{ {
size_t len = iov_length(iov, count); size_t len = iov_length(iov, count);
struct sk_buff *skb; struct sk_buff *skb;
__u8 pkt_type, dev_type; __u8 pkt_type, opcode;
unsigned long i; unsigned long i;
int ret; int ret;
...@@ -190,7 +209,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data, ...@@ -190,7 +209,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
cancel_delayed_work_sync(&data->open_timeout); cancel_delayed_work_sync(&data->open_timeout);
dev_type = *((__u8 *) skb->data); opcode = *((__u8 *) skb->data);
skb_pull(skb, 1); skb_pull(skb, 1);
if (skb->len > 0) { if (skb->len > 0) {
...@@ -200,10 +219,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data, ...@@ -200,10 +219,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
kfree_skb(skb); kfree_skb(skb);
if (dev_type != HCI_BREDR && dev_type != HCI_AMP) ret = vhci_create_device(data, opcode);
return -EINVAL;
ret = vhci_create_device(data, dev_type);
break; break;
default: default:
......
...@@ -603,16 +603,19 @@ static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, ...@@ -603,16 +603,19 @@ static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
if (ret) if (ret)
return ret; return ret;
src_ring->hw_index = read_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); if (read_index == 0xffffffff)
src_ring->hw_index &= nentries_mask; return -ENODEV;
read_index &= nentries_mask;
src_ring->hw_index = read_index;
ath10k_pci_sleep(ar); ath10k_pci_sleep(ar);
} }
read_index = src_ring->hw_index; read_index = src_ring->hw_index;
if ((read_index == sw_index) || (read_index == 0xffffffff)) if (read_index == sw_index)
return -EIO; return -EIO;
sbase = src_ring->shadow_base; sbase = src_ring->shadow_base;
......
...@@ -795,10 +795,14 @@ int ath10k_core_start(struct ath10k *ar) ...@@ -795,10 +795,14 @@ int ath10k_core_start(struct ath10k *ar)
if (status) if (status)
goto err_htc_stop; goto err_htc_stop;
ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1; if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
ar->free_vdev_map = (1 << TARGET_10X_NUM_VDEVS) - 1;
else
ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
INIT_LIST_HEAD(&ar->arvifs); 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", ath10k_info("%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
ar->hw_params.name, ar->hw_params.name,
ar->target_version, ar->target_version,
...@@ -807,6 +811,12 @@ int ath10k_core_start(struct ath10k *ar) ...@@ -807,6 +811,12 @@ int ath10k_core_start(struct ath10k *ar)
ar->fw_api, ar->fw_api,
ar->htt.target_version_major, ar->htt.target_version_major,
ar->htt.target_version_minor); 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); __set_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags);
...@@ -984,7 +994,9 @@ static void ath10k_core_register_work(struct work_struct *work) ...@@ -984,7 +994,9 @@ static void ath10k_core_register_work(struct work_struct *work)
err_release_fw: err_release_fw:
ath10k_core_free_firmware_files(ar); ath10k_core_free_firmware_files(ar);
err: 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; return;
} }
......
...@@ -290,6 +290,9 @@ struct ath10k_debug { ...@@ -290,6 +290,9 @@ struct ath10k_debug {
struct ath_dfs_pool_stats dfs_pool_stats; struct ath_dfs_pool_stats dfs_pool_stats;
u32 fw_dbglog_mask; u32 fw_dbglog_mask;
u8 htt_max_amsdu;
u8 htt_max_ampdu;
}; };
enum ath10k_state { enum ath10k_state {
......
...@@ -671,6 +671,72 @@ static const struct file_operations fops_htt_stats_mask = { ...@@ -671,6 +671,72 @@ static const struct file_operations fops_htt_stats_mask = {
.llseek = default_llseek, .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, static ssize_t ath10k_read_fw_dbglog(struct file *file,
char __user *user_buf, char __user *user_buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
...@@ -757,6 +823,9 @@ void ath10k_debug_stop(struct ath10k *ar) ...@@ -757,6 +823,9 @@ void ath10k_debug_stop(struct ath10k *ar)
* warning from del_timer(). */ * warning from del_timer(). */
if (ar->debug.htt_stats_mask != 0) if (ar->debug.htt_stats_mask != 0)
cancel_delayed_work(&ar->debug.htt_stats_dwork); 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, static ssize_t ath10k_write_simulate_radar(struct file *file,
...@@ -867,6 +936,10 @@ int ath10k_debug_create(struct ath10k *ar) ...@@ -867,6 +936,10 @@ int ath10k_debug_create(struct ath10k *ar)
debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy, debugfs_create_file("htt_stats_mask", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_htt_stats_mask); 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, debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_fw_dbglog); ar, &fops_fw_dbglog);
......
...@@ -240,16 +240,10 @@ struct htt_oob_sync_req { ...@@ -240,16 +240,10 @@ struct htt_oob_sync_req {
__le16 rsvd0; __le16 rsvd0;
} __packed; } __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 { struct htt_aggr_conf {
u8 max_num_ampdu_subframes; u8 max_num_ampdu_subframes;
union { /* amsdu_subframes is limited by 0x1F mask */
/* dont use bitfields; undefined behaviour */ u8 max_num_amsdu_subframes;
u8 flags; /* see %HTT_AGGR_CONF_MAX_NUM_AMSDU_SUBFRAMES_ */
u8 max_num_amsdu_subframes:5;
} __packed;
} __packed; } __packed;
#define HTT_MGMT_FRM_HDR_DOWNLOAD_LEN 32 #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); ...@@ -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_ver_req_msg(struct ath10k_htt *htt);
int ath10k_htt_h2t_stats_req(struct ath10k_htt *htt, u8 mask, u64 cookie); 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_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); void __ath10k_htt_tx_dec_pending(struct ath10k_htt *htt);
int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt); int ath10k_htt_tx_alloc_msdu_id(struct ath10k_htt *htt);
......
...@@ -312,7 +312,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -312,7 +312,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
int msdu_len, msdu_chaining = 0; int msdu_len, msdu_chaining = 0;
struct sk_buff *msdu; struct sk_buff *msdu;
struct htt_rx_desc *rx_desc; struct htt_rx_desc *rx_desc;
bool corrupted = false;
lockdep_assert_held(&htt->rx_ring.lock); lockdep_assert_held(&htt->rx_ring.lock);
...@@ -439,9 +438,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -439,9 +438,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) & last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) &
RX_MSDU_END_INFO0_LAST_MSDU; RX_MSDU_END_INFO0_LAST_MSDU;
if (msdu_chaining && !last_msdu)
corrupted = true;
if (last_msdu) { if (last_msdu) {
msdu->next = NULL; msdu->next = NULL;
break; break;
...@@ -456,20 +452,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, ...@@ -456,20 +452,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
if (*head_msdu == NULL) if (*head_msdu == NULL)
msdu_chaining = -1; msdu_chaining = -1;
/*
* Apparently FW sometimes reports weird chained MSDU sequences with
* more than one rx descriptor. This seems like a bug but needs more
* analyzing. For the time being fix it by dropping such sequences to
* avoid blowing up the host system.
*/
if (corrupted) {
ath10k_warn("failed to pop chained msdus, dropping\n");
ath10k_htt_rx_free_msdu_chain(*head_msdu);
*head_msdu = NULL;
*tail_msdu = NULL;
msdu_chaining = -EINVAL;
}
/* /*
* Don't refill the ring yet. * Don't refill the ring yet.
* *
......
...@@ -307,6 +307,52 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt) ...@@ -307,6 +307,52 @@ int ath10k_htt_send_rx_ring_cfg_ll(struct ath10k_htt *htt)
return 0; 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) int ath10k_htt_mgmt_tx(struct ath10k_htt *htt, struct sk_buff *msdu)
{ {
struct device *dev = htt->ar->dev; struct device *dev = htt->ar->dev;
......
...@@ -1362,8 +1362,6 @@ static int ath10k_pci_hif_exchange_bmi_msg(struct ath10k *ar, ...@@ -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); 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); ret = ath10k_ce_send(ce_tx, &xfer, req_paddr, req_len, -1, 0);
if (ret) if (ret)
goto err_resp; goto err_resp;
...@@ -1414,10 +1412,7 @@ static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state) ...@@ -1414,10 +1412,7 @@ static void ath10k_pci_bmi_send_done(struct ath10k_ce_pipe *ce_state)
&nbytes, &transfer_id)) &nbytes, &transfer_id))
return; return;
if (xfer->wait_for_resp) xfer->tx_done = true;
return;
complete(&xfer->done);
} }
static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state) 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) ...@@ -1438,7 +1433,7 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state)
} }
xfer->resp_len = nbytes; xfer->resp_len = nbytes;
complete(&xfer->done); xfer->rx_done = true;
} }
static int ath10k_pci_bmi_wait(struct ath10k_ce_pipe *tx_pipe, 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, ...@@ -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_send_done(tx_pipe);
ath10k_pci_bmi_recv_data(rx_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; return 0;
schedule(); schedule();
......
...@@ -38,7 +38,8 @@ ...@@ -38,7 +38,8 @@
#define DIAG_TRANSFER_LIMIT 2048 #define DIAG_TRANSFER_LIMIT 2048
struct bmi_xfer { struct bmi_xfer {
struct completion done; bool tx_done;
bool rx_done;
bool wait_for_resp; bool wait_for_resp;
u32 resp_len; u32 resp_len;
}; };
......
...@@ -2106,7 +2106,6 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -2106,7 +2106,6 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb)
{ {
struct wmi_cmd_hdr *cmd_hdr; struct wmi_cmd_hdr *cmd_hdr;
enum wmi_event_id id; enum wmi_event_id id;
u16 len;
cmd_hdr = (struct wmi_cmd_hdr *)skb->data; cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); 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) ...@@ -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) if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
return; return;
len = skb->len;
trace_ath10k_wmi_event(id, skb->data, skb->len); trace_ath10k_wmi_event(id, skb->data, skb->len);
switch (id) { switch (id) {
...@@ -2225,7 +2222,6 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb) ...@@ -2225,7 +2222,6 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb)
{ {
struct wmi_cmd_hdr *cmd_hdr; struct wmi_cmd_hdr *cmd_hdr;
enum wmi_10x_event_id id; enum wmi_10x_event_id id;
u16 len;
cmd_hdr = (struct wmi_cmd_hdr *)skb->data; cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
id = MS(__le32_to_cpu(cmd_hdr->cmd_id), WMI_CMD_HDR_CMD_ID); 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) ...@@ -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) if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
return; return;
len = skb->len;
trace_ath10k_wmi_event(id, skb->data, skb->len); trace_ath10k_wmi_event(id, skb->data, skb->len);
switch (id) { switch (id) {
......
...@@ -242,7 +242,8 @@ struct ath6kl_bmi_target_info { ...@@ -242,7 +242,8 @@ struct ath6kl_bmi_target_info {
(void) (check_type == val); \ (void) (check_type == val); \
addr = ath6kl_get_hi_item_addr(ar, HI_ITEM(item)); \ addr = ath6kl_get_hi_item_addr(ar, HI_ITEM(item)); \
ret = ath6kl_bmi_read(ar, addr, (u8 *) &tmp, 4); \ ret = ath6kl_bmi_read(ar, addr, (u8 *) &tmp, 4); \
*val = le32_to_cpu(tmp); \ if (!ret) \
*val = le32_to_cpu(tmp); \
ret; \ ret; \
}) })
......
...@@ -2899,7 +2899,8 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, ...@@ -2899,7 +2899,8 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev,
if (info->inactivity_timeout) { if (info->inactivity_timeout) {
inactivity_timeout = 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, inactivity_timeout = DIV_ROUND_UP(inactivity_timeout,
60); 60);
...@@ -3782,7 +3783,8 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) ...@@ -3782,7 +3783,8 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
ath6kl_band_5ghz.ht_cap.ht_supported = false; 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_2ghz.ht_cap.mcs.rx_mask[0] = 0xff;
ath6kl_band_5ghz.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; ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff;
......
...@@ -123,6 +123,22 @@ int ath6kl_core_init(struct ath6kl *ar, enum ath6kl_htc_type htc_type) ...@@ -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 */ /* 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) */ /* Indicate that WMI is enabled (although not ready yet) */
set_bit(WMI_ENABLED, &ar->flag); set_bit(WMI_ENABLED, &ar->flag);
ar->wmi = ath6kl_wmi_init(ar); ar->wmi = ath6kl_wmi_init(ar);
......
...@@ -136,6 +136,21 @@ enum ath6kl_fw_capability { ...@@ -136,6 +136,21 @@ enum ath6kl_fw_capability {
*/ */
ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, 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 */ /* this needs to be last */
ATH6KL_FW_CAPABILITY_MAX, ATH6KL_FW_CAPABILITY_MAX,
}; };
...@@ -149,15 +164,13 @@ struct ath6kl_fw_ie { ...@@ -149,15 +164,13 @@ struct ath6kl_fw_ie {
}; };
enum ath6kl_hw_flags { 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), ATH6KL_HW_SDIO_CRC_ERROR_WAR = BIT(3),
}; };
#define ATH6KL_FW_API2_FILE "fw-2.bin" #define ATH6KL_FW_API2_FILE "fw-2.bin"
#define ATH6KL_FW_API3_FILE "fw-3.bin" #define ATH6KL_FW_API3_FILE "fw-3.bin"
#define ATH6KL_FW_API4_FILE "fw-4.bin" #define ATH6KL_FW_API4_FILE "fw-4.bin"
#define ATH6KL_FW_API5_FILE "fw-5.bin"
/* AR6003 1.0 definitions */ /* AR6003 1.0 definitions */
#define AR6003_HW_1_0_VERSION 0x300002ba #define AR6003_HW_1_0_VERSION 0x300002ba
...@@ -215,8 +228,21 @@ enum ath6kl_hw_flags { ...@@ -215,8 +228,21 @@ enum ath6kl_hw_flags {
#define AR6004_HW_1_3_VERSION 0x31c8088a #define AR6004_HW_1_3_VERSION 0x31c8088a
#define AR6004_HW_1_3_FW_DIR "ath6k/AR6004/hw1.3" #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_FIRMWARE_FILE "fw.ram.bin"
#define AR6004_HW_1_3_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.bin" #define AR6004_HW_1_3_TCMD_FIRMWARE_FILE "utf.bin"
#define AR6004_HW_1_3_DEFAULT_BOARD_DATA_FILE "ath6k/AR6004/hw1.3/bdata.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 */ /* Per STA data, used in AP mode */
#define STA_PS_AWAKE BIT(0) #define STA_PS_AWAKE BIT(0)
......
...@@ -1170,8 +1170,12 @@ static int htc_wait_recv_ctrl_message(struct htc_target *target) ...@@ -1170,8 +1170,12 @@ static int htc_wait_recv_ctrl_message(struct htc_target *target)
static void htc_rxctrl_complete(struct htc_target *context, static void htc_rxctrl_complete(struct htc_target *context,
struct htc_packet *packet) struct htc_packet *packet)
{ {
/* TODO, can't really receive HTC control messages yet.... */ struct sk_buff *skb = packet->skb;
ath6kl_dbg(ATH6KL_DBG_HTC, "%s: invalid call function\n", __func__);
if (packet->endpoint == ENDPOINT_0 &&
packet->status == -ECANCELED &&
skb != NULL)
dev_kfree_skb(skb);
} }
/* htc pipe initialization */ /* htc pipe initialization */
...@@ -1678,7 +1682,29 @@ static void ath6kl_htc_pipe_activity_changed(struct htc_target *target, ...@@ -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) 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, static int ath6kl_htc_pipe_credit_setup(struct htc_target *target,
......
...@@ -93,8 +93,7 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -93,8 +93,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x433900, .board_addr = 0x433900,
.refclk_hz = 26000000, .refclk_hz = 26000000,
.uarttx_pin = 11, .uarttx_pin = 11,
.flags = ATH6KL_HW_64BIT_RATES | .flags = 0,
ATH6KL_HW_AP_INACTIVITY_MINS,
.fw = { .fw = {
.dir = AR6004_HW_1_0_FW_DIR, .dir = AR6004_HW_1_0_FW_DIR,
...@@ -114,8 +113,7 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -114,8 +113,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x43d400, .board_addr = 0x43d400,
.refclk_hz = 40000000, .refclk_hz = 40000000,
.uarttx_pin = 11, .uarttx_pin = 11,
.flags = ATH6KL_HW_64BIT_RATES | .flags = 0,
ATH6KL_HW_AP_INACTIVITY_MINS,
.fw = { .fw = {
.dir = AR6004_HW_1_1_FW_DIR, .dir = AR6004_HW_1_1_FW_DIR,
.fw = AR6004_HW_1_1_FIRMWARE_FILE, .fw = AR6004_HW_1_1_FIRMWARE_FILE,
...@@ -134,8 +132,7 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -134,8 +132,7 @@ static const struct ath6kl_hw hw_list[] = {
.board_addr = 0x435c00, .board_addr = 0x435c00,
.refclk_hz = 40000000, .refclk_hz = 40000000,
.uarttx_pin = 11, .uarttx_pin = 11,
.flags = ATH6KL_HW_64BIT_RATES | .flags = 0,
ATH6KL_HW_AP_INACTIVITY_MINS,
.fw = { .fw = {
.dir = AR6004_HW_1_2_FW_DIR, .dir = AR6004_HW_1_2_FW_DIR,
...@@ -152,20 +149,43 @@ static const struct ath6kl_hw hw_list[] = { ...@@ -152,20 +149,43 @@ static const struct ath6kl_hw hw_list[] = {
.board_ext_data_addr = 0x437000, .board_ext_data_addr = 0x437000,
.reserved_ram_size = 7168, .reserved_ram_size = 7168,
.board_addr = 0x436400, .board_addr = 0x436400,
.refclk_hz = 40000000, .refclk_hz = 0,
.uarttx_pin = 11, .uarttx_pin = 11,
.flags = ATH6KL_HW_64BIT_RATES | .flags = 0,
ATH6KL_HW_AP_INACTIVITY_MINS |
ATH6KL_HW_MAP_LP_ENDPOINT,
.fw = { .fw = {
.dir = AR6004_HW_1_3_FW_DIR, .dir = AR6004_HW_1_3_FW_DIR,
.fw = AR6004_HW_1_3_FIRMWARE_FILE, .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_board = AR6004_HW_1_3_BOARD_DATA_FILE,
.fw_default_board = AR6004_HW_1_3_DEFAULT_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) ...@@ -601,7 +621,9 @@ int ath6kl_configure_target(struct ath6kl *ar)
* but possible in theory. * 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; param = ar->hw.board_ext_data_addr;
ram_reserved_size = ar->hw.reserved_ram_size; ram_reserved_size = ar->hw.reserved_ram_size;
...@@ -629,9 +651,12 @@ int ath6kl_configure_target(struct ath6kl *ar) ...@@ -629,9 +651,12 @@ int ath6kl_configure_target(struct ath6kl *ar)
return status; return status;
/* Configure target refclk_hz */ /* Configure target refclk_hz */
status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz, ar->hw.refclk_hz); if (ar->hw.refclk_hz != 0) {
if (status) status = ath6kl_bmi_write_hi32(ar, hi_refclk_hz,
return status; ar->hw.refclk_hz);
if (status)
return status;
}
return 0; return 0;
} }
...@@ -1112,6 +1137,12 @@ int ath6kl_init_fetch_firmwares(struct ath6kl *ar) ...@@ -1112,6 +1137,12 @@ int ath6kl_init_fetch_firmwares(struct ath6kl *ar)
if (ret) if (ret)
return 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); ret = ath6kl_fetch_fw_apin(ar, ATH6KL_FW_API4_FILE);
if (ret == 0) { if (ret == 0) {
ar->fw_api = 4; ar->fw_api = 4;
...@@ -1161,11 +1192,19 @@ static int ath6kl_upload_board_file(struct ath6kl *ar) ...@@ -1161,11 +1192,19 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
ath6kl_bmi_write_hi32(ar, hi_board_data, ath6kl_bmi_write_hi32(ar, hi_board_data,
board_address); board_address);
} else { } 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 */ /* 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 && if (ar->target_type == TARGET_TYPE_AR6003 &&
board_ext_address == 0) { board_ext_address == 0) {
...@@ -1230,7 +1269,13 @@ static int ath6kl_upload_board_file(struct ath6kl *ar) ...@@ -1230,7 +1269,13 @@ static int ath6kl_upload_board_file(struct ath6kl *ar)
} }
/* record the fact that Board Data IS initialized */ /* 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; return ret;
} }
...@@ -1361,7 +1406,11 @@ static int ath6kl_upload_testscript(struct ath6kl *ar) ...@@ -1361,7 +1406,11 @@ static int ath6kl_upload_testscript(struct ath6kl *ar)
} }
ath6kl_bmi_write_hi32(ar, hi_ota_testscript, address); 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); ath6kl_bmi_write_hi32(ar, hi_test_apps_related, 1);
return 0; return 0;
...@@ -1567,6 +1616,11 @@ static const struct fw_capa_str_map { ...@@ -1567,6 +1616,11 @@ static const struct fw_capa_str_map {
{ ATH6KL_FW_CAPABILITY_REGDOMAIN, "regdomain" }, { ATH6KL_FW_CAPABILITY_REGDOMAIN, "regdomain" },
{ ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, "sched-scan-v2" }, { ATH6KL_FW_CAPABILITY_SCHED_SCAN_V2, "sched-scan-v2" },
{ ATH6KL_FW_CAPABILITY_HEART_BEAT_POLL, "hb-poll" }, { 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) static const char *ath6kl_init_get_fw_capa_name(unsigned int id)
......
...@@ -702,6 +702,7 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len) ...@@ -702,6 +702,7 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len)
struct ath6kl *ar = vif->ar; struct ath6kl *ar = vif->ar;
struct target_stats *stats = &vif->target_stats; struct target_stats *stats = &vif->target_stats;
struct tkip_ccmp_stats *ccmp_stats; struct tkip_ccmp_stats *ccmp_stats;
s32 rate;
u8 ac; u8 ac;
if (len < sizeof(*tgt_stats)) if (len < sizeof(*tgt_stats))
...@@ -731,8 +732,9 @@ static void ath6kl_update_target_stats(struct ath6kl_vif *vif, u8 *ptr, u32 len) ...@@ -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); le32_to_cpu(tgt_stats->stats.tx.mult_retry_cnt);
stats->tx_rts_fail_cnt += stats->tx_rts_fail_cnt +=
le32_to_cpu(tgt_stats->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_pkt += le32_to_cpu(tgt_stats->stats.rx.pkt);
stats->rx_byte += le32_to_cpu(tgt_stats->stats.rx.byte); 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) ...@@ -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); 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_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_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; ccmp_stats = &tgt_stats->stats.tkip_ccmp_stats;
...@@ -1290,6 +1293,8 @@ static const struct net_device_ops ath6kl_netdev_ops = { ...@@ -1290,6 +1293,8 @@ static const struct net_device_ops ath6kl_netdev_ops = {
void init_netdev(struct net_device *dev) void init_netdev(struct net_device *dev)
{ {
struct ath6kl *ar = ath6kl_priv(dev);
dev->netdev_ops = &ath6kl_netdev_ops; dev->netdev_ops = &ath6kl_netdev_ops;
dev->destructor = free_netdev; dev->destructor = free_netdev;
dev->watchdog_timeo = ATH6KL_TX_TIMEOUT; dev->watchdog_timeo = ATH6KL_TX_TIMEOUT;
...@@ -1301,7 +1306,9 @@ void init_netdev(struct net_device *dev) ...@@ -1301,7 +1306,9 @@ void init_netdev(struct net_device *dev)
WMI_MAX_TX_META_SZ + WMI_MAX_TX_META_SZ +
ATH6KL_HTC_ALIGN_BYTES, 4); 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; return;
} }
...@@ -802,7 +802,8 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id, ...@@ -802,7 +802,8 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
break; break;
case WMI_DATA_VI_SVC: 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; *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
else else
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP; *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, ...@@ -814,7 +815,8 @@ static int ath6kl_usb_map_service_pipe(struct ath6kl *ar, u16 svc_id,
break; break;
case WMI_DATA_VO_SVC: 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; *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_LP;
else else
*ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP; *ul_pipe = ATH6KL_USB_PIPE_TX_DATA_MP;
...@@ -1208,6 +1210,7 @@ static int ath6kl_usb_pm_reset_resume(struct usb_interface *intf) ...@@ -1208,6 +1210,7 @@ static int ath6kl_usb_pm_reset_resume(struct usb_interface *intf)
/* table of devices that work with this driver */ /* table of devices that work with this driver */
static struct usb_device_id ath6kl_usb_ids[] = { static struct usb_device_id ath6kl_usb_ids[] = {
{USB_DEVICE(0x0cf3, 0x9375)},
{USB_DEVICE(0x0cf3, 0x9374)}, {USB_DEVICE(0x0cf3, 0x9374)},
{ /* Terminating entry */ }, { /* Terminating entry */ },
}; };
......
...@@ -59,6 +59,55 @@ static const s32 wmi_rate_tbl[][2] = { ...@@ -59,6 +59,55 @@ static const s32 wmi_rate_tbl[][2] = {
{0, 0} {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 */ /* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
static const u8 up_to_ac[] = { static const u8 up_to_ac[] = {
WMM_AC_BE, WMM_AC_BE,
...@@ -2838,7 +2887,8 @@ int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx, ...@@ -2838,7 +2887,8 @@ int ath6kl_wmi_set_bitrate_mask(struct wmi *wmi, u8 if_idx,
{ {
struct ath6kl *ar = wmi->parent_dev; 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); return ath6kl_set_bitrate_mask64(wmi, if_idx, mask);
else else
return ath6kl_set_bitrate_mask32(wmi, if_idx, mask); 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) ...@@ -3279,9 +3329,11 @@ int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2)
NO_SYNC_WMIFLAG); 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; u8 sgi = 0;
s32 ret;
if (rate_index == RATE_AUTO) if (rate_index == RATE_AUTO)
return 0; return 0;
...@@ -3292,10 +3344,20 @@ s32 ath6kl_wmi_get_rate(s8 rate_index) ...@@ -3292,10 +3344,20 @@ s32 ath6kl_wmi_get_rate(s8 rate_index)
sgi = 1; sgi = 1;
} }
if (WARN_ON(rate_index > RATE_MCS_7_40)) if (test_bit(ATH6KL_FW_CAPABILITY_RATETABLE_MCS15,
rate_index = RATE_MCS_7_40; ar->fw_capabilities)) {
if (WARN_ON(rate_index >= ARRAY_SIZE(wmi_rate_tbl_mcs15)))
return 0;
ret = wmi_rate_tbl_mcs15[(u32) rate_index][sgi];
} else {
if (WARN_ON(rate_index >= ARRAY_SIZE(wmi_rate_tbl)))
return 0;
return wmi_rate_tbl[(u32) rate_index][sgi]; ret = wmi_rate_tbl[(u32) rate_index][sgi];
}
return ret;
} }
static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap, static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,
......
...@@ -2632,7 +2632,7 @@ int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx, ...@@ -2632,7 +2632,7 @@ int ath6kl_wmi_set_htcap_cmd(struct wmi *wmi, u8 if_idx,
struct ath6kl_htcap *htcap); struct ath6kl_htcap *htcap);
int ath6kl_wmi_test_cmd(struct wmi *wmi, void *buf, size_t len); 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, int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, u8 if_idx,
__be32 ips0, __be32 ips1); __be32 ips0, __be32 ips1);
......
...@@ -281,7 +281,7 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) ...@@ -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) ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen)
| (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | (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_VEOL ? AR_VEOL : 0)
| (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) | (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
| (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 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) ...@@ -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, 2)
| set11nRateFlags(i->rates, 3) | set11nRateFlags(i->rates, 3)
| SM(i->rtscts_rate, AR_RTSCTSRate); | 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, static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
......
...@@ -101,7 +101,7 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) ...@@ -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) ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen)
| (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) | (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_VEOL ? AR_VEOL : 0)
| (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0) | (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
| (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 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) ...@@ -151,6 +151,10 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i)
| SM(i->rtscts_rate, AR_RTSCTSRate); | SM(i->rtscts_rate, AR_RTSCTSRate);
ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding; 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) static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
......
...@@ -182,7 +182,8 @@ struct ath_atx_ac { ...@@ -182,7 +182,8 @@ struct ath_atx_ac {
struct ath_frame_info { struct ath_frame_info {
struct ath_buf *bf; struct ath_buf *bf;
int framelen; u16 framelen;
s8 txq;
enum ath9k_key_type keytype; enum ath9k_key_type keytype;
u8 keyix; u8 keyix;
u8 rtscts_rate; u8 rtscts_rate;
......
...@@ -202,7 +202,7 @@ static ssize_t write_file_ani(struct file *file, ...@@ -202,7 +202,7 @@ static ssize_t write_file_ani(struct file *file,
if (kstrtoul(buf, 0, &ani)) if (kstrtoul(buf, 0, &ani))
return -EINVAL; return -EINVAL;
if (ani < 0 || ani > 1) if (ani > 1)
return -EINVAL; return -EINVAL;
common->disable_ani = !ani; common->disable_ani = !ani;
......
...@@ -346,8 +346,14 @@ struct ar5416_desc { ...@@ -346,8 +346,14 @@ struct ar5416_desc {
#define AR_FrameLen 0x00000fff #define AR_FrameLen 0x00000fff
#define AR_VirtMoreFrag 0x00001000 #define AR_VirtMoreFrag 0x00001000
#define AR_TxCtlRsvd00 0x0000e000 #define AR_TxCtlRsvd00 0x0000e000
#define AR_XmitPower 0x003f0000 #define AR_XmitPower0 0x003f0000
#define AR_XmitPower_S 16 #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_RTSEnable 0x00400000
#define AR_VEOL 0x00800000 #define AR_VEOL 0x00800000
#define AR_ClrDestMask 0x01000000 #define AR_ClrDestMask 0x01000000
......
...@@ -313,7 +313,7 @@ static ssize_t write_file_spectral_short_repeat(struct file *file, ...@@ -313,7 +313,7 @@ static ssize_t write_file_spectral_short_repeat(struct file *file,
if (kstrtoul(buf, 0, &val)) if (kstrtoul(buf, 0, &val))
return -EINVAL; return -EINVAL;
if (val < 0 || val > 1) if (val > 1)
return -EINVAL; return -EINVAL;
sc->spec_config.short_repeat = val; sc->spec_config.short_repeat = val;
...@@ -361,7 +361,7 @@ static ssize_t write_file_spectral_count(struct file *file, ...@@ -361,7 +361,7 @@ static ssize_t write_file_spectral_count(struct file *file,
if (kstrtoul(buf, 0, &val)) if (kstrtoul(buf, 0, &val))
return -EINVAL; return -EINVAL;
if (val < 0 || val > 255) if (val > 255)
return -EINVAL; return -EINVAL;
sc->spec_config.count = val; sc->spec_config.count = val;
...@@ -409,7 +409,7 @@ static ssize_t write_file_spectral_period(struct file *file, ...@@ -409,7 +409,7 @@ static ssize_t write_file_spectral_period(struct file *file,
if (kstrtoul(buf, 0, &val)) if (kstrtoul(buf, 0, &val))
return -EINVAL; return -EINVAL;
if (val < 0 || val > 255) if (val > 255)
return -EINVAL; return -EINVAL;
sc->spec_config.period = val; sc->spec_config.period = val;
...@@ -457,7 +457,7 @@ static ssize_t write_file_spectral_fft_period(struct file *file, ...@@ -457,7 +457,7 @@ static ssize_t write_file_spectral_fft_period(struct file *file,
if (kstrtoul(buf, 0, &val)) if (kstrtoul(buf, 0, &val))
return -EINVAL; return -EINVAL;
if (val < 0 || val > 15) if (val > 15)
return -EINVAL; return -EINVAL;
sc->spec_config.fft_period = val; sc->spec_config.fft_period = val;
......
...@@ -157,15 +157,14 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq, ...@@ -157,15 +157,14 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq,
struct sk_buff *skb) struct sk_buff *skb)
{ {
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(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;
q = skb_get_queue_mapping(skb); int q = fi->txq;
if (txq == sc->tx.uapsdq)
txq = sc->tx.txq_map[q];
if (txq != sc->tx.txq_map[q]) if (q < 0)
return; return;
txq = sc->tx.txq_map[q];
if (WARN_ON(--txq->pending_frames < 0)) if (WARN_ON(--txq->pending_frames < 0))
txq->pending_frames = 0; txq->pending_frames = 0;
...@@ -2036,6 +2035,7 @@ static void setup_frame_info(struct ieee80211_hw *hw, ...@@ -2036,6 +2035,7 @@ static void setup_frame_info(struct ieee80211_hw *hw,
an = (struct ath_node *) sta->drv_priv; an = (struct ath_node *) sta->drv_priv;
memset(fi, 0, sizeof(*fi)); memset(fi, 0, sizeof(*fi));
fi->txq = -1;
if (hw_key) if (hw_key)
fi->keyix = hw_key->hw_key_idx; fi->keyix = hw_key->hw_key_idx;
else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0) else if (an && ieee80211_is_data(hdr->frame_control) && an->ps_key > 0)
...@@ -2187,6 +2187,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, ...@@ -2187,6 +2187,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_sta *sta = txctl->sta; struct ieee80211_sta *sta = txctl->sta;
struct ieee80211_vif *vif = info->control.vif; struct ieee80211_vif *vif = info->control.vif;
struct ath_frame_info *fi = get_frame_info(skb);
struct ath_vif *avp = NULL; struct ath_vif *avp = NULL;
struct ath_softc *sc = hw->priv; struct ath_softc *sc = hw->priv;
struct ath_txq *txq = txctl->txq; struct ath_txq *txq = txctl->txq;
...@@ -2216,11 +2217,13 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, ...@@ -2216,11 +2217,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; hw_queue = (info->hw_queue >= sc->hw->queues - 2) ? q : info->hw_queue;
ath_txq_lock(sc, txq); ath_txq_lock(sc, txq);
if (txq == sc->tx.txq_map[q] && if (txq == sc->tx.txq_map[q]) {
++txq->pending_frames > sc->tx.txq_max_pending[q] && fi->txq = q;
!txq->stopped) { if (++txq->pending_frames > sc->tx.txq_max_pending[q] &&
ieee80211_stop_queue(sc->hw, hw_queue); !txq->stopped) {
txq->stopped = true; ieee80211_stop_queue(sc->hw, hw_queue);
txq->stopped = true;
}
} }
queue = ieee80211_is_data_present(hdr->frame_control); queue = ieee80211_is_data_present(hdr->frame_control);
......
...@@ -448,8 +448,10 @@ static ssize_t wil_write_file_rxon(struct file *file, const char __user *buf, ...@@ -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); char *kbuf = kmalloc(len + 1, GFP_KERNEL);
if (!kbuf) if (!kbuf)
return -ENOMEM; return -ENOMEM;
if (copy_from_user(kbuf, buf, len)) if (copy_from_user(kbuf, buf, len)) {
kfree(kbuf);
return -EIO; return -EIO;
}
kbuf[len] = '\0'; kbuf[len] = '\0';
rc = kstrtol(kbuf, 0, &channel); rc = kstrtol(kbuf, 0, &channel);
...@@ -963,6 +965,26 @@ static const struct file_operations fops_sta = { ...@@ -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) int wil6210_debugfs_init(struct wil6210_priv *wil)
{ {
struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME, struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME,
...@@ -986,6 +1008,8 @@ int wil6210_debugfs_init(struct wil6210_priv *wil) ...@@ -986,6 +1008,8 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)
&wil->secure_pcp); &wil->secure_pcp);
wil_debugfs_create_ulong("status", S_IRUGO | S_IWUSR, dbg, wil_debugfs_create_ulong("status", S_IRUGO | S_IWUSR, dbg,
&wil->status); &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, wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg,
HOSTADDR(RGF_USER_USER_ICR)); HOSTADDR(RGF_USER_USER_ICR));
...@@ -998,6 +1022,9 @@ int wil6210_debugfs_init(struct wil6210_priv *wil) ...@@ -998,6 +1022,9 @@ int wil6210_debugfs_init(struct wil6210_priv *wil)
wil6210_debugfs_create_pseudo_ISR(wil, dbg); wil6210_debugfs_create_pseudo_ISR(wil, dbg);
wil6210_debugfs_create_ITR_CNT(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_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr);
debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread); debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread);
...@@ -1010,34 +1037,7 @@ int wil6210_debugfs_init(struct wil6210_priv *wil) ...@@ -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("link", S_IRUGO, dbg, wil, &fops_link);
debugfs_create_file("info", S_IRUGO, dbg, wil, &fops_info); debugfs_create_file("info", S_IRUGO, dbg, wil, &fops_info);
wil->rgf_blob.data = (void * __force)wil->csr + 0; wil6210_debugfs_init_blobs(wil, dbg);
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);
return 0; return 0;
} }
......
...@@ -314,8 +314,9 @@ static void wil_target_reset(struct wil6210_priv *wil) ...@@ -314,8 +314,9 @@ static void wil_target_reset(struct wil6210_priv *wil)
int delay = 0; int delay = 0;
u32 hw_state; u32 hw_state;
u32 rev_id; 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 */ /* register read */
#define R(a) ioread32(wil->csr + HOSTADDR(a)) #define R(a) ioread32(wil->csr + HOSTADDR(a))
...@@ -328,35 +329,59 @@ static void wil_target_reset(struct wil6210_priv *wil) ...@@ -328,35 +329,59 @@ static void wil_target_reset(struct wil6210_priv *wil)
wil->hw_version = R(RGF_USER_FW_REV_ID); wil->hw_version = R(RGF_USER_FW_REV_ID);
rev_id = wil->hw_version & 0xff; rev_id = wil->hw_version & 0xff;
/* Clear MAC link up */
S(RGF_HP_CTRL, BIT(15));
/* hpal_perst_from_pad_src_n_mask */ /* hpal_perst_from_pad_src_n_mask */
S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6)); S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6));
/* car_perst_rst_src_n_mask */ /* car_perst_rst_src_n_mask */
S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7)); S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7));
wmb(); /* order is important here */ 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_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */
W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */ W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */
wmb(); /* order is important here */ wmb(); /* order is important here */
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); 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_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); W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00);
wmb(); /* order is important here */ 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_3, 0);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 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_1, 0);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
wmb(); /* order is important here */ wmb(); /* order is important here */
W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001); if (is_sparrow) {
if (rev_id == 1) { W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000003);
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); /* reset A2 PCIE AHB */
} else {
W(RGF_PCIE_LOS_COUNTER_CTL, BIT(6) | BIT(8));
W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00008000); 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); W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
wmb(); /* order is important here */ wmb(); /* order is important here */
...@@ -371,7 +396,8 @@ static void wil_target_reset(struct wil6210_priv *wil) ...@@ -371,7 +396,8 @@ static void wil_target_reset(struct wil6210_priv *wil)
} }
} while (hw_state != HW_MACHINE_BOOT_DONE); } 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)); W(RGF_PCIE_LOS_COUNTER_CTL, BIT(8));
C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD); C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
......
...@@ -122,10 +122,12 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -122,10 +122,12 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
struct wil6210_priv *wil; struct wil6210_priv *wil;
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
void __iomem *csr; void __iomem *csr;
struct wil_board *board = (struct wil_board *)id->driver_data;
int rc; int rc;
/* check HW */ /* 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); (int)pdev->vendor, (int)pdev->device, (int)pdev->revision);
if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) { 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) ...@@ -175,6 +177,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_drvdata(pdev, wil); pci_set_drvdata(pdev, wil);
wil->pdev = pdev; wil->pdev = pdev;
wil->board = board;
wil6210_clear_irq(wil); wil6210_clear_irq(wil);
/* FW should raise IRQ when ready */ /* FW should raise IRQ when ready */
...@@ -225,8 +228,21 @@ static void wil_pcie_remove(struct pci_dev *pdev) ...@@ -225,8 +228,21 @@ static void wil_pcie_remove(struct pci_dev *pdev)
pci_disable_device(pdev); pci_disable_device(pdev);
} }
static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = { static const struct wil_board wil_board_marlon = {
{ PCI_DEVICE(0x1ae9, 0x0301) }, .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 */ }, { /* end: all zeroes */ },
}; };
MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids);
......
...@@ -1108,8 +1108,10 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid) ...@@ -1108,8 +1108,10 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
while (vring->swtail != new_swtail) { while (vring->swtail != new_swtail) {
struct vring_tx_desc dd, *d = &dd; struct vring_tx_desc dd, *d = &dd;
u16 dmalen; u16 dmalen;
struct wil_ctx *ctx = &vring->ctx[vring->swtail]; struct sk_buff *skb;
struct sk_buff *skb = ctx->skb;
ctx = &vring->ctx[vring->swtail];
skb = ctx->skb;
_d = &vring->va[vring->swtail].tx; _d = &vring->va[vring->swtail].tx;
*d = *_d; *d = *_d;
......
...@@ -24,6 +24,13 @@ ...@@ -24,6 +24,13 @@
#define WIL_NAME "wil6210" #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 * extract bits [@b0:@b1] (inclusive) from the value @x
* it should be @b0 <= @b1, or result is incorrect * it should be @b0 <= @b1, or result is incorrect
...@@ -78,6 +85,7 @@ struct RGF_ICR { ...@@ -78,6 +85,7 @@ struct RGF_ICR {
} __packed; } __packed;
/* registers - FW addresses */ /* registers - FW addresses */
#define RGF_USER_USAGE_1 (0x880004)
#define RGF_USER_HW_MACHINE_STATE (0x8801dc) #define RGF_USER_HW_MACHINE_STATE (0x8801dc)
#define HW_MACHINE_BOOT_DONE (0x3fffffd) #define HW_MACHINE_BOOT_DONE (0x3fffffd)
#define RGF_USER_USER_CPU_0 (0x8801e0) #define RGF_USER_USER_CPU_0 (0x8801e0)
...@@ -93,6 +101,7 @@ struct RGF_ICR { ...@@ -93,6 +101,7 @@ struct RGF_ICR {
#define RGF_USER_CLKS_CTL_SW_RST_MASK_0 (0x880b14) #define RGF_USER_CLKS_CTL_SW_RST_MASK_0 (0x880b14)
#define RGF_USER_USER_ICR (0x880b4c) /* struct RGF_ICR */ #define RGF_USER_USER_ICR (0x880b4c) /* struct RGF_ICR */
#define BIT_USER_USER_ICR_SW_INT_2 BIT(18) #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 RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */
#define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0) #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0)
...@@ -121,6 +130,7 @@ struct RGF_ICR { ...@@ -121,6 +130,7 @@ struct RGF_ICR {
#define BIT_DMA_PSEUDO_CAUSE_TX BIT(1) #define BIT_DMA_PSEUDO_CAUSE_TX BIT(1)
#define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2) #define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2)
#define RGF_HP_CTRL (0x88265c)
#define RGF_PCIE_LOS_COUNTER_CTL (0x882dc4) #define RGF_PCIE_LOS_COUNTER_CTL (0x882dc4)
/* popular locations */ /* popular locations */
...@@ -135,6 +145,14 @@ struct RGF_ICR { ...@@ -135,6 +145,14 @@ struct RGF_ICR {
#define ISR_MISC_FW_ERROR BIT_DMA_EP_MISC_ICR_FW_INT(3) #define ISR_MISC_FW_ERROR BIT_DMA_EP_MISC_ICR_FW_INT(3)
/* Hardware definitions end */ /* 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 * mk_cidxtid - construct @cidxtid field
...@@ -365,6 +383,7 @@ struct wil6210_priv { ...@@ -365,6 +383,7 @@ struct wil6210_priv {
ulong status; ulong status;
u32 fw_version; u32 fw_version;
u32 hw_version; u32 hw_version;
struct wil_board *board;
u8 n_mids; /* number of additional MIDs as reported by FW */ u8 n_mids; /* number of additional MIDs as reported by FW */
int recovery_count; /* num of FW recovery attempts in a short time */ int recovery_count; /* num of FW recovery attempts in a short time */
unsigned long last_fw_recovery; /* jiffies of last fw recovery */ unsigned long last_fw_recovery; /* jiffies of last fw recovery */
...@@ -415,12 +434,7 @@ struct wil6210_priv { ...@@ -415,12 +434,7 @@ struct wil6210_priv {
atomic_t isr_count_rx, isr_count_tx; atomic_t isr_count_rx, isr_count_tx;
/* debugfs */ /* debugfs */
struct dentry *debug; struct dentry *debug;
struct debugfs_blob_wrapper fw_code_blob; struct debugfs_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)];
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;
}; };
#define wil_to_wiphy(i) (i->wdev->wiphy) #define wil_to_wiphy(i) (i->wdev->wiphy)
......
...@@ -65,18 +65,17 @@ ...@@ -65,18 +65,17 @@
/** /**
* @fw_mapping provides memory remapping table * @fw_mapping provides memory remapping table
*
* array size should be in sync with the declaration in the wil6210.h
*/ */
static const struct { const struct fw_map fw_mapping[] = {
u32 from; /* linker address - from, inclusive */ {0x000000, 0x040000, 0x8c0000, "fw_code"}, /* FW code RAM 256k */
u32 to; /* linker address - to, exclusive */ {0x800000, 0x808000, 0x900000, "fw_data"}, /* FW data RAM 32k */
u32 host; /* PCI/Host address - BAR0 + 0x880000 */ {0x840000, 0x860000, 0x908000, "fw_peri"}, /* periph. data RAM 128k */
} fw_mapping[] = { {0x880000, 0x88a000, 0x880000, "rgf"}, /* various RGF 40k */
{0x000000, 0x040000, 0x8c0000}, /* FW code RAM 256k */ {0x88a000, 0x88b000, 0x88a000, "AGC_tbl"}, /* AGC table 4k */
{0x800000, 0x808000, 0x900000}, /* FW data RAM 32k */ {0x88b000, 0x88c000, 0x88b000, "rgf_ext"}, /* Pcie_ext_rgf 4k */
{0x840000, 0x860000, 0x908000}, /* peripheral data RAM 128k/96k used */ {0x8c0000, 0x949000, 0x8c0000, "upper"}, /* upper area 548k */
{0x880000, 0x88a000, 0x880000}, /* various RGF */
{0x88b000, 0x88c000, 0x88b000}, /* Pcie_ext_rgf */
{0x8c0000, 0x949000, 0x8c0000}, /* trivial mapping for upper area */
/* /*
* 920000..930000 ucode code RAM * 920000..930000 ucode code RAM
* 930000..932000 ucode data RAM * 930000..932000 ucode data RAM
......
...@@ -36,7 +36,7 @@ config B43_SSB ...@@ -36,7 +36,7 @@ config B43_SSB
choice choice
prompt "Supported bus types" prompt "Supported bus types"
depends on B43 depends on B43
default B43_BCMA_AND_SSB default B43_BUSES_BCMA_AND_SSB
config B43_BUSES_BCMA_AND_SSB config B43_BUSES_BCMA_AND_SSB
bool "BCMA and SSB" bool "BCMA and SSB"
......
...@@ -210,6 +210,9 @@ static struct ieee80211_channel b43_2ghz_chantable[] = { ...@@ -210,6 +210,9 @@ static struct ieee80211_channel b43_2ghz_chantable[] = {
CHAN2G(13, 2472, 0), CHAN2G(13, 2472, 0),
CHAN2G(14, 2484, 0), CHAN2G(14, 2484, 0),
}; };
/* No support for the last 3 channels (12, 13, 14) */
#define b43_2ghz_chantable_limited_size 11
#undef CHAN2G #undef CHAN2G
#define CHAN4G(_channel, _flags) { \ #define CHAN4G(_channel, _flags) { \
...@@ -335,6 +338,14 @@ static struct ieee80211_supported_band b43_band_2GHz = { ...@@ -335,6 +338,14 @@ static struct ieee80211_supported_band b43_band_2GHz = {
.n_bitrates = b43_g_ratetable_size, .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 void b43_wireless_core_exit(struct b43_wldev *dev);
static int b43_wireless_core_init(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); static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev);
...@@ -2953,6 +2964,45 @@ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on) ...@@ -2953,6 +2964,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) static void b43_adjust_opmode(struct b43_wldev *dev)
{ {
struct b43_wl *wl = dev->wl; struct b43_wl *wl = dev->wl;
...@@ -4329,6 +4379,7 @@ static char *b43_phy_name(struct b43_wldev *dev, u8 phy_type) ...@@ -4329,6 +4379,7 @@ static char *b43_phy_name(struct b43_wldev *dev, u8 phy_type)
static int b43_phy_versioning(struct b43_wldev *dev) static int b43_phy_versioning(struct b43_wldev *dev)
{ {
struct b43_phy *phy = &dev->phy; struct b43_phy *phy = &dev->phy;
const u8 core_rev = dev->dev->core_rev;
u32 tmp; u32 tmp;
u8 analog_type; u8 analog_type;
u8 phy_type; u8 phy_type;
...@@ -4359,7 +4410,7 @@ static int b43_phy_versioning(struct b43_wldev *dev) ...@@ -4359,7 +4410,7 @@ static int b43_phy_versioning(struct b43_wldev *dev)
#endif #endif
#ifdef CONFIG_B43_PHY_N #ifdef CONFIG_B43_PHY_N
case B43_PHYTYPE_N: case B43_PHYTYPE_N:
if (phy_rev > 9) if (phy_rev >= 19)
unsupported = 1; unsupported = 1;
break; break;
#endif #endif
...@@ -4394,7 +4445,15 @@ static int b43_phy_versioning(struct b43_wldev *dev) ...@@ -4394,7 +4445,15 @@ static int b43_phy_versioning(struct b43_wldev *dev)
analog_type, phy_type, b43_phy_name(dev, phy_type), phy_rev); analog_type, phy_type, b43_phy_name(dev, phy_type), phy_rev);
/* Get RADIO versioning */ /* Get RADIO versioning */
if (dev->dev->core_rev >= 24) { if (core_rev == 40 || core_rev == 42) {
radio_manuf = 0x17F;
b43_write16(dev, B43_MMIO_RADIO24_CONTROL, 0);
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);
} else if (core_rev >= 24) {
u16 radio24[3]; u16 radio24[3];
for (tmp = 0; tmp < 3; tmp++) { for (tmp = 0; tmp < 3; tmp++) {
...@@ -4450,7 +4509,10 @@ static int b43_phy_versioning(struct b43_wldev *dev) ...@@ -4450,7 +4509,10 @@ static int b43_phy_versioning(struct b43_wldev *dev)
unsupported = 1; unsupported = 1;
break; break;
case B43_PHYTYPE_N: case B43_PHYTYPE_N:
if (radio_ver != 0x2055 && radio_ver != 0x2056) if (radio_ver != 0x2055 && radio_ver != 0x2056 &&
radio_ver != 0x2057)
unsupported = 1;
if (radio_ver == 0x2057 && !(radio_rev == 9))
unsupported = 1; unsupported = 1;
break; break;
case B43_PHYTYPE_LP: case B43_PHYTYPE_LP:
...@@ -4469,13 +4531,13 @@ static int b43_phy_versioning(struct b43_wldev *dev) ...@@ -4469,13 +4531,13 @@ static int b43_phy_versioning(struct b43_wldev *dev)
B43_WARN_ON(1); B43_WARN_ON(1);
} }
if (unsupported) { if (unsupported) {
b43err(dev->wl, "FOUND UNSUPPORTED RADIO " b43err(dev->wl,
"(Manuf 0x%X, Version 0x%X, Revision %u)\n", "FOUND UNSUPPORTED RADIO (Manuf 0x%X, ID 0x%X, Revision %u)\n",
radio_manuf, radio_ver, radio_rev); radio_manuf, radio_ver, radio_rev);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
b43dbg(dev->wl, "Found Radio: Manuf 0x%X, Version 0x%X, Revision %u\n", b43info(dev->wl, "Found Radio: Manuf 0x%X, ID 0x%X, Revision %u\n",
radio_manuf, radio_ver, radio_rev); radio_manuf, radio_ver, radio_rev);
phy->radio_manuf = radio_manuf; phy->radio_manuf = radio_manuf;
phy->radio_ver = radio_ver; phy->radio_ver = radio_ver;
...@@ -5086,9 +5148,15 @@ static int b43_setup_bands(struct b43_wldev *dev, ...@@ -5086,9 +5148,15 @@ static int b43_setup_bands(struct b43_wldev *dev,
bool have_2ghz_phy, bool have_5ghz_phy) bool have_2ghz_phy, bool have_5ghz_phy)
{ {
struct ieee80211_hw *hw = dev->wl->hw; struct ieee80211_hw *hw = dev->wl->hw;
struct b43_phy *phy = &dev->phy;
bool limited_2g;
/* We don't support all 2 GHz channels on some devices */
limited_2g = phy->radio_ver == 0x2057 && phy->radio_rev == 9;
if (have_2ghz_phy) 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 (dev->phy.type == B43_PHYTYPE_N) {
if (have_5ghz_phy) if (have_5ghz_phy)
hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_nphy; hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_nphy;
...@@ -5239,13 +5307,16 @@ static int b43_wireless_core_attach(struct b43_wldev *dev) ...@@ -5239,13 +5307,16 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
b43_supported_bands(dev, &have_2ghz_phy, &have_5ghz_phy); b43_supported_bands(dev, &have_2ghz_phy, &have_5ghz_phy);
/* We don't support 5 GHz on some PHYs yet */ /* We don't support 5 GHz on some PHYs yet */
switch (dev->phy.type) { if (have_5ghz_phy) {
case B43_PHYTYPE_A: switch (dev->phy.type) {
case B43_PHYTYPE_N: case B43_PHYTYPE_A:
case B43_PHYTYPE_LP: case B43_PHYTYPE_G:
case B43_PHYTYPE_HT: case B43_PHYTYPE_N:
b43warn(wl, "5 GHz band is unsupported on this PHY\n"); case B43_PHYTYPE_LP:
have_5ghz_phy = false; 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) { if (!have_2ghz_phy && !have_5ghz_phy) {
......
...@@ -99,6 +99,7 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags); ...@@ -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_suspend(struct b43_wldev *dev);
void b43_mac_enable(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_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; struct b43_request_fw_context;
......
...@@ -54,39 +54,6 @@ enum lcn_sense_type { ...@@ -54,39 +54,6 @@ enum lcn_sense_type {
B43_SENSE_VBAT, 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. * Radio 2064.
**************************************************/ **************************************************/
...@@ -609,7 +576,7 @@ static void b43_phy_lcn_txrx_spur_avoidance_mode(struct b43_wldev *dev, ...@@ -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, 0x93b, ((0 << 13) + 23));
b43_phy_write(dev, 0x93c, ((0 << 13) + 1989)); b43_phy_write(dev, 0x93c, ((0 << 13) + 1989));
} }
b43_phy_switch_macfreq(dev, enable); b43_mac_switch_freq(dev, enable);
} }
/************************************************** /**************************************************
......
此差异已折叠。
...@@ -366,11 +366,13 @@ ...@@ -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_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_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_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_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_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_STAT2 B43_PHY_N(0x0EA) /* BIST status 2 */
#define B43_NPHY_BIST_STAT3 B43_PHY_N(0x0EB) /* BIST status 3 */ #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_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 B43_PHY_N(0x0ED) /* MIMO config */
#define B43_NPHY_MIMOCFG_GFMIX 0x0004 /* Greenfield or mixed mode */ #define B43_NPHY_MIMOCFG_GFMIX 0x0004 /* Greenfield or mixed mode */
#define B43_NPHY_MIMOCFG_AUTO 0x0100 /* Greenfield/mixed mode auto */ #define B43_NPHY_MIMOCFG_AUTO 0x0100 /* Greenfield/mixed mode auto */
...@@ -857,7 +859,18 @@ ...@@ -857,7 +859,18 @@
#define B43_NPHY_REV3_C2_CLIP2_GAIN_A B43_PHY_N(0x2AF) #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_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 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) #define B43_PHY_B_TEST B43_PHY_N_BMODE(0x00A)
struct b43_wldev; struct b43_wldev;
...@@ -935,6 +948,8 @@ struct b43_phy_n { ...@@ -935,6 +948,8 @@ struct b43_phy_n {
bool gain_boost; bool gain_boost;
bool elna_gain_config; bool elna_gain_config;
bool band5g_pwrgain; bool band5g_pwrgain;
bool use_int_tx_iq_lo_cal;
bool lpf_bw_overrode_for_sample_play;
u8 mphase_cal_phase_id; u8 mphase_cal_phase_id;
u16 mphase_txcal_cmdidx; u16 mphase_txcal_cmdidx;
......
...@@ -105,6 +105,27 @@ static u16 r2057_rev8_init[][2] = { ...@@ -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, \ #define RADIOREGS7(r00, r01, r02, r03, r04, r05, r06, r07, r08, r09, \
r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \ r10, r11, r12, r13, r14, r15, r16, r17, r18, r19, \
r20, r21, r22, r23, r24, r25, r26, r27) \ r20, r21, r22, r23, r24, r25, r26, r27) \
...@@ -137,6 +158,27 @@ static u16 r2057_rev8_init[][2] = { ...@@ -137,6 +158,27 @@ static u16 r2057_rev8_init[][2] = {
.radio_lna2g_tune_core1 = r26, \ .radio_lna2g_tune_core1 = r26, \
.radio_lna5g_tune_core1 = r27 .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) \ #define PHYREGS(r0, r1, r2, r3, r4, r5) \
.phy_regs.phy_bw1a = r0, \ .phy_regs.phy_bw1a = r0, \
.phy_regs.phy_bw2 = r1, \ .phy_regs.phy_bw2 = r1, \
...@@ -145,6 +187,353 @@ static u16 r2057_rev8_init[][2] = { ...@@ -145,6 +187,353 @@ static u16 r2057_rev8_init[][2] = {
.phy_regs.phy_bw5 = r4, \ .phy_regs.phy_bw5 = r4, \
.phy_regs.phy_bw6 = r5 .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) void r2057_upload_inittabs(struct b43_wldev *dev)
{ {
struct b43_phy *phy = &dev->phy; struct b43_phy *phy = &dev->phy;
...@@ -171,6 +560,18 @@ void r2057_upload_inittabs(struct b43_wldev *dev) ...@@ -171,6 +560,18 @@ void r2057_upload_inittabs(struct b43_wldev *dev)
size = ARRAY_SIZE(r2057_rev5a_init); size = ARRAY_SIZE(r2057_rev5a_init);
} }
break; 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); B43_WARN_ON(!table);
...@@ -193,8 +594,25 @@ void r2057_get_chantabent_rev7(struct b43_wldev *dev, u16 freq, ...@@ -193,8 +594,25 @@ void r2057_get_chantabent_rev7(struct b43_wldev *dev, u16 freq,
*tabent_r7 = NULL; *tabent_r7 = NULL;
*tabent_r7_2g = NULL; *tabent_r7_2g = NULL;
/* TODO */
switch (phy->rev) { 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: default:
break; break;
} }
......
...@@ -84,6 +84,8 @@ ...@@ -84,6 +84,8 @@
#define R2057_CMOSBUF_RX_RCCR 0x04c #define R2057_CMOSBUF_RX_RCCR 0x04c
#define R2057_LOGEN_SEL_PKDET 0x04d #define R2057_LOGEN_SEL_PKDET 0x04d
#define R2057_CMOSBUF_SHAREIQ_PTAT 0x04e #define R2057_CMOSBUF_SHAREIQ_PTAT 0x04e
/* MISC core 0 */
#define R2057_RXTXBIAS_CONFIG_CORE0 0x04f #define R2057_RXTXBIAS_CONFIG_CORE0 0x04f
#define R2057_TXGM_TXRF_PUS_CORE0 0x050 #define R2057_TXGM_TXRF_PUS_CORE0 0x050
#define R2057_TXGM_IDAC_BLEED_CORE0 0x051 #define R2057_TXGM_IDAC_BLEED_CORE0 0x051
...@@ -204,6 +206,8 @@ ...@@ -204,6 +206,8 @@
#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0x0d1 #define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE0 0x0d1
#define R2057_LPF_GAIN_CORE0 0x0d2 #define R2057_LPF_GAIN_CORE0 0x0d2
#define R2057_DACBUF_IDACS_BW_CORE0 0x0d3 #define R2057_DACBUF_IDACS_BW_CORE0 0x0d3
/* MISC core 1 */
#define R2057_RXTXBIAS_CONFIG_CORE1 0x0d4 #define R2057_RXTXBIAS_CONFIG_CORE1 0x0d4
#define R2057_TXGM_TXRF_PUS_CORE1 0x0d5 #define R2057_TXGM_TXRF_PUS_CORE1 0x0d5
#define R2057_TXGM_IDAC_BLEED_CORE1 0x0d6 #define R2057_TXGM_IDAC_BLEED_CORE1 0x0d6
...@@ -324,6 +328,7 @@ ...@@ -324,6 +328,7 @@
#define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156 #define R2057_RXBB_GPAIOSEL_RXLPF_RCCAL_CORE1 0x156
#define R2057_LPF_GAIN_CORE1 0x157 #define R2057_LPF_GAIN_CORE1 0x157
#define R2057_DACBUF_IDACS_BW_CORE1 0x158 #define R2057_DACBUF_IDACS_BW_CORE1 0x158
#define R2057_DACBUF_VINCM_CORE1 0x159 #define R2057_DACBUF_VINCM_CORE1 0x159
#define R2057_RCCAL_START_R1_Q1_P1 0x15a #define R2057_RCCAL_START_R1_Q1_P1 0x15a
#define R2057_RCCAL_X1 0x15b #define R2057_RCCAL_X1 0x15b
...@@ -345,6 +350,8 @@ ...@@ -345,6 +350,8 @@
#define R2057_RCCAL_BCAP_VAL 0x16b #define R2057_RCCAL_BCAP_VAL 0x16b
#define R2057_RCCAL_HPC_VAL 0x16c #define R2057_RCCAL_HPC_VAL 0x16c
#define R2057_RCCAL_OVERRIDES 0x16d #define R2057_RCCAL_OVERRIDES 0x16d
/* TX core 0 */
#define R2057_TX0_IQCAL_GAIN_BW 0x170 #define R2057_TX0_IQCAL_GAIN_BW 0x170
#define R2057_TX0_LOFT_FINE_I 0x171 #define R2057_TX0_LOFT_FINE_I 0x171
#define R2057_TX0_LOFT_FINE_Q 0x172 #define R2057_TX0_LOFT_FINE_Q 0x172
...@@ -362,6 +369,8 @@ ...@@ -362,6 +369,8 @@
#define R2057_TX0_TXRXCOUPLE_2G_PWRUP 0x17e #define R2057_TX0_TXRXCOUPLE_2G_PWRUP 0x17e
#define R2057_TX0_TXRXCOUPLE_5G_ATTEN 0x17f #define R2057_TX0_TXRXCOUPLE_5G_ATTEN 0x17f
#define R2057_TX0_TXRXCOUPLE_5G_PWRUP 0x180 #define R2057_TX0_TXRXCOUPLE_5G_PWRUP 0x180
/* TX core 1 */
#define R2057_TX1_IQCAL_GAIN_BW 0x190 #define R2057_TX1_IQCAL_GAIN_BW 0x190
#define R2057_TX1_LOFT_FINE_I 0x191 #define R2057_TX1_LOFT_FINE_I 0x191
#define R2057_TX1_LOFT_FINE_Q 0x192 #define R2057_TX1_LOFT_FINE_Q 0x192
...@@ -379,6 +388,7 @@ ...@@ -379,6 +388,7 @@
#define R2057_TX1_TXRXCOUPLE_2G_PWRUP 0x19e #define R2057_TX1_TXRXCOUPLE_2G_PWRUP 0x19e
#define R2057_TX1_TXRXCOUPLE_5G_ATTEN 0x19f #define R2057_TX1_TXRXCOUPLE_5G_ATTEN 0x19f
#define R2057_TX1_TXRXCOUPLE_5G_PWRUP 0x1a0 #define R2057_TX1_TXRXCOUPLE_5G_PWRUP 0x1a0
#define R2057_AFE_VCM_CAL_MASTER_CORE0 0x1a1 #define R2057_AFE_VCM_CAL_MASTER_CORE0 0x1a1
#define R2057_AFE_SET_VCM_I_CORE0 0x1a2 #define R2057_AFE_SET_VCM_I_CORE0 0x1a2
#define R2057_AFE_SET_VCM_Q_CORE0 0x1a3 #define R2057_AFE_SET_VCM_Q_CORE0 0x1a3
......
...@@ -165,6 +165,10 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent( ...@@ -165,6 +165,10 @@ struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
#define B43_NTAB_C1_LOFEEDTH_R3 B43_NTAB16(27, 448) /* Local Oscillator Feed Through lookup 1 */ #define B43_NTAB_C1_LOFEEDTH_R3 B43_NTAB16(27, 448) /* Local Oscillator Feed Through lookup 1 */
#define B43_NTAB_C1_PAPD_COMP_R3 B43_NTAB16(27, 576) #define B43_NTAB_C1_PAPD_COMP_R3 B43_NTAB16(27, 576)
/* Static N-PHY tables, PHY revision >= 7 */
#define B43_NTAB_TMAP_R7 B43_NTAB32(12, 0) /* TM AP */
#define B43_NTAB_NOISEVAR_R7 B43_NTAB32(16, 0) /* noise variance */
#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_40_SIZE 18 #define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_40_SIZE 18
#define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_20_SIZE 18 #define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_20_SIZE 18
#define B43_NTAB_TX_IQLO_CAL_IQIMB_LADDER_40_SIZE 18 #define B43_NTAB_TX_IQLO_CAL_IQIMB_LADDER_40_SIZE 18
......
...@@ -811,9 +811,13 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) ...@@ -811,9 +811,13 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
break; break;
case B43_PHYTYPE_G: case B43_PHYTYPE_G:
status.band = IEEE80211_BAND_2GHZ; status.band = IEEE80211_BAND_2GHZ;
/* chanid is the radio channel cookie value as used /* Somewhere between 478.104 and 508.1084 firmware for G-PHY
* to tune the radio. */ * has been modified to be compatible with N-PHY and others.
status.freq = chanid + 2400; */
if (dev->fw.rev >= 508)
status.freq = ieee80211_channel_to_frequency(chanid, status.band);
else
status.freq = chanid + 2400;
break; break;
case B43_PHYTYPE_N: case B43_PHYTYPE_N:
case B43_PHYTYPE_LP: case B43_PHYTYPE_LP:
......
...@@ -34,6 +34,7 @@ brcmfmac-objs += \ ...@@ -34,6 +34,7 @@ brcmfmac-objs += \
dhd_common.o \ dhd_common.o \
dhd_linux.o \ dhd_linux.o \
firmware.o \ firmware.o \
feature.o \
btcoex.o \ btcoex.o \
vendor.o vendor.o
brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
......
...@@ -25,7 +25,6 @@ ...@@ -25,7 +25,6 @@
#include <linux/mmc/sdio.h> #include <linux/mmc/sdio.h>
#include <linux/mmc/core.h> #include <linux/mmc/core.h>
#include <linux/mmc/sdio_func.h> #include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/card.h> #include <linux/mmc/card.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -979,18 +978,20 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev) ...@@ -979,18 +978,20 @@ static int brcmf_sdiod_probe(struct brcmf_sdio_dev *sdiodev)
return ret; return ret;
} }
#define BRCMF_SDIO_DEVICE(dev_id) \
{SDIO_DEVICE(BRCM_SDIO_VENDOR_ID_BROADCOM, dev_id)}
/* devices we support, null terminated */ /* devices we support, null terminated */
static const struct sdio_device_id brcmf_sdmmc_ids[] = { static const struct sdio_device_id brcmf_sdmmc_ids[] = {
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43143)}, BRCMF_SDIO_DEVICE(BRCM_SDIO_43143_DEVICE_ID),
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43241)}, BRCMF_SDIO_DEVICE(BRCM_SDIO_43241_DEVICE_ID),
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329)}, BRCMF_SDIO_DEVICE(BRCM_SDIO_4329_DEVICE_ID),
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4330)}, BRCMF_SDIO_DEVICE(BRCM_SDIO_4330_DEVICE_ID),
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4334)}, BRCMF_SDIO_DEVICE(BRCM_SDIO_4334_DEVICE_ID),
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_43362)}, BRCMF_SDIO_DEVICE(BRCM_SDIO_43362_DEVICE_ID),
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, BRCMF_SDIO_DEVICE(BRCM_SDIO_4335_4339_DEVICE_ID),
SDIO_DEVICE_ID_BROADCOM_4335_4339)}, BRCMF_SDIO_DEVICE(BRCM_SDIO_4354_DEVICE_ID),
{SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4354)}, { /* end: all zeroes */ }
{ /* end: all zeroes */ },
}; };
MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids); MODULE_DEVICE_TABLE(sdio, brcmf_sdmmc_ids);
......
...@@ -482,30 +482,30 @@ static inline int brcmf_chip_cores_check(struct brcmf_chip_priv *ci) ...@@ -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) static void brcmf_chip_get_raminfo(struct brcmf_chip_priv *ci)
{ {
switch (ci->pub.chip) { switch (ci->pub.chip) {
case BCM4329_CHIP_ID: case BRCM_CC_4329_CHIP_ID:
ci->pub.ramsize = BCM4329_RAMSIZE; ci->pub.ramsize = BCM4329_RAMSIZE;
break; break;
case BCM43143_CHIP_ID: case BRCM_CC_43143_CHIP_ID:
ci->pub.ramsize = BCM43143_RAMSIZE; ci->pub.ramsize = BCM43143_RAMSIZE;
break; break;
case BCM43241_CHIP_ID: case BRCM_CC_43241_CHIP_ID:
ci->pub.ramsize = 0x90000; ci->pub.ramsize = 0x90000;
break; break;
case BCM4330_CHIP_ID: case BRCM_CC_4330_CHIP_ID:
ci->pub.ramsize = 0x48000; ci->pub.ramsize = 0x48000;
break; break;
case BCM4334_CHIP_ID: case BRCM_CC_4334_CHIP_ID:
ci->pub.ramsize = 0x80000; ci->pub.ramsize = 0x80000;
break; break;
case BCM4335_CHIP_ID: case BRCM_CC_4335_CHIP_ID:
ci->pub.ramsize = 0xc0000; ci->pub.ramsize = 0xc0000;
ci->pub.rambase = 0x180000; ci->pub.rambase = 0x180000;
break; break;
case BCM43362_CHIP_ID: case BRCM_CC_43362_CHIP_ID:
ci->pub.ramsize = 0x3c000; ci->pub.ramsize = 0x3c000;
break; break;
case BCM4339_CHIP_ID: case BRCM_CC_4339_CHIP_ID:
case BCM4354_CHIP_ID: case BRCM_CC_4354_CHIP_ID:
ci->pub.ramsize = 0xc0000; ci->pub.ramsize = 0xc0000;
ci->pub.rambase = 0x180000; ci->pub.rambase = 0x180000;
break; break;
...@@ -682,7 +682,7 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) ...@@ -682,7 +682,7 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci)
ci->pub.chiprev); ci->pub.chiprev);
if (socitype == SOCI_SB) { 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"); brcmf_err("SB chip is not supported\n");
return -ENODEV; return -ENODEV;
} }
...@@ -1008,13 +1008,13 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub) ...@@ -1008,13 +1008,13 @@ bool brcmf_chip_sr_capable(struct brcmf_chip *pub)
chip = container_of(pub, struct brcmf_chip_priv, pub); chip = container_of(pub, struct brcmf_chip_priv, pub);
switch (pub->chip) { switch (pub->chip) {
case BCM4354_CHIP_ID: case BRCM_CC_4354_CHIP_ID:
/* explicitly check SR engine enable bit */ /* explicitly check SR engine enable bit */
pmu_cc3_mask = BIT(2); pmu_cc3_mask = BIT(2);
/* fall-through */ /* fall-through */
case BCM43241_CHIP_ID: case BRCM_CC_43241_CHIP_ID:
case BCM4335_CHIP_ID: case BRCM_CC_4335_CHIP_ID:
case BCM4339_CHIP_ID: case BRCM_CC_4339_CHIP_ID:
/* read PMU chipcontrol register 3 */ /* read PMU chipcontrol register 3 */
addr = CORE_CC_REG(base, chipcontrol_addr); addr = CORE_CC_REG(base, chipcontrol_addr);
chip->ops->write32(chip->ctx, addr, 3); chip->ops->write32(chip->ctx, addr, 3);
......
...@@ -103,6 +103,10 @@ struct brcmf_pub { ...@@ -103,6 +103,10 @@ struct brcmf_pub {
struct brcmf_ampdu_rx_reorder struct brcmf_ampdu_rx_reorder
*reorder_flows[BRCMF_AMPDU_RX_REORDER_MAXFLOWS]; *reorder_flows[BRCMF_AMPDU_RX_REORDER_MAXFLOWS];
u32 feat_flags;
u32 chip_quirks;
#ifdef DEBUG #ifdef DEBUG
struct dentry *dbgfs_dir; struct dentry *dbgfs_dir;
#endif #endif
...@@ -175,7 +179,6 @@ struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx, ...@@ -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_del_if(struct brcmf_pub *drvr, s32 bssidx);
void brcmf_txflowblock_if(struct brcmf_if *ifp, void brcmf_txflowblock_if(struct brcmf_if *ifp,
enum brcmf_netif_stop_reason reason, bool state); 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, void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
bool success); bool success);
......
...@@ -41,37 +41,12 @@ void brcmf_debugfs_exit(void) ...@@ -41,37 +41,12 @@ void brcmf_debugfs_exit(void)
root_folder = NULL; root_folder = NULL;
} }
static static int brcmf_debugfs_chipinfo_read(struct seq_file *seq, void *data)
ssize_t brcmf_debugfs_chipinfo_read(struct file *f, char __user *data,
size_t count, loff_t *ppos)
{ {
struct brcmf_pub *drvr = f->private_data; struct brcmf_bus *bus = dev_get_drvdata(seq->private);
struct brcmf_bus *bus = drvr->bus_if;
char buf[40];
int res;
/* 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)) seq_printf(seq, "chip: %x(%u) rev %u\n",
debugfs_create_file("chipinfo", S_IRUGO, dentry, drvr, bus->chip, bus->chip, bus->chiprev);
&brcmf_debugfs_chipinfo_ops);
return 0; return 0;
} }
...@@ -83,7 +58,8 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr) ...@@ -83,7 +58,8 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr)
return -ENODEV; return -ENODEV;
drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder); 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); return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
} }
...@@ -98,148 +74,44 @@ struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr) ...@@ -98,148 +74,44 @@ struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr)
return drvr->dbgfs_dir; return drvr->dbgfs_dir;
} }
static struct brcmf_debugfs_entry {
ssize_t brcmf_debugfs_sdio_counter_read(struct file *f, char __user *data, int (*read)(struct seq_file *seq, void *data);
size_t count, loff_t *ppos) struct brcmf_pub *drvr;
{
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
}; };
void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, static int brcmf_debugfs_entry_open(struct inode *inode, struct file *f)
struct brcmf_sdio_count *sdcnt)
{ {
struct dentry *dentry = drvr->dbgfs_dir; struct brcmf_debugfs_entry *entry = inode->i_private;
if (!IS_ERR_OR_NULL(dentry)) return single_open(f, entry->read, entry->drvr->bus_if->dev);
debugfs_create_file("counters", S_IRUGO, dentry,
sdcnt, &brcmf_debugfs_sdio_counter_ops);
}
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, .owner = THIS_MODULE,
.open = simple_open, .open = brcmf_debugfs_entry_open,
.read = brcmf_debugfs_fws_stats_read .release = single_release,
.read = seq_read,
.llseek = seq_lseek
}; };
void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
struct brcmf_fws_stats *stats) int (*read_fn)(struct seq_file *seq, void *data))
{ {
struct dentry *dentry = drvr->dbgfs_dir; struct dentry *dentry = drvr->dbgfs_dir;
struct brcmf_debugfs_entry *entry;
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);
if (!IS_ERR_OR_NULL(dentry)) return PTR_ERR_OR_ZERO(dentry);
debugfs_create_file("fws_stats", S_IRUGO, dentry,
stats, &brcmf_debugfs_fws_stats_ops);
} }
...@@ -100,68 +100,6 @@ do { \ ...@@ -100,68 +100,6 @@ do { \
extern int brcmf_msg_level; 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; struct brcmf_pub;
#ifdef DEBUG #ifdef DEBUG
void brcmf_debugfs_init(void); void brcmf_debugfs_init(void);
...@@ -169,10 +107,8 @@ void brcmf_debugfs_exit(void); ...@@ -169,10 +107,8 @@ void brcmf_debugfs_exit(void);
int brcmf_debugfs_attach(struct brcmf_pub *drvr); int brcmf_debugfs_attach(struct brcmf_pub *drvr);
void brcmf_debugfs_detach(struct brcmf_pub *drvr); void brcmf_debugfs_detach(struct brcmf_pub *drvr);
struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr); struct dentry *brcmf_debugfs_get_devdir(struct brcmf_pub *drvr);
void brcmf_debugfs_create_sdio_count(struct brcmf_pub *drvr, int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn,
struct brcmf_sdio_count *sdcnt); int (*read_fn)(struct seq_file *seq, void *data));
void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr,
struct brcmf_fws_stats *stats);
#else #else
static inline void brcmf_debugfs_init(void) static inline void brcmf_debugfs_init(void)
{ {
...@@ -187,9 +123,11 @@ static inline int brcmf_debugfs_attach(struct brcmf_pub *drvr) ...@@ -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_detach(struct brcmf_pub *drvr)
{ {
} }
static inline void brcmf_debugfs_create_fws_stats(struct brcmf_pub *drvr, static inline
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))
{ {
return 0;
} }
#endif #endif
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "wl_cfg80211.h" #include "wl_cfg80211.h"
#include "fwil.h" #include "fwil.h"
#include "fwsignal.h" #include "fwsignal.h"
#include "feature.h"
#include "proto.h" #include "proto.h"
MODULE_AUTHOR("Broadcom Corporation"); MODULE_AUTHOR("Broadcom Corporation");
...@@ -936,6 +937,8 @@ int brcmf_bus_start(struct device *dev) ...@@ -936,6 +937,8 @@ int brcmf_bus_start(struct device *dev)
if (ret < 0) if (ret < 0)
goto fail; goto fail;
brcmf_feat_attach(drvr);
ret = brcmf_fws_init(drvr); ret = brcmf_fws_init(drvr);
if (ret < 0) if (ret < 0)
goto fail; goto fail;
...@@ -1073,16 +1076,6 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev) ...@@ -1073,16 +1076,6 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
return !err; 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) static void brcmf_driver_register(struct work_struct *work)
{ {
#ifdef CONFIG_BRCMFMAC_SDIO #ifdef CONFIG_BRCMFMAC_SDIO
......
/*
* 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));
}
此差异已折叠。
此差异已折叠。
...@@ -185,6 +185,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, ...@@ -185,6 +185,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
skb_reserve(skb_aggr, headroom + sizeof(struct txpd)); skb_reserve(skb_aggr, headroom + sizeof(struct txpd));
tx_info_aggr = MWIFIEX_SKB_TXCB(skb_aggr); tx_info_aggr = MWIFIEX_SKB_TXCB(skb_aggr);
memset(tx_info_aggr, 0, sizeof(*tx_info_aggr));
tx_info_aggr->bss_type = tx_info_src->bss_type; tx_info_aggr->bss_type = tx_info_src->bss_type;
tx_info_aggr->bss_num = tx_info_src->bss_num; tx_info_aggr->bss_num = tx_info_src->bss_num;
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册