mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 11:19:37 +00:00
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next
John W. Linville says: ==================== Included is a Bluetooth pull -- Gustavo says: "These are the Bluetooth bits for inclusion in 3.8, there is basically one big thing here which is the High Speed patches from Andrei, he did a lot of work on A2MP and management of AMP devices. The rest are mostly clean up and bug fixes." Also included is an NFC pull -- Samuel says: "With this one we have: - pn544 p2p support. - pn544 physical and HCI layers separation. We are getting the pn544 driver ready to support non i2c physical layers. - LLCP SNL (Service Name Lookup). This is the NFC p2p service discovery protocol. - LLCP datagram sockets (connection less) support. - IDR library usage for NFC devices indexes assignement. - NFC netlink extension for setting and getting LLCP link characteristics. - Various code style fixes and cleanups spread over the pn533, LLCP, HCI and pn544 code." There are a couple of mac80211 pulls as well -- Johannes says: "Please pull my mac80211-next tree to get the first round of new features for 3.8. We have: * finally, the mac80211 multi-channel work * scan improvements: - bg scan - scan flush - forced AP scan * cfg80211 tracing * a bit of new code to allow implementing SAE (secure authentication of equals) in managed mode Along with a few random improvements, features and fixes." and... "Please pull from mac80211-next (per below pull request) to get a few updates. Most important is probably the fix for the WDS regression that my previous pull request introduced. Other than that, I have some tracing code, two mesh updates and a change to allow drivers to calculate the AES CMAC subkeys without having to implement the GF_mulx operation themselves." On top of that are the usual updates to iwlwifi, ath9k, rt2x00, brcmfmac, mwifiex, and a few others here and there. Of note is the addition of the ar5523 driver, ported from an original FreeBSD driver. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
b092d92a68
233 changed files with 13923 additions and 4312 deletions
|
@ -7509,6 +7509,12 @@ S: Maintained
|
||||||
F: Documentation/usb/acm.txt
|
F: Documentation/usb/acm.txt
|
||||||
F: drivers/usb/class/cdc-acm.*
|
F: drivers/usb/class/cdc-acm.*
|
||||||
|
|
||||||
|
USB AR5523 WIRELESS DRIVER
|
||||||
|
M: Pontus Fuchs <pontus.fuchs@gmail.com>
|
||||||
|
L: linux-wireless@vger.kernel.org
|
||||||
|
S: Maintained
|
||||||
|
F: drivers/net/wireless/ath/ar5523/
|
||||||
|
|
||||||
USB ATTACHED SCSI
|
USB ATTACHED SCSI
|
||||||
M: Matthew Wilcox <willy@linux.intel.com>
|
M: Matthew Wilcox <willy@linux.intel.com>
|
||||||
M: Sarah Sharp <sarah.a.sharp@linux.intel.com>
|
M: Sarah Sharp <sarah.a.sharp@linux.intel.com>
|
||||||
|
|
|
@ -43,8 +43,8 @@ static void early_nvram_init(void)
|
||||||
#ifdef CONFIG_BCM47XX_SSB
|
#ifdef CONFIG_BCM47XX_SSB
|
||||||
case BCM47XX_BUS_TYPE_SSB:
|
case BCM47XX_BUS_TYPE_SSB:
|
||||||
mcore_ssb = &bcm47xx_bus.ssb.mipscore;
|
mcore_ssb = &bcm47xx_bus.ssb.mipscore;
|
||||||
base = mcore_ssb->flash_window;
|
base = mcore_ssb->pflash.window;
|
||||||
lim = mcore_ssb->flash_window_size;
|
lim = mcore_ssb->pflash.window_size;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_BCM47XX_BCMA
|
#ifdef CONFIG_BCM47XX_BCMA
|
||||||
|
|
|
@ -156,10 +156,10 @@ static int __init wgt634u_init(void)
|
||||||
SSB_CHIPCO_IRQ_GPIO);
|
SSB_CHIPCO_IRQ_GPIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
wgt634u_flash_data.width = mcore->flash_buswidth;
|
wgt634u_flash_data.width = mcore->pflash.buswidth;
|
||||||
wgt634u_flash_resource.start = mcore->flash_window;
|
wgt634u_flash_resource.start = mcore->pflash.window;
|
||||||
wgt634u_flash_resource.end = mcore->flash_window
|
wgt634u_flash_resource.end = mcore->pflash.window
|
||||||
+ mcore->flash_window_size
|
+ mcore->pflash.window_size
|
||||||
- 1;
|
- 1;
|
||||||
return platform_add_devices(wgt634u_devices,
|
return platform_add_devices(wgt634u_devices,
|
||||||
ARRAY_SIZE(wgt634u_devices));
|
ARRAY_SIZE(wgt634u_devices));
|
||||||
|
|
|
@ -22,6 +22,23 @@ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset,
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc)
|
||||||
|
{
|
||||||
|
if (cc->early_setup_done)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (cc->core->id.rev >= 11)
|
||||||
|
cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
|
||||||
|
cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
|
||||||
|
if (cc->core->id.rev >= 35)
|
||||||
|
cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT);
|
||||||
|
|
||||||
|
if (cc->capabilities & BCMA_CC_CAP_PMU)
|
||||||
|
bcma_pmu_early_init(cc);
|
||||||
|
|
||||||
|
cc->early_setup_done = true;
|
||||||
|
}
|
||||||
|
|
||||||
void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
|
void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
|
||||||
{
|
{
|
||||||
u32 leddc_on = 10;
|
u32 leddc_on = 10;
|
||||||
|
@ -30,11 +47,7 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
|
||||||
if (cc->setup_done)
|
if (cc->setup_done)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (cc->core->id.rev >= 11)
|
bcma_core_chipcommon_early_init(cc);
|
||||||
cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT);
|
|
||||||
cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP);
|
|
||||||
if (cc->core->id.rev >= 35)
|
|
||||||
cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT);
|
|
||||||
|
|
||||||
if (cc->core->id.rev >= 20) {
|
if (cc->core->id.rev >= 20) {
|
||||||
bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0);
|
bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0);
|
||||||
|
|
|
@ -32,6 +32,9 @@ int bcma_nflash_init(struct bcma_drv_cc *cc)
|
||||||
}
|
}
|
||||||
|
|
||||||
cc->nflash.present = true;
|
cc->nflash.present = true;
|
||||||
|
if (cc->core->id.rev == 38 &&
|
||||||
|
(cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT))
|
||||||
|
cc->nflash.boot = true;
|
||||||
|
|
||||||
/* Prepare platform device, but don't register it yet. It's too early,
|
/* Prepare platform device, but don't register it yet. It's too early,
|
||||||
* malloc (required by device_private_init) is not available yet. */
|
* malloc (required by device_private_init) is not available yet. */
|
||||||
|
|
|
@ -144,7 +144,7 @@ static void bcma_pmu_workarounds(struct bcma_drv_cc *cc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bcma_pmu_init(struct bcma_drv_cc *cc)
|
void bcma_pmu_early_init(struct bcma_drv_cc *cc)
|
||||||
{
|
{
|
||||||
u32 pmucap;
|
u32 pmucap;
|
||||||
|
|
||||||
|
@ -153,7 +153,10 @@ void bcma_pmu_init(struct bcma_drv_cc *cc)
|
||||||
|
|
||||||
bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n",
|
bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n",
|
||||||
cc->pmu.rev, pmucap);
|
cc->pmu.rev, pmucap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bcma_pmu_init(struct bcma_drv_cc *cc)
|
||||||
|
{
|
||||||
if (cc->pmu.rev == 1)
|
if (cc->pmu.rev == 1)
|
||||||
bcma_cc_mask32(cc, BCMA_CC_PMU_CTL,
|
bcma_cc_mask32(cc, BCMA_CC_PMU_CTL,
|
||||||
~BCMA_CC_PMU_CTL_NOILPONW);
|
~BCMA_CC_PMU_CTL_NOILPONW);
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
static struct resource bcma_sflash_resource = {
|
static struct resource bcma_sflash_resource = {
|
||||||
.name = "bcma_sflash",
|
.name = "bcma_sflash",
|
||||||
.start = BCMA_SFLASH,
|
.start = BCMA_SOC_FLASH2,
|
||||||
.end = 0,
|
.end = 0,
|
||||||
.flags = IORESOURCE_MEM | IORESOURCE_READONLY,
|
.flags = IORESOURCE_MEM | IORESOURCE_READONLY,
|
||||||
};
|
};
|
||||||
|
@ -31,15 +31,42 @@ struct bcma_sflash_tbl_e {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = {
|
static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = {
|
||||||
{ "", 0x14, 0x10000, 32, },
|
{ "M25P20", 0x11, 0x10000, 4, },
|
||||||
|
{ "M25P40", 0x12, 0x10000, 8, },
|
||||||
|
|
||||||
|
{ "M25P16", 0x14, 0x10000, 32, },
|
||||||
|
{ "M25P32", 0x14, 0x10000, 64, },
|
||||||
|
{ "M25P64", 0x16, 0x10000, 128, },
|
||||||
|
{ "M25FL128", 0x17, 0x10000, 256, },
|
||||||
{ 0 },
|
{ 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
|
static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = {
|
||||||
|
{ "SST25WF512", 1, 0x1000, 16, },
|
||||||
|
{ "SST25VF512", 0x48, 0x1000, 16, },
|
||||||
|
{ "SST25WF010", 2, 0x1000, 32, },
|
||||||
|
{ "SST25VF010", 0x49, 0x1000, 32, },
|
||||||
|
{ "SST25WF020", 3, 0x1000, 64, },
|
||||||
|
{ "SST25VF020", 0x43, 0x1000, 64, },
|
||||||
|
{ "SST25WF040", 4, 0x1000, 128, },
|
||||||
|
{ "SST25VF040", 0x44, 0x1000, 128, },
|
||||||
|
{ "SST25VF040B", 0x8d, 0x1000, 128, },
|
||||||
|
{ "SST25WF080", 5, 0x1000, 256, },
|
||||||
|
{ "SST25VF080B", 0x8e, 0x1000, 256, },
|
||||||
|
{ "SST25VF016", 0x41, 0x1000, 512, },
|
||||||
|
{ "SST25VF032", 0x4a, 0x1000, 1024, },
|
||||||
|
{ "SST25VF064", 0x4b, 0x1000, 2048, },
|
||||||
{ 0 },
|
{ 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = {
|
static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = {
|
||||||
|
{ "AT45DB011", 0xc, 256, 512, },
|
||||||
|
{ "AT45DB021", 0x14, 256, 1024, },
|
||||||
|
{ "AT45DB041", 0x1c, 256, 2048, },
|
||||||
|
{ "AT45DB081", 0x24, 256, 4096, },
|
||||||
|
{ "AT45DB161", 0x2c, 512, 4096, },
|
||||||
|
{ "AT45DB321", 0x34, 512, 8192, },
|
||||||
|
{ "AT45DB642", 0x3c, 1024, 8192, },
|
||||||
{ 0 },
|
{ 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,6 +111,8 @@ int bcma_sflash_init(struct bcma_drv_cc *cc)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 0x13:
|
||||||
|
return -ENOTSUPP;
|
||||||
default:
|
default:
|
||||||
for (e = bcma_sflash_st_tbl; e->name; e++) {
|
for (e = bcma_sflash_st_tbl; e->name; e++) {
|
||||||
if (e->id == id)
|
if (e->id == id)
|
||||||
|
@ -116,7 +145,7 @@ int bcma_sflash_init(struct bcma_drv_cc *cc)
|
||||||
return -ENOTSUPP;
|
return -ENOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
sflash->window = BCMA_SFLASH;
|
sflash->window = BCMA_SOC_FLASH2;
|
||||||
sflash->blocksize = e->blocksize;
|
sflash->blocksize = e->blocksize;
|
||||||
sflash->numblocks = e->numblocks;
|
sflash->numblocks = e->numblocks;
|
||||||
sflash->size = sflash->blocksize * sflash->numblocks;
|
sflash->size = sflash->blocksize * sflash->numblocks;
|
||||||
|
|
|
@ -181,46 +181,65 @@ EXPORT_SYMBOL(bcma_cpu_clock);
|
||||||
static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
|
static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
|
||||||
{
|
{
|
||||||
struct bcma_bus *bus = mcore->core->bus;
|
struct bcma_bus *bus = mcore->core->bus;
|
||||||
|
struct bcma_drv_cc *cc = &bus->drv_cc;
|
||||||
|
|
||||||
switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) {
|
switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
|
||||||
case BCMA_CC_FLASHT_STSER:
|
case BCMA_CC_FLASHT_STSER:
|
||||||
case BCMA_CC_FLASHT_ATSER:
|
case BCMA_CC_FLASHT_ATSER:
|
||||||
bcma_debug(bus, "Found serial flash\n");
|
bcma_debug(bus, "Found serial flash\n");
|
||||||
bcma_sflash_init(&bus->drv_cc);
|
bcma_sflash_init(cc);
|
||||||
break;
|
break;
|
||||||
case BCMA_CC_FLASHT_PARA:
|
case BCMA_CC_FLASHT_PARA:
|
||||||
bcma_debug(bus, "Found parallel flash\n");
|
bcma_debug(bus, "Found parallel flash\n");
|
||||||
bus->drv_cc.pflash.window = 0x1c000000;
|
cc->pflash.present = true;
|
||||||
bus->drv_cc.pflash.window_size = 0x02000000;
|
cc->pflash.window = BCMA_SOC_FLASH2;
|
||||||
|
cc->pflash.window_size = BCMA_SOC_FLASH2_SZ;
|
||||||
|
|
||||||
if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) &
|
if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) &
|
||||||
BCMA_CC_FLASH_CFG_DS) == 0)
|
BCMA_CC_FLASH_CFG_DS) == 0)
|
||||||
bus->drv_cc.pflash.buswidth = 1;
|
cc->pflash.buswidth = 1;
|
||||||
else
|
else
|
||||||
bus->drv_cc.pflash.buswidth = 2;
|
cc->pflash.buswidth = 2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bcma_err(bus, "Flash type not supported\n");
|
bcma_err(bus, "Flash type not supported\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bus->drv_cc.core->id.rev == 38 ||
|
if (cc->core->id.rev == 38 ||
|
||||||
bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
|
bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
|
||||||
if (bus->drv_cc.capabilities & BCMA_CC_CAP_NFLASH) {
|
if (cc->capabilities & BCMA_CC_CAP_NFLASH) {
|
||||||
bcma_debug(bus, "Found NAND flash\n");
|
bcma_debug(bus, "Found NAND flash\n");
|
||||||
bcma_nflash_init(&bus->drv_cc);
|
bcma_nflash_init(cc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
|
||||||
|
{
|
||||||
|
struct bcma_bus *bus = mcore->core->bus;
|
||||||
|
|
||||||
|
if (mcore->early_setup_done)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bcma_chipco_serial_init(&bus->drv_cc);
|
||||||
|
bcma_core_mips_flash_detect(mcore);
|
||||||
|
|
||||||
|
mcore->early_setup_done = true;
|
||||||
|
}
|
||||||
|
|
||||||
void bcma_core_mips_init(struct bcma_drv_mips *mcore)
|
void bcma_core_mips_init(struct bcma_drv_mips *mcore)
|
||||||
{
|
{
|
||||||
struct bcma_bus *bus;
|
struct bcma_bus *bus;
|
||||||
struct bcma_device *core;
|
struct bcma_device *core;
|
||||||
bus = mcore->core->bus;
|
bus = mcore->core->bus;
|
||||||
|
|
||||||
|
if (mcore->setup_done)
|
||||||
|
return;
|
||||||
|
|
||||||
bcma_info(bus, "Initializing MIPS core...\n");
|
bcma_info(bus, "Initializing MIPS core...\n");
|
||||||
|
|
||||||
if (!mcore->setup_done)
|
bcma_core_mips_early_init(mcore);
|
||||||
|
|
||||||
mcore->assigned_irqs = 1;
|
mcore->assigned_irqs = 1;
|
||||||
|
|
||||||
/* Assign IRQs to all cores on the bus */
|
/* Assign IRQs to all cores on the bus */
|
||||||
|
@ -256,10 +275,5 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore)
|
||||||
bcma_info(bus, "IRQ reconfiguration done\n");
|
bcma_info(bus, "IRQ reconfiguration done\n");
|
||||||
bcma_core_mips_dump_irq(bus);
|
bcma_core_mips_dump_irq(bus);
|
||||||
|
|
||||||
if (mcore->setup_done)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bcma_chipco_serial_init(&bus->drv_cc);
|
|
||||||
bcma_core_mips_flash_detect(mcore);
|
|
||||||
mcore->setup_done = true;
|
mcore->setup_done = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,11 +35,6 @@ bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
|
||||||
chipid_top != 0x5300)
|
chipid_top != 0x5300)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
|
|
||||||
bcma_info(bus, "This PCI core is disabled and not working\n");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bcma_core_enable(pc->core, 0);
|
bcma_core_enable(pc->core, 0);
|
||||||
|
|
||||||
return !mips_busprobe32(tmp, pc->core->io_addr);
|
return !mips_busprobe32(tmp, pc->core->io_addr);
|
||||||
|
@ -396,6 +391,11 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
||||||
|
|
||||||
bcma_info(bus, "PCIEcore in host mode found\n");
|
bcma_info(bus, "PCIEcore in host mode found\n");
|
||||||
|
|
||||||
|
if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) {
|
||||||
|
bcma_info(bus, "This PCIE core is disabled and not working\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL);
|
pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL);
|
||||||
if (!pc_host) {
|
if (!pc_host) {
|
||||||
bcma_err(bus, "can not allocate memory");
|
bcma_err(bus, "can not allocate memory");
|
||||||
|
@ -452,6 +452,8 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
||||||
pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
|
pc_host->mem_resource.start = BCMA_SOC_PCI_MEM;
|
||||||
pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
|
pc_host->mem_resource.end = BCMA_SOC_PCI_MEM +
|
||||||
BCMA_SOC_PCI_MEM_SZ - 1;
|
BCMA_SOC_PCI_MEM_SZ - 1;
|
||||||
|
pc_host->io_resource.start = 0x100;
|
||||||
|
pc_host->io_resource.end = 0x47F;
|
||||||
pci_membase_1G = BCMA_SOC_PCIE_DMA_H32;
|
pci_membase_1G = BCMA_SOC_PCIE_DMA_H32;
|
||||||
pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
|
pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
|
||||||
tmp | BCMA_SOC_PCI_MEM);
|
tmp | BCMA_SOC_PCI_MEM);
|
||||||
|
@ -459,6 +461,8 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc)
|
||||||
pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM;
|
pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM;
|
||||||
pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM +
|
pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM +
|
||||||
BCMA_SOC_PCI_MEM_SZ - 1;
|
BCMA_SOC_PCI_MEM_SZ - 1;
|
||||||
|
pc_host->io_resource.start = 0x480;
|
||||||
|
pc_host->io_resource.end = 0x7FF;
|
||||||
pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32;
|
pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32;
|
||||||
pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG;
|
pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG;
|
||||||
pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
|
pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
|
||||||
|
|
|
@ -238,7 +238,7 @@ static void __devexit bcma_host_pci_remove(struct pci_dev *dev)
|
||||||
pci_set_drvdata(dev, NULL);
|
pci_set_drvdata(dev, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#ifdef CONFIG_PM_SLEEP
|
||||||
static int bcma_host_pci_suspend(struct device *dev)
|
static int bcma_host_pci_suspend(struct device *dev)
|
||||||
{
|
{
|
||||||
struct pci_dev *pdev = to_pci_dev(dev);
|
struct pci_dev *pdev = to_pci_dev(dev);
|
||||||
|
@ -261,11 +261,11 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend,
|
||||||
bcma_host_pci_resume);
|
bcma_host_pci_resume);
|
||||||
#define BCMA_PM_OPS (&bcma_pm_ops)
|
#define BCMA_PM_OPS (&bcma_pm_ops)
|
||||||
|
|
||||||
#else /* CONFIG_PM */
|
#else /* CONFIG_PM_SLEEP */
|
||||||
|
|
||||||
#define BCMA_PM_OPS NULL
|
#define BCMA_PM_OPS NULL
|
||||||
|
|
||||||
#endif /* CONFIG_PM */
|
#endif /* CONFIG_PM_SLEEP */
|
||||||
|
|
||||||
static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
|
static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
|
||||||
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
|
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
|
||||||
|
|
|
@ -81,6 +81,18 @@ struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(bcma_find_core);
|
EXPORT_SYMBOL_GPL(bcma_find_core);
|
||||||
|
|
||||||
|
static struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid,
|
||||||
|
u8 unit)
|
||||||
|
{
|
||||||
|
struct bcma_device *core;
|
||||||
|
|
||||||
|
list_for_each_entry(core, &bus->cores, list) {
|
||||||
|
if (core->id.id == coreid && core->core_unit == unit)
|
||||||
|
return core;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void bcma_release_core_dev(struct device *dev)
|
static void bcma_release_core_dev(struct device *dev)
|
||||||
{
|
{
|
||||||
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
|
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
|
||||||
|
@ -183,6 +195,20 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Early init CC core */
|
||||||
|
core = bcma_find_core(bus, bcma_cc_core_id(bus));
|
||||||
|
if (core) {
|
||||||
|
bus->drv_cc.core = core;
|
||||||
|
bcma_core_chipcommon_early_init(&bus->drv_cc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to get SPROM */
|
||||||
|
err = bcma_sprom_get(bus);
|
||||||
|
if (err == -ENOENT) {
|
||||||
|
bcma_err(bus, "No SPROM available\n");
|
||||||
|
} else if (err)
|
||||||
|
bcma_err(bus, "Failed to get SPROM: %d\n", err);
|
||||||
|
|
||||||
/* Init CC core */
|
/* Init CC core */
|
||||||
core = bcma_find_core(bus, bcma_cc_core_id(bus));
|
core = bcma_find_core(bus, bcma_cc_core_id(bus));
|
||||||
if (core) {
|
if (core) {
|
||||||
|
@ -198,10 +224,17 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init PCIE core */
|
/* Init PCIE core */
|
||||||
core = bcma_find_core(bus, BCMA_CORE_PCIE);
|
core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 0);
|
||||||
if (core) {
|
if (core) {
|
||||||
bus->drv_pci.core = core;
|
bus->drv_pci[0].core = core;
|
||||||
bcma_core_pci_init(&bus->drv_pci);
|
bcma_core_pci_init(&bus->drv_pci[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init PCIE core */
|
||||||
|
core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 1);
|
||||||
|
if (core) {
|
||||||
|
bus->drv_pci[1].core = core;
|
||||||
|
bcma_core_pci_init(&bus->drv_pci[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init GBIT MAC COMMON core */
|
/* Init GBIT MAC COMMON core */
|
||||||
|
@ -211,13 +244,6 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
|
||||||
bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn);
|
bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to get SPROM */
|
|
||||||
err = bcma_sprom_get(bus);
|
|
||||||
if (err == -ENOENT) {
|
|
||||||
bcma_err(bus, "No SPROM available\n");
|
|
||||||
} else if (err)
|
|
||||||
bcma_err(bus, "Failed to get SPROM: %d\n", err);
|
|
||||||
|
|
||||||
/* Register found cores */
|
/* Register found cores */
|
||||||
bcma_register_cores(bus);
|
bcma_register_cores(bus);
|
||||||
|
|
||||||
|
@ -275,18 +301,18 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init CC core */
|
/* Early init CC core */
|
||||||
core = bcma_find_core(bus, bcma_cc_core_id(bus));
|
core = bcma_find_core(bus, bcma_cc_core_id(bus));
|
||||||
if (core) {
|
if (core) {
|
||||||
bus->drv_cc.core = core;
|
bus->drv_cc.core = core;
|
||||||
bcma_core_chipcommon_init(&bus->drv_cc);
|
bcma_core_chipcommon_early_init(&bus->drv_cc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Init MIPS core */
|
/* Early init MIPS core */
|
||||||
core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
|
core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
|
||||||
if (core) {
|
if (core) {
|
||||||
bus->drv_mips.core = core;
|
bus->drv_mips.core = core;
|
||||||
bcma_core_mips_init(&bus->drv_mips);
|
bcma_core_mips_early_init(&bus->drv_mips);
|
||||||
}
|
}
|
||||||
|
|
||||||
bcma_info(bus, "Early bus registered\n");
|
bcma_info(bus, "Early bus registered\n");
|
||||||
|
|
|
@ -595,8 +595,11 @@ int bcma_sprom_get(struct bcma_bus *bus)
|
||||||
bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
|
bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
|
||||||
|
|
||||||
err = bcma_sprom_valid(sprom);
|
err = bcma_sprom_valid(sprom);
|
||||||
if (err)
|
if (err) {
|
||||||
|
bcma_warn(bus, "invalid sprom read from the PCIe card, try to use fallback sprom\n");
|
||||||
|
err = bcma_fill_sprom_with_fallback(bus, &bus->sprom);
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
bcma_sprom_extract_r8(bus, sprom);
|
bcma_sprom_extract_r8(bus, sprom);
|
||||||
|
|
||||||
|
|
|
@ -492,7 +492,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card)
|
||||||
static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
||||||
{
|
{
|
||||||
u16 buf_len = 0;
|
u16 buf_len = 0;
|
||||||
int ret, buf_block_len, blksz;
|
int ret, num_blocks, blksz;
|
||||||
struct sk_buff *skb = NULL;
|
struct sk_buff *skb = NULL;
|
||||||
u32 type;
|
u32 type;
|
||||||
u8 *payload = NULL;
|
u8 *payload = NULL;
|
||||||
|
@ -514,18 +514,17 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
||||||
}
|
}
|
||||||
|
|
||||||
blksz = SDIO_BLOCK_SIZE;
|
blksz = SDIO_BLOCK_SIZE;
|
||||||
buf_block_len = (buf_len + blksz - 1) / blksz;
|
num_blocks = DIV_ROUND_UP(buf_len, blksz);
|
||||||
|
|
||||||
if (buf_len <= SDIO_HEADER_LEN
|
if (buf_len <= SDIO_HEADER_LEN
|
||||||
|| (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
|
|| (num_blocks * blksz) > ALLOC_BUF_SIZE) {
|
||||||
BT_ERR("invalid packet length: %d", buf_len);
|
BT_ERR("invalid packet length: %d", buf_len);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate buffer */
|
/* Allocate buffer */
|
||||||
skb = bt_skb_alloc(buf_block_len * blksz + BTSDIO_DMA_ALIGN,
|
skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC);
|
||||||
GFP_ATOMIC);
|
|
||||||
if (skb == NULL) {
|
if (skb == NULL) {
|
||||||
BT_ERR("No free skb");
|
BT_ERR("No free skb");
|
||||||
goto exit;
|
goto exit;
|
||||||
|
@ -541,7 +540,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
||||||
payload = skb->data;
|
payload = skb->data;
|
||||||
|
|
||||||
ret = sdio_readsb(card->func, payload, card->ioport,
|
ret = sdio_readsb(card->func, payload, card->ioport,
|
||||||
buf_block_len * blksz);
|
num_blocks * blksz);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
BT_ERR("readsb failed: %d", ret);
|
BT_ERR("readsb failed: %d", ret);
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
|
@ -553,7 +552,16 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
buf_len = payload[0];
|
buf_len = payload[0];
|
||||||
buf_len |= (u16) payload[1] << 8;
|
buf_len |= payload[1] << 8;
|
||||||
|
buf_len |= payload[2] << 16;
|
||||||
|
|
||||||
|
if (buf_len > blksz * num_blocks) {
|
||||||
|
BT_ERR("Skip incorrect packet: hdrlen %d buffer %d",
|
||||||
|
buf_len, blksz * num_blocks);
|
||||||
|
ret = -EIO;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
type = payload[3];
|
type = payload[3];
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -589,8 +597,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
BT_ERR("Unknown packet type:%d", type);
|
BT_ERR("Unknown packet type:%d", type);
|
||||||
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload,
|
BT_ERR("hex: %*ph", blksz * num_blocks, payload);
|
||||||
blksz * buf_block_len);
|
|
||||||
|
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
skb = NULL;
|
skb = NULL;
|
||||||
|
@ -849,8 +856,7 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
i++;
|
i++;
|
||||||
BT_ERR("i=%d writesb failed: %d", i, ret);
|
BT_ERR("i=%d writesb failed: %d", i, ret);
|
||||||
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
|
BT_ERR("hex: %*ph", nb, payload);
|
||||||
payload, nb);
|
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
if (i > MAX_WRITE_IOMEM_RETRY)
|
if (i > MAX_WRITE_IOMEM_RETRY)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
|
@ -452,7 +452,7 @@ static size_t gelic_wl_synthesize_ie(u8 *buf,
|
||||||
if (rsn)
|
if (rsn)
|
||||||
*buf++ = WLAN_EID_RSN;
|
*buf++ = WLAN_EID_RSN;
|
||||||
else
|
else
|
||||||
*buf++ = WLAN_EID_GENERIC;
|
*buf++ = WLAN_EID_VENDOR_SPECIFIC;
|
||||||
|
|
||||||
/* length filed; set later */
|
/* length filed; set later */
|
||||||
buf++;
|
buf++;
|
||||||
|
@ -540,7 +540,7 @@ static void gelic_wl_parse_ie(u8 *data, size_t len,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
switch (item_id) {
|
switch (item_id) {
|
||||||
case WLAN_EID_GENERIC:
|
case WLAN_EID_VENDOR_SPECIFIC:
|
||||||
if ((OUI_LEN + 1 <= item_len) &&
|
if ((OUI_LEN + 1 <= item_len) &&
|
||||||
!memcmp(pos, wpa_oui, OUI_LEN) &&
|
!memcmp(pos, wpa_oui, OUI_LEN) &&
|
||||||
pos[OUI_LEN] == 0x01) {
|
pos[OUI_LEN] == 0x01) {
|
||||||
|
|
|
@ -7433,7 +7433,7 @@ static inline char *airo_translate_scan(struct net_device *dev,
|
||||||
num_null_ies++;
|
num_null_ies++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WLAN_EID_GENERIC:
|
case WLAN_EID_VENDOR_SPECIFIC:
|
||||||
if (ie[1] >= 4 &&
|
if (ie[1] >= 4 &&
|
||||||
ie[2] == 0x00 &&
|
ie[2] == 0x00 &&
|
||||||
ie[3] == 0x50 &&
|
ie[3] == 0x50 &&
|
||||||
|
|
|
@ -26,5 +26,6 @@ source "drivers/net/wireless/ath/ath5k/Kconfig"
|
||||||
source "drivers/net/wireless/ath/ath9k/Kconfig"
|
source "drivers/net/wireless/ath/ath9k/Kconfig"
|
||||||
source "drivers/net/wireless/ath/carl9170/Kconfig"
|
source "drivers/net/wireless/ath/carl9170/Kconfig"
|
||||||
source "drivers/net/wireless/ath/ath6kl/Kconfig"
|
source "drivers/net/wireless/ath/ath6kl/Kconfig"
|
||||||
|
source "drivers/net/wireless/ath/ar5523/Kconfig"
|
||||||
|
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -2,6 +2,7 @@ obj-$(CONFIG_ATH5K) += ath5k/
|
||||||
obj-$(CONFIG_ATH9K_HW) += ath9k/
|
obj-$(CONFIG_ATH9K_HW) += ath9k/
|
||||||
obj-$(CONFIG_CARL9170) += carl9170/
|
obj-$(CONFIG_CARL9170) += carl9170/
|
||||||
obj-$(CONFIG_ATH6KL) += ath6kl/
|
obj-$(CONFIG_ATH6KL) += ath6kl/
|
||||||
|
obj-$(CONFIG_AR5523) += ar5523/
|
||||||
|
|
||||||
obj-$(CONFIG_ATH_COMMON) += ath.o
|
obj-$(CONFIG_ATH_COMMON) += ath.o
|
||||||
|
|
||||||
|
|
7
drivers/net/wireless/ath/ar5523/Kconfig
Normal file
7
drivers/net/wireless/ath/ar5523/Kconfig
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
config AR5523
|
||||||
|
tristate "Atheros AR5523 wireless driver support"
|
||||||
|
depends on MAC80211 && USB
|
||||||
|
select FW_LOADER
|
||||||
|
---help---
|
||||||
|
This module add support for AR5523 based USB dongles such as D-Link
|
||||||
|
DWL-G132, Netgear WPN111 and many more.
|
1
drivers/net/wireless/ath/ar5523/Makefile
Normal file
1
drivers/net/wireless/ath/ar5523/Makefile
Normal file
|
@ -0,0 +1 @@
|
||||||
|
obj-$(CONFIG_AR5523) := ar5523.o
|
1806
drivers/net/wireless/ath/ar5523/ar5523.c
Normal file
1806
drivers/net/wireless/ath/ar5523/ar5523.c
Normal file
File diff suppressed because it is too large
Load diff
152
drivers/net/wireless/ath/ar5523/ar5523.h
Normal file
152
drivers/net/wireless/ath/ar5523/ar5523.h
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr>
|
||||||
|
* Copyright (c) 2006 Sam Leffler, Errno Consulting
|
||||||
|
* Copyright (c) 2007 Christoph Hellwig <hch@lst.de>
|
||||||
|
* Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org>
|
||||||
|
* Copyright (c) 2012 Pontus Fuchs <pontus.fuchs@gmail.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define AR5523_FLAG_PRE_FIRMWARE (1 << 0)
|
||||||
|
#define AR5523_FLAG_ABG (1 << 1)
|
||||||
|
|
||||||
|
#define AR5523_FIRMWARE_FILE "ar5523.bin"
|
||||||
|
|
||||||
|
#define AR5523_CMD_TX_PIPE 0x01
|
||||||
|
#define AR5523_DATA_TX_PIPE 0x02
|
||||||
|
#define AR5523_CMD_RX_PIPE 0x81
|
||||||
|
#define AR5523_DATA_RX_PIPE 0x82
|
||||||
|
|
||||||
|
#define ar5523_cmd_tx_pipe(dev) \
|
||||||
|
usb_sndbulkpipe((dev), AR5523_CMD_TX_PIPE)
|
||||||
|
#define ar5523_data_tx_pipe(dev) \
|
||||||
|
usb_sndbulkpipe((dev), AR5523_DATA_TX_PIPE)
|
||||||
|
#define ar5523_cmd_rx_pipe(dev) \
|
||||||
|
usb_rcvbulkpipe((dev), AR5523_CMD_RX_PIPE)
|
||||||
|
#define ar5523_data_rx_pipe(dev) \
|
||||||
|
usb_rcvbulkpipe((dev), AR5523_DATA_RX_PIPE)
|
||||||
|
|
||||||
|
#define AR5523_DATA_TIMEOUT 10000
|
||||||
|
#define AR5523_CMD_TIMEOUT 1000
|
||||||
|
|
||||||
|
#define AR5523_TX_DATA_COUNT 8
|
||||||
|
#define AR5523_TX_DATA_RESTART_COUNT 2
|
||||||
|
#define AR5523_RX_DATA_COUNT 16
|
||||||
|
#define AR5523_RX_DATA_REFILL_COUNT 8
|
||||||
|
|
||||||
|
#define AR5523_CMD_ID 1
|
||||||
|
#define AR5523_DATA_ID 2
|
||||||
|
|
||||||
|
#define AR5523_TX_WD_TIMEOUT (HZ * 2)
|
||||||
|
#define AR5523_FLUSH_TIMEOUT (HZ * 3)
|
||||||
|
|
||||||
|
enum AR5523_flags {
|
||||||
|
AR5523_HW_UP,
|
||||||
|
AR5523_USB_DISCONNECTED,
|
||||||
|
AR5523_CONNECTED
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ar5523_tx_cmd {
|
||||||
|
struct ar5523 *ar;
|
||||||
|
struct urb *urb_tx;
|
||||||
|
void *buf_tx;
|
||||||
|
void *odata;
|
||||||
|
int olen;
|
||||||
|
int flags;
|
||||||
|
int res;
|
||||||
|
struct completion done;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* This struct is placed in tx_info->driver_data. It must not be larger
|
||||||
|
* than IEEE80211_TX_INFO_DRIVER_DATA_SIZE.
|
||||||
|
*/
|
||||||
|
struct ar5523_tx_data {
|
||||||
|
struct list_head list;
|
||||||
|
struct ar5523 *ar;
|
||||||
|
struct sk_buff *skb;
|
||||||
|
struct urb *urb;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ar5523_rx_data {
|
||||||
|
struct list_head list;
|
||||||
|
struct ar5523 *ar;
|
||||||
|
struct urb *urb;
|
||||||
|
struct sk_buff *skb;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ar5523 {
|
||||||
|
struct usb_device *dev;
|
||||||
|
struct ieee80211_hw *hw;
|
||||||
|
|
||||||
|
unsigned long flags;
|
||||||
|
struct mutex mutex;
|
||||||
|
struct workqueue_struct *wq;
|
||||||
|
|
||||||
|
struct ar5523_tx_cmd tx_cmd;
|
||||||
|
|
||||||
|
struct delayed_work stat_work;
|
||||||
|
|
||||||
|
struct timer_list tx_wd_timer;
|
||||||
|
struct work_struct tx_wd_work;
|
||||||
|
struct work_struct tx_work;
|
||||||
|
struct list_head tx_queue_pending;
|
||||||
|
struct list_head tx_queue_submitted;
|
||||||
|
spinlock_t tx_data_list_lock;
|
||||||
|
wait_queue_head_t tx_flush_waitq;
|
||||||
|
|
||||||
|
/* Queued + Submitted TX frames */
|
||||||
|
atomic_t tx_nr_total;
|
||||||
|
|
||||||
|
/* Submitted TX frames */
|
||||||
|
atomic_t tx_nr_pending;
|
||||||
|
|
||||||
|
void *rx_cmd_buf;
|
||||||
|
struct urb *rx_cmd_urb;
|
||||||
|
|
||||||
|
struct ar5523_rx_data rx_data[AR5523_RX_DATA_COUNT];
|
||||||
|
spinlock_t rx_data_list_lock;
|
||||||
|
struct list_head rx_data_free;
|
||||||
|
struct list_head rx_data_used;
|
||||||
|
atomic_t rx_data_free_cnt;
|
||||||
|
|
||||||
|
struct work_struct rx_refill_work;
|
||||||
|
|
||||||
|
unsigned int rxbufsz;
|
||||||
|
u8 serial[16];
|
||||||
|
|
||||||
|
struct ieee80211_channel channels[14];
|
||||||
|
struct ieee80211_rate rates[12];
|
||||||
|
struct ieee80211_supported_band band;
|
||||||
|
struct ieee80211_vif *vif;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* flags for sending firmware commands */
|
||||||
|
#define AR5523_CMD_FLAG_READ (1 << 1)
|
||||||
|
#define AR5523_CMD_FLAG_MAGIC (1 << 2)
|
||||||
|
|
||||||
|
#define ar5523_dbg(ar, format, arg...) \
|
||||||
|
dev_dbg(&(ar)->dev->dev, format, ## arg)
|
||||||
|
|
||||||
|
/* On USB hot-unplug there can be a lot of URBs in flight and they'll all
|
||||||
|
* fail. Instead of dealing with them in every possible place just surpress
|
||||||
|
* any messages on USB disconnect.
|
||||||
|
*/
|
||||||
|
#define ar5523_err(ar, format, arg...) \
|
||||||
|
do { \
|
||||||
|
if (!test_bit(AR5523_USB_DISCONNECTED, &ar->flags)) { \
|
||||||
|
dev_err(&(ar)->dev->dev, format, ## arg); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
#define ar5523_info(ar, format, arg...) \
|
||||||
|
dev_info(&(ar)->dev->dev, format, ## arg)
|
431
drivers/net/wireless/ath/ar5523/ar5523_hw.h
Normal file
431
drivers/net/wireless/ath/ar5523/ar5523_hw.h
Normal file
|
@ -0,0 +1,431 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr>
|
||||||
|
* Copyright (c) 2006 Sam Leffler, Errno Consulting
|
||||||
|
* Copyright (c) 2007 Christoph Hellwig <hch@lst.de>
|
||||||
|
* Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org>
|
||||||
|
* Copyright (c) 2012 Pontus Fuchs <pontus.fuchs@gmail.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* all fields are big endian */
|
||||||
|
struct ar5523_fwblock {
|
||||||
|
__be32 flags;
|
||||||
|
#define AR5523_WRITE_BLOCK (1 << 4)
|
||||||
|
|
||||||
|
__be32 len;
|
||||||
|
#define AR5523_MAX_FWBLOCK_SIZE 2048
|
||||||
|
|
||||||
|
__be32 total;
|
||||||
|
__be32 remain;
|
||||||
|
__be32 rxtotal;
|
||||||
|
__be32 pad[123];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define AR5523_MAX_RXCMDSZ 1024
|
||||||
|
#define AR5523_MAX_TXCMDSZ 1024
|
||||||
|
|
||||||
|
struct ar5523_cmd_hdr {
|
||||||
|
__be32 len;
|
||||||
|
__be32 code;
|
||||||
|
/* NB: these are defined for rev 1.5 firmware; rev 1.6 is different */
|
||||||
|
/* messages from Host -> Target */
|
||||||
|
#define WDCMSG_HOST_AVAILABLE 0x01
|
||||||
|
#define WDCMSG_BIND 0x02
|
||||||
|
#define WDCMSG_TARGET_RESET 0x03
|
||||||
|
#define WDCMSG_TARGET_GET_CAPABILITY 0x04
|
||||||
|
#define WDCMSG_TARGET_SET_CONFIG 0x05
|
||||||
|
#define WDCMSG_TARGET_GET_STATUS 0x06
|
||||||
|
#define WDCMSG_TARGET_GET_STATS 0x07
|
||||||
|
#define WDCMSG_TARGET_START 0x08
|
||||||
|
#define WDCMSG_TARGET_STOP 0x09
|
||||||
|
#define WDCMSG_TARGET_ENABLE 0x0a
|
||||||
|
#define WDCMSG_TARGET_DISABLE 0x0b
|
||||||
|
#define WDCMSG_CREATE_CONNECTION 0x0c
|
||||||
|
#define WDCMSG_UPDATE_CONNECT_ATTR 0x0d
|
||||||
|
#define WDCMSG_DELETE_CONNECT 0x0e
|
||||||
|
#define WDCMSG_SEND 0x0f
|
||||||
|
#define WDCMSG_FLUSH 0x10
|
||||||
|
/* messages from Target -> Host */
|
||||||
|
#define WDCMSG_STATS_UPDATE 0x11
|
||||||
|
#define WDCMSG_BMISS 0x12
|
||||||
|
#define WDCMSG_DEVICE_AVAIL 0x13
|
||||||
|
#define WDCMSG_SEND_COMPLETE 0x14
|
||||||
|
#define WDCMSG_DATA_AVAIL 0x15
|
||||||
|
#define WDCMSG_SET_PWR_MODE 0x16
|
||||||
|
#define WDCMSG_BMISS_ACK 0x17
|
||||||
|
#define WDCMSG_SET_LED_STEADY 0x18
|
||||||
|
#define WDCMSG_SET_LED_BLINK 0x19
|
||||||
|
/* more messages */
|
||||||
|
#define WDCMSG_SETUP_BEACON_DESC 0x1a
|
||||||
|
#define WDCMSG_BEACON_INIT 0x1b
|
||||||
|
#define WDCMSG_RESET_KEY_CACHE 0x1c
|
||||||
|
#define WDCMSG_RESET_KEY_CACHE_ENTRY 0x1d
|
||||||
|
#define WDCMSG_SET_KEY_CACHE_ENTRY 0x1e
|
||||||
|
#define WDCMSG_SET_DECOMP_MASK 0x1f
|
||||||
|
#define WDCMSG_SET_REGULATORY_DOMAIN 0x20
|
||||||
|
#define WDCMSG_SET_LED_STATE 0x21
|
||||||
|
#define WDCMSG_WRITE_ASSOCID 0x22
|
||||||
|
#define WDCMSG_SET_STA_BEACON_TIMERS 0x23
|
||||||
|
#define WDCMSG_GET_TSF 0x24
|
||||||
|
#define WDCMSG_RESET_TSF 0x25
|
||||||
|
#define WDCMSG_SET_ADHOC_MODE 0x26
|
||||||
|
#define WDCMSG_SET_BASIC_RATE 0x27
|
||||||
|
#define WDCMSG_MIB_CONTROL 0x28
|
||||||
|
#define WDCMSG_GET_CHANNEL_DATA 0x29
|
||||||
|
#define WDCMSG_GET_CUR_RSSI 0x2a
|
||||||
|
#define WDCMSG_SET_ANTENNA_SWITCH 0x2b
|
||||||
|
#define WDCMSG_USE_SHORT_SLOT_TIME 0x2f
|
||||||
|
#define WDCMSG_SET_POWER_MODE 0x30
|
||||||
|
#define WDCMSG_SETUP_PSPOLL_DESC 0x31
|
||||||
|
#define WDCMSG_SET_RX_MULTICAST_FILTER 0x32
|
||||||
|
#define WDCMSG_RX_FILTER 0x33
|
||||||
|
#define WDCMSG_PER_CALIBRATION 0x34
|
||||||
|
#define WDCMSG_RESET 0x35
|
||||||
|
#define WDCMSG_DISABLE 0x36
|
||||||
|
#define WDCMSG_PHY_DISABLE 0x37
|
||||||
|
#define WDCMSG_SET_TX_POWER_LIMIT 0x38
|
||||||
|
#define WDCMSG_SET_TX_QUEUE_PARAMS 0x39
|
||||||
|
#define WDCMSG_SETUP_TX_QUEUE 0x3a
|
||||||
|
#define WDCMSG_RELEASE_TX_QUEUE 0x3b
|
||||||
|
#define WDCMSG_SET_DEFAULT_KEY 0x43
|
||||||
|
|
||||||
|
__u32 priv; /* driver private data,
|
||||||
|
don't care about endianess */
|
||||||
|
__be32 magic;
|
||||||
|
__be32 reserved2[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ar5523_cmd_host_available {
|
||||||
|
__be32 sw_ver_major;
|
||||||
|
__be32 sw_ver_minor;
|
||||||
|
__be32 sw_ver_patch;
|
||||||
|
__be32 sw_ver_build;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
#define ATH_SW_VER_MAJOR 1
|
||||||
|
#define ATH_SW_VER_MINOR 5
|
||||||
|
#define ATH_SW_VER_PATCH 0
|
||||||
|
#define ATH_SW_VER_BUILD 9999
|
||||||
|
|
||||||
|
struct ar5523_chunk {
|
||||||
|
u8 seqnum; /* sequence number for ordering */
|
||||||
|
u8 flags;
|
||||||
|
#define UATH_CFLAGS_FINAL 0x01 /* final chunk of a msg */
|
||||||
|
#define UATH_CFLAGS_RXMSG 0x02 /* chunk contains rx completion */
|
||||||
|
#define UATH_CFLAGS_DEBUG 0x04 /* for debugging */
|
||||||
|
__be16 length; /* chunk size in bytes */
|
||||||
|
/* chunk data follows */
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Message format for a WDCMSG_DATA_AVAIL message from Target to Host.
|
||||||
|
*/
|
||||||
|
struct ar5523_rx_desc {
|
||||||
|
__be32 len; /* msg length including header */
|
||||||
|
__be32 code; /* WDCMSG_DATA_AVAIL */
|
||||||
|
__be32 gennum; /* generation number */
|
||||||
|
__be32 status; /* start of RECEIVE_INFO */
|
||||||
|
#define UATH_STATUS_OK 0
|
||||||
|
#define UATH_STATUS_STOP_IN_PROGRESS 1
|
||||||
|
#define UATH_STATUS_CRC_ERR 2
|
||||||
|
#define UATH_STATUS_PHY_ERR 3
|
||||||
|
#define UATH_STATUS_DECRYPT_CRC_ERR 4
|
||||||
|
#define UATH_STATUS_DECRYPT_MIC_ERR 5
|
||||||
|
#define UATH_STATUS_DECOMP_ERR 6
|
||||||
|
#define UATH_STATUS_KEY_ERR 7
|
||||||
|
#define UATH_STATUS_ERR 8
|
||||||
|
__be32 tstamp_low; /* low-order 32-bits of rx timestamp */
|
||||||
|
__be32 tstamp_high; /* high-order 32-bits of rx timestamp */
|
||||||
|
__be32 framelen; /* frame length */
|
||||||
|
__be32 rate; /* rx rate code */
|
||||||
|
__be32 antenna;
|
||||||
|
__be32 rssi;
|
||||||
|
__be32 channel;
|
||||||
|
__be32 phyerror;
|
||||||
|
__be32 connix; /* key table ix for bss traffic */
|
||||||
|
__be32 decrypterror;
|
||||||
|
__be32 keycachemiss;
|
||||||
|
__be32 pad; /* XXX? */
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct ar5523_tx_desc {
|
||||||
|
__be32 msglen;
|
||||||
|
__be32 msgid; /* msg id (supplied by host) */
|
||||||
|
__be32 type; /* opcode: WDMSG_SEND or WDCMSG_FLUSH */
|
||||||
|
__be32 txqid; /* tx queue id and flags */
|
||||||
|
#define UATH_TXQID_MASK 0x0f
|
||||||
|
#define UATH_TXQID_MINRATE 0x10 /* use min tx rate */
|
||||||
|
#define UATH_TXQID_FF 0x20 /* content is fast frame */
|
||||||
|
__be32 connid; /* tx connection id */
|
||||||
|
#define UATH_ID_INVALID 0xffffffff /* for sending prior to connection */
|
||||||
|
__be32 flags; /* non-zero if response desired */
|
||||||
|
#define UATH_TX_NOTIFY (1 << 24) /* f/w will send a UATH_NOTIF_TX */
|
||||||
|
__be32 buflen; /* payload length */
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
|
||||||
|
#define AR5523_ID_BSS 2
|
||||||
|
#define AR5523_ID_BROADCAST 0xffffffff
|
||||||
|
|
||||||
|
/* structure for command UATH_CMD_WRITE_MAC */
|
||||||
|
struct ar5523_write_mac {
|
||||||
|
__be32 reg;
|
||||||
|
__be32 len;
|
||||||
|
u8 data[32];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct ar5523_cmd_rateset {
|
||||||
|
__u8 length;
|
||||||
|
#define AR5523_MAX_NRATES 32
|
||||||
|
__u8 set[AR5523_MAX_NRATES];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ar5523_cmd_set_associd { /* AR5523_WRITE_ASSOCID */
|
||||||
|
__be32 defaultrateix;
|
||||||
|
__be32 associd;
|
||||||
|
__be32 timoffset;
|
||||||
|
__be32 turboprime;
|
||||||
|
__u8 bssid[6];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* structure for command WDCMSG_RESET */
|
||||||
|
struct ar5523_cmd_reset {
|
||||||
|
__be32 flags; /* channel flags */
|
||||||
|
#define UATH_CHAN_TURBO 0x0100
|
||||||
|
#define UATH_CHAN_CCK 0x0200
|
||||||
|
#define UATH_CHAN_OFDM 0x0400
|
||||||
|
#define UATH_CHAN_2GHZ 0x1000
|
||||||
|
#define UATH_CHAN_5GHZ 0x2000
|
||||||
|
__be32 freq; /* channel frequency */
|
||||||
|
__be32 maxrdpower;
|
||||||
|
__be32 cfgctl;
|
||||||
|
__be32 twiceantennareduction;
|
||||||
|
__be32 channelchange;
|
||||||
|
__be32 keeprccontent;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* structure for command WDCMSG_SET_BASIC_RATE */
|
||||||
|
struct ar5523_cmd_rates {
|
||||||
|
__be32 connid;
|
||||||
|
__be32 keeprccontent;
|
||||||
|
__be32 size;
|
||||||
|
struct ar5523_cmd_rateset rateset;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
WLAN_MODE_NONE = 0,
|
||||||
|
WLAN_MODE_11b,
|
||||||
|
WLAN_MODE_11a,
|
||||||
|
WLAN_MODE_11g,
|
||||||
|
WLAN_MODE_11a_TURBO,
|
||||||
|
WLAN_MODE_11g_TURBO,
|
||||||
|
WLAN_MODE_11a_TURBO_PRIME,
|
||||||
|
WLAN_MODE_11g_TURBO_PRIME,
|
||||||
|
WLAN_MODE_11a_XR,
|
||||||
|
WLAN_MODE_11g_XR,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ar5523_cmd_connection_attr {
|
||||||
|
__be32 longpreambleonly;
|
||||||
|
struct ar5523_cmd_rateset rateset;
|
||||||
|
__be32 wlanmode;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
/* structure for command AR5523_CREATE_CONNECTION */
|
||||||
|
struct ar5523_cmd_create_connection {
|
||||||
|
__be32 connid;
|
||||||
|
__be32 bssid;
|
||||||
|
__be32 size;
|
||||||
|
struct ar5523_cmd_connection_attr connattr;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct ar5523_cmd_ledsteady { /* WDCMSG_SET_LED_STEADY */
|
||||||
|
__be32 lednum;
|
||||||
|
#define UATH_LED_LINK 0
|
||||||
|
#define UATH_LED_ACTIVITY 1
|
||||||
|
__be32 ledmode;
|
||||||
|
#define UATH_LED_OFF 0
|
||||||
|
#define UATH_LED_ON 1
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct ar5523_cmd_ledblink { /* WDCMSG_SET_LED_BLINK */
|
||||||
|
__be32 lednum;
|
||||||
|
__be32 ledmode;
|
||||||
|
__be32 blinkrate;
|
||||||
|
__be32 slowmode;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct ar5523_cmd_ledstate { /* WDCMSG_SET_LED_STATE */
|
||||||
|
__be32 connected;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct ar5523_cmd_txq_attr {
|
||||||
|
__be32 priority;
|
||||||
|
__be32 aifs;
|
||||||
|
__be32 logcwmin;
|
||||||
|
__be32 logcwmax;
|
||||||
|
__be32 bursttime;
|
||||||
|
__be32 mode;
|
||||||
|
__be32 qflags;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct ar5523_cmd_txq_setup { /* WDCMSG_SETUP_TX_QUEUE */
|
||||||
|
__be32 qid;
|
||||||
|
__be32 len;
|
||||||
|
struct ar5523_cmd_txq_attr attr;
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
struct ar5523_cmd_rx_filter { /* WDCMSG_RX_FILTER */
|
||||||
|
__be32 bits;
|
||||||
|
#define UATH_FILTER_RX_UCAST 0x00000001
|
||||||
|
#define UATH_FILTER_RX_MCAST 0x00000002
|
||||||
|
#define UATH_FILTER_RX_BCAST 0x00000004
|
||||||
|
#define UATH_FILTER_RX_CONTROL 0x00000008
|
||||||
|
#define UATH_FILTER_RX_BEACON 0x00000010 /* beacon frames */
|
||||||
|
#define UATH_FILTER_RX_PROM 0x00000020 /* promiscuous mode */
|
||||||
|
#define UATH_FILTER_RX_PHY_ERR 0x00000040 /* phy errors */
|
||||||
|
#define UATH_FILTER_RX_PHY_RADAR 0x00000080 /* radar phy errors */
|
||||||
|
#define UATH_FILTER_RX_XR_POOL 0x00000400 /* XR group polls */
|
||||||
|
#define UATH_FILTER_RX_PROBE_REQ 0x00000800
|
||||||
|
__be32 op;
|
||||||
|
#define UATH_FILTER_OP_INIT 0x0
|
||||||
|
#define UATH_FILTER_OP_SET 0x1
|
||||||
|
#define UATH_FILTER_OP_CLEAR 0x2
|
||||||
|
#define UATH_FILTER_OP_TEMP 0x3
|
||||||
|
#define UATH_FILTER_OP_RESTORE 0x4
|
||||||
|
} __packed;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CFG_NONE, /* Sentinal to indicate "no config" */
|
||||||
|
CFG_REG_DOMAIN, /* Regulatory Domain */
|
||||||
|
CFG_RATE_CONTROL_ENABLE,
|
||||||
|
CFG_DEF_XMIT_DATA_RATE, /* NB: if rate control is not enabled */
|
||||||
|
CFG_HW_TX_RETRIES,
|
||||||
|
CFG_SW_TX_RETRIES,
|
||||||
|
CFG_SLOW_CLOCK_ENABLE,
|
||||||
|
CFG_COMP_PROC,
|
||||||
|
CFG_USER_RTS_THRESHOLD,
|
||||||
|
CFG_XR2NORM_RATE_THRESHOLD,
|
||||||
|
CFG_XRMODE_SWITCH_COUNT,
|
||||||
|
CFG_PROTECTION_TYPE,
|
||||||
|
CFG_BURST_SEQ_THRESHOLD,
|
||||||
|
CFG_ABOLT,
|
||||||
|
CFG_IQ_LOG_COUNT_MAX,
|
||||||
|
CFG_MODE_CTS,
|
||||||
|
CFG_WME_ENABLED,
|
||||||
|
CFG_GPRS_CBR_PERIOD,
|
||||||
|
CFG_SERVICE_TYPE,
|
||||||
|
/* MAC Address to use. Overrides EEPROM */
|
||||||
|
CFG_MAC_ADDR,
|
||||||
|
CFG_DEBUG_EAR,
|
||||||
|
CFG_INIT_REGS,
|
||||||
|
/* An ID for use in error & debug messages */
|
||||||
|
CFG_DEBUG_ID,
|
||||||
|
CFG_COMP_WIN_SZ,
|
||||||
|
CFG_DIVERSITY_CTL,
|
||||||
|
CFG_TP_SCALE,
|
||||||
|
CFG_TPC_HALF_DBM5,
|
||||||
|
CFG_TPC_HALF_DBM2,
|
||||||
|
CFG_OVERRD_TX_POWER,
|
||||||
|
CFG_USE_32KHZ_CLOCK,
|
||||||
|
CFG_GMODE_PROTECTION,
|
||||||
|
CFG_GMODE_PROTECT_RATE_INDEX,
|
||||||
|
CFG_GMODE_NON_ERP_PREAMBLE,
|
||||||
|
CFG_WDC_TRANSPORT_CHUNK_SIZE,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
/* Sentinal to indicate "no capability" */
|
||||||
|
CAP_NONE,
|
||||||
|
CAP_ALL, /* ALL capabilities */
|
||||||
|
CAP_TARGET_VERSION,
|
||||||
|
CAP_TARGET_REVISION,
|
||||||
|
CAP_MAC_VERSION,
|
||||||
|
CAP_MAC_REVISION,
|
||||||
|
CAP_PHY_REVISION,
|
||||||
|
CAP_ANALOG_5GHz_REVISION,
|
||||||
|
CAP_ANALOG_2GHz_REVISION,
|
||||||
|
/* Target supports WDC message debug features */
|
||||||
|
CAP_DEBUG_WDCMSG_SUPPORT,
|
||||||
|
|
||||||
|
CAP_REG_DOMAIN,
|
||||||
|
CAP_COUNTRY_CODE,
|
||||||
|
CAP_REG_CAP_BITS,
|
||||||
|
|
||||||
|
CAP_WIRELESS_MODES,
|
||||||
|
CAP_CHAN_SPREAD_SUPPORT,
|
||||||
|
CAP_SLEEP_AFTER_BEACON_BROKEN,
|
||||||
|
CAP_COMPRESS_SUPPORT,
|
||||||
|
CAP_BURST_SUPPORT,
|
||||||
|
CAP_FAST_FRAMES_SUPPORT,
|
||||||
|
CAP_CHAP_TUNING_SUPPORT,
|
||||||
|
CAP_TURBOG_SUPPORT,
|
||||||
|
CAP_TURBO_PRIME_SUPPORT,
|
||||||
|
CAP_DEVICE_TYPE,
|
||||||
|
CAP_XR_SUPPORT,
|
||||||
|
CAP_WME_SUPPORT,
|
||||||
|
CAP_TOTAL_QUEUES,
|
||||||
|
CAP_CONNECTION_ID_MAX, /* Should absorb CAP_KEY_CACHE_SIZE */
|
||||||
|
|
||||||
|
CAP_LOW_5GHZ_CHAN,
|
||||||
|
CAP_HIGH_5GHZ_CHAN,
|
||||||
|
CAP_LOW_2GHZ_CHAN,
|
||||||
|
CAP_HIGH_2GHZ_CHAN,
|
||||||
|
|
||||||
|
CAP_MIC_AES_CCM,
|
||||||
|
CAP_MIC_CKIP,
|
||||||
|
CAP_MIC_TKIP,
|
||||||
|
CAP_MIC_TKIP_WME,
|
||||||
|
CAP_CIPHER_AES_CCM,
|
||||||
|
CAP_CIPHER_CKIP,
|
||||||
|
CAP_CIPHER_TKIP,
|
||||||
|
|
||||||
|
CAP_TWICE_ANTENNAGAIN_5G,
|
||||||
|
CAP_TWICE_ANTENNAGAIN_2G,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ST_NONE, /* Sentinal to indicate "no status" */
|
||||||
|
ST_ALL,
|
||||||
|
ST_SERVICE_TYPE,
|
||||||
|
ST_WLAN_MODE,
|
||||||
|
ST_FREQ,
|
||||||
|
ST_BAND,
|
||||||
|
ST_LAST_RSSI,
|
||||||
|
ST_PS_FRAMES_DROPPED,
|
||||||
|
ST_CACHED_DEF_ANT,
|
||||||
|
ST_COUNT_OTHER_RX_ANT,
|
||||||
|
ST_USE_FAST_DIVERSITY,
|
||||||
|
ST_MAC_ADDR,
|
||||||
|
ST_RX_GENERATION_NUM,
|
||||||
|
ST_TX_QUEUE_DEPTH,
|
||||||
|
ST_SERIAL_NUMBER,
|
||||||
|
ST_WDC_TRANSPORT_CHUNK_SIZE,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
TARGET_DEVICE_AWAKE,
|
||||||
|
TARGET_DEVICE_SLEEP,
|
||||||
|
TARGET_DEVICE_PWRDN,
|
||||||
|
TARGET_DEVICE_PWRSAVE,
|
||||||
|
TARGET_DEVICE_SUSPEND,
|
||||||
|
TARGET_DEVICE_RESUME,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* this is in net/ieee80211.h, but that conflicts with the mac80211 headers */
|
||||||
|
#define IEEE80211_2ADDR_LEN 16
|
||||||
|
|
||||||
|
#define AR5523_MIN_RXBUFSZ \
|
||||||
|
(((sizeof(__be32) + IEEE80211_2ADDR_LEN + \
|
||||||
|
sizeof(struct ar5523_rx_desc)) + 3) & ~3)
|
|
@ -301,7 +301,7 @@ static bool ath6kl_cfg80211_ready(struct ath6kl_vif *vif)
|
||||||
|
|
||||||
static bool ath6kl_is_wpa_ie(const u8 *pos)
|
static bool ath6kl_is_wpa_ie(const u8 *pos)
|
||||||
{
|
{
|
||||||
return pos[0] == WLAN_EID_WPA && pos[1] >= 4 &&
|
return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
|
||||||
pos[2] == 0x00 && pos[3] == 0x50 &&
|
pos[2] == 0x00 && pos[3] == 0x50 &&
|
||||||
pos[4] == 0xf2 && pos[5] == 0x01;
|
pos[4] == 0xf2 && pos[5] == 0x01;
|
||||||
}
|
}
|
||||||
|
@ -3651,7 +3651,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
|
||||||
|
|
||||||
if (test_bit(ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT,
|
if (test_bit(ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT,
|
||||||
ar->fw_capabilities))
|
ar->fw_capabilities))
|
||||||
ar->wiphy->features = NL80211_FEATURE_INACTIVITY_TIMER;
|
ar->wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER;
|
||||||
|
|
||||||
ar->wiphy->probe_resp_offload =
|
ar->wiphy->probe_resp_offload =
|
||||||
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
|
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
|
||||||
|
|
|
@ -276,6 +276,11 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
|
||||||
offset_array[i],
|
offset_array[i],
|
||||||
REG_READ(ah, offset_array[i]));
|
REG_READ(ah, offset_array[i]));
|
||||||
|
|
||||||
|
if (AR_SREV_9565(ah) &&
|
||||||
|
(iCoff == 63 || qCoff == 63 ||
|
||||||
|
iCoff == -63 || qCoff == -63))
|
||||||
|
return;
|
||||||
|
|
||||||
REG_RMW_FIELD(ah, offset_array[i],
|
REG_RMW_FIELD(ah, offset_array[i],
|
||||||
AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
|
AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
|
||||||
iCoff);
|
iCoff);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "hw.h"
|
#include "hw.h"
|
||||||
#include "ar9003_phy.h"
|
#include "ar9003_phy.h"
|
||||||
#include "ar9003_eeprom.h"
|
#include "ar9003_eeprom.h"
|
||||||
|
#include "ar9003_mci.h"
|
||||||
|
|
||||||
#define COMP_HDR_LEN 4
|
#define COMP_HDR_LEN 4
|
||||||
#define COMP_CKSUM_LEN 2
|
#define COMP_CKSUM_LEN 2
|
||||||
|
@ -41,7 +42,6 @@
|
||||||
static int ar9003_hw_power_interpolate(int32_t x,
|
static int ar9003_hw_power_interpolate(int32_t x,
|
||||||
int32_t *px, int32_t *py, u_int16_t np);
|
int32_t *px, int32_t *py, u_int16_t np);
|
||||||
|
|
||||||
|
|
||||||
static const struct ar9300_eeprom ar9300_default = {
|
static const struct ar9300_eeprom ar9300_default = {
|
||||||
.eepromVersion = 2,
|
.eepromVersion = 2,
|
||||||
.templateVersion = 2,
|
.templateVersion = 2,
|
||||||
|
@ -2989,7 +2989,7 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
|
||||||
case EEP_PAPRD:
|
case EEP_PAPRD:
|
||||||
if (AR_SREV_9462(ah))
|
if (AR_SREV_9462(ah))
|
||||||
return false;
|
return false;
|
||||||
if (!ah->config.enable_paprd);
|
if (!ah->config.enable_paprd)
|
||||||
return false;
|
return false;
|
||||||
return !!(pBase->featureEnable & BIT(5));
|
return !!(pBase->featureEnable & BIT(5));
|
||||||
case EEP_CHAIN_MASK_REDUCE:
|
case EEP_CHAIN_MASK_REDUCE:
|
||||||
|
@ -3601,7 +3601,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz)
|
||||||
* 7:4 R/W SWITCH_TABLE_COM_SPDT_WLAN_IDLE
|
* 7:4 R/W SWITCH_TABLE_COM_SPDT_WLAN_IDLE
|
||||||
* SWITCH_TABLE_COM_SPDT_WLAN_IDLE
|
* SWITCH_TABLE_COM_SPDT_WLAN_IDLE
|
||||||
*/
|
*/
|
||||||
if (AR_SREV_9462_20_OR_LATER(ah)) {
|
if (AR_SREV_9462_20(ah) || AR_SREV_9565(ah)) {
|
||||||
value = ar9003_switch_com_spdt_get(ah, is2ghz);
|
value = ar9003_switch_com_spdt_get(ah, is2ghz);
|
||||||
REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL,
|
REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL,
|
||||||
AR_SWITCH_TABLE_COM_SPDT_ALL, value);
|
AR_SWITCH_TABLE_COM_SPDT_ALL, value);
|
||||||
|
@ -5037,16 +5037,28 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah,
|
||||||
case CTL_5GHT20:
|
case CTL_5GHT20:
|
||||||
case CTL_2GHT20:
|
case CTL_2GHT20:
|
||||||
for (i = ALL_TARGET_HT20_0_8_16;
|
for (i = ALL_TARGET_HT20_0_8_16;
|
||||||
i <= ALL_TARGET_HT20_23; i++)
|
i <= ALL_TARGET_HT20_23; i++) {
|
||||||
pPwrArray[i] = (u8)min((u16)pPwrArray[i],
|
pPwrArray[i] = (u8)min((u16)pPwrArray[i],
|
||||||
minCtlPower);
|
minCtlPower);
|
||||||
|
if (ath9k_hw_mci_is_enabled(ah))
|
||||||
|
pPwrArray[i] =
|
||||||
|
(u8)min((u16)pPwrArray[i],
|
||||||
|
ar9003_mci_get_max_txpower(ah,
|
||||||
|
pCtlMode[ctlMode]));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case CTL_5GHT40:
|
case CTL_5GHT40:
|
||||||
case CTL_2GHT40:
|
case CTL_2GHT40:
|
||||||
for (i = ALL_TARGET_HT40_0_8_16;
|
for (i = ALL_TARGET_HT40_0_8_16;
|
||||||
i <= ALL_TARGET_HT40_23; i++)
|
i <= ALL_TARGET_HT40_23; i++) {
|
||||||
pPwrArray[i] = (u8)min((u16)pPwrArray[i],
|
pPwrArray[i] = (u8)min((u16)pPwrArray[i],
|
||||||
minCtlPower);
|
minCtlPower);
|
||||||
|
if (ath9k_hw_mci_is_enabled(ah))
|
||||||
|
pPwrArray[i] =
|
||||||
|
(u8)min((u16)pPwrArray[i],
|
||||||
|
ar9003_mci_get_max_txpower(ah,
|
||||||
|
pCtlMode[ctlMode]));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -219,10 +219,10 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
|
||||||
|
|
||||||
/* Awake -> Sleep Setting */
|
/* Awake -> Sleep Setting */
|
||||||
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
||||||
ar9462_pciephy_pll_on_clkreq_disable_L1_2p0);
|
ar9462_pciephy_clkreq_disable_L1_2p0);
|
||||||
/* Sleep -> Awake Setting */
|
/* Sleep -> Awake Setting */
|
||||||
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
|
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
|
||||||
ar9462_pciephy_pll_on_clkreq_disable_L1_2p0);
|
ar9462_pciephy_clkreq_disable_L1_2p0);
|
||||||
|
|
||||||
/* Fast clock modal settings */
|
/* Fast clock modal settings */
|
||||||
INIT_INI_ARRAY(&ah->iniModesFastClock,
|
INIT_INI_ARRAY(&ah->iniModesFastClock,
|
||||||
|
@ -328,9 +328,9 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
|
||||||
ar9565_1p0_Modes_lowest_ob_db_tx_gain_table);
|
ar9565_1p0_Modes_lowest_ob_db_tx_gain_table);
|
||||||
|
|
||||||
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
||||||
ar9565_1p0_pciephy_pll_on_clkreq_disable_L1);
|
ar9565_1p0_pciephy_clkreq_disable_L1);
|
||||||
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
|
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
|
||||||
ar9565_1p0_pciephy_pll_on_clkreq_disable_L1);
|
ar9565_1p0_pciephy_clkreq_disable_L1);
|
||||||
|
|
||||||
INIT_INI_ARRAY(&ah->iniModesFastClock,
|
INIT_INI_ARRAY(&ah->iniModesFastClock,
|
||||||
ar9565_1p0_modes_fast_clock);
|
ar9565_1p0_modes_fast_clock);
|
||||||
|
|
|
@ -750,6 +750,9 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||||
|
|
||||||
mci_hw->bt_state = MCI_BT_AWAKE;
|
mci_hw->bt_state = MCI_BT_AWAKE;
|
||||||
|
|
||||||
|
REG_CLR_BIT(ah, AR_PHY_TIMING4,
|
||||||
|
1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT);
|
||||||
|
|
||||||
if (caldata) {
|
if (caldata) {
|
||||||
caldata->done_txiqcal_once = false;
|
caldata->done_txiqcal_once = false;
|
||||||
caldata->done_txclcal_once = false;
|
caldata->done_txclcal_once = false;
|
||||||
|
@ -759,6 +762,9 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
|
||||||
if (!ath9k_hw_init_cal(ah, chan))
|
if (!ath9k_hw_init_cal(ah, chan))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
|
REG_SET_BIT(ah, AR_PHY_TIMING4,
|
||||||
|
1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
ar9003_mci_enable_interrupt(ah);
|
ar9003_mci_enable_interrupt(ah);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -799,6 +805,9 @@ static void ar9003_mci_osla_setup(struct ath_hw *ah, bool enable)
|
||||||
REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2,
|
REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2,
|
||||||
AR_MCI_SCHD_TABLE_2_MEM_BASED, 1);
|
AR_MCI_SCHD_TABLE_2_MEM_BASED, 1);
|
||||||
|
|
||||||
|
if (AR_SREV_9565(ah))
|
||||||
|
REG_RMW_FIELD(ah, AR_MCI_MISC, AR_MCI_MISC_HW_FIX_EN, 1);
|
||||||
|
|
||||||
if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) {
|
if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) {
|
||||||
thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH);
|
thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH);
|
||||||
REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
|
REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
|
||||||
|
@ -818,7 +827,7 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
|
||||||
{
|
{
|
||||||
struct ath_common *common = ath9k_hw_common(ah);
|
struct ath_common *common = ath9k_hw_common(ah);
|
||||||
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
||||||
u32 regval;
|
u32 regval, i;
|
||||||
|
|
||||||
ath_dbg(common, MCI, "MCI Reset (full_sleep = %d, is_2g = %d)\n",
|
ath_dbg(common, MCI, "MCI Reset (full_sleep = %d, is_2g = %d)\n",
|
||||||
is_full_sleep, is_2g);
|
is_full_sleep, is_2g);
|
||||||
|
@ -847,11 +856,18 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
|
||||||
SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
|
SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) |
|
||||||
SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
|
SM(1, AR_BTCOEX_CTRL_PA_SHARED) |
|
||||||
SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
|
SM(1, AR_BTCOEX_CTRL_LNA_SHARED) |
|
||||||
SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
|
|
||||||
SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) |
|
|
||||||
SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
|
SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) |
|
||||||
SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
|
SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) |
|
||||||
SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
|
SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN);
|
||||||
|
if (AR_SREV_9565(ah)) {
|
||||||
|
regval |= SM(1, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
|
||||||
|
SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK);
|
||||||
|
REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
|
||||||
|
AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x1);
|
||||||
|
} else {
|
||||||
|
regval |= SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) |
|
||||||
|
SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
|
REG_WRITE(ah, AR_BTCOEX_CTRL, regval);
|
||||||
|
|
||||||
|
@ -865,9 +881,24 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
|
||||||
REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3,
|
REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3,
|
||||||
AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20);
|
AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20);
|
||||||
|
|
||||||
REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 1);
|
REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 0);
|
||||||
REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
|
REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0);
|
||||||
|
|
||||||
|
/* Set the time out to 3.125ms (5 BT slots) */
|
||||||
|
REG_RMW_FIELD(ah, AR_BTCOEX_WL_LNA, AR_BTCOEX_WL_LNA_TIMEOUT, 0x3D090);
|
||||||
|
|
||||||
|
/* concurrent tx priority */
|
||||||
|
if (mci->config & ATH_MCI_CONFIG_CONCUR_TX) {
|
||||||
|
REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
|
||||||
|
AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE, 0);
|
||||||
|
REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2,
|
||||||
|
AR_BTCOEX_CTRL2_TXPWR_THRESH, 0x7f);
|
||||||
|
REG_RMW_FIELD(ah, AR_BTCOEX_CTRL,
|
||||||
|
AR_BTCOEX_CTRL_REDUCE_TXPWR, 0);
|
||||||
|
for (i = 0; i < 8; i++)
|
||||||
|
REG_WRITE(ah, AR_BTCOEX_MAX_TXPWR(i), 0x7f7f7f7f);
|
||||||
|
}
|
||||||
|
|
||||||
regval = MS(mci->config, ATH_MCI_CONFIG_CLK_DIV);
|
regval = MS(mci->config, ATH_MCI_CONFIG_CLK_DIV);
|
||||||
REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, regval);
|
REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, regval);
|
||||||
REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN);
|
REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN);
|
||||||
|
@ -910,6 +941,9 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
|
||||||
mci->ready = true;
|
mci->ready = true;
|
||||||
ar9003_mci_prep_interface(ah);
|
ar9003_mci_prep_interface(ah);
|
||||||
|
|
||||||
|
if (AR_SREV_9565(ah))
|
||||||
|
REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL,
|
||||||
|
AR_MCI_DBG_CNT_CTRL_ENABLE, 0);
|
||||||
if (en_int)
|
if (en_int)
|
||||||
ar9003_mci_enable_interrupt(ah);
|
ar9003_mci_enable_interrupt(ah);
|
||||||
|
|
||||||
|
@ -1028,6 +1062,8 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force)
|
||||||
|
|
||||||
if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
|
if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
|
||||||
ar9003_mci_osla_setup(ah, true);
|
ar9003_mci_osla_setup(ah, true);
|
||||||
|
|
||||||
|
if (AR_SREV_9462(ah))
|
||||||
REG_WRITE(ah, AR_SELFGEN_MASK, 0x02);
|
REG_WRITE(ah, AR_SELFGEN_MASK, 0x02);
|
||||||
} else {
|
} else {
|
||||||
ar9003_mci_send_lna_take(ah, true);
|
ar9003_mci_send_lna_take(ah, true);
|
||||||
|
@ -1170,7 +1206,7 @@ EXPORT_SYMBOL(ar9003_mci_cleanup);
|
||||||
u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type)
|
u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type)
|
||||||
{
|
{
|
||||||
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
||||||
u32 value = 0;
|
u32 value = 0, tsf;
|
||||||
u8 query_type;
|
u8 query_type;
|
||||||
|
|
||||||
switch (state_type) {
|
switch (state_type) {
|
||||||
|
@ -1228,6 +1264,14 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type)
|
||||||
ar9003_mci_send_coex_bt_status_query(ah, true, query_type);
|
ar9003_mci_send_coex_bt_status_query(ah, true, query_type);
|
||||||
break;
|
break;
|
||||||
case MCI_STATE_RECOVER_RX:
|
case MCI_STATE_RECOVER_RX:
|
||||||
|
tsf = ath9k_hw_gettsf32(ah);
|
||||||
|
if ((tsf - mci->last_recovery) <= MCI_RECOVERY_DUR_TSF) {
|
||||||
|
ath_dbg(ath9k_hw_common(ah), MCI,
|
||||||
|
"(MCI) ignore Rx recovery\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ath_dbg(ath9k_hw_common(ah), MCI, "(MCI) RECOVER RX\n");
|
||||||
|
mci->last_recovery = tsf;
|
||||||
ar9003_mci_prep_interface(ah);
|
ar9003_mci_prep_interface(ah);
|
||||||
mci->query_bt = true;
|
mci->query_bt = true;
|
||||||
mci->need_flush_btinfo = true;
|
mci->need_flush_btinfo = true;
|
||||||
|
@ -1426,3 +1470,17 @@ void ar9003_mci_send_wlan_channels(struct ath_hw *ah)
|
||||||
ar9003_mci_send_coex_wlan_channels(ah, true);
|
ar9003_mci_send_coex_wlan_channels(ah, true);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ar9003_mci_send_wlan_channels);
|
EXPORT_SYMBOL(ar9003_mci_send_wlan_channels);
|
||||||
|
|
||||||
|
u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode)
|
||||||
|
{
|
||||||
|
if (!ah->btcoex_hw.mci.concur_tx)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (ctlmode == CTL_2GHT20)
|
||||||
|
return ATH_BTCOEX_HT20_MAX_TXPOWER;
|
||||||
|
else if (ctlmode == CTL_2GHT40)
|
||||||
|
return ATH_BTCOEX_HT40_MAX_TXPOWER;
|
||||||
|
|
||||||
|
out:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#define AR9003_MCI_H
|
#define AR9003_MCI_H
|
||||||
|
|
||||||
#define MCI_FLAG_DISABLE_TIMESTAMP 0x00000001 /* Disable time stamp */
|
#define MCI_FLAG_DISABLE_TIMESTAMP 0x00000001 /* Disable time stamp */
|
||||||
|
#define MCI_RECOVERY_DUR_TSF (100 * 1000) /* 100 ms */
|
||||||
|
|
||||||
/* Default remote BT device MCI COEX version */
|
/* Default remote BT device MCI COEX version */
|
||||||
#define MCI_GPM_COEX_MAJOR_VERSION_DEFAULT 3
|
#define MCI_GPM_COEX_MAJOR_VERSION_DEFAULT 3
|
||||||
|
@ -125,6 +126,7 @@ enum ath_mci_gpm_coex_profile_type {
|
||||||
MCI_GPM_COEX_PROFILE_HID,
|
MCI_GPM_COEX_PROFILE_HID,
|
||||||
MCI_GPM_COEX_PROFILE_BNEP,
|
MCI_GPM_COEX_PROFILE_BNEP,
|
||||||
MCI_GPM_COEX_PROFILE_VOICE,
|
MCI_GPM_COEX_PROFILE_VOICE,
|
||||||
|
MCI_GPM_COEX_PROFILE_A2DPVO,
|
||||||
MCI_GPM_COEX_PROFILE_MAX
|
MCI_GPM_COEX_PROFILE_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -196,7 +198,6 @@ enum mci_state_type {
|
||||||
MCI_STATE_SEND_WLAN_COEX_VERSION,
|
MCI_STATE_SEND_WLAN_COEX_VERSION,
|
||||||
MCI_STATE_SEND_VERSION_QUERY,
|
MCI_STATE_SEND_VERSION_QUERY,
|
||||||
MCI_STATE_SEND_STATUS_QUERY,
|
MCI_STATE_SEND_STATUS_QUERY,
|
||||||
MCI_STATE_SET_CONCUR_TX_PRI,
|
|
||||||
MCI_STATE_RECOVER_RX,
|
MCI_STATE_RECOVER_RX,
|
||||||
MCI_STATE_NEED_FTP_STOMP,
|
MCI_STATE_NEED_FTP_STOMP,
|
||||||
MCI_STATE_DEBUG,
|
MCI_STATE_DEBUG,
|
||||||
|
@ -278,6 +279,7 @@ void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked);
|
||||||
void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah);
|
void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah);
|
||||||
void ar9003_mci_set_power_awake(struct ath_hw *ah);
|
void ar9003_mci_set_power_awake(struct ath_hw *ah);
|
||||||
void ar9003_mci_check_gpm_offset(struct ath_hw *ah);
|
void ar9003_mci_check_gpm_offset(struct ath_hw *ah);
|
||||||
|
u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
@ -324,6 +326,10 @@ static inline void ar9003_mci_set_power_awake(struct ath_hw *ah)
|
||||||
static inline void ar9003_mci_check_gpm_offset(struct ath_hw *ah)
|
static inline void ar9003_mci_check_gpm_offset(struct ath_hw *ah)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
static inline u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
|
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#define AR_PHY_SPUR_REG (AR_CHAN_BASE + 0x1c)
|
#define AR_PHY_SPUR_REG (AR_CHAN_BASE + 0x1c)
|
||||||
#define AR_PHY_RX_IQCAL_CORR_B0 (AR_CHAN_BASE + 0xdc)
|
#define AR_PHY_RX_IQCAL_CORR_B0 (AR_CHAN_BASE + 0xdc)
|
||||||
#define AR_PHY_TX_IQCAL_CONTROL_3 (AR_CHAN_BASE + 0xb0)
|
#define AR_PHY_TX_IQCAL_CONTROL_3 (AR_CHAN_BASE + 0xb0)
|
||||||
|
#define AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT 16
|
||||||
|
|
||||||
#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000
|
#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000
|
||||||
#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20
|
#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20
|
||||||
|
|
|
@ -768,9 +768,9 @@ static const u32 ar9565_1p0_Modes_lowest_ob_db_tx_gain_table[][5] = {
|
||||||
{0x00016054, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
{0x00016054, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u32 ar9565_1p0_pciephy_pll_on_clkreq_disable_L1[][2] = {
|
static const u32 ar9565_1p0_pciephy_clkreq_disable_L1[][2] = {
|
||||||
/* Addr allmodes */
|
/* Addr allmodes */
|
||||||
{0x00018c00, 0x18212ede},
|
{0x00018c00, 0x18213ede},
|
||||||
{0x00018c04, 0x000801d8},
|
{0x00018c04, 0x000801d8},
|
||||||
{0x00018c08, 0x0003780c},
|
{0x00018c08, 0x0003780c},
|
||||||
};
|
};
|
||||||
|
|
|
@ -437,6 +437,7 @@ void ath9k_set_beacon(struct ath_softc *sc);
|
||||||
#define ATH_LONG_CALINTERVAL_INT 1000 /* 1000 ms */
|
#define ATH_LONG_CALINTERVAL_INT 1000 /* 1000 ms */
|
||||||
#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */
|
#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */
|
||||||
#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */
|
#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */
|
||||||
|
#define ATH_ANI_MAX_SKIP_COUNT 10
|
||||||
|
|
||||||
#define ATH_PAPRD_TIMEOUT 100 /* msecs */
|
#define ATH_PAPRD_TIMEOUT 100 /* msecs */
|
||||||
#define ATH_PLL_WORK_INTERVAL 100
|
#define ATH_PLL_WORK_INTERVAL 100
|
||||||
|
@ -478,6 +479,7 @@ struct ath_btcoex {
|
||||||
u32 btscan_no_stomp; /* in usec */
|
u32 btscan_no_stomp; /* in usec */
|
||||||
u32 duty_cycle;
|
u32 duty_cycle;
|
||||||
u32 bt_wait_time;
|
u32 bt_wait_time;
|
||||||
|
int rssi_count;
|
||||||
struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
|
struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
|
||||||
struct ath_mci_profile mci;
|
struct ath_mci_profile mci;
|
||||||
};
|
};
|
||||||
|
@ -492,6 +494,7 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc);
|
||||||
void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status);
|
void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status);
|
||||||
u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen);
|
u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen);
|
||||||
void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc);
|
void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc);
|
||||||
|
int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 len, u32 size);
|
||||||
#else
|
#else
|
||||||
static inline int ath9k_init_btcoex(struct ath_softc *sc)
|
static inline int ath9k_init_btcoex(struct ath_softc *sc)
|
||||||
{
|
{
|
||||||
|
@ -518,6 +521,11 @@ static inline u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc,
|
||||||
static inline void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
|
static inline void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
static inline int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf,
|
||||||
|
u32 len, u32 size)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
|
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
|
||||||
|
|
||||||
struct ath9k_wow_pattern {
|
struct ath9k_wow_pattern {
|
||||||
|
@ -642,6 +650,7 @@ enum sc_op_flags {
|
||||||
#define PS_WAIT_FOR_PSPOLL_DATA BIT(2)
|
#define PS_WAIT_FOR_PSPOLL_DATA BIT(2)
|
||||||
#define PS_WAIT_FOR_TX_ACK BIT(3)
|
#define PS_WAIT_FOR_TX_ACK BIT(3)
|
||||||
#define PS_BEACON_SYNC BIT(4)
|
#define PS_BEACON_SYNC BIT(4)
|
||||||
|
#define PS_WAIT_FOR_ANI BIT(5)
|
||||||
|
|
||||||
struct ath_rate_table;
|
struct ath_rate_table;
|
||||||
|
|
||||||
|
|
|
@ -195,7 +195,7 @@ void ath9k_hw_btcoex_init_mci(struct ath_hw *ah)
|
||||||
ah->btcoex_hw.mci.need_flush_btinfo = false;
|
ah->btcoex_hw.mci.need_flush_btinfo = false;
|
||||||
ah->btcoex_hw.mci.wlan_cal_seq = 0;
|
ah->btcoex_hw.mci.wlan_cal_seq = 0;
|
||||||
ah->btcoex_hw.mci.wlan_cal_done = 0;
|
ah->btcoex_hw.mci.wlan_cal_done = 0;
|
||||||
ah->btcoex_hw.mci.config = 0x2201;
|
ah->btcoex_hw.mci.config = (AR_SREV_9462(ah)) ? 0x2201 : 0xa4c1;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ath9k_hw_btcoex_init_mci);
|
EXPORT_SYMBOL(ath9k_hw_btcoex_init_mci);
|
||||||
|
|
||||||
|
@ -218,27 +218,45 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
|
||||||
enum ath_stomp_type stomp_type)
|
enum ath_stomp_type stomp_type)
|
||||||
{
|
{
|
||||||
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
|
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
|
||||||
|
struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
|
||||||
if (AR_SREV_9300_20_OR_LATER(ah)) {
|
u8 txprio_shift[] = { 24, 16, 16, 0 }; /* tx priority weight */
|
||||||
|
bool concur_tx = (mci_hw->concur_tx && btcoex_hw->tx_prio[stomp_type]);
|
||||||
const u32 *weight = ar9003_wlan_weights[stomp_type];
|
const u32 *weight = ar9003_wlan_weights[stomp_type];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (!AR_SREV_9300_20_OR_LATER(ah)) {
|
||||||
|
btcoex_hw->bt_coex_weights =
|
||||||
|
SM(bt_weight, AR_BTCOEX_BT_WGHT) |
|
||||||
|
SM(wlan_weight, AR_BTCOEX_WL_WGHT);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
|
if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
|
||||||
if ((stomp_type == ATH_BTCOEX_STOMP_LOW) &&
|
enum ath_stomp_type stype =
|
||||||
btcoex_hw->mci.stomp_ftp)
|
((stomp_type == ATH_BTCOEX_STOMP_LOW) &&
|
||||||
stomp_type = ATH_BTCOEX_STOMP_LOW_FTP;
|
btcoex_hw->mci.stomp_ftp) ?
|
||||||
weight = mci_wlan_weights[stomp_type];
|
ATH_BTCOEX_STOMP_LOW_FTP : stomp_type;
|
||||||
|
weight = mci_wlan_weights[stype];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) {
|
for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) {
|
||||||
btcoex_hw->bt_weight[i] = AR9300_BT_WGHT;
|
btcoex_hw->bt_weight[i] = AR9300_BT_WGHT;
|
||||||
btcoex_hw->wlan_weight[i] = weight[i];
|
btcoex_hw->wlan_weight[i] = weight[i];
|
||||||
|
if (concur_tx && i) {
|
||||||
|
btcoex_hw->wlan_weight[i] &=
|
||||||
|
~(0xff << txprio_shift[i-1]);
|
||||||
|
btcoex_hw->wlan_weight[i] |=
|
||||||
|
(btcoex_hw->tx_prio[stomp_type] <<
|
||||||
|
txprio_shift[i-1]);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
btcoex_hw->bt_coex_weights =
|
|
||||||
SM(bt_weight, AR_BTCOEX_BT_WGHT) |
|
|
||||||
SM(wlan_weight, AR_BTCOEX_WL_WGHT);
|
|
||||||
}
|
}
|
||||||
|
/* Last WLAN weight has to be adjusted wrt tx priority */
|
||||||
|
if (concur_tx) {
|
||||||
|
btcoex_hw->wlan_weight[i-1] &= ~(0xff << txprio_shift[i-1]);
|
||||||
|
btcoex_hw->wlan_weight[i-1] |= (btcoex_hw->tx_prio[stomp_type]
|
||||||
|
<< txprio_shift[i-1]);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight);
|
EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight);
|
||||||
|
|
||||||
|
@ -385,3 +403,13 @@ void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ath9k_hw_btcoex_bt_stomp);
|
EXPORT_SYMBOL(ath9k_hw_btcoex_bt_stomp);
|
||||||
|
|
||||||
|
void ath9k_hw_btcoex_set_concur_txprio(struct ath_hw *ah, u8 *stomp_txprio)
|
||||||
|
{
|
||||||
|
struct ath_btcoex_hw *btcoex = &ah->btcoex_hw;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++)
|
||||||
|
btcoex->tx_prio[i] = stomp_txprio[i];
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ath9k_hw_btcoex_set_concur_txprio);
|
||||||
|
|
|
@ -39,6 +39,9 @@
|
||||||
#define ATH_BTCOEX_RX_WAIT_TIME 100
|
#define ATH_BTCOEX_RX_WAIT_TIME 100
|
||||||
#define ATH_BTCOEX_STOMP_FTP_THRESH 5
|
#define ATH_BTCOEX_STOMP_FTP_THRESH 5
|
||||||
|
|
||||||
|
#define ATH_BTCOEX_HT20_MAX_TXPOWER 0x14
|
||||||
|
#define ATH_BTCOEX_HT40_MAX_TXPOWER 0x10
|
||||||
|
|
||||||
#define AR9300_NUM_BT_WEIGHTS 4
|
#define AR9300_NUM_BT_WEIGHTS 4
|
||||||
#define AR9300_NUM_WLAN_WEIGHTS 4
|
#define AR9300_NUM_WLAN_WEIGHTS 4
|
||||||
/* Defines the BT AR_BT_COEX_WGHT used */
|
/* Defines the BT AR_BT_COEX_WGHT used */
|
||||||
|
@ -84,6 +87,8 @@ struct ath9k_hw_mci {
|
||||||
u8 bt_ver_minor;
|
u8 bt_ver_minor;
|
||||||
u8 bt_state;
|
u8 bt_state;
|
||||||
u8 stomp_ftp;
|
u8 stomp_ftp;
|
||||||
|
bool concur_tx;
|
||||||
|
u32 last_recovery;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ath_btcoex_hw {
|
struct ath_btcoex_hw {
|
||||||
|
@ -98,6 +103,7 @@ struct ath_btcoex_hw {
|
||||||
u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */
|
u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */
|
||||||
u32 bt_weight[AR9300_NUM_BT_WEIGHTS];
|
u32 bt_weight[AR9300_NUM_BT_WEIGHTS];
|
||||||
u32 wlan_weight[AR9300_NUM_WLAN_WEIGHTS];
|
u32 wlan_weight[AR9300_NUM_WLAN_WEIGHTS];
|
||||||
|
u8 tx_prio[ATH_BTCOEX_STOMP_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah);
|
void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah);
|
||||||
|
@ -112,5 +118,6 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
|
||||||
void ath9k_hw_btcoex_disable(struct ath_hw *ah);
|
void ath9k_hw_btcoex_disable(struct ath_hw *ah);
|
||||||
void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
|
void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
|
||||||
enum ath_stomp_type stomp_type);
|
enum ath_stomp_type stomp_type);
|
||||||
|
void ath9k_hw_btcoex_set_concur_txprio(struct ath_hw *ah, u8 *stomp_txprio);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -410,6 +410,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
|
||||||
|
|
||||||
ah->caldata->channel = chan->channel;
|
ah->caldata->channel = chan->channel;
|
||||||
ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT;
|
ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT;
|
||||||
|
ah->caldata->chanmode = chan->chanmode;
|
||||||
h = ah->caldata->nfCalHist;
|
h = ah->caldata->nfCalHist;
|
||||||
default_nf = ath9k_hw_get_default_nf(ah, chan);
|
default_nf = ath9k_hw_get_default_nf(ah, chan);
|
||||||
for (i = 0; i < NUM_NF_READINGS; i++) {
|
for (i = 0; i < NUM_NF_READINGS; i++) {
|
||||||
|
|
|
@ -1586,6 +1586,35 @@ static const struct file_operations fops_samps = {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
|
||||||
|
static ssize_t read_file_btcoex(struct file *file, char __user *user_buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
struct ath_softc *sc = file->private_data;
|
||||||
|
u32 len = 0, size = 1500;
|
||||||
|
char *buf;
|
||||||
|
size_t retval;
|
||||||
|
|
||||||
|
buf = kzalloc(size, GFP_KERNEL);
|
||||||
|
if (buf == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
len = ath9k_dump_btcoex(sc, buf, len, size);
|
||||||
|
|
||||||
|
retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
|
||||||
|
kfree(buf);
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations fops_btcoex = {
|
||||||
|
.read = read_file_btcoex,
|
||||||
|
.open = simple_open,
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.llseek = default_llseek,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
int ath9k_init_debug(struct ath_hw *ah)
|
int ath9k_init_debug(struct ath_hw *ah)
|
||||||
{
|
{
|
||||||
struct ath_common *common = ath9k_hw_common(ah);
|
struct ath_common *common = ath9k_hw_common(ah);
|
||||||
|
@ -1658,6 +1687,9 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||||
sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
|
sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
|
||||||
debugfs_create_file("diversity", S_IRUSR | S_IWUSR,
|
debugfs_create_file("diversity", S_IRUSR | S_IWUSR,
|
||||||
sc->debug.debugfs_phy, sc, &fops_ant_diversity);
|
sc->debug.debugfs_phy, sc, &fops_ant_diversity);
|
||||||
|
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
|
||||||
|
debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc,
|
||||||
|
&fops_btcoex);
|
||||||
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -187,34 +187,12 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static void ath_mci_ftp_adjust(struct ath_softc *sc)
|
||||||
* This is the master bt coex timer which runs for every
|
|
||||||
* 45ms, bt traffic will be given priority during 55% of this
|
|
||||||
* period while wlan gets remaining 45%
|
|
||||||
*/
|
|
||||||
static void ath_btcoex_period_timer(unsigned long data)
|
|
||||||
{
|
{
|
||||||
struct ath_softc *sc = (struct ath_softc *) data;
|
|
||||||
struct ath_hw *ah = sc->sc_ah;
|
|
||||||
struct ath_btcoex *btcoex = &sc->btcoex;
|
struct ath_btcoex *btcoex = &sc->btcoex;
|
||||||
struct ath_mci_profile *mci = &btcoex->mci;
|
struct ath_mci_profile *mci = &btcoex->mci;
|
||||||
u32 timer_period;
|
struct ath_hw *ah = sc->sc_ah;
|
||||||
bool is_btscan;
|
|
||||||
unsigned long flags;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&sc->sc_pm_lock, flags);
|
|
||||||
if (sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP) {
|
|
||||||
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
|
|
||||||
goto skip_hw_wakeup;
|
|
||||||
}
|
|
||||||
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
|
|
||||||
|
|
||||||
ath9k_ps_wakeup(sc);
|
|
||||||
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
|
|
||||||
ath_detect_bt_priority(sc);
|
|
||||||
is_btscan = test_bit(BT_OP_SCAN, &btcoex->op_flags);
|
|
||||||
|
|
||||||
btcoex->bt_wait_time += btcoex->btcoex_period;
|
|
||||||
if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) {
|
if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) {
|
||||||
if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) &&
|
if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) &&
|
||||||
(mci->num_pan || mci->num_other_acl))
|
(mci->num_pan || mci->num_other_acl))
|
||||||
|
@ -225,13 +203,55 @@ static void ath_btcoex_period_timer(unsigned long data)
|
||||||
btcoex->bt_wait_time = 0;
|
btcoex->bt_wait_time = 0;
|
||||||
sc->rx.num_pkts = 0;
|
sc->rx.num_pkts = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the master bt coex timer which runs for every
|
||||||
|
* 45ms, bt traffic will be given priority during 55% of this
|
||||||
|
* period while wlan gets remaining 45%
|
||||||
|
*/
|
||||||
|
static void ath_btcoex_period_timer(unsigned long data)
|
||||||
|
{
|
||||||
|
struct ath_softc *sc = (struct ath_softc *) data;
|
||||||
|
struct ath_hw *ah = sc->sc_ah;
|
||||||
|
struct ath_btcoex *btcoex = &sc->btcoex;
|
||||||
|
enum ath_stomp_type stomp_type;
|
||||||
|
u32 timer_period;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
|
spin_lock_irqsave(&sc->sc_pm_lock, flags);
|
||||||
|
if (sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP) {
|
||||||
|
btcoex->bt_wait_time += btcoex->btcoex_period;
|
||||||
|
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
|
||||||
|
goto skip_hw_wakeup;
|
||||||
|
}
|
||||||
|
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
|
||||||
|
|
||||||
|
ath9k_mci_update_rssi(sc);
|
||||||
|
|
||||||
|
ath9k_ps_wakeup(sc);
|
||||||
|
|
||||||
|
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
|
||||||
|
ath_detect_bt_priority(sc);
|
||||||
|
|
||||||
|
if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI)
|
||||||
|
ath_mci_ftp_adjust(sc);
|
||||||
|
|
||||||
spin_lock_bh(&btcoex->btcoex_lock);
|
spin_lock_bh(&btcoex->btcoex_lock);
|
||||||
|
|
||||||
ath9k_hw_btcoex_bt_stomp(ah, is_btscan ? ATH_BTCOEX_STOMP_ALL :
|
stomp_type = btcoex->bt_stomp_type;
|
||||||
btcoex->bt_stomp_type);
|
timer_period = btcoex->btcoex_no_stomp;
|
||||||
|
|
||||||
|
if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) {
|
||||||
|
if (test_bit(BT_OP_SCAN, &btcoex->op_flags)) {
|
||||||
|
stomp_type = ATH_BTCOEX_STOMP_ALL;
|
||||||
|
timer_period = btcoex->btscan_no_stomp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ath9k_hw_btcoex_bt_stomp(ah, stomp_type);
|
||||||
ath9k_hw_btcoex_enable(ah);
|
ath9k_hw_btcoex_enable(ah);
|
||||||
|
|
||||||
spin_unlock_bh(&btcoex->btcoex_lock);
|
spin_unlock_bh(&btcoex->btcoex_lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -243,17 +263,16 @@ static void ath_btcoex_period_timer(unsigned long data)
|
||||||
if (btcoex->hw_timer_enabled)
|
if (btcoex->hw_timer_enabled)
|
||||||
ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
|
ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
|
||||||
|
|
||||||
timer_period = is_btscan ? btcoex->btscan_no_stomp :
|
|
||||||
btcoex->btcoex_no_stomp;
|
|
||||||
ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period,
|
ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period,
|
||||||
timer_period * 10);
|
timer_period * 10);
|
||||||
btcoex->hw_timer_enabled = true;
|
btcoex->hw_timer_enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ath9k_ps_restore(sc);
|
ath9k_ps_restore(sc);
|
||||||
|
|
||||||
skip_hw_wakeup:
|
skip_hw_wakeup:
|
||||||
timer_period = btcoex->btcoex_period;
|
mod_timer(&btcoex->period_timer,
|
||||||
mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period));
|
jiffies + msecs_to_jiffies(btcoex->btcoex_period));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -273,7 +292,8 @@ static void ath_btcoex_no_stomp_timer(void *arg)
|
||||||
spin_lock_bh(&btcoex->btcoex_lock);
|
spin_lock_bh(&btcoex->btcoex_lock);
|
||||||
|
|
||||||
if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW ||
|
if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW ||
|
||||||
test_bit(BT_OP_SCAN, &btcoex->op_flags))
|
(!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI) &&
|
||||||
|
test_bit(BT_OP_SCAN, &btcoex->op_flags)))
|
||||||
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
|
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
|
||||||
else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
|
else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
|
||||||
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
|
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
|
||||||
|
@ -474,4 +494,52 @@ int ath9k_init_btcoex(struct ath_softc *sc)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 len, u32 size)
|
||||||
|
{
|
||||||
|
#define ATH_DUMP_BTCOEX(_s, _val) \
|
||||||
|
do { \
|
||||||
|
len += snprintf(buf + len, size - len, \
|
||||||
|
"%20s : %10d\n", _s, (_val)); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
struct ath_btcoex *btcoex = &sc->btcoex;
|
||||||
|
struct ath_mci_profile *mci = &btcoex->mci;
|
||||||
|
struct ath_hw *ah = sc->sc_ah;
|
||||||
|
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ATH_DUMP_BTCOEX("Total BT profiles", NUM_PROF(mci));
|
||||||
|
ATH_DUMP_BTCOEX("Number of MGMT", mci->num_mgmt);
|
||||||
|
ATH_DUMP_BTCOEX("Number of SCO", mci->num_sco);
|
||||||
|
ATH_DUMP_BTCOEX("Number of A2DP", mci->num_a2dp);
|
||||||
|
ATH_DUMP_BTCOEX("Number of HID", mci->num_hid);
|
||||||
|
ATH_DUMP_BTCOEX("Number of PAN", mci->num_pan);
|
||||||
|
ATH_DUMP_BTCOEX("Number of ACL", mci->num_other_acl);
|
||||||
|
ATH_DUMP_BTCOEX("Number of BDR", mci->num_bdr);
|
||||||
|
ATH_DUMP_BTCOEX("Aggr. Limit", mci->aggr_limit);
|
||||||
|
ATH_DUMP_BTCOEX("Stomp Type", btcoex->bt_stomp_type);
|
||||||
|
ATH_DUMP_BTCOEX("BTCoex Period (msec)", btcoex->btcoex_period);
|
||||||
|
ATH_DUMP_BTCOEX("Duty Cycle", btcoex->duty_cycle);
|
||||||
|
ATH_DUMP_BTCOEX("BT Wait time", btcoex->bt_wait_time);
|
||||||
|
ATH_DUMP_BTCOEX("Concurrent Tx", btcoex_hw->mci.concur_tx);
|
||||||
|
ATH_DUMP_BTCOEX("Concur RSSI count", btcoex->rssi_count);
|
||||||
|
len += snprintf(buf + len, size - len, "BT Weights: ");
|
||||||
|
for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
|
||||||
|
len += snprintf(buf + len, size - len, "%08x ",
|
||||||
|
btcoex_hw->bt_weight[i]);
|
||||||
|
len += snprintf(buf + len, size - len, "\n");
|
||||||
|
len += snprintf(buf + len, size - len, "WLAN Weights: ");
|
||||||
|
for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
|
||||||
|
len += snprintf(buf + len, size - len, "%08x ",
|
||||||
|
btcoex_hw->wlan_weight[i]);
|
||||||
|
len += snprintf(buf + len, size - len, "\n");
|
||||||
|
len += snprintf(buf + len, size - len, "Tx Priorities: ");
|
||||||
|
for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++)
|
||||||
|
len += snprintf(buf + len, size - len, "%08x ",
|
||||||
|
btcoex_hw->tx_prio[i]);
|
||||||
|
len += snprintf(buf + len, size - len, "\n");
|
||||||
|
#undef ATH_DUMP_BTCOEX
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
|
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
|
||||||
|
|
|
@ -694,6 +694,20 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct ieee80211_iface_limit if_limits[] = {
|
||||||
|
{ .max = 2, .types = BIT(NL80211_IFTYPE_STATION) |
|
||||||
|
BIT(NL80211_IFTYPE_P2P_CLIENT) },
|
||||||
|
{ .max = 2, .types = BIT(NL80211_IFTYPE_AP) |
|
||||||
|
BIT(NL80211_IFTYPE_P2P_GO) },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct ieee80211_iface_combination if_comb = {
|
||||||
|
.limits = if_limits,
|
||||||
|
.n_limits = ARRAY_SIZE(if_limits),
|
||||||
|
.max_interfaces = 2,
|
||||||
|
.num_different_channels = 1,
|
||||||
|
};
|
||||||
|
|
||||||
static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
|
static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
|
||||||
struct ieee80211_hw *hw)
|
struct ieee80211_hw *hw)
|
||||||
{
|
{
|
||||||
|
@ -716,6 +730,9 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv,
|
||||||
BIT(NL80211_IFTYPE_P2P_GO) |
|
BIT(NL80211_IFTYPE_P2P_GO) |
|
||||||
BIT(NL80211_IFTYPE_P2P_CLIENT);
|
BIT(NL80211_IFTYPE_P2P_CLIENT);
|
||||||
|
|
||||||
|
hw->wiphy->iface_combinations = &if_comb;
|
||||||
|
hw->wiphy->n_iface_combinations = 1;
|
||||||
|
|
||||||
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
|
||||||
|
|
||||||
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN |
|
hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN |
|
||||||
|
|
|
@ -1036,26 +1036,6 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
|
||||||
|
|
||||||
mutex_lock(&priv->mutex);
|
mutex_lock(&priv->mutex);
|
||||||
|
|
||||||
if (priv->nvifs >= ATH9K_HTC_MAX_VIF) {
|
|
||||||
mutex_unlock(&priv->mutex);
|
|
||||||
return -ENOBUFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->num_ibss_vif ||
|
|
||||||
(priv->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
|
|
||||||
ath_err(common, "IBSS coexistence with other modes is not allowed\n");
|
|
||||||
mutex_unlock(&priv->mutex);
|
|
||||||
return -ENOBUFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((vif->type == NL80211_IFTYPE_AP) ||
|
|
||||||
(vif->type == NL80211_IFTYPE_ADHOC)) &&
|
|
||||||
((priv->num_ap_vif + priv->num_ibss_vif) >= ATH9K_HTC_MAX_BCN_VIF)) {
|
|
||||||
ath_err(common, "Max. number of beaconing interfaces reached\n");
|
|
||||||
mutex_unlock(&priv->mutex);
|
|
||||||
return -ENOBUFS;
|
|
||||||
}
|
|
||||||
|
|
||||||
ath9k_htc_ps_wakeup(priv);
|
ath9k_htc_ps_wakeup(priv);
|
||||||
memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
|
memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
|
||||||
memcpy(&hvif.myaddr, vif->addr, ETH_ALEN);
|
memcpy(&hvif.myaddr, vif->addr, ETH_ALEN);
|
||||||
|
|
|
@ -2153,9 +2153,6 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah)
|
||||||
AR_RTC_FORCE_WAKE_EN);
|
AR_RTC_FORCE_WAKE_EN);
|
||||||
udelay(50);
|
udelay(50);
|
||||||
|
|
||||||
if (ath9k_hw_mci_is_enabled(ah))
|
|
||||||
ar9003_mci_set_power_awake(ah);
|
|
||||||
|
|
||||||
for (i = POWER_UP_TIME / 50; i > 0; i--) {
|
for (i = POWER_UP_TIME / 50; i > 0; i--) {
|
||||||
val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
|
val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
|
||||||
if (val == AR_RTC_STATUS_ON)
|
if (val == AR_RTC_STATUS_ON)
|
||||||
|
@ -2171,6 +2168,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ath9k_hw_mci_is_enabled(ah))
|
||||||
|
ar9003_mci_set_power_awake(ah);
|
||||||
|
|
||||||
REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
|
REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -401,6 +401,7 @@ enum ath9k_int {
|
||||||
struct ath9k_hw_cal_data {
|
struct ath9k_hw_cal_data {
|
||||||
u16 channel;
|
u16 channel;
|
||||||
u32 channelFlags;
|
u32 channelFlags;
|
||||||
|
u32 chanmode;
|
||||||
int32_t CalValid;
|
int32_t CalValid;
|
||||||
int8_t iCoff;
|
int8_t iCoff;
|
||||||
int8_t qCoff;
|
int8_t qCoff;
|
||||||
|
@ -834,6 +835,7 @@ struct ath_hw {
|
||||||
int coarse_low[5];
|
int coarse_low[5];
|
||||||
int firpwr[5];
|
int firpwr[5];
|
||||||
enum ath9k_ani_cmd ani_function;
|
enum ath9k_ani_cmd ani_function;
|
||||||
|
u32 ani_skip_count;
|
||||||
|
|
||||||
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
|
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
|
||||||
struct ath_btcoex_hw btcoex_hw;
|
struct ath_btcoex_hw btcoex_hw;
|
||||||
|
|
|
@ -687,6 +687,7 @@ static const struct ieee80211_iface_combination if_comb = {
|
||||||
.n_limits = ARRAY_SIZE(if_limits),
|
.n_limits = ARRAY_SIZE(if_limits),
|
||||||
.max_interfaces = 2048,
|
.max_interfaces = 2048,
|
||||||
.num_different_channels = 1,
|
.num_different_channels = 1,
|
||||||
|
.beacon_int_infra_match = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
|
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
|
||||||
|
|
|
@ -350,8 +350,18 @@ void ath_ani_calibrate(unsigned long data)
|
||||||
ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
|
ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
|
||||||
|
|
||||||
/* Only calibrate if awake */
|
/* Only calibrate if awake */
|
||||||
if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE)
|
if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) {
|
||||||
|
if (++ah->ani_skip_count >= ATH_ANI_MAX_SKIP_COUNT) {
|
||||||
|
spin_lock_irqsave(&sc->sc_pm_lock, flags);
|
||||||
|
sc->ps_flags |= PS_WAIT_FOR_ANI;
|
||||||
|
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
|
||||||
|
}
|
||||||
goto set_timer;
|
goto set_timer;
|
||||||
|
}
|
||||||
|
ah->ani_skip_count = 0;
|
||||||
|
spin_lock_irqsave(&sc->sc_pm_lock, flags);
|
||||||
|
sc->ps_flags &= ~PS_WAIT_FOR_ANI;
|
||||||
|
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
|
||||||
|
|
||||||
ath9k_ps_wakeup(sc);
|
ath9k_ps_wakeup(sc);
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,8 @@ void ath9k_ps_restore(struct ath_softc *sc)
|
||||||
!(sc->ps_flags & (PS_WAIT_FOR_BEACON |
|
!(sc->ps_flags & (PS_WAIT_FOR_BEACON |
|
||||||
PS_WAIT_FOR_CAB |
|
PS_WAIT_FOR_CAB |
|
||||||
PS_WAIT_FOR_PSPOLL_DATA |
|
PS_WAIT_FOR_PSPOLL_DATA |
|
||||||
PS_WAIT_FOR_TX_ACK))) {
|
PS_WAIT_FOR_TX_ACK |
|
||||||
|
PS_WAIT_FOR_ANI))) {
|
||||||
mode = ATH9K_PM_NETWORK_SLEEP;
|
mode = ATH9K_PM_NETWORK_SLEEP;
|
||||||
if (ath9k_hw_btcoex_is_enabled(sc->sc_ah))
|
if (ath9k_hw_btcoex_is_enabled(sc->sc_ah))
|
||||||
ath9k_btcoex_stop_gen_timer(sc);
|
ath9k_btcoex_stop_gen_timer(sc);
|
||||||
|
@ -292,6 +293,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ath9k_hw_mci_is_enabled(sc->sc_ah) &&
|
||||||
|
(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
|
||||||
|
ath9k_mci_set_txpower(sc, true, false);
|
||||||
|
|
||||||
if (!ath_complete_reset(sc, true))
|
if (!ath_complete_reset(sc, true))
|
||||||
r = -EIO;
|
r = -EIO;
|
||||||
|
|
||||||
|
@ -1449,6 +1454,9 @@ static void ath9k_set_assoc_state(struct ath_softc *sc,
|
||||||
sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
|
sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
|
||||||
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
|
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
|
||||||
|
|
||||||
|
if (ath9k_hw_mci_is_enabled(sc->sc_ah))
|
||||||
|
ath9k_mci_update_wlan_channels(sc, false);
|
||||||
|
|
||||||
ath_dbg(common, CONFIG,
|
ath_dbg(common, CONFIG,
|
||||||
"Primary Station interface: %pM, BSSID: %pM\n",
|
"Primary Station interface: %pM, BSSID: %pM\n",
|
||||||
vif->addr, common->curbssid);
|
vif->addr, common->curbssid);
|
||||||
|
@ -1505,6 +1513,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
|
||||||
memset(common->curbssid, 0, ETH_ALEN);
|
memset(common->curbssid, 0, ETH_ALEN);
|
||||||
common->curaid = 0;
|
common->curaid = 0;
|
||||||
ath9k_hw_write_associd(sc->sc_ah);
|
ath9k_hw_write_associd(sc->sc_ah);
|
||||||
|
if (ath9k_hw_mci_is_enabled(sc->sc_ah))
|
||||||
|
ath9k_mci_update_wlan_channels(sc, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ static bool ath_mci_add_profile(struct ath_common *common,
|
||||||
struct ath_mci_profile_info *info)
|
struct ath_mci_profile_info *info)
|
||||||
{
|
{
|
||||||
struct ath_mci_profile_info *entry;
|
struct ath_mci_profile_info *entry;
|
||||||
|
u8 voice_priority[] = { 110, 110, 110, 112, 110, 110, 114, 116, 118 };
|
||||||
|
|
||||||
if ((mci->num_sco == ATH_MCI_MAX_SCO_PROFILE) &&
|
if ((mci->num_sco == ATH_MCI_MAX_SCO_PROFILE) &&
|
||||||
(info->type == MCI_GPM_COEX_PROFILE_VOICE))
|
(info->type == MCI_GPM_COEX_PROFILE_VOICE))
|
||||||
|
@ -59,6 +60,12 @@ static bool ath_mci_add_profile(struct ath_common *common,
|
||||||
memcpy(entry, info, 10);
|
memcpy(entry, info, 10);
|
||||||
INC_PROF(mci, info);
|
INC_PROF(mci, info);
|
||||||
list_add_tail(&entry->list, &mci->info);
|
list_add_tail(&entry->list, &mci->info);
|
||||||
|
if (info->type == MCI_GPM_COEX_PROFILE_VOICE) {
|
||||||
|
if (info->voice_type < sizeof(voice_priority))
|
||||||
|
mci->voice_priority = voice_priority[info->voice_type];
|
||||||
|
else
|
||||||
|
mci->voice_priority = 110;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -150,7 +157,7 @@ static void ath_mci_update_scheme(struct ath_softc *sc)
|
||||||
* For single PAN/FTP profile, allocate 35% for BT
|
* For single PAN/FTP profile, allocate 35% for BT
|
||||||
* to improve WLAN throughput.
|
* to improve WLAN throughput.
|
||||||
*/
|
*/
|
||||||
btcoex->duty_cycle = 35;
|
btcoex->duty_cycle = AR_SREV_9565(sc->sc_ah) ? 40 : 35;
|
||||||
btcoex->btcoex_period = 53;
|
btcoex->btcoex_period = 53;
|
||||||
ath_dbg(common, MCI,
|
ath_dbg(common, MCI,
|
||||||
"Single PAN/FTP bt period %d ms dutycycle %d\n",
|
"Single PAN/FTP bt period %d ms dutycycle %d\n",
|
||||||
|
@ -250,6 +257,57 @@ static void ath9k_mci_work(struct work_struct *work)
|
||||||
ath_mci_update_scheme(sc);
|
ath_mci_update_scheme(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ath_mci_update_stomp_txprio(u8 cur_txprio, u8 *stomp_prio)
|
||||||
|
{
|
||||||
|
if (cur_txprio < stomp_prio[ATH_BTCOEX_STOMP_NONE])
|
||||||
|
stomp_prio[ATH_BTCOEX_STOMP_NONE] = cur_txprio;
|
||||||
|
|
||||||
|
if (cur_txprio > stomp_prio[ATH_BTCOEX_STOMP_ALL])
|
||||||
|
stomp_prio[ATH_BTCOEX_STOMP_ALL] = cur_txprio;
|
||||||
|
|
||||||
|
if ((cur_txprio > ATH_MCI_HI_PRIO) &&
|
||||||
|
(cur_txprio < stomp_prio[ATH_BTCOEX_STOMP_LOW]))
|
||||||
|
stomp_prio[ATH_BTCOEX_STOMP_LOW] = cur_txprio;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ath_mci_set_concur_txprio(struct ath_softc *sc)
|
||||||
|
{
|
||||||
|
struct ath_btcoex *btcoex = &sc->btcoex;
|
||||||
|
struct ath_mci_profile *mci = &btcoex->mci;
|
||||||
|
u8 stomp_txprio[] = { 0, 0, 0, 0 }; /* all, low, none, low_ftp */
|
||||||
|
|
||||||
|
if (mci->num_mgmt) {
|
||||||
|
stomp_txprio[ATH_BTCOEX_STOMP_ALL] = ATH_MCI_INQUIRY_PRIO;
|
||||||
|
if (!mci->num_pan && !mci->num_other_acl)
|
||||||
|
stomp_txprio[ATH_BTCOEX_STOMP_NONE] =
|
||||||
|
ATH_MCI_INQUIRY_PRIO;
|
||||||
|
} else {
|
||||||
|
u8 prof_prio[] = { 50, 90, 94, 52 };/* RFCOMM, A2DP, HID, PAN */
|
||||||
|
|
||||||
|
stomp_txprio[ATH_BTCOEX_STOMP_LOW] =
|
||||||
|
stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0xff;
|
||||||
|
|
||||||
|
if (mci->num_sco)
|
||||||
|
ath_mci_update_stomp_txprio(mci->voice_priority,
|
||||||
|
stomp_txprio);
|
||||||
|
if (mci->num_other_acl)
|
||||||
|
ath_mci_update_stomp_txprio(prof_prio[0], stomp_txprio);
|
||||||
|
if (mci->num_a2dp)
|
||||||
|
ath_mci_update_stomp_txprio(prof_prio[1], stomp_txprio);
|
||||||
|
if (mci->num_hid)
|
||||||
|
ath_mci_update_stomp_txprio(prof_prio[2], stomp_txprio);
|
||||||
|
if (mci->num_pan)
|
||||||
|
ath_mci_update_stomp_txprio(prof_prio[3], stomp_txprio);
|
||||||
|
|
||||||
|
if (stomp_txprio[ATH_BTCOEX_STOMP_NONE] == 0xff)
|
||||||
|
stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0;
|
||||||
|
|
||||||
|
if (stomp_txprio[ATH_BTCOEX_STOMP_LOW] == 0xff)
|
||||||
|
stomp_txprio[ATH_BTCOEX_STOMP_LOW] = 0;
|
||||||
|
}
|
||||||
|
ath9k_hw_btcoex_set_concur_txprio(sc->sc_ah, stomp_txprio);
|
||||||
|
}
|
||||||
|
|
||||||
static u8 ath_mci_process_profile(struct ath_softc *sc,
|
static u8 ath_mci_process_profile(struct ath_softc *sc,
|
||||||
struct ath_mci_profile_info *info)
|
struct ath_mci_profile_info *info)
|
||||||
{
|
{
|
||||||
|
@ -281,6 +339,7 @@ static u8 ath_mci_process_profile(struct ath_softc *sc,
|
||||||
} else
|
} else
|
||||||
ath_mci_del_profile(common, mci, entry);
|
ath_mci_del_profile(common, mci, entry);
|
||||||
|
|
||||||
|
ath_mci_set_concur_txprio(sc);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,6 +373,7 @@ static u8 ath_mci_process_status(struct ath_softc *sc,
|
||||||
mci->num_mgmt++;
|
mci->num_mgmt++;
|
||||||
} while (++i < ATH_MCI_MAX_PROFILE);
|
} while (++i < ATH_MCI_MAX_PROFILE);
|
||||||
|
|
||||||
|
ath_mci_set_concur_txprio(sc);
|
||||||
if (old_num_mgmt != mci->num_mgmt)
|
if (old_num_mgmt != mci->num_mgmt)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -600,3 +660,112 @@ void ath_mci_enable(struct ath_softc *sc)
|
||||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI)
|
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI)
|
||||||
sc->sc_ah->imask |= ATH9K_INT_MCI;
|
sc->sc_ah->imask |= ATH9K_INT_MCI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all)
|
||||||
|
{
|
||||||
|
struct ath_hw *ah = sc->sc_ah;
|
||||||
|
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
||||||
|
struct ath9k_channel *chan = ah->curchan;
|
||||||
|
u32 channelmap[] = {0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff};
|
||||||
|
int i;
|
||||||
|
s16 chan_start, chan_end;
|
||||||
|
u16 wlan_chan;
|
||||||
|
|
||||||
|
if (!chan || !IS_CHAN_2GHZ(chan))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (allow_all)
|
||||||
|
goto send_wlan_chan;
|
||||||
|
|
||||||
|
wlan_chan = chan->channel - 2402;
|
||||||
|
|
||||||
|
chan_start = wlan_chan - 10;
|
||||||
|
chan_end = wlan_chan + 10;
|
||||||
|
|
||||||
|
if (chan->chanmode == CHANNEL_G_HT40PLUS)
|
||||||
|
chan_end += 20;
|
||||||
|
else if (chan->chanmode == CHANNEL_G_HT40MINUS)
|
||||||
|
chan_start -= 20;
|
||||||
|
|
||||||
|
/* adjust side band */
|
||||||
|
chan_start -= 7;
|
||||||
|
chan_end += 7;
|
||||||
|
|
||||||
|
if (chan_start <= 0)
|
||||||
|
chan_start = 0;
|
||||||
|
if (chan_end >= ATH_MCI_NUM_BT_CHANNELS)
|
||||||
|
chan_end = ATH_MCI_NUM_BT_CHANNELS - 1;
|
||||||
|
|
||||||
|
ath_dbg(ath9k_hw_common(ah), MCI,
|
||||||
|
"WLAN current channel %d mask BT channel %d - %d\n",
|
||||||
|
wlan_chan, chan_start, chan_end);
|
||||||
|
|
||||||
|
for (i = chan_start; i < chan_end; i++)
|
||||||
|
MCI_GPM_CLR_CHANNEL_BIT(&channelmap, i);
|
||||||
|
|
||||||
|
send_wlan_chan:
|
||||||
|
/* update and send wlan channels info to BT */
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
mci->wlan_channels[i] = channelmap[i];
|
||||||
|
ar9003_mci_send_wlan_channels(ah);
|
||||||
|
ar9003_mci_state(ah, MCI_STATE_SEND_VERSION_QUERY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel,
|
||||||
|
bool concur_tx)
|
||||||
|
{
|
||||||
|
struct ath_hw *ah = sc->sc_ah;
|
||||||
|
struct ath9k_hw_mci *mci_hw = &sc->sc_ah->btcoex_hw.mci;
|
||||||
|
bool old_concur_tx = mci_hw->concur_tx;
|
||||||
|
|
||||||
|
if (!(mci_hw->config & ATH_MCI_CONFIG_CONCUR_TX)) {
|
||||||
|
mci_hw->concur_tx = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IS_CHAN_2GHZ(ah->curchan))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (setchannel) {
|
||||||
|
struct ath9k_hw_cal_data *caldata = &sc->caldata;
|
||||||
|
if ((caldata->chanmode == CHANNEL_G_HT40PLUS) &&
|
||||||
|
(ah->curchan->channel > caldata->channel) &&
|
||||||
|
(ah->curchan->channel <= caldata->channel + 20))
|
||||||
|
return;
|
||||||
|
if ((caldata->chanmode == CHANNEL_G_HT40MINUS) &&
|
||||||
|
(ah->curchan->channel < caldata->channel) &&
|
||||||
|
(ah->curchan->channel >= caldata->channel - 20))
|
||||||
|
return;
|
||||||
|
mci_hw->concur_tx = false;
|
||||||
|
} else
|
||||||
|
mci_hw->concur_tx = concur_tx;
|
||||||
|
|
||||||
|
if (old_concur_tx != mci_hw->concur_tx)
|
||||||
|
ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ath9k_mci_update_rssi(struct ath_softc *sc)
|
||||||
|
{
|
||||||
|
struct ath_hw *ah = sc->sc_ah;
|
||||||
|
struct ath_btcoex *btcoex = &sc->btcoex;
|
||||||
|
struct ath9k_hw_mci *mci_hw = &sc->sc_ah->btcoex_hw.mci;
|
||||||
|
|
||||||
|
if (!(mci_hw->config & ATH_MCI_CONFIG_CONCUR_TX))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ah->stats.avgbrssi >= 40) {
|
||||||
|
if (btcoex->rssi_count < 0)
|
||||||
|
btcoex->rssi_count = 0;
|
||||||
|
if (++btcoex->rssi_count >= ATH_MCI_CONCUR_TX_SWITCH) {
|
||||||
|
btcoex->rssi_count = 0;
|
||||||
|
ath9k_mci_set_txpower(sc, false, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (btcoex->rssi_count > 0)
|
||||||
|
btcoex->rssi_count = 0;
|
||||||
|
if (--btcoex->rssi_count <= -ATH_MCI_CONCUR_TX_SWITCH) {
|
||||||
|
btcoex->rssi_count = 0;
|
||||||
|
ath9k_mci_set_txpower(sc, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -32,6 +32,27 @@
|
||||||
#define ATH_MCI_MAX_PROFILE (ATH_MCI_MAX_ACL_PROFILE +\
|
#define ATH_MCI_MAX_PROFILE (ATH_MCI_MAX_ACL_PROFILE +\
|
||||||
ATH_MCI_MAX_SCO_PROFILE)
|
ATH_MCI_MAX_SCO_PROFILE)
|
||||||
|
|
||||||
|
#define ATH_MCI_INQUIRY_PRIO 62
|
||||||
|
#define ATH_MCI_HI_PRIO 60
|
||||||
|
#define ATH_MCI_NUM_BT_CHANNELS 79
|
||||||
|
#define ATH_MCI_CONCUR_TX_SWITCH 5
|
||||||
|
|
||||||
|
#define MCI_GPM_SET_CHANNEL_BIT(_p_gpm, _bt_chan) \
|
||||||
|
do { \
|
||||||
|
if (_bt_chan < ATH_MCI_NUM_BT_CHANNELS) { \
|
||||||
|
*(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_CHANNEL_MAP + \
|
||||||
|
(_bt_chan / 8)) |= (1 << (_bt_chan & 7)); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define MCI_GPM_CLR_CHANNEL_BIT(_p_gpm, _bt_chan) \
|
||||||
|
do { \
|
||||||
|
if (_bt_chan < ATH_MCI_NUM_BT_CHANNELS) { \
|
||||||
|
*(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_CHANNEL_MAP + \
|
||||||
|
(_bt_chan / 8)) &= ~(1 << (_bt_chan & 7));\
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#define INC_PROF(_mci, _info) do { \
|
#define INC_PROF(_mci, _info) do { \
|
||||||
switch (_info->type) { \
|
switch (_info->type) { \
|
||||||
case MCI_GPM_COEX_PROFILE_RFCOMM:\
|
case MCI_GPM_COEX_PROFILE_RFCOMM:\
|
||||||
|
@ -49,6 +70,7 @@
|
||||||
_mci->num_pan++; \
|
_mci->num_pan++; \
|
||||||
break; \
|
break; \
|
||||||
case MCI_GPM_COEX_PROFILE_VOICE: \
|
case MCI_GPM_COEX_PROFILE_VOICE: \
|
||||||
|
case MCI_GPM_COEX_PROFILE_A2DPVO:\
|
||||||
_mci->num_sco++; \
|
_mci->num_sco++; \
|
||||||
break; \
|
break; \
|
||||||
default: \
|
default: \
|
||||||
|
@ -73,6 +95,7 @@
|
||||||
_mci->num_pan--; \
|
_mci->num_pan--; \
|
||||||
break; \
|
break; \
|
||||||
case MCI_GPM_COEX_PROFILE_VOICE: \
|
case MCI_GPM_COEX_PROFILE_VOICE: \
|
||||||
|
case MCI_GPM_COEX_PROFILE_A2DPVO:\
|
||||||
_mci->num_sco--; \
|
_mci->num_sco--; \
|
||||||
break; \
|
break; \
|
||||||
default: \
|
default: \
|
||||||
|
@ -113,6 +136,7 @@ struct ath_mci_profile {
|
||||||
u8 num_pan;
|
u8 num_pan;
|
||||||
u8 num_other_acl;
|
u8 num_other_acl;
|
||||||
u8 num_bdr;
|
u8 num_bdr;
|
||||||
|
u8 voice_priority;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ath_mci_buf {
|
struct ath_mci_buf {
|
||||||
|
@ -130,13 +154,25 @@ void ath_mci_flush_profile(struct ath_mci_profile *mci);
|
||||||
int ath_mci_setup(struct ath_softc *sc);
|
int ath_mci_setup(struct ath_softc *sc);
|
||||||
void ath_mci_cleanup(struct ath_softc *sc);
|
void ath_mci_cleanup(struct ath_softc *sc);
|
||||||
void ath_mci_intr(struct ath_softc *sc);
|
void ath_mci_intr(struct ath_softc *sc);
|
||||||
|
void ath9k_mci_update_rssi(struct ath_softc *sc);
|
||||||
|
|
||||||
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
|
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
|
||||||
void ath_mci_enable(struct ath_softc *sc);
|
void ath_mci_enable(struct ath_softc *sc);
|
||||||
|
void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all);
|
||||||
|
void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel,
|
||||||
|
bool concur_tx);
|
||||||
#else
|
#else
|
||||||
static inline void ath_mci_enable(struct ath_softc *sc)
|
static inline void ath_mci_enable(struct ath_softc *sc)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
static inline void ath9k_mci_update_wlan_channels(struct ath_softc *sc,
|
||||||
|
bool allow_all)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
static inline void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel,
|
||||||
|
bool concur_tx)
|
||||||
|
{
|
||||||
|
}
|
||||||
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
|
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
|
||||||
|
|
||||||
#endif /* MCI_H*/
|
#endif /* MCI_H*/
|
||||||
|
|
|
@ -1105,7 +1105,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
||||||
else
|
else
|
||||||
rs.is_mybeacon = false;
|
rs.is_mybeacon = false;
|
||||||
|
|
||||||
|
if (ieee80211_is_data_present(hdr->frame_control) &&
|
||||||
|
!ieee80211_is_qos_nullfunc(hdr->frame_control))
|
||||||
sc->rx.num_pkts++;
|
sc->rx.num_pkts++;
|
||||||
|
|
||||||
ath_debug_stat_rx(sc, &rs);
|
ath_debug_stat_rx(sc, &rs);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -907,10 +907,6 @@
|
||||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
|
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
|
||||||
((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20))
|
((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20))
|
||||||
|
|
||||||
#define AR_SREV_9462_20_OR_LATER(_ah) \
|
|
||||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
|
|
||||||
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20))
|
|
||||||
|
|
||||||
#define AR_SREV_9565(_ah) \
|
#define AR_SREV_9565(_ah) \
|
||||||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565))
|
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565))
|
||||||
|
|
||||||
|
@ -2315,6 +2311,8 @@ enum {
|
||||||
#define AR_BTCOEX_MAX_TXPWR(_x) (0x18c0 + ((_x) << 2))
|
#define AR_BTCOEX_MAX_TXPWR(_x) (0x18c0 + ((_x) << 2))
|
||||||
#define AR_BTCOEX_WL_LNA 0x1940
|
#define AR_BTCOEX_WL_LNA 0x1940
|
||||||
#define AR_BTCOEX_RFGAIN_CTRL 0x1944
|
#define AR_BTCOEX_RFGAIN_CTRL 0x1944
|
||||||
|
#define AR_BTCOEX_WL_LNA_TIMEOUT 0x003FFFFF
|
||||||
|
#define AR_BTCOEX_WL_LNA_TIMEOUT_S 0
|
||||||
|
|
||||||
#define AR_BTCOEX_CTRL2 0x1948
|
#define AR_BTCOEX_CTRL2 0x1948
|
||||||
#define AR_BTCOEX_CTRL2_TXPWR_THRESH 0x0007F800
|
#define AR_BTCOEX_CTRL2_TXPWR_THRESH 0x0007F800
|
||||||
|
@ -2360,4 +2358,11 @@ enum {
|
||||||
#define AR_GLB_SWREG_DISCONT_MODE 0x2002c
|
#define AR_GLB_SWREG_DISCONT_MODE 0x2002c
|
||||||
#define AR_GLB_SWREG_DISCONT_EN_BT_WLAN 0x3
|
#define AR_GLB_SWREG_DISCONT_EN_BT_WLAN 0x3
|
||||||
|
|
||||||
|
#define AR_MCI_MISC 0x1a74
|
||||||
|
#define AR_MCI_MISC_HW_FIX_EN 0x00000001
|
||||||
|
#define AR_MCI_MISC_HW_FIX_EN_S 0
|
||||||
|
#define AR_MCI_DBG_CNT_CTRL 0x1a78
|
||||||
|
#define AR_MCI_DBG_CNT_CTRL_ENABLE 0x00000001
|
||||||
|
#define AR_MCI_DBG_CNT_CTRL_ENABLE_S 0
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -118,7 +118,7 @@ static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah)
|
||||||
(ap_mac_addr[1] << 8) | (ap_mac_addr[0]);
|
(ap_mac_addr[1] << 8) | (ap_mac_addr[0]);
|
||||||
data_word[5] = (ap_mac_addr[5] << 8) | (ap_mac_addr[4]);
|
data_word[5] = (ap_mac_addr[5] << 8) | (ap_mac_addr[4]);
|
||||||
|
|
||||||
if (AR_SREV_9462_20_OR_LATER(ah)) {
|
if (AR_SREV_9462_20(ah)) {
|
||||||
/* AR9462 2.0 has an extra descriptor word (time based
|
/* AR9462 2.0 has an extra descriptor word (time based
|
||||||
* discard) compared to other chips */
|
* discard) compared to other chips */
|
||||||
REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0);
|
REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0);
|
||||||
|
|
|
@ -343,7 +343,24 @@ int carl9170_set_operating_mode(struct ar9170 *ar)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mac_addr = NULL;
|
/*
|
||||||
|
* Enable monitor mode
|
||||||
|
*
|
||||||
|
* rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER;
|
||||||
|
* sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC;
|
||||||
|
*
|
||||||
|
* When the hardware is in SNIFFER_PROMISC mode,
|
||||||
|
* it generates spurious ACKs for every incoming
|
||||||
|
* frame. This confuses every peer in the
|
||||||
|
* vicinity and the network throughput will suffer
|
||||||
|
* badly.
|
||||||
|
*
|
||||||
|
* Hence, the hardware will be put into station
|
||||||
|
* mode and just the rx filters are disabled.
|
||||||
|
*/
|
||||||
|
cam_mode |= AR9170_MAC_CAM_STA;
|
||||||
|
rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST;
|
||||||
|
mac_addr = common->macaddr;
|
||||||
bssid = NULL;
|
bssid = NULL;
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
@ -355,8 +372,6 @@ int carl9170_set_operating_mode(struct ar9170 *ar)
|
||||||
enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
|
enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
|
||||||
|
|
||||||
if (ar->sniffer_enabled) {
|
if (ar->sniffer_enabled) {
|
||||||
rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER;
|
|
||||||
sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC;
|
|
||||||
enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
|
enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -164,9 +164,6 @@ void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
|
||||||
struct carl9170_rsp *cmd = buf;
|
struct carl9170_rsp *cmd = buf;
|
||||||
struct ieee80211_vif *vif;
|
struct ieee80211_vif *vif;
|
||||||
|
|
||||||
if (carl9170_check_sequence(ar, cmd->hdr.seq))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ((cmd->hdr.cmd & CARL9170_RSP_FLAG) != CARL9170_RSP_FLAG) {
|
if ((cmd->hdr.cmd & CARL9170_RSP_FLAG) != CARL9170_RSP_FLAG) {
|
||||||
if (!(cmd->hdr.cmd & CARL9170_CMD_ASYNC_FLAG))
|
if (!(cmd->hdr.cmd & CARL9170_CMD_ASYNC_FLAG))
|
||||||
carl9170_cmd_callback(ar, len, buf);
|
carl9170_cmd_callback(ar, len, buf);
|
||||||
|
@ -663,6 +660,35 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len,
|
||||||
|
struct ieee80211_rx_status *status)
|
||||||
|
{
|
||||||
|
struct sk_buff *skb;
|
||||||
|
|
||||||
|
/* (driver) frame trap handler
|
||||||
|
*
|
||||||
|
* Because power-saving mode handing has to be implemented by
|
||||||
|
* the driver/firmware. We have to check each incoming beacon
|
||||||
|
* from the associated AP, if there's new data for us (either
|
||||||
|
* broadcast/multicast or unicast) we have to react quickly.
|
||||||
|
*
|
||||||
|
* So, if you have you want to add additional frame trap
|
||||||
|
* handlers, this would be the perfect place!
|
||||||
|
*/
|
||||||
|
|
||||||
|
carl9170_ps_beacon(ar, buf, len);
|
||||||
|
|
||||||
|
carl9170_ba_check(ar, buf, len);
|
||||||
|
|
||||||
|
skb = carl9170_rx_copy_data(buf, len);
|
||||||
|
if (!skb)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
|
||||||
|
ieee80211_rx(ar->hw, skb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the frame alignment is right (or the kernel has
|
* If the frame alignment is right (or the kernel has
|
||||||
* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there
|
* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there
|
||||||
|
@ -672,14 +698,12 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms,
|
||||||
* mode, and we need to observe the proper ordering,
|
* mode, and we need to observe the proper ordering,
|
||||||
* this is non-trivial.
|
* this is non-trivial.
|
||||||
*/
|
*/
|
||||||
|
static void carl9170_rx_untie_data(struct ar9170 *ar, u8 *buf, int len)
|
||||||
static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
|
|
||||||
{
|
{
|
||||||
struct ar9170_rx_head *head;
|
struct ar9170_rx_head *head;
|
||||||
struct ar9170_rx_macstatus *mac;
|
struct ar9170_rx_macstatus *mac;
|
||||||
struct ar9170_rx_phystatus *phy = NULL;
|
struct ar9170_rx_phystatus *phy = NULL;
|
||||||
struct ieee80211_rx_status status;
|
struct ieee80211_rx_status status;
|
||||||
struct sk_buff *skb;
|
|
||||||
int mpdu_len;
|
int mpdu_len;
|
||||||
u8 mac_status;
|
u8 mac_status;
|
||||||
|
|
||||||
|
@ -791,18 +815,10 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
|
||||||
if (phy)
|
if (phy)
|
||||||
carl9170_rx_phy_status(ar, phy, &status);
|
carl9170_rx_phy_status(ar, phy, &status);
|
||||||
|
|
||||||
carl9170_ps_beacon(ar, buf, mpdu_len);
|
if (carl9170_handle_mpdu(ar, buf, mpdu_len, &status))
|
||||||
|
|
||||||
carl9170_ba_check(ar, buf, mpdu_len);
|
|
||||||
|
|
||||||
skb = carl9170_rx_copy_data(buf, mpdu_len);
|
|
||||||
if (!skb)
|
|
||||||
goto drop;
|
goto drop;
|
||||||
|
|
||||||
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
|
|
||||||
ieee80211_rx(ar->hw, skb);
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
drop:
|
drop:
|
||||||
ar->rx_dropped++;
|
ar->rx_dropped++;
|
||||||
}
|
}
|
||||||
|
@ -820,6 +836,9 @@ static void carl9170_rx_untie_cmds(struct ar9170 *ar, const u8 *respbuf,
|
||||||
if (unlikely(i > resplen))
|
if (unlikely(i > resplen))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
if (carl9170_check_sequence(ar, cmd->hdr.seq))
|
||||||
|
break;
|
||||||
|
|
||||||
carl9170_handle_command_response(ar, cmd, cmd->hdr.len + 4);
|
carl9170_handle_command_response(ar, cmd, cmd->hdr.len + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -851,7 +870,7 @@ static void __carl9170_rx(struct ar9170 *ar, u8 *buf, unsigned int len)
|
||||||
if (i == 12)
|
if (i == 12)
|
||||||
carl9170_rx_untie_cmds(ar, buf, len);
|
carl9170_rx_untie_cmds(ar, buf, len);
|
||||||
else
|
else
|
||||||
carl9170_handle_mpdu(ar, buf, len);
|
carl9170_rx_untie_data(ar, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len)
|
static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len)
|
||||||
|
|
|
@ -295,6 +295,13 @@ static void carl9170_usb_rx_irq_complete(struct urb *urb)
|
||||||
goto resubmit;
|
goto resubmit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* While the carl9170 firmware does not use this EP, the
|
||||||
|
* firmware loader in the EEPROM unfortunately does.
|
||||||
|
* Therefore we need to be ready to handle out-of-band
|
||||||
|
* responses and traps in case the firmware crashed and
|
||||||
|
* the loader took over again.
|
||||||
|
*/
|
||||||
carl9170_handle_command_response(ar, urb->transfer_buffer,
|
carl9170_handle_command_response(ar, urb->transfer_buffer,
|
||||||
urb->actual_length);
|
urb->actual_length);
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "reg.h"
|
#include "reg.h"
|
||||||
|
|
||||||
#define REG_READ (common->ops->read)
|
#define REG_READ (common->ops->read)
|
||||||
#define REG_WRITE (common->ops->write)
|
#define REG_WRITE(_ah, _reg, _val) (common->ops->write)(_ah, _val, _reg)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ath_hw_set_bssid_mask - filter out bssids we listen
|
* ath_hw_set_bssid_mask - filter out bssids we listen
|
||||||
|
@ -119,8 +119,8 @@ void ath_hw_setbssidmask(struct ath_common *common)
|
||||||
{
|
{
|
||||||
void *ah = common->ah;
|
void *ah = common->ah;
|
||||||
|
|
||||||
REG_WRITE(ah, get_unaligned_le32(common->bssidmask), AR_BSSMSKL);
|
REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(common->bssidmask));
|
||||||
REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU);
|
REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(common->bssidmask + 4));
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ath_hw_setbssidmask);
|
EXPORT_SYMBOL(ath_hw_setbssidmask);
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ void ath_hw_cycle_counters_update(struct ath_common *common)
|
||||||
void *ah = common->ah;
|
void *ah = common->ah;
|
||||||
|
|
||||||
/* freeze */
|
/* freeze */
|
||||||
REG_WRITE(ah, AR_MIBC_FMC, AR_MIBC);
|
REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
|
||||||
|
|
||||||
/* read */
|
/* read */
|
||||||
cycles = REG_READ(ah, AR_CCCNT);
|
cycles = REG_READ(ah, AR_CCCNT);
|
||||||
|
@ -148,13 +148,13 @@ void ath_hw_cycle_counters_update(struct ath_common *common)
|
||||||
tx = REG_READ(ah, AR_TFCNT);
|
tx = REG_READ(ah, AR_TFCNT);
|
||||||
|
|
||||||
/* clear */
|
/* clear */
|
||||||
REG_WRITE(ah, 0, AR_CCCNT);
|
REG_WRITE(ah, AR_CCCNT, 0);
|
||||||
REG_WRITE(ah, 0, AR_RFCNT);
|
REG_WRITE(ah, AR_RFCNT, 0);
|
||||||
REG_WRITE(ah, 0, AR_RCCNT);
|
REG_WRITE(ah, AR_RCCNT, 0);
|
||||||
REG_WRITE(ah, 0, AR_TFCNT);
|
REG_WRITE(ah, AR_TFCNT, 0);
|
||||||
|
|
||||||
/* unfreeze */
|
/* unfreeze */
|
||||||
REG_WRITE(ah, 0, AR_MIBC);
|
REG_WRITE(ah, AR_MIBC, 0);
|
||||||
|
|
||||||
/* update all cycle counters here */
|
/* update all cycle counters here */
|
||||||
common->cc_ani.cycles += cycles;
|
common->cc_ani.cycles += cycles;
|
||||||
|
|
|
@ -4652,7 +4652,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
|
||||||
switch (dev->dev->bus_type) {
|
switch (dev->dev->bus_type) {
|
||||||
#ifdef CONFIG_B43_BCMA
|
#ifdef CONFIG_B43_BCMA
|
||||||
case B43_BUS_BCMA:
|
case B43_BUS_BCMA:
|
||||||
bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci,
|
bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci[0],
|
||||||
dev->dev->bdev, true);
|
dev->dev->bdev, true);
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,6 +24,7 @@ ccflags-y += -D__CHECK_ENDIAN__
|
||||||
obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
|
obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
|
||||||
brcmfmac-objs += \
|
brcmfmac-objs += \
|
||||||
wl_cfg80211.o \
|
wl_cfg80211.o \
|
||||||
|
fwil.o \
|
||||||
dhd_cdc.o \
|
dhd_cdc.o \
|
||||||
dhd_common.o \
|
dhd_common.o \
|
||||||
dhd_linux.o
|
dhd_linux.o
|
||||||
|
|
|
@ -318,6 +318,12 @@ struct brcmf_event {
|
||||||
#define BRCMF_E_LINK_ASSOC_REC 3
|
#define BRCMF_E_LINK_ASSOC_REC 3
|
||||||
#define BRCMF_E_LINK_BSSCFG_DIS 4
|
#define BRCMF_E_LINK_BSSCFG_DIS 4
|
||||||
|
|
||||||
|
/* Small, medium and maximum buffer size for dcmd
|
||||||
|
*/
|
||||||
|
#define BRCMF_DCMD_SMLEN 256
|
||||||
|
#define BRCMF_DCMD_MEDLEN 1536
|
||||||
|
#define BRCMF_DCMD_MAXLEN 8192
|
||||||
|
|
||||||
/* Pattern matching filter. Specifies an offset within received packets to
|
/* Pattern matching filter. Specifies an offset within received packets to
|
||||||
* start matching, the pattern to match, the size of the pattern, and a bitmask
|
* start matching, the pattern to match, the size of the pattern, and a bitmask
|
||||||
* that indicates which bits within the pattern should be matched.
|
* that indicates which bits within the pattern should be matched.
|
||||||
|
@ -623,7 +629,6 @@ struct brcmf_pub {
|
||||||
u8 wme_dp; /* wme discard priority */
|
u8 wme_dp; /* wme discard priority */
|
||||||
|
|
||||||
/* Dongle media info */
|
/* Dongle media info */
|
||||||
bool iswl; /* Dongle-resident driver is wl */
|
|
||||||
unsigned long drv_version; /* Version of dongle-resident driver */
|
unsigned long drv_version; /* Version of dongle-resident driver */
|
||||||
u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */
|
u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */
|
||||||
|
|
||||||
|
@ -651,16 +656,10 @@ struct brcmf_pub {
|
||||||
int in_suspend; /* flag set to 1 when early suspend called */
|
int in_suspend; /* flag set to 1 when early suspend called */
|
||||||
int dtim_skip; /* dtim skip , default 0 means wake each dtim */
|
int dtim_skip; /* dtim skip , default 0 means wake each dtim */
|
||||||
|
|
||||||
/* Pkt filter defination */
|
|
||||||
char *pktfilter[100];
|
|
||||||
int pktfilter_count;
|
|
||||||
|
|
||||||
u8 country_code[BRCM_CNTRY_BUF_SZ];
|
|
||||||
char eventmask[BRCMF_EVENTING_MASK_LEN];
|
|
||||||
|
|
||||||
struct brcmf_if *iflist[BRCMF_MAX_IFS];
|
struct brcmf_if *iflist[BRCMF_MAX_IFS];
|
||||||
|
|
||||||
struct mutex proto_block;
|
struct mutex proto_block;
|
||||||
|
unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
|
||||||
|
|
||||||
struct work_struct setmacaddr_work;
|
struct work_struct setmacaddr_work;
|
||||||
struct work_struct multicast_work;
|
struct work_struct multicast_work;
|
||||||
|
@ -671,6 +670,11 @@ struct brcmf_pub {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct bcmevent_name {
|
||||||
|
uint event;
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
struct brcmf_if_event {
|
struct brcmf_if_event {
|
||||||
u8 ifidx;
|
u8 ifidx;
|
||||||
u8 action;
|
u8 action;
|
||||||
|
@ -678,47 +682,60 @@ struct brcmf_if_event {
|
||||||
u8 bssidx;
|
u8 bssidx;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bcmevent_name {
|
/* forward declaration */
|
||||||
uint event;
|
struct brcmf_cfg80211_vif;
|
||||||
const char *name;
|
|
||||||
|
/**
|
||||||
|
* struct brcmf_if - interface control information.
|
||||||
|
*
|
||||||
|
* @drvr: points to device related information.
|
||||||
|
* @vif: points to cfg80211 specific interface information.
|
||||||
|
* @ndev: associated network device.
|
||||||
|
* @stats: interface specific network statistics.
|
||||||
|
* @idx: interface index in device firmware.
|
||||||
|
* @bssidx: index of bss associated with this interface.
|
||||||
|
* @mac_addr: assigned mac address.
|
||||||
|
*/
|
||||||
|
struct brcmf_if {
|
||||||
|
struct brcmf_pub *drvr;
|
||||||
|
struct brcmf_cfg80211_vif *vif;
|
||||||
|
struct net_device *ndev;
|
||||||
|
struct net_device_stats stats;
|
||||||
|
int idx;
|
||||||
|
s32 bssidx;
|
||||||
|
u8 mac_addr[ETH_ALEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static inline s32 brcmf_ndev_bssidx(struct net_device *ndev)
|
||||||
|
{
|
||||||
|
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||||
|
return ifp->bssidx;
|
||||||
|
}
|
||||||
|
|
||||||
extern const struct bcmevent_name bcmevent_names[];
|
extern const struct bcmevent_name bcmevent_names[];
|
||||||
|
|
||||||
extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen,
|
extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen,
|
||||||
char *buf, uint len);
|
char *buf, uint len);
|
||||||
extern uint brcmf_c_mkiovar_bsscfg(char *name, char *data, uint datalen,
|
|
||||||
char *buf, uint buflen, s32 bssidx);
|
|
||||||
|
|
||||||
extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev);
|
extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev);
|
||||||
|
|
||||||
extern s32 brcmf_exec_dcmd(struct net_device *dev, u32 cmd, void *arg, u32 len);
|
|
||||||
extern int brcmf_netlink_dcmd(struct net_device *ndev, struct brcmf_dcmd *dcmd);
|
|
||||||
|
|
||||||
/* Return pointer to interface name */
|
/* Return pointer to interface name */
|
||||||
extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
|
extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
|
||||||
|
|
||||||
/* Query dongle */
|
/* Query dongle */
|
||||||
extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx,
|
extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx,
|
||||||
uint cmd, void *buf, uint len);
|
uint cmd, void *buf, uint len);
|
||||||
|
extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
|
||||||
#ifdef DEBUG
|
void *buf, uint len);
|
||||||
extern int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size);
|
|
||||||
#endif /* DEBUG */
|
|
||||||
|
|
||||||
extern int brcmf_ifname2idx(struct brcmf_pub *drvr, char *name);
|
extern int brcmf_ifname2idx(struct brcmf_pub *drvr, char *name);
|
||||||
extern int brcmf_c_host_event(struct brcmf_pub *drvr, int *idx,
|
extern int brcmf_c_host_event(struct brcmf_pub *drvr, int *idx,
|
||||||
void *pktdata, struct brcmf_event_msg *,
|
void *pktdata, struct brcmf_event_msg *,
|
||||||
void **data_ptr);
|
void **data_ptr);
|
||||||
|
|
||||||
|
extern int brcmf_net_attach(struct brcmf_if *ifp);
|
||||||
|
extern struct brcmf_if *brcmf_add_if(struct device *dev, int ifidx, s32 bssidx,
|
||||||
|
char *name, u8 *mac_addr);
|
||||||
extern void brcmf_del_if(struct brcmf_pub *drvr, int ifidx);
|
extern void brcmf_del_if(struct brcmf_pub *drvr, int ifidx);
|
||||||
|
|
||||||
extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg);
|
|
||||||
extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg,
|
|
||||||
int enable, int master_mode);
|
|
||||||
|
|
||||||
#define BRCMF_DCMD_SMLEN 256 /* "small" cmd buffer required */
|
|
||||||
#define BRCMF_DCMD_MEDLEN 1536 /* "med" cmd buffer required */
|
|
||||||
#define BRCMF_DCMD_MAXLEN 8192 /* max length cmd buffer required */
|
|
||||||
|
|
||||||
#endif /* _BRCMF_H_ */
|
#endif /* _BRCMF_H_ */
|
||||||
|
|
|
@ -111,9 +111,6 @@ extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp,
|
||||||
|
|
||||||
extern int brcmf_bus_start(struct device *dev);
|
extern int brcmf_bus_start(struct device *dev);
|
||||||
|
|
||||||
extern int brcmf_add_if(struct device *dev, int ifidx,
|
|
||||||
char *name, u8 *mac_addr);
|
|
||||||
|
|
||||||
#ifdef CONFIG_BRCMFMAC_SDIO
|
#ifdef CONFIG_BRCMFMAC_SDIO
|
||||||
extern void brcmf_sdio_exit(void);
|
extern void brcmf_sdio_exit(void);
|
||||||
extern void brcmf_sdio_init(void);
|
extern void brcmf_sdio_init(void);
|
||||||
|
|
|
@ -458,35 +458,6 @@ void brcmf_proto_detach(struct brcmf_pub *drvr)
|
||||||
drvr->prot = NULL;
|
drvr->prot = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int brcmf_proto_init(struct brcmf_pub *drvr)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
char buf[128];
|
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "Enter\n");
|
|
||||||
|
|
||||||
mutex_lock(&drvr->proto_block);
|
|
||||||
|
|
||||||
/* Get the device MAC address */
|
|
||||||
strcpy(buf, "cur_etheraddr");
|
|
||||||
ret = brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR,
|
|
||||||
buf, sizeof(buf));
|
|
||||||
if (ret < 0) {
|
|
||||||
mutex_unlock(&drvr->proto_block);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
memcpy(drvr->mac, buf, ETH_ALEN);
|
|
||||||
|
|
||||||
mutex_unlock(&drvr->proto_block);
|
|
||||||
|
|
||||||
ret = brcmf_c_preinit_dcmds(drvr);
|
|
||||||
|
|
||||||
/* Always assumes wl for now */
|
|
||||||
drvr->iswl = true;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void brcmf_proto_stop(struct brcmf_pub *drvr)
|
void brcmf_proto_stop(struct brcmf_pub *drvr)
|
||||||
{
|
{
|
||||||
/* Nothing to do for CDC */
|
/* Nothing to do for CDC */
|
||||||
|
|
|
@ -28,12 +28,17 @@
|
||||||
#include "dhd_bus.h"
|
#include "dhd_bus.h"
|
||||||
#include "dhd_proto.h"
|
#include "dhd_proto.h"
|
||||||
#include "dhd_dbg.h"
|
#include "dhd_dbg.h"
|
||||||
|
#include "fwil.h"
|
||||||
|
|
||||||
#define BRCM_OUI "\x00\x10\x18"
|
#define BRCM_OUI "\x00\x10\x18"
|
||||||
#define DOT11_OUI_LEN 3
|
#define DOT11_OUI_LEN 3
|
||||||
#define BCMILCP_BCM_SUBTYPE_EVENT 1
|
#define BCMILCP_BCM_SUBTYPE_EVENT 1
|
||||||
#define PKTFILTER_BUF_SIZE 2048
|
#define PKTFILTER_BUF_SIZE 128
|
||||||
#define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */
|
#define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */
|
||||||
|
#define BRCMF_DEFAULT_BCN_TIMEOUT 3
|
||||||
|
#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40
|
||||||
|
#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40
|
||||||
|
#define BRCMF_DEFAULT_PACKET_FILTER "100 0 0 0 0x01 0x00"
|
||||||
|
|
||||||
#define MSGTRACE_VERSION 1
|
#define MSGTRACE_VERSION 1
|
||||||
|
|
||||||
|
@ -88,52 +93,6 @@ brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint
|
|
||||||
brcmf_c_mkiovar_bsscfg(char *name, char *data, uint datalen,
|
|
||||||
char *buf, uint buflen, s32 bssidx)
|
|
||||||
{
|
|
||||||
const s8 *prefix = "bsscfg:";
|
|
||||||
s8 *p;
|
|
||||||
u32 prefixlen;
|
|
||||||
u32 namelen;
|
|
||||||
u32 iolen;
|
|
||||||
__le32 bssidx_le;
|
|
||||||
|
|
||||||
if (bssidx == 0)
|
|
||||||
return brcmf_c_mkiovar(name, data, datalen, buf, buflen);
|
|
||||||
|
|
||||||
prefixlen = (u32) strlen(prefix); /* lengh of bsscfg prefix */
|
|
||||||
namelen = (u32) strlen(name) + 1; /* lengh of iovar name + null */
|
|
||||||
iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen;
|
|
||||||
|
|
||||||
if (buflen < 0 || iolen > (u32)buflen) {
|
|
||||||
brcmf_dbg(ERROR, "buffer is too short\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = buf;
|
|
||||||
|
|
||||||
/* copy prefix, no null */
|
|
||||||
memcpy(p, prefix, prefixlen);
|
|
||||||
p += prefixlen;
|
|
||||||
|
|
||||||
/* copy iovar name including null */
|
|
||||||
memcpy(p, name, namelen);
|
|
||||||
p += namelen;
|
|
||||||
|
|
||||||
/* bss config index as first data */
|
|
||||||
bssidx_le = cpu_to_le32(bssidx);
|
|
||||||
memcpy(p, &bssidx_le, sizeof(bssidx_le));
|
|
||||||
p += sizeof(bssidx_le);
|
|
||||||
|
|
||||||
/* parameter buffer follows */
|
|
||||||
if (datalen)
|
|
||||||
memcpy(p, data, datalen);
|
|
||||||
|
|
||||||
return iolen;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
|
bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
|
||||||
struct sk_buff *pkt, int prec)
|
struct sk_buff *pkt, int prec)
|
||||||
{
|
{
|
||||||
|
@ -490,6 +449,7 @@ brcmf_c_host_event(struct brcmf_pub *drvr, int *ifidx, void *pktdata,
|
||||||
/* check whether packet is a BRCM event pkt */
|
/* check whether packet is a BRCM event pkt */
|
||||||
struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata;
|
struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata;
|
||||||
struct brcmf_if_event *ifevent;
|
struct brcmf_if_event *ifevent;
|
||||||
|
struct brcmf_if *ifp;
|
||||||
char *event_data;
|
char *event_data;
|
||||||
u32 type, status;
|
u32 type, status;
|
||||||
u16 flags;
|
u16 flags;
|
||||||
|
@ -525,12 +485,17 @@ brcmf_c_host_event(struct brcmf_pub *drvr, int *ifidx, void *pktdata,
|
||||||
brcmf_dbg(TRACE, "if event\n");
|
brcmf_dbg(TRACE, "if event\n");
|
||||||
|
|
||||||
if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) {
|
if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) {
|
||||||
if (ifevent->action == BRCMF_E_IF_ADD)
|
if (ifevent->action == BRCMF_E_IF_ADD) {
|
||||||
brcmf_add_if(drvr->dev, ifevent->ifidx,
|
ifp = brcmf_add_if(drvr->dev, ifevent->ifidx,
|
||||||
|
ifevent->bssidx,
|
||||||
event->ifname,
|
event->ifname,
|
||||||
pvt_data->eth.h_dest);
|
pvt_data->eth.h_dest);
|
||||||
else
|
if (IS_ERR(ifp))
|
||||||
|
return PTR_ERR(ifp);
|
||||||
|
brcmf_net_attach(ifp);
|
||||||
|
} else {
|
||||||
brcmf_del_if(drvr, ifevent->ifidx);
|
brcmf_del_if(drvr, ifevent->ifidx);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
brcmf_dbg(ERROR, "Invalid ifidx %d for %s\n",
|
brcmf_dbg(ERROR, "Invalid ifidx %d for %s\n",
|
||||||
ifevent->ifidx, event->ifname);
|
ifevent->ifidx, event->ifname);
|
||||||
|
@ -603,90 +568,57 @@ static int brcmf_c_pattern_atoh(char *src, char *dst)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable,
|
brcmf_c_pktfilter_offload_enable(struct brcmf_if *ifp, char *arg, int enable,
|
||||||
int master_mode)
|
int master_mode)
|
||||||
{
|
{
|
||||||
unsigned long res;
|
unsigned long res;
|
||||||
char *argv[8];
|
char *argv;
|
||||||
int i = 0;
|
|
||||||
const char *str;
|
|
||||||
int buf_len;
|
|
||||||
int str_len;
|
|
||||||
char *arg_save = NULL, *arg_org = NULL;
|
char *arg_save = NULL, *arg_org = NULL;
|
||||||
int rc;
|
s32 err;
|
||||||
char buf[128];
|
|
||||||
struct brcmf_pkt_filter_enable_le enable_parm;
|
struct brcmf_pkt_filter_enable_le enable_parm;
|
||||||
struct brcmf_pkt_filter_enable_le *pkt_filterp;
|
|
||||||
__le32 mmode_le;
|
|
||||||
|
|
||||||
arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC);
|
arg_save = kstrdup(arg, GFP_ATOMIC);
|
||||||
if (!arg_save)
|
if (!arg_save)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
arg_org = arg_save;
|
arg_org = arg_save;
|
||||||
memcpy(arg_save, arg, strlen(arg) + 1);
|
|
||||||
|
|
||||||
argv[i] = strsep(&arg_save, " ");
|
argv = strsep(&arg_save, " ");
|
||||||
|
|
||||||
i = 0;
|
if (argv == NULL) {
|
||||||
if (NULL == argv[i]) {
|
|
||||||
brcmf_dbg(ERROR, "No args provided\n");
|
brcmf_dbg(ERROR, "No args provided\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = "pkt_filter_enable";
|
|
||||||
str_len = strlen(str);
|
|
||||||
strncpy(buf, str, str_len);
|
|
||||||
buf[str_len] = '\0';
|
|
||||||
buf_len = str_len + 1;
|
|
||||||
|
|
||||||
pkt_filterp = (struct brcmf_pkt_filter_enable_le *) (buf + str_len + 1);
|
|
||||||
|
|
||||||
/* Parse packet filter id. */
|
/* Parse packet filter id. */
|
||||||
enable_parm.id = 0;
|
enable_parm.id = 0;
|
||||||
if (!kstrtoul(argv[i], 0, &res))
|
if (!kstrtoul(argv, 0, &res))
|
||||||
enable_parm.id = cpu_to_le32((u32)res);
|
enable_parm.id = cpu_to_le32((u32)res);
|
||||||
|
|
||||||
/* Parse enable/disable value. */
|
/* Enable/disable the specified filter. */
|
||||||
enable_parm.enable = cpu_to_le32(enable);
|
enable_parm.enable = cpu_to_le32(enable);
|
||||||
|
|
||||||
buf_len += sizeof(enable_parm);
|
err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_enable", &enable_parm,
|
||||||
memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm));
|
sizeof(enable_parm));
|
||||||
|
if (err)
|
||||||
|
brcmf_dbg(ERROR, "Set pkt_filter_enable error (%d)\n", err);
|
||||||
|
|
||||||
/* Enable/disable the specified filter. */
|
/* Control the master mode */
|
||||||
rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
|
err = brcmf_fil_iovar_int_set(ifp, "pkt_filter_mode", master_mode);
|
||||||
rc = rc >= 0 ? 0 : rc;
|
if (err)
|
||||||
if (rc)
|
brcmf_dbg(ERROR, "Set pkt_filter_mode error (%d)\n", err);
|
||||||
brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n",
|
|
||||||
arg, rc);
|
|
||||||
else
|
|
||||||
brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg);
|
|
||||||
|
|
||||||
/* Contorl the master mode */
|
|
||||||
mmode_le = cpu_to_le32(master_mode);
|
|
||||||
brcmf_c_mkiovar("pkt_filter_mode", (char *)&mmode_le, 4, buf,
|
|
||||||
sizeof(buf));
|
|
||||||
rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf,
|
|
||||||
sizeof(buf));
|
|
||||||
rc = rc >= 0 ? 0 : rc;
|
|
||||||
if (rc)
|
|
||||||
brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n",
|
|
||||||
arg, rc);
|
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
kfree(arg_org);
|
kfree(arg_org);
|
||||||
}
|
}
|
||||||
|
|
||||||
void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
|
static void brcmf_c_pktfilter_offload_set(struct brcmf_if *ifp, char *arg)
|
||||||
{
|
{
|
||||||
const char *str;
|
struct brcmf_pkt_filter_le *pkt_filter;
|
||||||
struct brcmf_pkt_filter_le pkt_filter;
|
|
||||||
struct brcmf_pkt_filter_le *pkt_filterp;
|
|
||||||
unsigned long res;
|
unsigned long res;
|
||||||
int buf_len;
|
int buf_len;
|
||||||
int str_len;
|
s32 err;
|
||||||
int rc;
|
|
||||||
u32 mask_size;
|
u32 mask_size;
|
||||||
u32 pattern_size;
|
u32 pattern_size;
|
||||||
char *argv[8], *buf = NULL;
|
char *argv[8], *buf = NULL;
|
||||||
|
@ -704,104 +636,64 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
argv[i] = strsep(&arg_save, " ");
|
argv[i] = strsep(&arg_save, " ");
|
||||||
while (argv[i++])
|
while (argv[i]) {
|
||||||
|
i++;
|
||||||
|
if (i >= 8) {
|
||||||
|
brcmf_dbg(ERROR, "Too many parameters\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
argv[i] = strsep(&arg_save, " ");
|
argv[i] = strsep(&arg_save, " ");
|
||||||
|
}
|
||||||
|
|
||||||
i = 0;
|
if (i != 6) {
|
||||||
if (NULL == argv[i]) {
|
brcmf_dbg(ERROR, "Not enough args provided %d\n", i);
|
||||||
brcmf_dbg(ERROR, "No args provided\n");
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = "pkt_filter_add";
|
pkt_filter = (struct brcmf_pkt_filter_le *)buf;
|
||||||
strcpy(buf, str);
|
|
||||||
str_len = strlen(str);
|
|
||||||
buf_len = str_len + 1;
|
|
||||||
|
|
||||||
pkt_filterp = (struct brcmf_pkt_filter_le *) (buf + str_len + 1);
|
|
||||||
|
|
||||||
/* Parse packet filter id. */
|
/* Parse packet filter id. */
|
||||||
pkt_filter.id = 0;
|
pkt_filter->id = 0;
|
||||||
if (!kstrtoul(argv[i], 0, &res))
|
if (!kstrtoul(argv[0], 0, &res))
|
||||||
pkt_filter.id = cpu_to_le32((u32)res);
|
pkt_filter->id = cpu_to_le32((u32)res);
|
||||||
|
|
||||||
if (NULL == argv[++i]) {
|
|
||||||
brcmf_dbg(ERROR, "Polarity not provided\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse filter polarity. */
|
/* Parse filter polarity. */
|
||||||
pkt_filter.negate_match = 0;
|
pkt_filter->negate_match = 0;
|
||||||
if (!kstrtoul(argv[i], 0, &res))
|
if (!kstrtoul(argv[1], 0, &res))
|
||||||
pkt_filter.negate_match = cpu_to_le32((u32)res);
|
pkt_filter->negate_match = cpu_to_le32((u32)res);
|
||||||
|
|
||||||
if (NULL == argv[++i]) {
|
|
||||||
brcmf_dbg(ERROR, "Filter type not provided\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse filter type. */
|
/* Parse filter type. */
|
||||||
pkt_filter.type = 0;
|
pkt_filter->type = 0;
|
||||||
if (!kstrtoul(argv[i], 0, &res))
|
if (!kstrtoul(argv[2], 0, &res))
|
||||||
pkt_filter.type = cpu_to_le32((u32)res);
|
pkt_filter->type = cpu_to_le32((u32)res);
|
||||||
|
|
||||||
if (NULL == argv[++i]) {
|
|
||||||
brcmf_dbg(ERROR, "Offset not provided\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse pattern filter offset. */
|
/* Parse pattern filter offset. */
|
||||||
pkt_filter.u.pattern.offset = 0;
|
pkt_filter->u.pattern.offset = 0;
|
||||||
if (!kstrtoul(argv[i], 0, &res))
|
if (!kstrtoul(argv[3], 0, &res))
|
||||||
pkt_filter.u.pattern.offset = cpu_to_le32((u32)res);
|
pkt_filter->u.pattern.offset = cpu_to_le32((u32)res);
|
||||||
|
|
||||||
if (NULL == argv[++i]) {
|
|
||||||
brcmf_dbg(ERROR, "Bitmask not provided\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse pattern filter mask. */
|
/* Parse pattern filter mask. */
|
||||||
mask_size =
|
mask_size = brcmf_c_pattern_atoh(argv[4],
|
||||||
brcmf_c_pattern_atoh
|
(char *)pkt_filter->u.pattern.mask_and_pattern);
|
||||||
(argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern);
|
|
||||||
|
|
||||||
if (NULL == argv[++i]) {
|
|
||||||
brcmf_dbg(ERROR, "Pattern not provided\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Parse pattern filter pattern. */
|
/* Parse pattern filter pattern. */
|
||||||
pattern_size =
|
pattern_size = brcmf_c_pattern_atoh(argv[5],
|
||||||
brcmf_c_pattern_atoh(argv[i],
|
(char *)&pkt_filter->u.pattern.mask_and_pattern[mask_size]);
|
||||||
(char *)&pkt_filterp->u.pattern.
|
|
||||||
mask_and_pattern[mask_size]);
|
|
||||||
|
|
||||||
if (mask_size != pattern_size) {
|
if (mask_size != pattern_size) {
|
||||||
brcmf_dbg(ERROR, "Mask and pattern not the same size\n");
|
brcmf_dbg(ERROR, "Mask and pattern not the same size\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
pkt_filter.u.pattern.size_bytes = cpu_to_le32(mask_size);
|
pkt_filter->u.pattern.size_bytes = cpu_to_le32(mask_size);
|
||||||
buf_len += BRCMF_PKT_FILTER_FIXED_LEN;
|
buf_len = sizeof(*pkt_filter);
|
||||||
buf_len += (BRCMF_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
|
buf_len -= sizeof(pkt_filter->u.pattern.mask_and_pattern);
|
||||||
|
buf_len += mask_size + pattern_size;
|
||||||
|
|
||||||
/* Keep-alive attributes are set in local
|
err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_add", pkt_filter,
|
||||||
* variable (keep_alive_pkt), and
|
buf_len);
|
||||||
** then memcpy'ed into buffer (keep_alive_pktp) since there is no
|
if (err)
|
||||||
** guarantee that the buffer is properly aligned.
|
brcmf_dbg(ERROR, "Set pkt_filter_add error (%d)\n", err);
|
||||||
*/
|
|
||||||
memcpy((char *)pkt_filterp,
|
|
||||||
&pkt_filter,
|
|
||||||
BRCMF_PKT_FILTER_FIXED_LEN + BRCMF_PKT_FILTER_PATTERN_FIXED_LEN);
|
|
||||||
|
|
||||||
rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len);
|
|
||||||
rc = rc >= 0 ? 0 : rc;
|
|
||||||
|
|
||||||
if (rc)
|
|
||||||
brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n",
|
|
||||||
arg, rc);
|
|
||||||
else
|
|
||||||
brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg);
|
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
kfree(arg_org);
|
kfree(arg_org);
|
||||||
|
@ -809,130 +701,125 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
|
||||||
kfree(buf);
|
kfree(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode)
|
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
|
||||||
{
|
{
|
||||||
char iovbuf[32];
|
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
|
||||||
int retcode;
|
u8 buf[BRCMF_DCMD_SMLEN];
|
||||||
__le32 arp_mode_le;
|
char *ptr;
|
||||||
|
s32 err;
|
||||||
arp_mode_le = cpu_to_le32(arp_mode);
|
|
||||||
brcmf_c_mkiovar("arp_ol", (char *)&arp_mode_le, 4, iovbuf,
|
|
||||||
sizeof(iovbuf));
|
|
||||||
retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
|
|
||||||
iovbuf, sizeof(iovbuf));
|
|
||||||
retcode = retcode >= 0 ? 0 : retcode;
|
|
||||||
if (retcode)
|
|
||||||
brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, retcode = %d\n",
|
|
||||||
arp_mode, retcode);
|
|
||||||
else
|
|
||||||
brcmf_dbg(TRACE, "successfully set ARP offload mode to 0x%x\n",
|
|
||||||
arp_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable)
|
|
||||||
{
|
|
||||||
char iovbuf[32];
|
|
||||||
int retcode;
|
|
||||||
__le32 arp_enable_le;
|
|
||||||
|
|
||||||
arp_enable_le = cpu_to_le32(arp_enable);
|
|
||||||
|
|
||||||
brcmf_c_mkiovar("arpoe", (char *)&arp_enable_le, 4,
|
|
||||||
iovbuf, sizeof(iovbuf));
|
|
||||||
retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
|
|
||||||
iovbuf, sizeof(iovbuf));
|
|
||||||
retcode = retcode >= 0 ? 0 : retcode;
|
|
||||||
if (retcode)
|
|
||||||
brcmf_dbg(TRACE, "failed to enable ARP offload to %d, retcode = %d\n",
|
|
||||||
arp_enable, retcode);
|
|
||||||
else
|
|
||||||
brcmf_dbg(TRACE, "successfully enabled ARP offload to %d\n",
|
|
||||||
arp_enable);
|
|
||||||
}
|
|
||||||
|
|
||||||
int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
|
|
||||||
{
|
|
||||||
char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for
|
|
||||||
"event_msgs" + '\0' + bitvec */
|
|
||||||
char buf[128], *ptr;
|
|
||||||
__le32 roaming_le = cpu_to_le32(1);
|
|
||||||
__le32 bcn_timeout_le = cpu_to_le32(3);
|
|
||||||
__le32 scan_assoc_time_le = cpu_to_le32(40);
|
|
||||||
__le32 scan_unassoc_time_le = cpu_to_le32(40);
|
|
||||||
int i;
|
|
||||||
struct brcmf_bus_dcmd *cmdlst;
|
struct brcmf_bus_dcmd *cmdlst;
|
||||||
struct list_head *cur, *q;
|
struct list_head *cur, *q;
|
||||||
|
|
||||||
mutex_lock(&drvr->proto_block);
|
/* retreive mac address */
|
||||||
|
err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
|
||||||
/* Set Country code */
|
sizeof(ifp->mac_addr));
|
||||||
if (drvr->country_code[0] != 0) {
|
if (err < 0) {
|
||||||
if (brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_COUNTRY,
|
brcmf_dbg(ERROR, "Retreiving cur_etheraddr failed, %d\n",
|
||||||
drvr->country_code,
|
err);
|
||||||
sizeof(drvr->country_code)) < 0)
|
goto done;
|
||||||
brcmf_dbg(ERROR, "country code setting failed\n");
|
|
||||||
}
|
}
|
||||||
|
memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
|
||||||
|
|
||||||
/* query for 'ver' to get version info from firmware */
|
/* query for 'ver' to get version info from firmware */
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
ptr = buf;
|
strcpy(buf, "ver");
|
||||||
brcmf_c_mkiovar("ver", NULL, 0, buf, sizeof(buf));
|
err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
|
||||||
brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, buf, sizeof(buf));
|
if (err < 0) {
|
||||||
|
brcmf_dbg(ERROR, "Retreiving version information failed, %d\n",
|
||||||
|
err);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
ptr = (char *)buf;
|
||||||
strsep(&ptr, "\n");
|
strsep(&ptr, "\n");
|
||||||
/* Print fw version info */
|
/* Print fw version info */
|
||||||
brcmf_dbg(ERROR, "Firmware version = %s\n", buf);
|
brcmf_dbg(ERROR, "Firmware version = %s\n", buf);
|
||||||
|
|
||||||
/* Setup timeout if Beacons are lost and roam is off to report
|
/*
|
||||||
link down */
|
* Setup timeout if Beacons are lost and roam is off to report
|
||||||
brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout_le, 4, iovbuf,
|
* link down
|
||||||
sizeof(iovbuf));
|
*/
|
||||||
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
|
err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout",
|
||||||
sizeof(iovbuf));
|
BRCMF_DEFAULT_BCN_TIMEOUT);
|
||||||
|
if (err) {
|
||||||
/* Enable/Disable build-in roaming to allowed ext supplicant to take
|
brcmf_dbg(ERROR, "bcn_timeout error (%d)\n", err);
|
||||||
of romaing */
|
goto done;
|
||||||
brcmf_c_mkiovar("roam_off", (char *)&roaming_le, 4,
|
|
||||||
iovbuf, sizeof(iovbuf));
|
|
||||||
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
|
|
||||||
sizeof(iovbuf));
|
|
||||||
|
|
||||||
/* Setup event_msgs */
|
|
||||||
brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
|
|
||||||
iovbuf, sizeof(iovbuf));
|
|
||||||
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
|
|
||||||
sizeof(iovbuf));
|
|
||||||
|
|
||||||
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME,
|
|
||||||
(char *)&scan_assoc_time_le, sizeof(scan_assoc_time_le));
|
|
||||||
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME,
|
|
||||||
(char *)&scan_unassoc_time_le, sizeof(scan_unassoc_time_le));
|
|
||||||
|
|
||||||
/* Set and enable ARP offload feature */
|
|
||||||
brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE);
|
|
||||||
brcmf_c_arp_offload_enable(drvr, true);
|
|
||||||
|
|
||||||
/* Set up pkt filter */
|
|
||||||
for (i = 0; i < drvr->pktfilter_count; i++) {
|
|
||||||
brcmf_c_pktfilter_offload_set(drvr, drvr->pktfilter[i]);
|
|
||||||
brcmf_c_pktfilter_offload_enable(drvr, drvr->pktfilter[i],
|
|
||||||
0, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Enable/Disable build-in roaming to allowed ext supplicant to take
|
||||||
|
* of romaing
|
||||||
|
*/
|
||||||
|
err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1);
|
||||||
|
if (err) {
|
||||||
|
brcmf_dbg(ERROR, "roam_off error (%d)\n", err);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup event_msgs, enable E_IF */
|
||||||
|
err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
|
||||||
|
BRCMF_EVENTING_MASK_LEN);
|
||||||
|
if (err) {
|
||||||
|
brcmf_dbg(ERROR, "Get event_msgs error (%d)\n", err);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
setbit(eventmask, BRCMF_E_IF);
|
||||||
|
err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask,
|
||||||
|
BRCMF_EVENTING_MASK_LEN);
|
||||||
|
if (err) {
|
||||||
|
brcmf_dbg(ERROR, "Set event_msgs error (%d)\n", err);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup default scan channel time */
|
||||||
|
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
|
||||||
|
BRCMF_DEFAULT_SCAN_CHANNEL_TIME);
|
||||||
|
if (err) {
|
||||||
|
brcmf_dbg(ERROR, "BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n",
|
||||||
|
err);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup default scan unassoc time */
|
||||||
|
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
|
||||||
|
BRCMF_DEFAULT_SCAN_UNASSOC_TIME);
|
||||||
|
if (err) {
|
||||||
|
brcmf_dbg(ERROR, "BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n",
|
||||||
|
err);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to set and enable ARP offload feature, this may fail */
|
||||||
|
err = brcmf_fil_iovar_int_set(ifp, "arp_ol", BRCMF_ARPOL_MODE);
|
||||||
|
if (err) {
|
||||||
|
brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n",
|
||||||
|
BRCMF_ARPOL_MODE, err);
|
||||||
|
err = 0;
|
||||||
|
} else {
|
||||||
|
err = brcmf_fil_iovar_int_set(ifp, "arpoe", 1);
|
||||||
|
if (err) {
|
||||||
|
brcmf_dbg(TRACE, "failed to enable ARP offload err = %d\n",
|
||||||
|
err);
|
||||||
|
err = 0;
|
||||||
|
} else
|
||||||
|
brcmf_dbg(TRACE, "successfully enabled ARP offload to 0x%x\n",
|
||||||
|
BRCMF_ARPOL_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup packet filter */
|
||||||
|
brcmf_c_pktfilter_offload_set(ifp, BRCMF_DEFAULT_PACKET_FILTER);
|
||||||
|
brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER,
|
||||||
|
0, true);
|
||||||
|
|
||||||
/* set bus specific command if there is any */
|
/* set bus specific command if there is any */
|
||||||
list_for_each_safe(cur, q, &drvr->bus_if->dcmd_list) {
|
list_for_each_safe(cur, q, &ifp->drvr->bus_if->dcmd_list) {
|
||||||
cmdlst = list_entry(cur, struct brcmf_bus_dcmd, list);
|
cmdlst = list_entry(cur, struct brcmf_bus_dcmd, list);
|
||||||
if (cmdlst->name && cmdlst->param && cmdlst->param_len) {
|
if (cmdlst->name && cmdlst->param && cmdlst->param_len) {
|
||||||
brcmf_c_mkiovar(cmdlst->name, cmdlst->param,
|
brcmf_fil_iovar_data_set(ifp, cmdlst->name,
|
||||||
cmdlst->param_len, iovbuf,
|
cmdlst->param,
|
||||||
sizeof(iovbuf));
|
cmdlst->param_len);
|
||||||
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
|
|
||||||
iovbuf, sizeof(iovbuf));
|
|
||||||
}
|
}
|
||||||
list_del(cur);
|
list_del(cur);
|
||||||
kfree(cmdlst);
|
kfree(cmdlst);
|
||||||
}
|
}
|
||||||
|
done:
|
||||||
mutex_unlock(&drvr->proto_block);
|
return err;
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,8 +16,10 @@
|
||||||
#include <linux/debugfs.h>
|
#include <linux/debugfs.h>
|
||||||
#include <linux/if_ether.h>
|
#include <linux/if_ether.h>
|
||||||
#include <linux/if.h>
|
#include <linux/if.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
#include <linux/ieee80211.h>
|
#include <linux/ieee80211.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
|
||||||
#include <defs.h>
|
#include <defs.h>
|
||||||
#include <brcmu_wifi.h>
|
#include <brcmu_wifi.h>
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#define BRCMF_EVENT_VAL 0x0800
|
#define BRCMF_EVENT_VAL 0x0800
|
||||||
#define BRCMF_BTA_VAL 0x1000
|
#define BRCMF_BTA_VAL 0x1000
|
||||||
#define BRCMF_ISCAN_VAL 0x2000
|
#define BRCMF_ISCAN_VAL 0x2000
|
||||||
|
#define BRCMF_FIL_VAL 0x4000
|
||||||
|
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
|
|
||||||
|
@ -56,6 +57,7 @@ do { \
|
||||||
#define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL)
|
#define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL)
|
||||||
#define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL)
|
#define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL)
|
||||||
#define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL)
|
#define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL)
|
||||||
|
#define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL)
|
||||||
|
|
||||||
#else /* (defined DEBUG) || (defined DEBUG) */
|
#else /* (defined DEBUG) || (defined DEBUG) */
|
||||||
|
|
||||||
|
@ -67,6 +69,7 @@ do { \
|
||||||
#define BRCMF_BYTES_ON() 0
|
#define BRCMF_BYTES_ON() 0
|
||||||
#define BRCMF_GLOM_ON() 0
|
#define BRCMF_GLOM_ON() 0
|
||||||
#define BRCMF_EVENT_ON() 0
|
#define BRCMF_EVENT_ON() 0
|
||||||
|
#define BRCMF_FIL_ON() 0
|
||||||
|
|
||||||
#endif /* defined(DEBUG) */
|
#endif /* defined(DEBUG) */
|
||||||
|
|
||||||
|
|
|
@ -52,16 +52,6 @@ MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards");
|
||||||
MODULE_LICENSE("Dual BSD/GPL");
|
MODULE_LICENSE("Dual BSD/GPL");
|
||||||
|
|
||||||
|
|
||||||
/* Interface control information */
|
|
||||||
struct brcmf_if {
|
|
||||||
struct brcmf_pub *drvr; /* back pointer to brcmf_pub */
|
|
||||||
/* OS/stack specifics */
|
|
||||||
struct net_device *ndev;
|
|
||||||
struct net_device_stats stats;
|
|
||||||
int idx; /* iface idx in dongle */
|
|
||||||
u8 mac_addr[ETH_ALEN]; /* assigned MAC address */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Error bits */
|
/* Error bits */
|
||||||
int brcmf_msg_level = BRCMF_ERROR_VAL;
|
int brcmf_msg_level = BRCMF_ERROR_VAL;
|
||||||
module_param(brcmf_msg_level, int, 0);
|
module_param(brcmf_msg_level, int, 0);
|
||||||
|
@ -629,12 +619,9 @@ static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr)
|
||||||
brcmf_dbg(ERROR, "dongle is not up\n");
|
brcmf_dbg(ERROR, "dongle is not up\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* finally, report dongle driver type */
|
/* finally, report dongle driver type */
|
||||||
else if (drvr->iswl)
|
|
||||||
sprintf(info.driver, "wl");
|
|
||||||
else
|
else
|
||||||
sprintf(info.driver, "xx");
|
sprintf(info.driver, "wl");
|
||||||
|
|
||||||
sprintf(info.version, "%lu", drvr->drv_version);
|
sprintf(info.version, "%lu", drvr->drv_version);
|
||||||
if (copy_to_user(uaddr, &info, sizeof(info)))
|
if (copy_to_user(uaddr, &info, sizeof(info)))
|
||||||
|
@ -719,65 +706,6 @@ static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr,
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* called only from within this driver. Sends a command to the dongle. */
|
|
||||||
s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len)
|
|
||||||
{
|
|
||||||
struct brcmf_dcmd dcmd;
|
|
||||||
s32 err = 0;
|
|
||||||
int buflen = 0;
|
|
||||||
bool is_set_key_cmd;
|
|
||||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
|
||||||
struct brcmf_pub *drvr = ifp->drvr;
|
|
||||||
|
|
||||||
memset(&dcmd, 0, sizeof(dcmd));
|
|
||||||
dcmd.cmd = cmd;
|
|
||||||
dcmd.buf = arg;
|
|
||||||
dcmd.len = len;
|
|
||||||
|
|
||||||
if (dcmd.buf != NULL)
|
|
||||||
buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN);
|
|
||||||
|
|
||||||
/* send to dongle (must be up, and wl) */
|
|
||||||
if ((drvr->bus_if->state != BRCMF_BUS_DATA)) {
|
|
||||||
brcmf_dbg(ERROR, "DONGLE_DOWN\n");
|
|
||||||
err = -EIO;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!drvr->iswl) {
|
|
||||||
err = -EIO;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Intercept BRCMF_C_SET_KEY CMD - serialize M4 send and
|
|
||||||
* set key CMD to prevent M4 encryption.
|
|
||||||
*/
|
|
||||||
is_set_key_cmd = ((dcmd.cmd == BRCMF_C_SET_KEY) ||
|
|
||||||
((dcmd.cmd == BRCMF_C_SET_VAR) &&
|
|
||||||
!(strncmp("wsec_key", dcmd.buf, 9))) ||
|
|
||||||
((dcmd.cmd == BRCMF_C_SET_VAR) &&
|
|
||||||
!(strncmp("bsscfg:wsec_key", dcmd.buf, 15))));
|
|
||||||
if (is_set_key_cmd)
|
|
||||||
brcmf_netdev_wait_pend8021x(ndev);
|
|
||||||
|
|
||||||
err = brcmf_proto_dcmd(drvr, ifp->idx, &dcmd, buflen);
|
|
||||||
|
|
||||||
done:
|
|
||||||
if (err > 0)
|
|
||||||
err = 0;
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
int brcmf_netlink_dcmd(struct net_device *ndev, struct brcmf_dcmd *dcmd)
|
|
||||||
{
|
|
||||||
brcmf_dbg(TRACE, "enter: cmd %x buf %p len %d\n",
|
|
||||||
dcmd->cmd, dcmd->buf, dcmd->len);
|
|
||||||
|
|
||||||
return brcmf_exec_dcmd(ndev, dcmd->cmd, dcmd->buf, dcmd->len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int brcmf_netdev_stop(struct net_device *ndev)
|
static int brcmf_netdev_stop(struct net_device *ndev)
|
||||||
{
|
{
|
||||||
struct brcmf_if *ifp = netdev_priv(ndev);
|
struct brcmf_if *ifp = netdev_priv(ndev);
|
||||||
|
@ -851,7 +779,7 @@ static const struct net_device_ops brcmf_netdev_ops_pri = {
|
||||||
.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
|
.ndo_set_rx_mode = brcmf_netdev_set_multicast_list
|
||||||
};
|
};
|
||||||
|
|
||||||
static int brcmf_net_attach(struct brcmf_if *ifp)
|
int brcmf_net_attach(struct brcmf_if *ifp)
|
||||||
{
|
{
|
||||||
struct brcmf_pub *drvr = ifp->drvr;
|
struct brcmf_pub *drvr = ifp->drvr;
|
||||||
struct net_device *ndev;
|
struct net_device *ndev;
|
||||||
|
@ -885,15 +813,6 @@ static int brcmf_net_attach(struct brcmf_if *ifp)
|
||||||
|
|
||||||
memcpy(ndev->dev_addr, temp_addr, ETH_ALEN);
|
memcpy(ndev->dev_addr, temp_addr, ETH_ALEN);
|
||||||
|
|
||||||
/* attach to cfg80211 for primary interface */
|
|
||||||
if (!ifp->idx) {
|
|
||||||
drvr->config = brcmf_cfg80211_attach(ndev, drvr->dev, drvr);
|
|
||||||
if (drvr->config == NULL) {
|
|
||||||
brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (register_netdev(ndev) != 0) {
|
if (register_netdev(ndev) != 0) {
|
||||||
brcmf_dbg(ERROR, "couldn't register the net device\n");
|
brcmf_dbg(ERROR, "couldn't register the net device\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -905,11 +824,12 @@ static int brcmf_net_attach(struct brcmf_if *ifp)
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
ndev->netdev_ops = NULL;
|
ndev->netdev_ops = NULL;
|
||||||
|
free_netdev(ndev);
|
||||||
return -EBADE;
|
return -EBADE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
struct brcmf_if *brcmf_add_if(struct device *dev, int ifidx, s32 bssidx,
|
||||||
brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr)
|
char *name, u8 *mac_addr)
|
||||||
{
|
{
|
||||||
struct brcmf_if *ifp;
|
struct brcmf_if *ifp;
|
||||||
struct net_device *ndev;
|
struct net_device *ndev;
|
||||||
|
@ -936,7 +856,7 @@ brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr)
|
||||||
ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
|
ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup);
|
||||||
if (!ndev) {
|
if (!ndev) {
|
||||||
brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
|
brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
|
||||||
return -ENOMEM;
|
return ERR_PTR(-ENOMEM);
|
||||||
}
|
}
|
||||||
|
|
||||||
ifp = netdev_priv(ndev);
|
ifp = netdev_priv(ndev);
|
||||||
|
@ -944,20 +864,14 @@ brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr)
|
||||||
ifp->drvr = drvr;
|
ifp->drvr = drvr;
|
||||||
drvr->iflist[ifidx] = ifp;
|
drvr->iflist[ifidx] = ifp;
|
||||||
ifp->idx = ifidx;
|
ifp->idx = ifidx;
|
||||||
|
ifp->bssidx = bssidx;
|
||||||
if (mac_addr != NULL)
|
if (mac_addr != NULL)
|
||||||
memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
|
memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN);
|
||||||
|
|
||||||
if (brcmf_net_attach(ifp)) {
|
|
||||||
brcmf_dbg(ERROR, "brcmf_net_attach failed");
|
|
||||||
free_netdev(ifp->ndev);
|
|
||||||
drvr->iflist[ifidx] = NULL;
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
}
|
|
||||||
|
|
||||||
brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n",
|
brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n",
|
||||||
current->pid, ifp->ndev->name);
|
current->pid, ifp->ndev->name);
|
||||||
|
|
||||||
return 0;
|
return ifp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
|
void brcmf_del_if(struct brcmf_pub *drvr, int ifidx)
|
||||||
|
@ -1036,10 +950,9 @@ int brcmf_attach(uint bus_hdrlen, struct device *dev)
|
||||||
int brcmf_bus_start(struct device *dev)
|
int brcmf_bus_start(struct device *dev)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
/* Room for "event_msgs" + '\0' + bitvec */
|
|
||||||
char iovbuf[BRCMF_EVENTING_MASK_LEN + 12];
|
|
||||||
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
|
||||||
struct brcmf_pub *drvr = bus_if->drvr;
|
struct brcmf_pub *drvr = bus_if->drvr;
|
||||||
|
struct brcmf_if *ifp;
|
||||||
|
|
||||||
brcmf_dbg(TRACE, "\n");
|
brcmf_dbg(TRACE, "\n");
|
||||||
|
|
||||||
|
@ -1050,49 +963,30 @@ int brcmf_bus_start(struct device *dev)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN,
|
|
||||||
iovbuf, sizeof(iovbuf));
|
|
||||||
brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, iovbuf,
|
|
||||||
sizeof(iovbuf));
|
|
||||||
memcpy(drvr->eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN);
|
|
||||||
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_SET_SSID);
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_PRUNE);
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_AUTH);
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_REASSOC);
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_REASSOC_IND);
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_DEAUTH_IND);
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_DISASSOC_IND);
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_DISASSOC);
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_JOIN);
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_ASSOC_IND);
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_PSK_SUP);
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_LINK);
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_NDIS_LINK);
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_MIC_ERROR);
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_PMKID_CACHE);
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_TXFAIL);
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_JOIN_START);
|
|
||||||
setbit(drvr->eventmask, BRCMF_E_SCAN_COMPLETE);
|
|
||||||
|
|
||||||
/* enable dongle roaming event */
|
|
||||||
|
|
||||||
drvr->pktfilter_count = 1;
|
|
||||||
/* Setup filter to allow only unicast */
|
|
||||||
drvr->pktfilter[0] = "100 0 0 0 0x01 0x00";
|
|
||||||
|
|
||||||
/* Bus is ready, do any protocol initialization */
|
|
||||||
ret = brcmf_proto_init(drvr);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
/* add primary networking interface */
|
/* add primary networking interface */
|
||||||
ret = brcmf_add_if(dev, 0, "wlan%d", drvr->mac);
|
ifp = brcmf_add_if(dev, 0, 0, "wlan%d", NULL);
|
||||||
if (ret < 0)
|
if (IS_ERR(ifp))
|
||||||
return ret;
|
return PTR_ERR(ifp);
|
||||||
|
|
||||||
/* signal bus ready */
|
/* signal bus ready */
|
||||||
bus_if->state = BRCMF_BUS_DATA;
|
bus_if->state = BRCMF_BUS_DATA;
|
||||||
|
|
||||||
|
/* Bus is ready, do any initialization */
|
||||||
|
ret = brcmf_c_preinit_dcmds(ifp);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
drvr->config = brcmf_cfg80211_attach(drvr);
|
||||||
|
if (drvr->config == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = brcmf_net_attach(ifp);
|
||||||
|
if (ret < 0) {
|
||||||
|
brcmf_dbg(ERROR, "brcmf_net_attach failed");
|
||||||
|
drvr->iflist[0] = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1163,42 +1057,6 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
|
||||||
return pend;
|
return pend;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size)
|
|
||||||
{
|
|
||||||
int ret = 0;
|
|
||||||
struct file *fp;
|
|
||||||
mm_segment_t old_fs;
|
|
||||||
loff_t pos = 0;
|
|
||||||
|
|
||||||
/* change to KERNEL_DS address limit */
|
|
||||||
old_fs = get_fs();
|
|
||||||
set_fs(KERNEL_DS);
|
|
||||||
|
|
||||||
/* open file to write */
|
|
||||||
fp = filp_open("/tmp/mem_dump", O_WRONLY | O_CREAT, 0640);
|
|
||||||
if (!fp) {
|
|
||||||
brcmf_dbg(ERROR, "open file error\n");
|
|
||||||
ret = -1;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write buf to file */
|
|
||||||
fp->f_op->write(fp, (char __user *)buf, size, &pos);
|
|
||||||
|
|
||||||
exit:
|
|
||||||
/* free buf before return */
|
|
||||||
kfree(buf);
|
|
||||||
/* close file before return */
|
|
||||||
if (fp)
|
|
||||||
filp_close(fp, NULL);
|
|
||||||
/* restore previous address limit */
|
|
||||||
set_fs(old_fs);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
#endif /* DEBUG */
|
|
||||||
|
|
||||||
static void brcmf_driver_init(struct work_struct *work)
|
static void brcmf_driver_init(struct work_struct *work)
|
||||||
{
|
{
|
||||||
brcmf_debugfs_init();
|
brcmf_debugfs_init();
|
||||||
|
|
|
@ -27,11 +27,6 @@ extern int brcmf_proto_attach(struct brcmf_pub *drvr);
|
||||||
/* Unlink, frees allocated protocol memory (including brcmf_proto) */
|
/* Unlink, frees allocated protocol memory (including brcmf_proto) */
|
||||||
extern void brcmf_proto_detach(struct brcmf_pub *drvr);
|
extern void brcmf_proto_detach(struct brcmf_pub *drvr);
|
||||||
|
|
||||||
/* Initialize protocol: sync w/dongle state.
|
|
||||||
* Sets dongle media info (iswl, drv_version, mac address).
|
|
||||||
*/
|
|
||||||
extern int brcmf_proto_init(struct brcmf_pub *drvr);
|
|
||||||
|
|
||||||
/* Stop protocol: sync w/dongle state. */
|
/* Stop protocol: sync w/dongle state. */
|
||||||
extern void brcmf_proto_stop(struct brcmf_pub *drvr);
|
extern void brcmf_proto_stop(struct brcmf_pub *drvr);
|
||||||
|
|
||||||
|
@ -45,7 +40,8 @@ extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx,
|
||||||
extern int brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx,
|
extern int brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx,
|
||||||
struct brcmf_dcmd *dcmd, int len);
|
struct brcmf_dcmd *dcmd, int len);
|
||||||
|
|
||||||
extern int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr);
|
/* Sets dongle media info (drv_version, mac address). */
|
||||||
|
extern int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
|
||||||
|
|
||||||
extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx,
|
extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx,
|
||||||
uint cmd, void *buf, uint len);
|
uint cmd, void *buf, uint len);
|
||||||
|
|
|
@ -614,6 +614,12 @@ static const uint max_roundup = 512;
|
||||||
|
|
||||||
#define ALIGNMENT 4
|
#define ALIGNMENT 4
|
||||||
|
|
||||||
|
enum brcmf_sdio_frmtype {
|
||||||
|
BRCMF_SDIO_FT_NORMAL,
|
||||||
|
BRCMF_SDIO_FT_SUPER,
|
||||||
|
BRCMF_SDIO_FT_SUB,
|
||||||
|
};
|
||||||
|
|
||||||
static void pkt_align(struct sk_buff *p, int len, int align)
|
static void pkt_align(struct sk_buff *p, int len, int align)
|
||||||
{
|
{
|
||||||
uint datalign;
|
uint datalign;
|
||||||
|
@ -1032,7 +1038,8 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus)
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
||||||
struct brcmf_sdio_read *rd)
|
struct brcmf_sdio_read *rd,
|
||||||
|
enum brcmf_sdio_frmtype type)
|
||||||
{
|
{
|
||||||
u16 len, checksum;
|
u16 len, checksum;
|
||||||
u8 rx_seq, fc, tx_seq_max;
|
u8 rx_seq, fc, tx_seq_max;
|
||||||
|
@ -1059,6 +1066,15 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
||||||
brcmf_dbg(ERROR, "HW header length error\n");
|
brcmf_dbg(ERROR, "HW header length error\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (type == BRCMF_SDIO_FT_SUPER &&
|
||||||
|
(roundup(len, bus->blocksize) != rd->len)) {
|
||||||
|
brcmf_dbg(ERROR, "HW superframe header length error\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (type == BRCMF_SDIO_FT_SUB && len > rd->len) {
|
||||||
|
brcmf_dbg(ERROR, "HW subframe header length error\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
rd->len = len;
|
rd->len = len;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1071,9 +1087,16 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
||||||
* Byte 5: Maximum Sequence number allow for Tx
|
* Byte 5: Maximum Sequence number allow for Tx
|
||||||
* Byte 6~7: Reserved
|
* Byte 6~7: Reserved
|
||||||
*/
|
*/
|
||||||
|
if (type == BRCMF_SDIO_FT_SUPER &&
|
||||||
|
SDPCM_GLOMDESC(&header[SDPCM_FRAMETAG_LEN])) {
|
||||||
|
brcmf_dbg(ERROR, "Glom descriptor found in superframe head\n");
|
||||||
|
rd->len = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
rx_seq = SDPCM_PACKET_SEQUENCE(&header[SDPCM_FRAMETAG_LEN]);
|
rx_seq = SDPCM_PACKET_SEQUENCE(&header[SDPCM_FRAMETAG_LEN]);
|
||||||
rd->channel = SDPCM_PACKET_CHANNEL(&header[SDPCM_FRAMETAG_LEN]);
|
rd->channel = SDPCM_PACKET_CHANNEL(&header[SDPCM_FRAMETAG_LEN]);
|
||||||
if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL) {
|
if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL &&
|
||||||
|
type != BRCMF_SDIO_FT_SUPER) {
|
||||||
brcmf_dbg(ERROR, "HW header length too long\n");
|
brcmf_dbg(ERROR, "HW header length too long\n");
|
||||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||||
bus->sdcnt.rx_toolong++;
|
bus->sdcnt.rx_toolong++;
|
||||||
|
@ -1081,6 +1104,17 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
||||||
rd->len = 0;
|
rd->len = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (type == BRCMF_SDIO_FT_SUPER && rd->channel != SDPCM_GLOM_CHANNEL) {
|
||||||
|
brcmf_dbg(ERROR, "Wrong channel for superframe\n");
|
||||||
|
rd->len = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (type == BRCMF_SDIO_FT_SUB && rd->channel != SDPCM_DATA_CHANNEL &&
|
||||||
|
rd->channel != SDPCM_EVENT_CHANNEL) {
|
||||||
|
brcmf_dbg(ERROR, "Wrong channel for subframe\n");
|
||||||
|
rd->len = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
rd->dat_offset = SDPCM_DOFFSET_VALUE(&header[SDPCM_FRAMETAG_LEN]);
|
rd->dat_offset = SDPCM_DOFFSET_VALUE(&header[SDPCM_FRAMETAG_LEN]);
|
||||||
if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) {
|
if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) {
|
||||||
brcmf_dbg(ERROR, "seq %d: bad data offset\n", rx_seq);
|
brcmf_dbg(ERROR, "seq %d: bad data offset\n", rx_seq);
|
||||||
|
@ -1095,6 +1129,9 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
||||||
bus->sdcnt.rx_badseq++;
|
bus->sdcnt.rx_badseq++;
|
||||||
rd->seq_num = rx_seq;
|
rd->seq_num = rx_seq;
|
||||||
}
|
}
|
||||||
|
/* no need to check the reset for subframe */
|
||||||
|
if (type == BRCMF_SDIO_FT_SUB)
|
||||||
|
return true;
|
||||||
rd->len_nxtfrm = header[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
|
rd->len_nxtfrm = header[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
|
||||||
if (rd->len_nxtfrm << 4 > MAX_RX_DATASZ) {
|
if (rd->len_nxtfrm << 4 > MAX_RX_DATASZ) {
|
||||||
/* only warm for NON glom packet */
|
/* only warm for NON glom packet */
|
||||||
|
@ -1126,16 +1163,16 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
||||||
u16 dlen, totlen;
|
u16 dlen, totlen;
|
||||||
u8 *dptr, num = 0;
|
u8 *dptr, num = 0;
|
||||||
|
|
||||||
u16 sublen, check;
|
u16 sublen;
|
||||||
struct sk_buff *pfirst, *pnext;
|
struct sk_buff *pfirst, *pnext;
|
||||||
|
|
||||||
int errcode;
|
int errcode;
|
||||||
u8 chan, seq, doff, sfdoff;
|
u8 doff, sfdoff;
|
||||||
u8 txmax;
|
|
||||||
|
|
||||||
int ifidx = 0;
|
int ifidx = 0;
|
||||||
bool usechain = bus->use_rxchain;
|
bool usechain = bus->use_rxchain;
|
||||||
u16 next_len;
|
|
||||||
|
struct brcmf_sdio_read rd_new;
|
||||||
|
|
||||||
/* If packets, issue read(s) and send up packet chain */
|
/* If packets, issue read(s) and send up packet chain */
|
||||||
/* Return sequence numbers consumed? */
|
/* Return sequence numbers consumed? */
|
||||||
|
@ -1279,68 +1316,15 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
||||||
pfirst->data, min_t(int, pfirst->len, 48),
|
pfirst->data, min_t(int, pfirst->len, 48),
|
||||||
"SUPERFRAME:\n");
|
"SUPERFRAME:\n");
|
||||||
|
|
||||||
/* Validate the superframe header */
|
rd_new.seq_num = rxseq;
|
||||||
dptr = (u8 *) (pfirst->data);
|
rd_new.len = dlen;
|
||||||
sublen = get_unaligned_le16(dptr);
|
errcode = -!brcmf_sdio_hdparser(bus, pfirst->data, &rd_new,
|
||||||
check = get_unaligned_le16(dptr + sizeof(u16));
|
BRCMF_SDIO_FT_SUPER);
|
||||||
|
bus->cur_read.len = rd_new.len_nxtfrm << 4;
|
||||||
chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
|
|
||||||
seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
|
|
||||||
next_len = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
|
|
||||||
if ((next_len << 4) > MAX_RX_DATASZ) {
|
|
||||||
brcmf_dbg(INFO, "nextlen too large (%d) seq %d\n",
|
|
||||||
next_len, seq);
|
|
||||||
next_len = 0;
|
|
||||||
}
|
|
||||||
bus->cur_read.len = next_len << 4;
|
|
||||||
doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
|
|
||||||
txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
|
|
||||||
|
|
||||||
errcode = 0;
|
|
||||||
if ((u16)~(sublen ^ check)) {
|
|
||||||
brcmf_dbg(ERROR, "(superframe): HW hdr error: len/check 0x%04x/0x%04x\n",
|
|
||||||
sublen, check);
|
|
||||||
errcode = -1;
|
|
||||||
} else if (roundup(sublen, bus->blocksize) != dlen) {
|
|
||||||
brcmf_dbg(ERROR, "(superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n",
|
|
||||||
sublen, roundup(sublen, bus->blocksize),
|
|
||||||
dlen);
|
|
||||||
errcode = -1;
|
|
||||||
} else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) !=
|
|
||||||
SDPCM_GLOM_CHANNEL) {
|
|
||||||
brcmf_dbg(ERROR, "(superframe): bad channel %d\n",
|
|
||||||
SDPCM_PACKET_CHANNEL(
|
|
||||||
&dptr[SDPCM_FRAMETAG_LEN]));
|
|
||||||
errcode = -1;
|
|
||||||
} else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) {
|
|
||||||
brcmf_dbg(ERROR, "(superframe): got 2nd descriptor?\n");
|
|
||||||
errcode = -1;
|
|
||||||
} else if ((doff < SDPCM_HDRLEN) ||
|
|
||||||
(doff > (pfirst->len - SDPCM_HDRLEN))) {
|
|
||||||
brcmf_dbg(ERROR, "(superframe): Bad data offset %d: HW %d pkt %d min %d\n",
|
|
||||||
doff, sublen, pfirst->len, SDPCM_HDRLEN);
|
|
||||||
errcode = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check sequence number of superframe SW header */
|
|
||||||
if (rxseq != seq) {
|
|
||||||
brcmf_dbg(INFO, "(superframe) rx_seq %d, expected %d\n",
|
|
||||||
seq, rxseq);
|
|
||||||
bus->sdcnt.rx_badseq++;
|
|
||||||
rxseq = seq;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check window for sanity */
|
|
||||||
if ((u8) (txmax - bus->tx_seq) > 0x40) {
|
|
||||||
brcmf_dbg(ERROR, "unlikely tx max %d with tx_seq %d\n",
|
|
||||||
txmax, bus->tx_seq);
|
|
||||||
txmax = bus->tx_seq + 2;
|
|
||||||
}
|
|
||||||
bus->tx_max = txmax;
|
|
||||||
|
|
||||||
/* Remove superframe header, remember offset */
|
/* Remove superframe header, remember offset */
|
||||||
skb_pull(pfirst, doff);
|
skb_pull(pfirst, rd_new.dat_offset);
|
||||||
sfdoff = doff;
|
sfdoff = rd_new.dat_offset;
|
||||||
num = 0;
|
num = 0;
|
||||||
|
|
||||||
/* Validate all the subframe headers */
|
/* Validate all the subframe headers */
|
||||||
|
@ -1349,34 +1333,14 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
||||||
if (errcode)
|
if (errcode)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
dptr = (u8 *) (pnext->data);
|
rd_new.len = pnext->len;
|
||||||
dlen = (u16) (pnext->len);
|
rd_new.seq_num = rxseq++;
|
||||||
sublen = get_unaligned_le16(dptr);
|
errcode = -!brcmf_sdio_hdparser(bus, pnext->data,
|
||||||
check = get_unaligned_le16(dptr + sizeof(u16));
|
&rd_new,
|
||||||
chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
|
BRCMF_SDIO_FT_SUB);
|
||||||
doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
|
|
||||||
brcmf_dbg_hex_dump(BRCMF_GLOM_ON(),
|
brcmf_dbg_hex_dump(BRCMF_GLOM_ON(),
|
||||||
dptr, 32, "subframe:\n");
|
pnext->data, 32, "subframe:\n");
|
||||||
|
|
||||||
if ((u16)~(sublen ^ check)) {
|
|
||||||
brcmf_dbg(ERROR, "(subframe %d): HW hdr error: len/check 0x%04x/0x%04x\n",
|
|
||||||
num, sublen, check);
|
|
||||||
errcode = -1;
|
|
||||||
} else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) {
|
|
||||||
brcmf_dbg(ERROR, "(subframe %d): length mismatch: len 0x%04x, expect 0x%04x\n",
|
|
||||||
num, sublen, dlen);
|
|
||||||
errcode = -1;
|
|
||||||
} else if ((chan != SDPCM_DATA_CHANNEL) &&
|
|
||||||
(chan != SDPCM_EVENT_CHANNEL)) {
|
|
||||||
brcmf_dbg(ERROR, "(subframe %d): bad channel %d\n",
|
|
||||||
num, chan);
|
|
||||||
errcode = -1;
|
|
||||||
} else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
|
|
||||||
brcmf_dbg(ERROR, "(subframe %d): Bad data offset %d: HW %d min %d\n",
|
|
||||||
num, doff, sublen, SDPCM_HDRLEN);
|
|
||||||
errcode = -1;
|
|
||||||
}
|
|
||||||
/* increase the subframe count */
|
|
||||||
num++;
|
num++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1402,27 +1366,11 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
||||||
skb_queue_walk_safe(&bus->glom, pfirst, pnext) {
|
skb_queue_walk_safe(&bus->glom, pfirst, pnext) {
|
||||||
dptr = (u8 *) (pfirst->data);
|
dptr = (u8 *) (pfirst->data);
|
||||||
sublen = get_unaligned_le16(dptr);
|
sublen = get_unaligned_le16(dptr);
|
||||||
chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
|
|
||||||
seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
|
|
||||||
doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
|
doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
|
||||||
|
|
||||||
brcmf_dbg(GLOM, "Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n",
|
|
||||||
num, pfirst, pfirst->data,
|
|
||||||
pfirst->len, sublen, chan, seq);
|
|
||||||
|
|
||||||
/* precondition: chan == SDPCM_DATA_CHANNEL ||
|
|
||||||
chan == SDPCM_EVENT_CHANNEL */
|
|
||||||
|
|
||||||
if (rxseq != seq) {
|
|
||||||
brcmf_dbg(GLOM, "rx_seq %d, expected %d\n",
|
|
||||||
seq, rxseq);
|
|
||||||
bus->sdcnt.rx_badseq++;
|
|
||||||
rxseq = seq;
|
|
||||||
}
|
|
||||||
rxseq++;
|
|
||||||
|
|
||||||
brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(),
|
brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(),
|
||||||
dptr, dlen, "Rx Subframe Data:\n");
|
dptr, pfirst->len,
|
||||||
|
"Rx Subframe Data:\n");
|
||||||
|
|
||||||
__skb_trim(pfirst, sublen);
|
__skb_trim(pfirst, sublen);
|
||||||
skb_pull(pfirst, doff);
|
skb_pull(pfirst, doff);
|
||||||
|
@ -1642,7 +1590,8 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
||||||
bus->rxhdr, SDPCM_HDRLEN,
|
bus->rxhdr, SDPCM_HDRLEN,
|
||||||
"RxHdr:\n");
|
"RxHdr:\n");
|
||||||
|
|
||||||
if (!brcmf_sdio_hdparser(bus, bus->rxhdr, rd)) {
|
if (!brcmf_sdio_hdparser(bus, bus->rxhdr, rd,
|
||||||
|
BRCMF_SDIO_FT_NORMAL)) {
|
||||||
if (!bus->rxpending)
|
if (!bus->rxpending)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
|
@ -1701,7 +1650,8 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
||||||
} else {
|
} else {
|
||||||
memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN);
|
memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN);
|
||||||
rd_new.seq_num = rd->seq_num;
|
rd_new.seq_num = rd->seq_num;
|
||||||
if (!brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new)) {
|
if (!brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new,
|
||||||
|
BRCMF_SDIO_FT_NORMAL)) {
|
||||||
rd->len = 0;
|
rd->len = 0;
|
||||||
brcmu_pkt_buf_free_skb(pkt);
|
brcmu_pkt_buf_free_skb(pkt);
|
||||||
}
|
}
|
||||||
|
|
336
drivers/net/wireless/brcm80211/brcmfmac/fwil.c
Normal file
336
drivers/net/wireless/brcm80211/brcmfmac/fwil.c
Normal file
|
@ -0,0 +1,336 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* FWIL is the Firmware Interface Layer. In this module the support functions
|
||||||
|
* are located to set and get variables to and from the firmware.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/netdevice.h>
|
||||||
|
#include <defs.h>
|
||||||
|
#include <brcmu_utils.h>
|
||||||
|
#include <brcmu_wifi.h>
|
||||||
|
#include "dhd.h"
|
||||||
|
#include "dhd_bus.h"
|
||||||
|
#include "dhd_dbg.h"
|
||||||
|
#include "fwil.h"
|
||||||
|
|
||||||
|
|
||||||
|
static s32
|
||||||
|
brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
|
||||||
|
{
|
||||||
|
struct brcmf_pub *drvr = ifp->drvr;
|
||||||
|
s32 err;
|
||||||
|
|
||||||
|
if (drvr->bus_if->state == BRCMF_BUS_DOWN) {
|
||||||
|
brcmf_dbg(ERROR, "bus is down. we have nothing to do.\n");
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data != NULL)
|
||||||
|
len = min_t(uint, len, BRCMF_DCMD_MAXLEN);
|
||||||
|
if (set)
|
||||||
|
err = brcmf_proto_cdc_set_dcmd(drvr, ifp->idx, cmd, data, len);
|
||||||
|
else
|
||||||
|
err = brcmf_proto_cdc_query_dcmd(drvr, ifp->idx, cmd, data,
|
||||||
|
len);
|
||||||
|
|
||||||
|
if (err >= 0)
|
||||||
|
err = 0;
|
||||||
|
else
|
||||||
|
brcmf_dbg(ERROR, "Failed err=%d\n", err);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32
|
||||||
|
brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
|
||||||
|
{
|
||||||
|
s32 err;
|
||||||
|
|
||||||
|
mutex_lock(&ifp->drvr->proto_block);
|
||||||
|
|
||||||
|
brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
|
||||||
|
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
|
||||||
|
|
||||||
|
err = brcmf_fil_cmd_data(ifp, cmd, data, len, true);
|
||||||
|
mutex_unlock(&ifp->drvr->proto_block);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32
|
||||||
|
brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len)
|
||||||
|
{
|
||||||
|
s32 err;
|
||||||
|
|
||||||
|
mutex_lock(&ifp->drvr->proto_block);
|
||||||
|
err = brcmf_fil_cmd_data(ifp, cmd, data, len, false);
|
||||||
|
|
||||||
|
brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
|
||||||
|
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
|
||||||
|
|
||||||
|
mutex_unlock(&ifp->drvr->proto_block);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
s32
|
||||||
|
brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data)
|
||||||
|
{
|
||||||
|
s32 err;
|
||||||
|
__le32 data_le = cpu_to_le32(data);
|
||||||
|
|
||||||
|
mutex_lock(&ifp->drvr->proto_block);
|
||||||
|
err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), true);
|
||||||
|
mutex_unlock(&ifp->drvr->proto_block);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32
|
||||||
|
brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data)
|
||||||
|
{
|
||||||
|
s32 err;
|
||||||
|
__le32 data_le = cpu_to_le32(*data);
|
||||||
|
|
||||||
|
mutex_lock(&ifp->drvr->proto_block);
|
||||||
|
err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), false);
|
||||||
|
mutex_unlock(&ifp->drvr->proto_block);
|
||||||
|
*data = le32_to_cpu(data_le);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32
|
||||||
|
brcmf_create_iovar(char *name, char *data, u32 datalen, char *buf, u32 buflen)
|
||||||
|
{
|
||||||
|
u32 len;
|
||||||
|
|
||||||
|
len = strlen(name) + 1;
|
||||||
|
|
||||||
|
if ((len + datalen) > buflen)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
memcpy(buf, name, len);
|
||||||
|
|
||||||
|
/* append data onto the end of the name string */
|
||||||
|
if (data && datalen)
|
||||||
|
memcpy(&buf[len], data, datalen);
|
||||||
|
|
||||||
|
return len + datalen;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
s32
|
||||||
|
brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
|
||||||
|
u32 len)
|
||||||
|
{
|
||||||
|
struct brcmf_pub *drvr = ifp->drvr;
|
||||||
|
s32 err;
|
||||||
|
u32 buflen;
|
||||||
|
|
||||||
|
mutex_lock(&drvr->proto_block);
|
||||||
|
|
||||||
|
brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
|
||||||
|
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
|
||||||
|
|
||||||
|
buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
|
||||||
|
sizeof(drvr->proto_buf));
|
||||||
|
if (buflen) {
|
||||||
|
err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
|
||||||
|
buflen, true);
|
||||||
|
} else {
|
||||||
|
err = -EPERM;
|
||||||
|
brcmf_dbg(ERROR, "Creating iovar failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&drvr->proto_block);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32
|
||||||
|
brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
|
||||||
|
u32 len)
|
||||||
|
{
|
||||||
|
struct brcmf_pub *drvr = ifp->drvr;
|
||||||
|
s32 err;
|
||||||
|
u32 buflen;
|
||||||
|
|
||||||
|
mutex_lock(&drvr->proto_block);
|
||||||
|
|
||||||
|
buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf,
|
||||||
|
sizeof(drvr->proto_buf));
|
||||||
|
if (buflen) {
|
||||||
|
err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
|
||||||
|
buflen, false);
|
||||||
|
if (err == 0)
|
||||||
|
memcpy(data, drvr->proto_buf, len);
|
||||||
|
} else {
|
||||||
|
err = -EPERM;
|
||||||
|
brcmf_dbg(ERROR, "Creating iovar failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
|
||||||
|
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
|
||||||
|
|
||||||
|
mutex_unlock(&drvr->proto_block);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32
|
||||||
|
brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data)
|
||||||
|
{
|
||||||
|
__le32 data_le = cpu_to_le32(data);
|
||||||
|
|
||||||
|
return brcmf_fil_iovar_data_set(ifp, name, &data_le, sizeof(data_le));
|
||||||
|
}
|
||||||
|
|
||||||
|
s32
|
||||||
|
brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data)
|
||||||
|
{
|
||||||
|
__le32 data_le = cpu_to_le32(*data);
|
||||||
|
s32 err;
|
||||||
|
|
||||||
|
err = brcmf_fil_iovar_data_get(ifp, name, &data_le, sizeof(data_le));
|
||||||
|
if (err == 0)
|
||||||
|
*data = le32_to_cpu(data_le);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32
|
||||||
|
brcmf_create_bsscfg(s32 bssidx, char *name, char *data, u32 datalen, char *buf,
|
||||||
|
u32 buflen)
|
||||||
|
{
|
||||||
|
const s8 *prefix = "bsscfg:";
|
||||||
|
s8 *p;
|
||||||
|
u32 prefixlen;
|
||||||
|
u32 namelen;
|
||||||
|
u32 iolen;
|
||||||
|
__le32 bssidx_le;
|
||||||
|
|
||||||
|
if (bssidx == 0)
|
||||||
|
return brcmf_create_iovar(name, data, datalen, buf, buflen);
|
||||||
|
|
||||||
|
prefixlen = strlen(prefix);
|
||||||
|
namelen = strlen(name) + 1; /* lengh of iovar name + null */
|
||||||
|
iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen;
|
||||||
|
|
||||||
|
if (buflen < iolen) {
|
||||||
|
brcmf_dbg(ERROR, "buffer is too short\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
|
||||||
|
/* copy prefix, no null */
|
||||||
|
memcpy(p, prefix, prefixlen);
|
||||||
|
p += prefixlen;
|
||||||
|
|
||||||
|
/* copy iovar name including null */
|
||||||
|
memcpy(p, name, namelen);
|
||||||
|
p += namelen;
|
||||||
|
|
||||||
|
/* bss config index as first data */
|
||||||
|
bssidx_le = cpu_to_le32(bssidx);
|
||||||
|
memcpy(p, &bssidx_le, sizeof(bssidx_le));
|
||||||
|
p += sizeof(bssidx_le);
|
||||||
|
|
||||||
|
/* parameter buffer follows */
|
||||||
|
if (datalen)
|
||||||
|
memcpy(p, data, datalen);
|
||||||
|
|
||||||
|
return iolen;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32
|
||||||
|
brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name,
|
||||||
|
void *data, u32 len)
|
||||||
|
{
|
||||||
|
struct brcmf_pub *drvr = ifp->drvr;
|
||||||
|
s32 err;
|
||||||
|
u32 buflen;
|
||||||
|
|
||||||
|
mutex_lock(&drvr->proto_block);
|
||||||
|
|
||||||
|
brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
|
||||||
|
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
|
||||||
|
|
||||||
|
buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len,
|
||||||
|
drvr->proto_buf, sizeof(drvr->proto_buf));
|
||||||
|
if (buflen) {
|
||||||
|
err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf,
|
||||||
|
buflen, true);
|
||||||
|
} else {
|
||||||
|
err = -EPERM;
|
||||||
|
brcmf_dbg(ERROR, "Creating bsscfg failed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&drvr->proto_block);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
s32
|
||||||
|
brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name,
|
||||||
|
void *data, u32 len)
|
||||||
|
{
|
||||||
|
struct brcmf_pub *drvr = ifp->drvr;
|
||||||
|
s32 err;
|
||||||
|
u32 buflen;
|
||||||
|
|
||||||
|
mutex_lock(&drvr->proto_block);
|
||||||
|
|
||||||
|
buflen = brcmf_create_bsscfg(ifp->bssidx, name, NULL, len,
|
||||||
|
drvr->proto_buf, sizeof(drvr->proto_buf));
|
||||||
|
if (buflen) {
|
||||||
|
err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf,
|
||||||
|
buflen, false);
|
||||||
|
if (err == 0)
|
||||||
|
memcpy(data, drvr->proto_buf, len);
|
||||||
|
} else {
|
||||||
|
err = -EPERM;
|
||||||
|
brcmf_dbg(ERROR, "Creating bsscfg failed\n");
|
||||||
|
}
|
||||||
|
brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
|
||||||
|
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data");
|
||||||
|
|
||||||
|
mutex_unlock(&drvr->proto_block);
|
||||||
|
return err;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
s32
|
||||||
|
brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data)
|
||||||
|
{
|
||||||
|
__le32 data_le = cpu_to_le32(data);
|
||||||
|
|
||||||
|
return brcmf_fil_bsscfg_data_set(ifp, name, &data_le,
|
||||||
|
sizeof(data_le));
|
||||||
|
}
|
||||||
|
|
||||||
|
s32
|
||||||
|
brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data)
|
||||||
|
{
|
||||||
|
__le32 data_le = cpu_to_le32(*data);
|
||||||
|
s32 err;
|
||||||
|
|
||||||
|
err = brcmf_fil_bsscfg_data_get(ifp, name, &data_le,
|
||||||
|
sizeof(data_le));
|
||||||
|
if (err == 0)
|
||||||
|
*data = le32_to_cpu(data_le);
|
||||||
|
return err;
|
||||||
|
}
|
39
drivers/net/wireless/brcm80211/brcmfmac/fwil.h
Normal file
39
drivers/net/wireless/brcm80211/brcmfmac/fwil.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2012 Broadcom Corporation
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and/or distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||||
|
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||||
|
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||||
|
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _fwil_h_
|
||||||
|
#define _fwil_h_
|
||||||
|
|
||||||
|
s32 brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len);
|
||||||
|
s32 brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len);
|
||||||
|
s32 brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data);
|
||||||
|
s32 brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data);
|
||||||
|
|
||||||
|
s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data,
|
||||||
|
u32 len);
|
||||||
|
s32 brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data,
|
||||||
|
u32 len);
|
||||||
|
s32 brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data);
|
||||||
|
s32 brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data);
|
||||||
|
|
||||||
|
s32 brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name, void *data,
|
||||||
|
u32 len);
|
||||||
|
s32 brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, void *data,
|
||||||
|
u32 len);
|
||||||
|
s32 brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data);
|
||||||
|
s32 brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data);
|
||||||
|
|
||||||
|
#endif /* _fwil_h_ */
|
|
@ -42,7 +42,6 @@
|
||||||
|
|
||||||
#define IOCTL_RESP_TIMEOUT 2000
|
#define IOCTL_RESP_TIMEOUT 2000
|
||||||
|
|
||||||
#define BRCMF_USB_SYNC_TIMEOUT 300 /* ms */
|
|
||||||
#define BRCMF_USB_DLIMAGE_SPINWAIT 100 /* in unit of ms */
|
#define BRCMF_USB_DLIMAGE_SPINWAIT 100 /* in unit of ms */
|
||||||
#define BRCMF_USB_DLIMAGE_LIMIT 500 /* spinwait limit (ms) */
|
#define BRCMF_USB_DLIMAGE_LIMIT 500 /* spinwait limit (ms) */
|
||||||
|
|
||||||
|
@ -116,10 +115,6 @@ struct brcmf_usbdev_info {
|
||||||
u8 *image; /* buffer for combine fw and nvram */
|
u8 *image; /* buffer for combine fw and nvram */
|
||||||
int image_len;
|
int image_len;
|
||||||
|
|
||||||
wait_queue_head_t wait;
|
|
||||||
bool waitdone;
|
|
||||||
int sync_urb_status;
|
|
||||||
|
|
||||||
struct usb_device *usbdev;
|
struct usb_device *usbdev;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
|
||||||
|
@ -131,7 +126,6 @@ struct brcmf_usbdev_info {
|
||||||
int ctl_urb_status;
|
int ctl_urb_status;
|
||||||
int ctl_completed;
|
int ctl_completed;
|
||||||
wait_queue_head_t ioctl_resp_wait;
|
wait_queue_head_t ioctl_resp_wait;
|
||||||
wait_queue_head_t ctrl_wait;
|
|
||||||
ulong ctl_op;
|
ulong ctl_op;
|
||||||
|
|
||||||
struct urb *bulk_urb; /* used for FW download */
|
struct urb *bulk_urb; /* used for FW download */
|
||||||
|
@ -754,34 +748,14 @@ static void brcmf_usb_down(struct device *dev)
|
||||||
brcmf_usb_free_q(&devinfo->rx_postq, true);
|
brcmf_usb_free_q(&devinfo->rx_postq, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
|
||||||
brcmf_usb_sync_wait(struct brcmf_usbdev_info *devinfo, u16 time)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
int err = 0;
|
|
||||||
int ms = time;
|
|
||||||
|
|
||||||
ret = wait_event_interruptible_timeout(devinfo->wait,
|
|
||||||
devinfo->waitdone == true, (ms * HZ / 1000));
|
|
||||||
|
|
||||||
if ((devinfo->waitdone == false) || (devinfo->sync_urb_status)) {
|
|
||||||
brcmf_dbg(ERROR, "timeout(%d) or urb err=%d\n",
|
|
||||||
ret, devinfo->sync_urb_status);
|
|
||||||
err = -EINVAL;
|
|
||||||
}
|
|
||||||
devinfo->waitdone = false;
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
brcmf_usb_sync_complete(struct urb *urb)
|
brcmf_usb_sync_complete(struct urb *urb)
|
||||||
{
|
{
|
||||||
struct brcmf_usbdev_info *devinfo =
|
struct brcmf_usbdev_info *devinfo =
|
||||||
(struct brcmf_usbdev_info *)urb->context;
|
(struct brcmf_usbdev_info *)urb->context;
|
||||||
|
|
||||||
devinfo->waitdone = true;
|
devinfo->ctl_completed = true;
|
||||||
wake_up_interruptible(&devinfo->wait);
|
brcmf_usb_ioctl_resp_wake(devinfo);
|
||||||
devinfo->sync_urb_status = urb->status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
|
static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
|
||||||
|
@ -813,6 +787,7 @@ static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
|
||||||
(void *) tmpbuf, size,
|
(void *) tmpbuf, size,
|
||||||
(usb_complete_t)brcmf_usb_sync_complete, devinfo);
|
(usb_complete_t)brcmf_usb_sync_complete, devinfo);
|
||||||
|
|
||||||
|
devinfo->ctl_completed = false;
|
||||||
ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
|
ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
|
brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
|
||||||
|
@ -820,11 +795,11 @@ static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT);
|
ret = brcmf_usb_ioctl_resp_wait(devinfo);
|
||||||
memcpy(buffer, tmpbuf, buflen);
|
memcpy(buffer, tmpbuf, buflen);
|
||||||
kfree(tmpbuf);
|
kfree(tmpbuf);
|
||||||
|
|
||||||
return (ret == 0);
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
|
@ -918,13 +893,14 @@ brcmf_usb_dl_send_bulk(struct brcmf_usbdev_info *devinfo, void *buffer, int len)
|
||||||
|
|
||||||
devinfo->bulk_urb->transfer_flags |= URB_ZERO_PACKET;
|
devinfo->bulk_urb->transfer_flags |= URB_ZERO_PACKET;
|
||||||
|
|
||||||
|
devinfo->ctl_completed = false;
|
||||||
ret = usb_submit_urb(devinfo->bulk_urb, GFP_ATOMIC);
|
ret = usb_submit_urb(devinfo->bulk_urb, GFP_ATOMIC);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
|
brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT);
|
ret = brcmf_usb_ioctl_resp_wait(devinfo);
|
||||||
return ret;
|
return (ret == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -1284,7 +1260,6 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
init_waitqueue_head(&devinfo->wait);
|
|
||||||
if (!brcmf_usb_dlneeded(devinfo))
|
if (!brcmf_usb_dlneeded(devinfo))
|
||||||
return &devinfo->bus_pub;
|
return &devinfo->bus_pub;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -127,15 +127,15 @@ do { \
|
||||||
#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */
|
#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */
|
||||||
#define IE_MAX_LEN 512
|
#define IE_MAX_LEN 512
|
||||||
|
|
||||||
/* dongle status */
|
/**
|
||||||
enum wl_status {
|
* enum brcmf_scan_status - dongle scan status
|
||||||
WL_STATUS_READY,
|
*
|
||||||
WL_STATUS_SCANNING,
|
* @BRCMF_SCAN_STATUS_BUSY: scanning in progress on dongle.
|
||||||
WL_STATUS_SCAN_ABORTING,
|
* @BRCMF_SCAN_STATUS_ABORT: scan being aborted on dongle.
|
||||||
WL_STATUS_CONNECTING,
|
*/
|
||||||
WL_STATUS_CONNECTED,
|
enum brcmf_scan_status {
|
||||||
WL_STATUS_AP_CREATING,
|
BRCMF_SCAN_STATUS_BUSY,
|
||||||
WL_STATUS_AP_CREATED
|
BRCMF_SCAN_STATUS_ABORT,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* wi-fi mode */
|
/* wi-fi mode */
|
||||||
|
@ -145,19 +145,6 @@ enum wl_mode {
|
||||||
WL_MODE_AP
|
WL_MODE_AP
|
||||||
};
|
};
|
||||||
|
|
||||||
/* dongle profile list */
|
|
||||||
enum wl_prof_list {
|
|
||||||
WL_PROF_MODE,
|
|
||||||
WL_PROF_SSID,
|
|
||||||
WL_PROF_SEC,
|
|
||||||
WL_PROF_IBSS,
|
|
||||||
WL_PROF_BAND,
|
|
||||||
WL_PROF_BSSID,
|
|
||||||
WL_PROF_ACT,
|
|
||||||
WL_PROF_BEACONINT,
|
|
||||||
WL_PROF_DTIMPERIOD
|
|
||||||
};
|
|
||||||
|
|
||||||
/* dongle iscan state */
|
/* dongle iscan state */
|
||||||
enum wl_iscan_state {
|
enum wl_iscan_state {
|
||||||
WL_ISCAN_STATE_IDLE,
|
WL_ISCAN_STATE_IDLE,
|
||||||
|
@ -214,25 +201,73 @@ struct brcmf_cfg80211_security {
|
||||||
u32 wpa_auth;
|
u32 wpa_auth;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ibss information for currently joined ibss network */
|
/**
|
||||||
struct brcmf_cfg80211_ibss {
|
* struct brcmf_cfg80211_profile - profile information.
|
||||||
u8 beacon_interval; /* in millisecond */
|
*
|
||||||
u8 atim; /* in millisecond */
|
* @ssid: ssid of associated/associating ap.
|
||||||
s8 join_only;
|
* @bssid: bssid of joined/joining ibss.
|
||||||
u8 band;
|
* @sec: security information.
|
||||||
u8 channel;
|
*/
|
||||||
};
|
|
||||||
|
|
||||||
/* dongle profile */
|
|
||||||
struct brcmf_cfg80211_profile {
|
struct brcmf_cfg80211_profile {
|
||||||
u32 mode;
|
|
||||||
struct brcmf_ssid ssid;
|
struct brcmf_ssid ssid;
|
||||||
u8 bssid[ETH_ALEN];
|
u8 bssid[ETH_ALEN];
|
||||||
u16 beacon_interval;
|
|
||||||
u8 dtim_period;
|
|
||||||
struct brcmf_cfg80211_security sec;
|
struct brcmf_cfg80211_security sec;
|
||||||
struct brcmf_cfg80211_ibss ibss;
|
};
|
||||||
s32 band;
|
|
||||||
|
/**
|
||||||
|
* enum brcmf_vif_status - bit indices for vif status.
|
||||||
|
*
|
||||||
|
* @BRCMF_VIF_STATUS_READY: ready for operation.
|
||||||
|
* @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress.
|
||||||
|
* @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully.
|
||||||
|
* @BRCMF_VIF_STATUS_AP_CREATING: interface configured for AP operation.
|
||||||
|
* @BRCMF_VIF_STATUS_AP_CREATED: AP operation started.
|
||||||
|
*/
|
||||||
|
enum brcmf_vif_status {
|
||||||
|
BRCMF_VIF_STATUS_READY,
|
||||||
|
BRCMF_VIF_STATUS_CONNECTING,
|
||||||
|
BRCMF_VIF_STATUS_CONNECTED,
|
||||||
|
BRCMF_VIF_STATUS_AP_CREATING,
|
||||||
|
BRCMF_VIF_STATUS_AP_CREATED
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct vif_saved_ie - holds saved IEs for a virtual interface.
|
||||||
|
*
|
||||||
|
* @probe_res_ie: IE info for probe response.
|
||||||
|
* @beacon_ie: IE info for beacon frame.
|
||||||
|
* @probe_res_ie_len: IE info length for probe response.
|
||||||
|
* @beacon_ie_len: IE info length for beacon frame.
|
||||||
|
*/
|
||||||
|
struct vif_saved_ie {
|
||||||
|
u8 probe_res_ie[IE_MAX_LEN];
|
||||||
|
u8 beacon_ie[IE_MAX_LEN];
|
||||||
|
u32 probe_res_ie_len;
|
||||||
|
u32 beacon_ie_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct brcmf_cfg80211_vif - virtual interface specific information.
|
||||||
|
*
|
||||||
|
* @ifp: lower layer interface pointer
|
||||||
|
* @wdev: wireless device.
|
||||||
|
* @profile: profile information.
|
||||||
|
* @mode: operating mode.
|
||||||
|
* @roam_off: roaming state.
|
||||||
|
* @sme_state: SME state using enum brcmf_vif_status bits.
|
||||||
|
* @pm_block: power-management blocked.
|
||||||
|
* @list: linked list.
|
||||||
|
*/
|
||||||
|
struct brcmf_cfg80211_vif {
|
||||||
|
struct brcmf_if *ifp;
|
||||||
|
struct wireless_dev wdev;
|
||||||
|
struct brcmf_cfg80211_profile profile;
|
||||||
|
s32 mode;
|
||||||
|
s32 roam_off;
|
||||||
|
unsigned long sme_state;
|
||||||
|
bool pm_block;
|
||||||
|
struct vif_saved_ie saved_ie;
|
||||||
|
struct list_head list;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* dongle iscan event loop */
|
/* dongle iscan event loop */
|
||||||
|
@ -383,7 +418,7 @@ struct brcmf_pno_scanresults_le {
|
||||||
/**
|
/**
|
||||||
* struct brcmf_cfg80211_info - dongle private data of cfg80211 interface
|
* struct brcmf_cfg80211_info - dongle private data of cfg80211 interface
|
||||||
*
|
*
|
||||||
* @wdev: representing wl cfg80211 device.
|
* @wiphy: wiphy object for cfg80211 interface.
|
||||||
* @conf: dongle configuration.
|
* @conf: dongle configuration.
|
||||||
* @scan_request: cfg80211 scan request object.
|
* @scan_request: cfg80211 scan request object.
|
||||||
* @el: main event loop.
|
* @el: main event loop.
|
||||||
|
@ -395,12 +430,11 @@ struct brcmf_pno_scanresults_le {
|
||||||
* @scan_req_int: internal scan request object.
|
* @scan_req_int: internal scan request object.
|
||||||
* @bss_info: bss information for cfg80211 layer.
|
* @bss_info: bss information for cfg80211 layer.
|
||||||
* @ie: information element object for internal purpose.
|
* @ie: information element object for internal purpose.
|
||||||
* @profile: holding dongle profile.
|
|
||||||
* @iscan: iscan controller information.
|
* @iscan: iscan controller information.
|
||||||
* @conn_info: association info.
|
* @conn_info: association info.
|
||||||
* @pmk_list: wpa2 pmk list.
|
* @pmk_list: wpa2 pmk list.
|
||||||
* @event_work: event handler work struct.
|
* @event_work: event handler work struct.
|
||||||
* @status: current dongle status.
|
* @scan_status: scan activity on the dongle.
|
||||||
* @pub: common driver information.
|
* @pub: common driver information.
|
||||||
* @channel: current channel.
|
* @channel: current channel.
|
||||||
* @iscan_on: iscan on/off switch.
|
* @iscan_on: iscan on/off switch.
|
||||||
|
@ -422,10 +456,11 @@ struct brcmf_pno_scanresults_le {
|
||||||
* @escan_timeout_work: scan timeout worker.
|
* @escan_timeout_work: scan timeout worker.
|
||||||
* @escan_ioctl_buf: dongle command buffer for escan commands.
|
* @escan_ioctl_buf: dongle command buffer for escan commands.
|
||||||
* @ap_info: host ap information.
|
* @ap_info: host ap information.
|
||||||
* @ci: used to link this structure to netdev private data.
|
* @vif_list: linked list of vif instances.
|
||||||
|
* @vif_cnt: number of vif instances.
|
||||||
*/
|
*/
|
||||||
struct brcmf_cfg80211_info {
|
struct brcmf_cfg80211_info {
|
||||||
struct wireless_dev *wdev;
|
struct wiphy *wiphy;
|
||||||
struct brcmf_cfg80211_conf *conf;
|
struct brcmf_cfg80211_conf *conf;
|
||||||
struct cfg80211_scan_request *scan_request;
|
struct cfg80211_scan_request *scan_request;
|
||||||
struct brcmf_cfg80211_event_loop el;
|
struct brcmf_cfg80211_event_loop el;
|
||||||
|
@ -437,12 +472,11 @@ struct brcmf_cfg80211_info {
|
||||||
struct brcmf_cfg80211_scan_req *scan_req_int;
|
struct brcmf_cfg80211_scan_req *scan_req_int;
|
||||||
struct wl_cfg80211_bss_info *bss_info;
|
struct wl_cfg80211_bss_info *bss_info;
|
||||||
struct brcmf_cfg80211_ie ie;
|
struct brcmf_cfg80211_ie ie;
|
||||||
struct brcmf_cfg80211_profile *profile;
|
|
||||||
struct brcmf_cfg80211_iscan_ctrl *iscan;
|
struct brcmf_cfg80211_iscan_ctrl *iscan;
|
||||||
struct brcmf_cfg80211_connect_info conn_info;
|
struct brcmf_cfg80211_connect_info conn_info;
|
||||||
struct brcmf_cfg80211_pmk_list *pmk_list;
|
struct brcmf_cfg80211_pmk_list *pmk_list;
|
||||||
struct work_struct event_work;
|
struct work_struct event_work;
|
||||||
unsigned long status;
|
unsigned long scan_status;
|
||||||
struct brcmf_pub *pub;
|
struct brcmf_pub *pub;
|
||||||
u32 channel;
|
u32 channel;
|
||||||
bool iscan_on;
|
bool iscan_on;
|
||||||
|
@ -464,11 +498,13 @@ struct brcmf_cfg80211_info {
|
||||||
struct work_struct escan_timeout_work;
|
struct work_struct escan_timeout_work;
|
||||||
u8 *escan_ioctl_buf;
|
u8 *escan_ioctl_buf;
|
||||||
struct ap_info *ap_info;
|
struct ap_info *ap_info;
|
||||||
|
struct list_head vif_list;
|
||||||
|
u8 vif_cnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *w)
|
static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *cfg)
|
||||||
{
|
{
|
||||||
return w->wdev->wiphy;
|
return cfg->wiphy;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct brcmf_cfg80211_info *wiphy_to_cfg(struct wiphy *w)
|
static inline struct brcmf_cfg80211_info *wiphy_to_cfg(struct wiphy *w)
|
||||||
|
@ -481,9 +517,12 @@ static inline struct brcmf_cfg80211_info *wdev_to_cfg(struct wireless_dev *wd)
|
||||||
return (struct brcmf_cfg80211_info *)(wdev_priv(wd));
|
return (struct brcmf_cfg80211_info *)(wdev_priv(wd));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg)
|
static inline
|
||||||
|
struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg)
|
||||||
{
|
{
|
||||||
return cfg->wdev->netdev;
|
struct brcmf_cfg80211_vif *vif;
|
||||||
|
vif = list_first_entry(&cfg->vif_list, struct brcmf_cfg80211_vif, list);
|
||||||
|
return vif->wdev.netdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev)
|
static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev)
|
||||||
|
@ -491,6 +530,12 @@ static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev)
|
||||||
return wdev_to_cfg(ndev->ieee80211_ptr);
|
return wdev_to_cfg(ndev->ieee80211_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline struct brcmf_cfg80211_profile *ndev_to_prof(struct net_device *nd)
|
||||||
|
{
|
||||||
|
struct brcmf_if *ifp = netdev_priv(nd);
|
||||||
|
return &ifp->vif->profile;
|
||||||
|
}
|
||||||
|
|
||||||
#define iscan_to_cfg(i) ((struct brcmf_cfg80211_info *)(i->data))
|
#define iscan_to_cfg(i) ((struct brcmf_cfg80211_info *)(i->data))
|
||||||
#define cfg_to_iscan(w) (w->iscan)
|
#define cfg_to_iscan(w) (w->iscan)
|
||||||
|
|
||||||
|
@ -500,9 +545,7 @@ brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg)
|
||||||
return &cfg->conn_info;
|
return &cfg->conn_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct net_device *ndev,
|
struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr);
|
||||||
struct device *busdev,
|
|
||||||
struct brcmf_pub *drvr);
|
|
||||||
void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
|
void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
|
||||||
|
|
||||||
/* event handler from dongle */
|
/* event handler from dongle */
|
||||||
|
|
|
@ -692,7 +692,7 @@ void ai_pci_up(struct si_pub *sih)
|
||||||
sii = container_of(sih, struct si_info, pub);
|
sii = container_of(sih, struct si_info, pub);
|
||||||
|
|
||||||
if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
|
if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
|
||||||
bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, true);
|
bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci[0], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unconfigure and/or apply various WARs when going down */
|
/* Unconfigure and/or apply various WARs when going down */
|
||||||
|
@ -703,7 +703,7 @@ void ai_pci_down(struct si_pub *sih)
|
||||||
sii = container_of(sih, struct si_info, pub);
|
sii = container_of(sih, struct si_info, pub);
|
||||||
|
|
||||||
if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
|
if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI)
|
||||||
bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, false);
|
bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci[0], false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Enable BT-COEX & Ex-PA for 4313 */
|
/* Enable BT-COEX & Ex-PA for 4313 */
|
||||||
|
|
|
@ -5077,7 +5077,7 @@ static int brcms_b_up_prep(struct brcms_hardware *wlc_hw)
|
||||||
* Configure pci/pcmcia here instead of in brcms_c_attach()
|
* Configure pci/pcmcia here instead of in brcms_c_attach()
|
||||||
* to allow mfg hotswap: down, hotswap (chip power cycle), up.
|
* to allow mfg hotswap: down, hotswap (chip power cycle), up.
|
||||||
*/
|
*/
|
||||||
bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci, wlc_hw->d11core,
|
bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci[0], wlc_hw->d11core,
|
||||||
true);
|
true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -415,7 +415,7 @@ static void hostap_rx_sta_beacon(local_info_t *local, struct sk_buff *skb,
|
||||||
ssid = pos + 2;
|
ssid = pos + 2;
|
||||||
ssid_len = pos[1];
|
ssid_len = pos[1];
|
||||||
break;
|
break;
|
||||||
case WLAN_EID_GENERIC:
|
case WLAN_EID_VENDOR_SPECIFIC:
|
||||||
if (pos[1] >= 4 &&
|
if (pos[1] >= 4 &&
|
||||||
pos[2] == 0x00 && pos[3] == 0x50 &&
|
pos[2] == 0x00 && pos[3] == 0x50 &&
|
||||||
pos[4] == 0xf2 && pos[5] == 1) {
|
pos[4] == 0xf2 && pos[5] == 1) {
|
||||||
|
|
|
@ -1108,7 +1108,7 @@ static const char *get_info_element_string(u16 id)
|
||||||
MFIE_STRING(ERP_INFO);
|
MFIE_STRING(ERP_INFO);
|
||||||
MFIE_STRING(RSN);
|
MFIE_STRING(RSN);
|
||||||
MFIE_STRING(EXT_SUPP_RATES);
|
MFIE_STRING(EXT_SUPP_RATES);
|
||||||
MFIE_STRING(GENERIC);
|
MFIE_STRING(VENDOR_SPECIFIC);
|
||||||
MFIE_STRING(QOS_PARAMETER);
|
MFIE_STRING(QOS_PARAMETER);
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
|
@ -1248,8 +1248,8 @@ static int libipw_parse_info_param(struct libipw_info_element
|
||||||
LIBIPW_DEBUG_MGMT("WLAN_EID_CHALLENGE: ignored\n");
|
LIBIPW_DEBUG_MGMT("WLAN_EID_CHALLENGE: ignored\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WLAN_EID_GENERIC:
|
case WLAN_EID_VENDOR_SPECIFIC:
|
||||||
LIBIPW_DEBUG_MGMT("WLAN_EID_GENERIC: %d bytes\n",
|
LIBIPW_DEBUG_MGMT("WLAN_EID_VENDOR_SPECIFIC: %d bytes\n",
|
||||||
info_element->len);
|
info_element->len);
|
||||||
if (!libipw_parse_qos_info_param_IE(info_element,
|
if (!libipw_parse_qos_info_param_IE(info_element,
|
||||||
network))
|
network))
|
||||||
|
|
|
@ -1191,8 +1191,6 @@ static void iwl_option_config(struct iwl_priv *priv)
|
||||||
|
|
||||||
static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
|
static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
|
||||||
{
|
{
|
||||||
u16 radio_cfg;
|
|
||||||
|
|
||||||
priv->eeprom_data->sku = priv->eeprom_data->sku;
|
priv->eeprom_data->sku = priv->eeprom_data->sku;
|
||||||
|
|
||||||
if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE &&
|
if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE &&
|
||||||
|
@ -1208,8 +1206,6 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
|
||||||
|
|
||||||
IWL_INFO(priv, "Device SKU: 0x%X\n", priv->eeprom_data->sku);
|
IWL_INFO(priv, "Device SKU: 0x%X\n", priv->eeprom_data->sku);
|
||||||
|
|
||||||
radio_cfg = priv->eeprom_data->radio_cfg;
|
|
||||||
|
|
||||||
priv->hw_params.tx_chains_num =
|
priv->hw_params.tx_chains_num =
|
||||||
num_of_ant(priv->eeprom_data->valid_tx_ant);
|
num_of_ant(priv->eeprom_data->valid_tx_ant);
|
||||||
if (priv->cfg->rx_with_siso_diversity)
|
if (priv->cfg->rx_with_siso_diversity)
|
||||||
|
@ -1334,6 +1330,9 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
|
||||||
/* Configure transport layer */
|
/* Configure transport layer */
|
||||||
iwl_trans_configure(priv->trans, &trans_cfg);
|
iwl_trans_configure(priv->trans, &trans_cfg);
|
||||||
|
|
||||||
|
trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
|
||||||
|
trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start);
|
||||||
|
|
||||||
/* At this point both hw and priv are allocated. */
|
/* At this point both hw and priv are allocated. */
|
||||||
|
|
||||||
SET_IEEE80211_DEV(priv->hw, priv->trans->dev);
|
SET_IEEE80211_DEV(priv->hw, priv->trans->dev);
|
||||||
|
@ -2152,8 +2151,6 @@ static int __init iwl_init(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
|
|
||||||
pr_info(DRV_COPYRIGHT "\n");
|
|
||||||
|
|
||||||
ret = iwlagn_rate_control_register();
|
ret = iwlagn_rate_control_register();
|
||||||
if (ret) {
|
if (ret) {
|
||||||
|
|
|
@ -25,6 +25,39 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ)
|
#if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ)
|
||||||
|
#include <linux/skbuff.h>
|
||||||
|
#include <linux/ieee80211.h>
|
||||||
|
#include <net/cfg80211.h>
|
||||||
|
#include "iwl-trans.h"
|
||||||
|
#if !defined(__IWLWIFI_DEVICE_TRACE)
|
||||||
|
static inline bool iwl_trace_data(struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
struct ieee80211_hdr *hdr = (void *)skb->data;
|
||||||
|
|
||||||
|
if (ieee80211_is_data(hdr->frame_control))
|
||||||
|
return skb->protocol != cpu_to_be16(ETH_P_PAE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline size_t iwl_rx_trace_len(const struct iwl_trans *trans,
|
||||||
|
void *rxbuf, size_t len)
|
||||||
|
{
|
||||||
|
struct iwl_cmd_header *cmd = (void *)((u8 *)rxbuf + sizeof(__le32));
|
||||||
|
struct ieee80211_hdr *hdr;
|
||||||
|
|
||||||
|
if (cmd->cmd != trans->rx_mpdu_cmd)
|
||||||
|
return len;
|
||||||
|
|
||||||
|
hdr = (void *)((u8 *)cmd + sizeof(struct iwl_cmd_header) +
|
||||||
|
trans->rx_mpdu_cmd_hdr_size);
|
||||||
|
if (!ieee80211_is_data(hdr->frame_control))
|
||||||
|
return len;
|
||||||
|
/* maybe try to identify EAPOL frames? */
|
||||||
|
return sizeof(__le32) + sizeof(*cmd) + trans->rx_mpdu_cmd_hdr_size +
|
||||||
|
ieee80211_hdrlen(hdr->frame_control);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#define __IWLWIFI_DEVICE_TRACE
|
#define __IWLWIFI_DEVICE_TRACE
|
||||||
|
|
||||||
#include <linux/tracepoint.h>
|
#include <linux/tracepoint.h>
|
||||||
|
@ -234,6 +267,48 @@ TRACE_EVENT(iwlwifi_dbg,
|
||||||
TP_printk("%s", (char *)__get_dynamic_array(msg))
|
TP_printk("%s", (char *)__get_dynamic_array(msg))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#undef TRACE_SYSTEM
|
||||||
|
#define TRACE_SYSTEM iwlwifi_data
|
||||||
|
|
||||||
|
TRACE_EVENT(iwlwifi_dev_tx_data,
|
||||||
|
TP_PROTO(const struct device *dev,
|
||||||
|
struct sk_buff *skb,
|
||||||
|
void *data, size_t data_len),
|
||||||
|
TP_ARGS(dev, skb, data, data_len),
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
DEV_ENTRY
|
||||||
|
|
||||||
|
__dynamic_array(u8, data, iwl_trace_data(skb) ? data_len : 0)
|
||||||
|
),
|
||||||
|
TP_fast_assign(
|
||||||
|
DEV_ASSIGN;
|
||||||
|
if (iwl_trace_data(skb))
|
||||||
|
memcpy(__get_dynamic_array(data), data, data_len);
|
||||||
|
),
|
||||||
|
TP_printk("[%s] TX frame data", __get_str(dev))
|
||||||
|
);
|
||||||
|
|
||||||
|
TRACE_EVENT(iwlwifi_dev_rx_data,
|
||||||
|
TP_PROTO(const struct device *dev,
|
||||||
|
const struct iwl_trans *trans,
|
||||||
|
void *rxbuf, size_t len),
|
||||||
|
TP_ARGS(dev, trans, rxbuf, len),
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
DEV_ENTRY
|
||||||
|
|
||||||
|
__dynamic_array(u8, data,
|
||||||
|
len - iwl_rx_trace_len(trans, rxbuf, len))
|
||||||
|
),
|
||||||
|
TP_fast_assign(
|
||||||
|
size_t offs = iwl_rx_trace_len(trans, rxbuf, len);
|
||||||
|
DEV_ASSIGN;
|
||||||
|
if (offs < len)
|
||||||
|
memcpy(__get_dynamic_array(data),
|
||||||
|
((u8 *)rxbuf) + offs, len - offs);
|
||||||
|
),
|
||||||
|
TP_printk("[%s] TX frame data", __get_str(dev))
|
||||||
|
);
|
||||||
|
|
||||||
#undef TRACE_SYSTEM
|
#undef TRACE_SYSTEM
|
||||||
#define TRACE_SYSTEM iwlwifi
|
#define TRACE_SYSTEM iwlwifi
|
||||||
|
|
||||||
|
@ -270,25 +345,28 @@ TRACE_EVENT(iwlwifi_dev_hcmd,
|
||||||
);
|
);
|
||||||
|
|
||||||
TRACE_EVENT(iwlwifi_dev_rx,
|
TRACE_EVENT(iwlwifi_dev_rx,
|
||||||
TP_PROTO(const struct device *dev, void *rxbuf, size_t len),
|
TP_PROTO(const struct device *dev, const struct iwl_trans *trans,
|
||||||
TP_ARGS(dev, rxbuf, len),
|
void *rxbuf, size_t len),
|
||||||
|
TP_ARGS(dev, trans, rxbuf, len),
|
||||||
TP_STRUCT__entry(
|
TP_STRUCT__entry(
|
||||||
DEV_ENTRY
|
DEV_ENTRY
|
||||||
__dynamic_array(u8, rxbuf, len)
|
__dynamic_array(u8, rxbuf, iwl_rx_trace_len(trans, rxbuf, len))
|
||||||
),
|
),
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
DEV_ASSIGN;
|
DEV_ASSIGN;
|
||||||
memcpy(__get_dynamic_array(rxbuf), rxbuf, len);
|
memcpy(__get_dynamic_array(rxbuf), rxbuf,
|
||||||
|
iwl_rx_trace_len(trans, rxbuf, len));
|
||||||
),
|
),
|
||||||
TP_printk("[%s] RX cmd %#.2x",
|
TP_printk("[%s] RX cmd %#.2x",
|
||||||
__get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4])
|
__get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4])
|
||||||
);
|
);
|
||||||
|
|
||||||
TRACE_EVENT(iwlwifi_dev_tx,
|
TRACE_EVENT(iwlwifi_dev_tx,
|
||||||
TP_PROTO(const struct device *dev, void *tfd, size_t tfdlen,
|
TP_PROTO(const struct device *dev, struct sk_buff *skb,
|
||||||
|
void *tfd, size_t tfdlen,
|
||||||
void *buf0, size_t buf0_len,
|
void *buf0, size_t buf0_len,
|
||||||
void *buf1, size_t buf1_len),
|
void *buf1, size_t buf1_len),
|
||||||
TP_ARGS(dev, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
|
TP_ARGS(dev, skb, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
|
||||||
TP_STRUCT__entry(
|
TP_STRUCT__entry(
|
||||||
DEV_ENTRY
|
DEV_ENTRY
|
||||||
|
|
||||||
|
@ -301,13 +379,14 @@ TRACE_EVENT(iwlwifi_dev_tx,
|
||||||
* for the possible padding).
|
* for the possible padding).
|
||||||
*/
|
*/
|
||||||
__dynamic_array(u8, buf0, buf0_len)
|
__dynamic_array(u8, buf0, buf0_len)
|
||||||
__dynamic_array(u8, buf1, buf1_len)
|
__dynamic_array(u8, buf1, iwl_trace_data(skb) ? 0 : buf1_len)
|
||||||
),
|
),
|
||||||
TP_fast_assign(
|
TP_fast_assign(
|
||||||
DEV_ASSIGN;
|
DEV_ASSIGN;
|
||||||
__entry->framelen = buf0_len + buf1_len;
|
__entry->framelen = buf0_len + buf1_len;
|
||||||
memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
|
memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
|
||||||
memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
|
memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
|
||||||
|
if (!iwl_trace_data(skb))
|
||||||
memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
|
memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
|
||||||
),
|
),
|
||||||
TP_printk("[%s] TX %.2x (%zu bytes)",
|
TP_printk("[%s] TX %.2x (%zu bytes)",
|
||||||
|
|
|
@ -327,11 +327,11 @@ u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr)
|
||||||
EXPORT_SYMBOL_GPL(iwl_read_targ_mem);
|
EXPORT_SYMBOL_GPL(iwl_read_targ_mem);
|
||||||
|
|
||||||
int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
|
int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
|
||||||
void *buf, int dwords)
|
const void *buf, int dwords)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int offs, result = 0;
|
int offs, result = 0;
|
||||||
u32 *vals = buf;
|
const u32 *vals = buf;
|
||||||
|
|
||||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||||
if (likely(iwl_grab_nic_access(trans))) {
|
if (likely(iwl_grab_nic_access(trans))) {
|
||||||
|
|
|
@ -87,7 +87,7 @@ void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
|
int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
|
||||||
void *buf, int dwords);
|
const void *buf, int dwords);
|
||||||
|
|
||||||
u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr);
|
u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr);
|
||||||
int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val);
|
int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val);
|
||||||
|
|
|
@ -213,6 +213,9 @@
|
||||||
#define SCD_CONTEXT_QUEUE_OFFSET(x)\
|
#define SCD_CONTEXT_QUEUE_OFFSET(x)\
|
||||||
(SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8))
|
(SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8))
|
||||||
|
|
||||||
|
#define SCD_TX_STTS_QUEUE_OFFSET(x)\
|
||||||
|
(SCD_TX_STTS_MEM_LOWER_BOUND + ((x) * 16))
|
||||||
|
|
||||||
#define SCD_TRANS_TBL_OFFSET_QUEUE(x) \
|
#define SCD_TRANS_TBL_OFFSET_QUEUE(x) \
|
||||||
((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc)
|
((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc)
|
||||||
|
|
||||||
|
|
|
@ -444,6 +444,10 @@ enum iwl_trans_state {
|
||||||
* @dev_cmd_headroom: room needed for the transport's private use before the
|
* @dev_cmd_headroom: room needed for the transport's private use before the
|
||||||
* device_cmd for Tx - for internal use only
|
* device_cmd for Tx - for internal use only
|
||||||
* The user should use iwl_trans_{alloc,free}_tx_cmd.
|
* The user should use iwl_trans_{alloc,free}_tx_cmd.
|
||||||
|
* @rx_mpdu_cmd: MPDU RX command ID, must be assigned by opmode before
|
||||||
|
* starting the firmware, used for tracing
|
||||||
|
* @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the
|
||||||
|
* start of the 802.11 header in the @rx_mpdu_cmd
|
||||||
*/
|
*/
|
||||||
struct iwl_trans {
|
struct iwl_trans {
|
||||||
const struct iwl_trans_ops *ops;
|
const struct iwl_trans_ops *ops;
|
||||||
|
@ -457,6 +461,8 @@ struct iwl_trans {
|
||||||
u32 hw_id;
|
u32 hw_id;
|
||||||
char hw_id_str[52];
|
char hw_id_str[52];
|
||||||
|
|
||||||
|
u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size;
|
||||||
|
|
||||||
bool pm_support;
|
bool pm_support;
|
||||||
|
|
||||||
wait_queue_head_t wait_command_queue;
|
wait_queue_head_t wait_command_queue;
|
||||||
|
@ -516,6 +522,8 @@ static inline int iwl_trans_start_fw(struct iwl_trans *trans,
|
||||||
{
|
{
|
||||||
might_sleep();
|
might_sleep();
|
||||||
|
|
||||||
|
WARN_ON_ONCE(!trans->rx_mpdu_cmd);
|
||||||
|
|
||||||
return trans->ops->start_fw(trans, fw);
|
return trans->ops->start_fw(trans, fw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -411,7 +411,8 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans,
|
||||||
|
|
||||||
len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
|
len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
|
||||||
len += sizeof(u32); /* account for status word */
|
len += sizeof(u32); /* account for status word */
|
||||||
trace_iwlwifi_dev_rx(trans->dev, pkt, len);
|
trace_iwlwifi_dev_rx(trans->dev, trans, pkt, len);
|
||||||
|
trace_iwlwifi_dev_rx_data(trans->dev, trans, pkt, len);
|
||||||
|
|
||||||
/* Reclaim a command buffer only if this packet is a response
|
/* Reclaim a command buffer only if this packet is a response
|
||||||
* to a (driver-originated) command.
|
* to a (driver-originated) command.
|
||||||
|
|
|
@ -300,7 +300,7 @@ static void iwl_trans_pcie_queue_stuck_timer(unsigned long data)
|
||||||
struct iwl_trans_pcie *trans_pcie = txq->trans_pcie;
|
struct iwl_trans_pcie *trans_pcie = txq->trans_pcie;
|
||||||
struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie);
|
struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie);
|
||||||
u32 scd_sram_addr = trans_pcie->scd_base_addr +
|
u32 scd_sram_addr = trans_pcie->scd_base_addr +
|
||||||
SCD_TX_STTS_MEM_LOWER_BOUND + (16 * txq->q.id);
|
SCD_TX_STTS_QUEUE_OFFSET(txq->q.id);
|
||||||
u8 buf[16];
|
u8 buf[16];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
@ -1385,11 +1385,13 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
|
||||||
dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen,
|
dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen,
|
||||||
DMA_BIDIRECTIONAL);
|
DMA_BIDIRECTIONAL);
|
||||||
|
|
||||||
trace_iwlwifi_dev_tx(trans->dev,
|
trace_iwlwifi_dev_tx(trans->dev, skb,
|
||||||
&txq->tfds[txq->q.write_ptr],
|
&txq->tfds[txq->q.write_ptr],
|
||||||
sizeof(struct iwl_tfd),
|
sizeof(struct iwl_tfd),
|
||||||
&dev_cmd->hdr, firstlen,
|
&dev_cmd->hdr, firstlen,
|
||||||
skb->data + hdr_len, secondlen);
|
skb->data + hdr_len, secondlen);
|
||||||
|
trace_iwlwifi_dev_tx_data(trans->dev, skb,
|
||||||
|
skb->data + hdr_len, secondlen);
|
||||||
|
|
||||||
/* start timer if queue currently empty */
|
/* start timer if queue currently empty */
|
||||||
if (txq->need_update && q->read_ptr == q->write_ptr &&
|
if (txq->need_update && q->read_ptr == q->write_ptr &&
|
||||||
|
@ -1514,14 +1516,13 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
|
||||||
struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
|
struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id];
|
||||||
/* n_bd is usually 256 => n_bd - 1 = 0xff */
|
/* n_bd is usually 256 => n_bd - 1 = 0xff */
|
||||||
int tfd_num = ssn & (txq->q.n_bd - 1);
|
int tfd_num = ssn & (txq->q.n_bd - 1);
|
||||||
int freed = 0;
|
|
||||||
|
|
||||||
spin_lock(&txq->lock);
|
spin_lock(&txq->lock);
|
||||||
|
|
||||||
if (txq->q.read_ptr != tfd_num) {
|
if (txq->q.read_ptr != tfd_num) {
|
||||||
IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n",
|
IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n",
|
||||||
txq_id, txq->q.read_ptr, tfd_num, ssn);
|
txq_id, txq->q.read_ptr, tfd_num, ssn);
|
||||||
freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
|
iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs);
|
||||||
if (iwl_queue_space(&txq->q) > txq->q.low_mark)
|
if (iwl_queue_space(&txq->q) > txq->q.low_mark)
|
||||||
iwl_wake_queue(trans, txq);
|
iwl_wake_queue(trans, txq);
|
||||||
}
|
}
|
||||||
|
|
|
@ -480,21 +480,20 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo,
|
||||||
void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id)
|
void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id)
|
||||||
{
|
{
|
||||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||||
u16 rd_ptr, wr_ptr;
|
u32 stts_addr = trans_pcie->scd_base_addr +
|
||||||
int n_bd = trans_pcie->txq[txq_id].q.n_bd;
|
SCD_TX_STTS_QUEUE_OFFSET(txq_id);
|
||||||
|
static const u32 zero_val[4] = {};
|
||||||
|
|
||||||
if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) {
|
if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) {
|
||||||
WARN_ONCE(1, "queue %d not used", txq_id);
|
WARN_ONCE(1, "queue %d not used", txq_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rd_ptr = iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & (n_bd - 1);
|
|
||||||
wr_ptr = iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id));
|
|
||||||
|
|
||||||
WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]",
|
|
||||||
txq_id, rd_ptr, wr_ptr);
|
|
||||||
|
|
||||||
iwl_txq_set_inactive(trans, txq_id);
|
iwl_txq_set_inactive(trans, txq_id);
|
||||||
|
|
||||||
|
_iwl_write_targ_mem_dwords(trans, stts_addr,
|
||||||
|
zero_val, ARRAY_SIZE(zero_val));
|
||||||
|
|
||||||
IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id);
|
IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,7 +548,10 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd)
|
||||||
* allocated into separate TFDs, then we will need to
|
* allocated into separate TFDs, then we will need to
|
||||||
* increase the size of the buffers.
|
* increase the size of the buffers.
|
||||||
*/
|
*/
|
||||||
if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE))
|
if (WARN(copy_size > TFD_MAX_PAYLOAD_SIZE,
|
||||||
|
"Command %s (%#x) is too large (%d bytes)\n",
|
||||||
|
trans_pcie_get_cmd_string(trans_pcie, cmd->id),
|
||||||
|
cmd->id, copy_size))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
spin_lock_bh(&txq->lock);
|
spin_lock_bh(&txq->lock);
|
||||||
|
|
|
@ -101,7 +101,7 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case CMD_ACT_MESH_CONFIG_START:
|
case CMD_ACT_MESH_CONFIG_START:
|
||||||
ie->id = WLAN_EID_GENERIC;
|
ie->id = WLAN_EID_VENDOR_SPECIFIC;
|
||||||
ie->val.oui[0] = 0x00;
|
ie->val.oui[0] = 0x00;
|
||||||
ie->val.oui[1] = 0x50;
|
ie->val.oui[1] = 0x50;
|
||||||
ie->val.oui[2] = 0x43;
|
ie->val.oui[2] = 0x43;
|
||||||
|
|
|
@ -58,8 +58,7 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv,
|
||||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||||
mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
|
mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
|
||||||
else
|
else
|
||||||
mwifiex_process_rx_packet(priv->adapter,
|
mwifiex_process_rx_packet(priv, rx_tmp_ptr);
|
||||||
rx_tmp_ptr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +105,7 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
|
||||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||||
mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
|
mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
|
||||||
else
|
else
|
||||||
mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
|
mwifiex_process_rx_packet(priv, rx_tmp_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_irqsave(&priv->rx_pkt_lock, flags);
|
spin_lock_irqsave(&priv->rx_pkt_lock, flags);
|
||||||
|
@ -442,8 +441,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
|
||||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||||
mwifiex_handle_uap_rx_forward(priv, payload);
|
mwifiex_handle_uap_rx_forward(priv, payload);
|
||||||
else
|
else
|
||||||
mwifiex_process_rx_packet(priv->adapter,
|
mwifiex_process_rx_packet(priv, payload);
|
||||||
payload);
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -471,13 +471,13 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
|
||||||
flag = 1;
|
flag = 1;
|
||||||
first_chan = (u32) ch->hw_value;
|
first_chan = (u32) ch->hw_value;
|
||||||
next_chan = first_chan;
|
next_chan = first_chan;
|
||||||
max_pwr = ch->max_reg_power;
|
max_pwr = ch->max_power;
|
||||||
no_of_parsed_chan = 1;
|
no_of_parsed_chan = 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch->hw_value == next_chan + 1 &&
|
if (ch->hw_value == next_chan + 1 &&
|
||||||
ch->max_reg_power == max_pwr) {
|
ch->max_power == max_pwr) {
|
||||||
next_chan++;
|
next_chan++;
|
||||||
no_of_parsed_chan++;
|
no_of_parsed_chan++;
|
||||||
} else {
|
} else {
|
||||||
|
@ -488,7 +488,7 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
|
||||||
no_of_triplet++;
|
no_of_triplet++;
|
||||||
first_chan = (u32) ch->hw_value;
|
first_chan = (u32) ch->hw_value;
|
||||||
next_chan = first_chan;
|
next_chan = first_chan;
|
||||||
max_pwr = ch->max_reg_power;
|
max_pwr = ch->max_power;
|
||||||
no_of_parsed_chan = 1;
|
no_of_parsed_chan = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1819,12 +1819,18 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
|
||||||
|
|
||||||
wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name);
|
wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name);
|
||||||
|
|
||||||
if (atomic_read(&priv->wmm.tx_pkts_queued) >=
|
if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
|
||||||
|
atomic_read(&priv->wmm.tx_pkts_queued) >=
|
||||||
MWIFIEX_MIN_TX_PENDING_TO_CANCEL_SCAN) {
|
MWIFIEX_MIN_TX_PENDING_TO_CANCEL_SCAN) {
|
||||||
dev_dbg(priv->adapter->dev, "scan rejected due to traffic\n");
|
dev_dbg(priv->adapter->dev, "scan rejected due to traffic\n");
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->user_scan_cfg) {
|
||||||
|
dev_err(priv->adapter->dev, "cmd: Scan already in process..\n");
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg),
|
priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!priv->user_scan_cfg) {
|
if (!priv->user_scan_cfg) {
|
||||||
|
@ -2116,7 +2122,6 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
|
||||||
}
|
}
|
||||||
|
|
||||||
sema_init(&priv->async_sem, 1);
|
sema_init(&priv->async_sem, 1);
|
||||||
priv->scan_pending_on_block = false;
|
|
||||||
|
|
||||||
dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name);
|
dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name);
|
||||||
|
|
||||||
|
@ -2253,8 +2258,9 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
|
||||||
wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
|
wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1;
|
||||||
wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;
|
wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;
|
||||||
|
|
||||||
wiphy->features = NL80211_FEATURE_HT_IBSS |
|
wiphy->features |= NL80211_FEATURE_HT_IBSS |
|
||||||
NL80211_FEATURE_INACTIVITY_TIMER;
|
NL80211_FEATURE_INACTIVITY_TIMER |
|
||||||
|
NL80211_FEATURE_LOW_PRIORITY_SCAN;
|
||||||
|
|
||||||
/* Reserve space for mwifiex specific private data for BSS */
|
/* Reserve space for mwifiex specific private data for BSS */
|
||||||
wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
|
wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
|
||||||
|
|
|
@ -917,21 +917,24 @@ mwifiex_cmd_timeout_func(unsigned long function_context)
|
||||||
|
|
||||||
dev_err(adapter->dev, "last_cmd_index = %d\n",
|
dev_err(adapter->dev, "last_cmd_index = %d\n",
|
||||||
adapter->dbg.last_cmd_index);
|
adapter->dbg.last_cmd_index);
|
||||||
print_hex_dump_bytes("last_cmd_id: ", DUMP_PREFIX_OFFSET,
|
dev_err(adapter->dev, "last_cmd_id: %*ph\n",
|
||||||
adapter->dbg.last_cmd_id, DBG_CMD_NUM);
|
(int)sizeof(adapter->dbg.last_cmd_id),
|
||||||
print_hex_dump_bytes("last_cmd_act: ", DUMP_PREFIX_OFFSET,
|
adapter->dbg.last_cmd_id);
|
||||||
adapter->dbg.last_cmd_act, DBG_CMD_NUM);
|
dev_err(adapter->dev, "last_cmd_act: %*ph\n",
|
||||||
|
(int)sizeof(adapter->dbg.last_cmd_act),
|
||||||
|
adapter->dbg.last_cmd_act);
|
||||||
|
|
||||||
dev_err(adapter->dev, "last_cmd_resp_index = %d\n",
|
dev_err(adapter->dev, "last_cmd_resp_index = %d\n",
|
||||||
adapter->dbg.last_cmd_resp_index);
|
adapter->dbg.last_cmd_resp_index);
|
||||||
print_hex_dump_bytes("last_cmd_resp_id: ", DUMP_PREFIX_OFFSET,
|
dev_err(adapter->dev, "last_cmd_resp_id: %*ph\n",
|
||||||
adapter->dbg.last_cmd_resp_id,
|
(int)sizeof(adapter->dbg.last_cmd_resp_id),
|
||||||
DBG_CMD_NUM);
|
adapter->dbg.last_cmd_resp_id);
|
||||||
|
|
||||||
dev_err(adapter->dev, "last_event_index = %d\n",
|
dev_err(adapter->dev, "last_event_index = %d\n",
|
||||||
adapter->dbg.last_event_index);
|
adapter->dbg.last_event_index);
|
||||||
print_hex_dump_bytes("last_event: ", DUMP_PREFIX_OFFSET,
|
dev_err(adapter->dev, "last_event: %*ph\n",
|
||||||
adapter->dbg.last_event, DBG_CMD_NUM);
|
(int)sizeof(adapter->dbg.last_event),
|
||||||
|
adapter->dbg.last_event);
|
||||||
|
|
||||||
dev_err(adapter->dev, "data_sent=%d cmd_sent=%d\n",
|
dev_err(adapter->dev, "data_sent=%d cmd_sent=%d\n",
|
||||||
adapter->data_sent, adapter->cmd_sent);
|
adapter->data_sent, adapter->cmd_sent);
|
||||||
|
|
|
@ -84,17 +84,18 @@ static void scan_delay_timer_fn(unsigned long data)
|
||||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||||
|
|
||||||
if (priv->user_scan_cfg) {
|
if (priv->user_scan_cfg) {
|
||||||
|
if (priv->scan_request) {
|
||||||
dev_dbg(priv->adapter->dev,
|
dev_dbg(priv->adapter->dev,
|
||||||
"info: %s: scan aborted\n", __func__);
|
"info: aborting scan\n");
|
||||||
cfg80211_scan_done(priv->scan_request, 1);
|
cfg80211_scan_done(priv->scan_request, 1);
|
||||||
priv->scan_request = NULL;
|
priv->scan_request = NULL;
|
||||||
kfree(priv->user_scan_cfg);
|
} else {
|
||||||
priv->user_scan_cfg = NULL;
|
dev_dbg(priv->adapter->dev,
|
||||||
|
"info: scan already aborted\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->scan_pending_on_block) {
|
kfree(priv->user_scan_cfg);
|
||||||
priv->scan_pending_on_block = false;
|
priv->user_scan_cfg = NULL;
|
||||||
up(&priv->async_sem);
|
|
||||||
}
|
}
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
|
@ -472,6 +472,14 @@ mwifiex_open(struct net_device *dev)
|
||||||
static int
|
static int
|
||||||
mwifiex_close(struct net_device *dev)
|
mwifiex_close(struct net_device *dev)
|
||||||
{
|
{
|
||||||
|
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
|
||||||
|
|
||||||
|
if (priv->scan_request) {
|
||||||
|
dev_dbg(priv->adapter->dev, "aborting scan on ndo_stop\n");
|
||||||
|
cfg80211_scan_done(priv->scan_request, 1);
|
||||||
|
priv->scan_request = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,8 +115,6 @@ enum {
|
||||||
#define MWIFIEX_TYPE_DATA 0
|
#define MWIFIEX_TYPE_DATA 0
|
||||||
#define MWIFIEX_TYPE_EVENT 3
|
#define MWIFIEX_TYPE_EVENT 3
|
||||||
|
|
||||||
#define DBG_CMD_NUM 5
|
|
||||||
|
|
||||||
#define MAX_BITMAP_RATES_SIZE 10
|
#define MAX_BITMAP_RATES_SIZE 10
|
||||||
|
|
||||||
#define MAX_CHANNEL_BAND_BG 14
|
#define MAX_CHANNEL_BAND_BG 14
|
||||||
|
@ -484,7 +482,6 @@ struct mwifiex_private {
|
||||||
u8 nick_name[16];
|
u8 nick_name[16];
|
||||||
u16 current_key_index;
|
u16 current_key_index;
|
||||||
struct semaphore async_sem;
|
struct semaphore async_sem;
|
||||||
u8 scan_pending_on_block;
|
|
||||||
u8 report_scan_result;
|
u8 report_scan_result;
|
||||||
struct cfg80211_scan_request *scan_request;
|
struct cfg80211_scan_request *scan_request;
|
||||||
struct mwifiex_user_scan_cfg *user_scan_cfg;
|
struct mwifiex_user_scan_cfg *user_scan_cfg;
|
||||||
|
@ -750,9 +747,9 @@ int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter);
|
||||||
|
|
||||||
int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *);
|
int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *);
|
||||||
|
|
||||||
int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb);
|
int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb);
|
||||||
|
|
||||||
int mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter,
|
int mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
|
||||||
struct sk_buff *skb);
|
struct sk_buff *skb);
|
||||||
|
|
||||||
int mwifiex_process_event(struct mwifiex_adapter *adapter);
|
int mwifiex_process_event(struct mwifiex_adapter *adapter);
|
||||||
|
@ -809,7 +806,7 @@ void mwifiex_hs_activated_event(struct mwifiex_private *priv,
|
||||||
u8 activated);
|
u8 activated);
|
||||||
int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
|
int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
|
||||||
struct host_cmd_ds_command *resp);
|
struct host_cmd_ds_command *resp);
|
||||||
int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
|
int mwifiex_process_rx_packet(struct mwifiex_private *priv,
|
||||||
struct sk_buff *skb);
|
struct sk_buff *skb);
|
||||||
int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no,
|
int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no,
|
||||||
u16 cmd_action, u32 cmd_oid,
|
u16 cmd_action, u32 cmd_oid,
|
||||||
|
@ -819,9 +816,9 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
|
||||||
void *data_buf, void *cmd_buf);
|
void *data_buf, void *cmd_buf);
|
||||||
int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no,
|
int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no,
|
||||||
struct host_cmd_ds_command *resp);
|
struct host_cmd_ds_command *resp);
|
||||||
int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *,
|
int mwifiex_process_sta_rx_packet(struct mwifiex_private *,
|
||||||
struct sk_buff *skb);
|
struct sk_buff *skb);
|
||||||
int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
|
int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
|
||||||
struct sk_buff *skb);
|
struct sk_buff *skb);
|
||||||
int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
|
int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
|
||||||
struct sk_buff *skb);
|
struct sk_buff *skb);
|
||||||
|
|
|
@ -153,7 +153,7 @@ mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
|
||||||
|
|
||||||
if (((bss_desc->bcn_wpa_ie) &&
|
if (((bss_desc->bcn_wpa_ie) &&
|
||||||
((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id ==
|
((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id ==
|
||||||
WLAN_EID_WPA))) {
|
WLAN_EID_VENDOR_SPECIFIC))) {
|
||||||
iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data;
|
iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data;
|
||||||
oui = &mwifiex_wpa_oui[cipher][0];
|
oui = &mwifiex_wpa_oui[cipher][0];
|
||||||
ret = mwifiex_search_oui_in_ie(iebody, oui);
|
ret = mwifiex_search_oui_in_ie(iebody, oui);
|
||||||
|
@ -202,7 +202,7 @@ mwifiex_is_bss_no_sec(struct mwifiex_private *priv,
|
||||||
if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
|
if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
|
||||||
!priv->sec_info.wpa2_enabled && ((!bss_desc->bcn_wpa_ie) ||
|
!priv->sec_info.wpa2_enabled && ((!bss_desc->bcn_wpa_ie) ||
|
||||||
((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id !=
|
((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id !=
|
||||||
WLAN_EID_WPA)) &&
|
WLAN_EID_VENDOR_SPECIFIC)) &&
|
||||||
((!bss_desc->bcn_rsn_ie) ||
|
((!bss_desc->bcn_rsn_ie) ||
|
||||||
((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id !=
|
((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id !=
|
||||||
WLAN_EID_RSN)) &&
|
WLAN_EID_RSN)) &&
|
||||||
|
@ -237,7 +237,8 @@ mwifiex_is_bss_wpa(struct mwifiex_private *priv,
|
||||||
{
|
{
|
||||||
if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled &&
|
if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled &&
|
||||||
!priv->sec_info.wpa2_enabled && ((bss_desc->bcn_wpa_ie) &&
|
!priv->sec_info.wpa2_enabled && ((bss_desc->bcn_wpa_ie) &&
|
||||||
((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id == WLAN_EID_WPA))
|
((*(bss_desc->bcn_wpa_ie)).
|
||||||
|
vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC))
|
||||||
/*
|
/*
|
||||||
* Privacy bit may NOT be set in some APs like
|
* Privacy bit may NOT be set in some APs like
|
||||||
* LinkSys WRT54G && bss_desc->privacy
|
* LinkSys WRT54G && bss_desc->privacy
|
||||||
|
@ -309,7 +310,8 @@ mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv,
|
||||||
if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
|
if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
|
||||||
!priv->sec_info.wpa2_enabled &&
|
!priv->sec_info.wpa2_enabled &&
|
||||||
((!bss_desc->bcn_wpa_ie) ||
|
((!bss_desc->bcn_wpa_ie) ||
|
||||||
((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != WLAN_EID_WPA)) &&
|
((*(bss_desc->bcn_wpa_ie)).
|
||||||
|
vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) &&
|
||||||
((!bss_desc->bcn_rsn_ie) ||
|
((!bss_desc->bcn_rsn_ie) ||
|
||||||
((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
|
((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
|
||||||
!priv->sec_info.encryption_mode && bss_desc->privacy) {
|
!priv->sec_info.encryption_mode && bss_desc->privacy) {
|
||||||
|
@ -329,7 +331,8 @@ mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv,
|
||||||
if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
|
if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
|
||||||
!priv->sec_info.wpa2_enabled &&
|
!priv->sec_info.wpa2_enabled &&
|
||||||
((!bss_desc->bcn_wpa_ie) ||
|
((!bss_desc->bcn_wpa_ie) ||
|
||||||
((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != WLAN_EID_WPA)) &&
|
((*(bss_desc->bcn_wpa_ie)).
|
||||||
|
vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) &&
|
||||||
((!bss_desc->bcn_rsn_ie) ||
|
((!bss_desc->bcn_rsn_ie) ||
|
||||||
((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
|
((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) &&
|
||||||
priv->sec_info.encryption_mode && bss_desc->privacy) {
|
priv->sec_info.encryption_mode && bss_desc->privacy) {
|
||||||
|
@ -938,6 +941,11 @@ mwifiex_config_scan(struct mwifiex_private *priv,
|
||||||
chan_idx)->chan_scan_mode_bitmap
|
chan_idx)->chan_scan_mode_bitmap
|
||||||
&= ~MWIFIEX_PASSIVE_SCAN;
|
&= ~MWIFIEX_PASSIVE_SCAN;
|
||||||
|
|
||||||
|
if (*filtered_scan)
|
||||||
|
(scan_chan_list +
|
||||||
|
chan_idx)->chan_scan_mode_bitmap
|
||||||
|
|= MWIFIEX_DISABLE_CHAN_FILT;
|
||||||
|
|
||||||
if (user_scan_in->chan_list[chan_idx].scan_time) {
|
if (user_scan_in->chan_list[chan_idx].scan_time) {
|
||||||
scan_dur = (u16) user_scan_in->
|
scan_dur = (u16) user_scan_in->
|
||||||
chan_list[chan_idx].scan_time;
|
chan_list[chan_idx].scan_time;
|
||||||
|
@ -1759,26 +1767,39 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
|
||||||
}
|
}
|
||||||
if (priv->report_scan_result)
|
if (priv->report_scan_result)
|
||||||
priv->report_scan_result = false;
|
priv->report_scan_result = false;
|
||||||
if (priv->scan_pending_on_block) {
|
|
||||||
priv->scan_pending_on_block = false;
|
|
||||||
up(&priv->async_sem);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->user_scan_cfg) {
|
if (priv->user_scan_cfg) {
|
||||||
|
if (priv->scan_request) {
|
||||||
dev_dbg(priv->adapter->dev,
|
dev_dbg(priv->adapter->dev,
|
||||||
"info: %s: sending scan results\n", __func__);
|
"info: notifying scan done\n");
|
||||||
cfg80211_scan_done(priv->scan_request, 0);
|
cfg80211_scan_done(priv->scan_request, 0);
|
||||||
priv->scan_request = NULL;
|
priv->scan_request = NULL;
|
||||||
|
} else {
|
||||||
|
dev_dbg(priv->adapter->dev,
|
||||||
|
"info: scan already aborted\n");
|
||||||
|
}
|
||||||
|
|
||||||
kfree(priv->user_scan_cfg);
|
kfree(priv->user_scan_cfg);
|
||||||
priv->user_scan_cfg = NULL;
|
priv->user_scan_cfg = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!mwifiex_wmm_lists_empty(adapter)) {
|
if (priv->user_scan_cfg && !priv->scan_request) {
|
||||||
|
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
|
||||||
|
flags);
|
||||||
|
adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT;
|
||||||
|
mod_timer(&priv->scan_delay_timer, jiffies);
|
||||||
|
dev_dbg(priv->adapter->dev,
|
||||||
|
"info: %s: triggerring scan abort\n", __func__);
|
||||||
|
} else if (!mwifiex_wmm_lists_empty(adapter) &&
|
||||||
|
(priv->scan_request && (priv->scan_request->flags &
|
||||||
|
NL80211_SCAN_FLAG_LOW_PRIORITY))) {
|
||||||
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
|
spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
|
||||||
flags);
|
flags);
|
||||||
adapter->scan_delay_cnt = 1;
|
adapter->scan_delay_cnt = 1;
|
||||||
mod_timer(&priv->scan_delay_timer, jiffies +
|
mod_timer(&priv->scan_delay_timer, jiffies +
|
||||||
msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
|
msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
|
||||||
|
dev_dbg(priv->adapter->dev,
|
||||||
|
"info: %s: deferring scan\n", __func__);
|
||||||
} else {
|
} else {
|
||||||
/* Get scan command from scan_pending_q and put to
|
/* Get scan command from scan_pending_q and put to
|
||||||
cmd_pending_q */
|
cmd_pending_q */
|
||||||
|
@ -1891,7 +1912,6 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
|
||||||
__func__);
|
__func__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
priv->scan_pending_on_block = true;
|
|
||||||
|
|
||||||
priv->adapter->scan_wait_q_woken = false;
|
priv->adapter->scan_wait_q_woken = false;
|
||||||
|
|
||||||
|
@ -1905,10 +1925,7 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = mwifiex_wait_queue_complete(priv->adapter);
|
ret = mwifiex_wait_queue_complete(priv->adapter);
|
||||||
|
|
||||||
if (ret == -1) {
|
|
||||||
priv->scan_pending_on_block = false;
|
|
||||||
up(&priv->async_sem);
|
up(&priv->async_sem);
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,10 +85,6 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
|
||||||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||||
if (priv->report_scan_result)
|
if (priv->report_scan_result)
|
||||||
priv->report_scan_result = false;
|
priv->report_scan_result = false;
|
||||||
if (priv->scan_pending_on_block) {
|
|
||||||
priv->scan_pending_on_block = false;
|
|
||||||
up(&priv->async_sem);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HostCmd_CMD_MAC_CONTROL:
|
case HostCmd_CMD_MAC_CONTROL:
|
||||||
|
|
|
@ -713,7 +713,7 @@ static int mwifiex_set_wpa_ie_helper(struct mwifiex_private *priv,
|
||||||
dev_dbg(priv->adapter->dev, "cmd: Set Wpa_ie_len=%d IE=%#x\n",
|
dev_dbg(priv->adapter->dev, "cmd: Set Wpa_ie_len=%d IE=%#x\n",
|
||||||
priv->wpa_ie_len, priv->wpa_ie[0]);
|
priv->wpa_ie_len, priv->wpa_ie[0]);
|
||||||
|
|
||||||
if (priv->wpa_ie[0] == WLAN_EID_WPA) {
|
if (priv->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) {
|
||||||
priv->sec_info.wpa_enabled = true;
|
priv->sec_info.wpa_enabled = true;
|
||||||
} else if (priv->wpa_ie[0] == WLAN_EID_RSN) {
|
} else if (priv->wpa_ie[0] == WLAN_EID_RSN) {
|
||||||
priv->sec_info.wpa2_enabled = true;
|
priv->sec_info.wpa2_enabled = true;
|
||||||
|
@ -1253,7 +1253,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
|
||||||
}
|
}
|
||||||
pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
|
pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;
|
||||||
/* Test to see if it is a WPA IE, if not, then it is a gen IE */
|
/* Test to see if it is a WPA IE, if not, then it is a gen IE */
|
||||||
if (((pvendor_ie->element_id == WLAN_EID_WPA) &&
|
if (((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) &&
|
||||||
(!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) ||
|
(!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) ||
|
||||||
(pvendor_ie->element_id == WLAN_EID_RSN)) {
|
(pvendor_ie->element_id == WLAN_EID_RSN)) {
|
||||||
|
|
||||||
|
|
|
@ -38,14 +38,10 @@
|
||||||
*
|
*
|
||||||
* The completion callback is called after processing in complete.
|
* The completion callback is called after processing in complete.
|
||||||
*/
|
*/
|
||||||
int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
|
int mwifiex_process_rx_packet(struct mwifiex_private *priv,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
|
|
||||||
struct mwifiex_private *priv =
|
|
||||||
mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
|
|
||||||
rx_info->bss_type);
|
|
||||||
struct rx_packet_hdr *rx_pkt_hdr;
|
struct rx_packet_hdr *rx_pkt_hdr;
|
||||||
struct rxpd *local_rx_pd;
|
struct rxpd *local_rx_pd;
|
||||||
int hdr_chop;
|
int hdr_chop;
|
||||||
|
@ -98,9 +94,9 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
|
||||||
|
|
||||||
priv->rxpd_htinfo = local_rx_pd->ht_info;
|
priv->rxpd_htinfo = local_rx_pd->ht_info;
|
||||||
|
|
||||||
ret = mwifiex_recv_packet(adapter, skb);
|
ret = mwifiex_recv_packet(priv, skb);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
dev_err(adapter->dev, "recv packet failed\n");
|
dev_err(priv->adapter->dev, "recv packet failed\n");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -117,21 +113,15 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
|
||||||
*
|
*
|
||||||
* The completion callback is called after processing in complete.
|
* The completion callback is called after processing in complete.
|
||||||
*/
|
*/
|
||||||
int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
|
int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
struct mwifiex_adapter *adapter = priv->adapter;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct rxpd *local_rx_pd;
|
struct rxpd *local_rx_pd;
|
||||||
struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
|
|
||||||
struct rx_packet_hdr *rx_pkt_hdr;
|
struct rx_packet_hdr *rx_pkt_hdr;
|
||||||
u8 ta[ETH_ALEN];
|
u8 ta[ETH_ALEN];
|
||||||
u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num;
|
u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num;
|
||||||
struct mwifiex_private *priv =
|
|
||||||
mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
|
|
||||||
rx_info->bss_type);
|
|
||||||
|
|
||||||
if (!priv)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
local_rx_pd = (struct rxpd *) (skb->data);
|
local_rx_pd = (struct rxpd *) (skb->data);
|
||||||
rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type);
|
rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type);
|
||||||
|
@ -169,13 +159,13 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
|
||||||
|
|
||||||
while (!skb_queue_empty(&list)) {
|
while (!skb_queue_empty(&list)) {
|
||||||
rx_skb = __skb_dequeue(&list);
|
rx_skb = __skb_dequeue(&list);
|
||||||
ret = mwifiex_recv_packet(adapter, rx_skb);
|
ret = mwifiex_recv_packet(priv, rx_skb);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
dev_err(adapter->dev, "Rx of A-MSDU failed");
|
dev_err(adapter->dev, "Rx of A-MSDU failed");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} else if (rx_pkt_type == PKT_TYPE_MGMT) {
|
} else if (rx_pkt_type == PKT_TYPE_MGMT) {
|
||||||
ret = mwifiex_process_mgmt_packet(adapter, skb);
|
ret = mwifiex_process_mgmt_packet(priv, skb);
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_err(adapter->dev, "Rx of mgmt packet failed");
|
dev_err(adapter->dev, "Rx of mgmt packet failed");
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
|
@ -188,7 +178,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
|
||||||
*/
|
*/
|
||||||
if (!IS_11N_ENABLED(priv) ||
|
if (!IS_11N_ENABLED(priv) ||
|
||||||
memcmp(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN)) {
|
memcmp(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN)) {
|
||||||
mwifiex_process_rx_packet(adapter, skb);
|
mwifiex_process_rx_packet(priv, skb);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,13 +48,19 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
|
||||||
if (!priv)
|
if (!priv)
|
||||||
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
|
priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
|
||||||
|
|
||||||
|
if (!priv) {
|
||||||
|
dev_err(adapter->dev, "data: priv not found. Drop RX packet\n");
|
||||||
|
dev_kfree_skb_any(skb);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
rx_info->bss_num = priv->bss_num;
|
rx_info->bss_num = priv->bss_num;
|
||||||
rx_info->bss_type = priv->bss_type;
|
rx_info->bss_type = priv->bss_type;
|
||||||
|
|
||||||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||||
return mwifiex_process_uap_rx_packet(adapter, skb);
|
return mwifiex_process_uap_rx_packet(priv, skb);
|
||||||
|
|
||||||
return mwifiex_process_sta_rx_packet(adapter, skb);
|
return mwifiex_process_sta_rx_packet(priv, skb);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet);
|
EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet);
|
||||||
|
|
||||||
|
|
|
@ -188,10 +188,19 @@ mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg,
|
||||||
int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
|
int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
|
||||||
const u8 *var_pos = params->beacon.head + var_offset;
|
const u8 *var_pos = params->beacon.head + var_offset;
|
||||||
int len = params->beacon.head_len - var_offset;
|
int len = params->beacon.head_len - var_offset;
|
||||||
|
u8 rate_len = 0;
|
||||||
|
|
||||||
rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len);
|
rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len);
|
||||||
if (rate_ie)
|
if (rate_ie) {
|
||||||
memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len);
|
memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len);
|
||||||
|
rate_len = rate_ie->len;
|
||||||
|
}
|
||||||
|
|
||||||
|
rate_ie = (void *)cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES,
|
||||||
|
params->beacon.tail,
|
||||||
|
params->beacon.tail_len);
|
||||||
|
if (rate_ie)
|
||||||
|
memcpy(bss_cfg->rates + rate_len, rate_ie + 1, rate_ie->len);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,7 +146,7 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Forward unicat/Inter-BSS packets to kernel. */
|
/* Forward unicat/Inter-BSS packets to kernel. */
|
||||||
return mwifiex_process_rx_packet(adapter, skb);
|
return mwifiex_process_rx_packet(priv, skb);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -159,24 +159,17 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
|
||||||
*
|
*
|
||||||
* The completion callback is called after processing is complete.
|
* The completion callback is called after processing is complete.
|
||||||
*/
|
*/
|
||||||
int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
|
int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
struct mwifiex_adapter *adapter = priv->adapter;
|
||||||
int ret;
|
int ret;
|
||||||
struct uap_rxpd *uap_rx_pd;
|
struct uap_rxpd *uap_rx_pd;
|
||||||
struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
|
|
||||||
struct rx_packet_hdr *rx_pkt_hdr;
|
struct rx_packet_hdr *rx_pkt_hdr;
|
||||||
u16 rx_pkt_type;
|
u16 rx_pkt_type;
|
||||||
u8 ta[ETH_ALEN], pkt_type;
|
u8 ta[ETH_ALEN], pkt_type;
|
||||||
struct mwifiex_sta_node *node;
|
struct mwifiex_sta_node *node;
|
||||||
|
|
||||||
struct mwifiex_private *priv =
|
|
||||||
mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
|
|
||||||
rx_info->bss_type);
|
|
||||||
|
|
||||||
if (!priv)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
uap_rx_pd = (struct uap_rxpd *)(skb->data);
|
uap_rx_pd = (struct uap_rxpd *)(skb->data);
|
||||||
rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type);
|
rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type);
|
||||||
rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
|
rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
|
||||||
|
@ -210,7 +203,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
|
||||||
|
|
||||||
while (!skb_queue_empty(&list)) {
|
while (!skb_queue_empty(&list)) {
|
||||||
rx_skb = __skb_dequeue(&list);
|
rx_skb = __skb_dequeue(&list);
|
||||||
ret = mwifiex_recv_packet(adapter, rx_skb);
|
ret = mwifiex_recv_packet(priv, rx_skb);
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_err(adapter->dev,
|
dev_err(adapter->dev,
|
||||||
"AP:Rx A-MSDU failed");
|
"AP:Rx A-MSDU failed");
|
||||||
|
@ -218,7 +211,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
} else if (rx_pkt_type == PKT_TYPE_MGMT) {
|
} else if (rx_pkt_type == PKT_TYPE_MGMT) {
|
||||||
ret = mwifiex_process_mgmt_packet(adapter, skb);
|
ret = mwifiex_process_mgmt_packet(priv, skb);
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_err(adapter->dev, "Rx of mgmt packet failed");
|
dev_err(adapter->dev, "Rx of mgmt packet failed");
|
||||||
dev_kfree_skb_any(skb);
|
dev_kfree_skb_any(skb);
|
||||||
|
|
|
@ -146,20 +146,16 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv,
|
||||||
* to the kernel.
|
* to the kernel.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter,
|
mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct rxpd *rx_pd;
|
struct rxpd *rx_pd;
|
||||||
struct mwifiex_private *priv;
|
|
||||||
u16 pkt_len;
|
u16 pkt_len;
|
||||||
|
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
rx_pd = (struct rxpd *)skb->data;
|
rx_pd = (struct rxpd *)skb->data;
|
||||||
priv = mwifiex_get_priv_by_id(adapter, rx_pd->bss_num, rx_pd->bss_type);
|
|
||||||
if (!priv)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset));
|
skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset));
|
||||||
skb_pull(skb, sizeof(pkt_len));
|
skb_pull(skb, sizeof(pkt_len));
|
||||||
|
@ -190,20 +186,11 @@ mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter,
|
||||||
* the function creates a blank SKB, fills it with the data from the
|
* the function creates a blank SKB, fills it with the data from the
|
||||||
* received buffer and then sends this new SKB to the kernel.
|
* received buffer and then sends this new SKB to the kernel.
|
||||||
*/
|
*/
|
||||||
int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb)
|
int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
struct mwifiex_rxinfo *rx_info;
|
|
||||||
struct mwifiex_private *priv;
|
|
||||||
|
|
||||||
if (!skb)
|
if (!skb)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
rx_info = MWIFIEX_SKB_RXCB(skb);
|
|
||||||
priv = mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
|
|
||||||
rx_info->bss_type);
|
|
||||||
if (!priv)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
skb->dev = priv->netdev;
|
skb->dev = priv->netdev;
|
||||||
skb->protocol = eth_type_trans(skb, priv->netdev);
|
skb->protocol = eth_type_trans(skb, priv->netdev);
|
||||||
skb->ip_summed = CHECKSUM_NONE;
|
skb->ip_summed = CHECKSUM_NONE;
|
||||||
|
@ -225,7 +212,7 @@ int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb)
|
||||||
* fragments. Currently we fail the Filesndl-ht.scr script
|
* fragments. Currently we fail the Filesndl-ht.scr script
|
||||||
* for UDP, hence this fix
|
* for UDP, hence this fix
|
||||||
*/
|
*/
|
||||||
if ((adapter->iface_type == MWIFIEX_USB) &&
|
if ((priv->adapter->iface_type == MWIFIEX_USB) &&
|
||||||
(skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE))
|
(skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE))
|
||||||
skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE);
|
skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE);
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ static inline u8 *orinoco_get_wpa_ie(u8 *data, size_t len)
|
||||||
{
|
{
|
||||||
u8 *p = data;
|
u8 *p = data;
|
||||||
while ((p + 2 + WPA_SELECTOR_LEN) < (data + len)) {
|
while ((p + 2 + WPA_SELECTOR_LEN) < (data + len)) {
|
||||||
if ((p[0] == WLAN_EID_GENERIC) &&
|
if ((p[0] == WLAN_EID_VENDOR_SPECIFIC) &&
|
||||||
(memcmp(&p[2], WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0))
|
(memcmp(&p[2], WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0))
|
||||||
return p;
|
return p;
|
||||||
p += p[1] + 2;
|
p += p[1] + 2;
|
||||||
|
|
|
@ -865,7 +865,7 @@ static int ezusb_firmware_download(struct ezusb_priv *upriv,
|
||||||
static int ezusb_access_ltv(struct ezusb_priv *upriv,
|
static int ezusb_access_ltv(struct ezusb_priv *upriv,
|
||||||
struct request_context *ctx,
|
struct request_context *ctx,
|
||||||
u16 length, const void *data, u16 frame_type,
|
u16 length, const void *data, u16 frame_type,
|
||||||
void *ans_buff, int ans_size, u16 *ans_length)
|
void *ans_buff, unsigned ans_size, u16 *ans_length)
|
||||||
{
|
{
|
||||||
int req_size;
|
int req_size;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
@ -933,7 +933,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv,
|
||||||
}
|
}
|
||||||
if (ctx->in_rid) {
|
if (ctx->in_rid) {
|
||||||
struct ezusb_packet *ans = ctx->buf;
|
struct ezusb_packet *ans = ctx->buf;
|
||||||
int exp_len;
|
unsigned exp_len;
|
||||||
|
|
||||||
if (ans->hermes_len != 0)
|
if (ans->hermes_len != 0)
|
||||||
exp_len = le16_to_cpu(ans->hermes_len) * 2 + 12;
|
exp_len = le16_to_cpu(ans->hermes_len) * 2 + 12;
|
||||||
|
@ -949,8 +949,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ans_buff)
|
if (ans_buff)
|
||||||
memcpy(ans_buff, ans->data,
|
memcpy(ans_buff, ans->data, min(exp_len, ans_size));
|
||||||
min_t(int, exp_len, ans_size));
|
|
||||||
if (ans_length)
|
if (ans_length)
|
||||||
*ans_length = le16_to_cpu(ans->hermes_len);
|
*ans_length = le16_to_cpu(ans->hermes_len);
|
||||||
}
|
}
|
||||||
|
@ -995,7 +994,7 @@ static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid,
|
||||||
struct ezusb_priv *upriv = hw->priv;
|
struct ezusb_priv *upriv = hw->priv;
|
||||||
struct request_context *ctx;
|
struct request_context *ctx;
|
||||||
|
|
||||||
if ((bufsize < 0) || (bufsize % 2))
|
if (bufsize % 2)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
ctx = ezusb_alloc_ctx(upriv, rid, rid);
|
ctx = ezusb_alloc_ctx(upriv, rid, rid);
|
||||||
|
|
|
@ -2520,20 +2520,37 @@ static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev,
|
||||||
return comp_value;
|
return comp_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rt2800_get_txpower_reg_delta(struct rt2x00_dev *rt2x00dev,
|
||||||
|
int power_level, int max_power)
|
||||||
|
{
|
||||||
|
int delta;
|
||||||
|
|
||||||
|
if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX: We don't know the maximum transmit power of our hardware since
|
||||||
|
* the EEPROM doesn't expose it. We only know that we are calibrated
|
||||||
|
* to 100% tx power.
|
||||||
|
*
|
||||||
|
* Hence, we assume the regulatory limit that cfg80211 calulated for
|
||||||
|
* the current channel is our maximum and if we are requested to lower
|
||||||
|
* the value we just reduce our tx power accordingly.
|
||||||
|
*/
|
||||||
|
delta = power_level - max_power;
|
||||||
|
return min(delta, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
|
static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
|
||||||
enum ieee80211_band band, int power_level,
|
enum ieee80211_band band, int power_level,
|
||||||
u8 txpower, int delta)
|
u8 txpower, int delta)
|
||||||
{
|
{
|
||||||
u32 reg;
|
|
||||||
u16 eeprom;
|
u16 eeprom;
|
||||||
u8 criterion;
|
u8 criterion;
|
||||||
u8 eirp_txpower;
|
u8 eirp_txpower;
|
||||||
u8 eirp_txpower_criterion;
|
u8 eirp_txpower_criterion;
|
||||||
u8 reg_limit;
|
u8 reg_limit;
|
||||||
|
|
||||||
if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b))
|
|
||||||
return txpower;
|
|
||||||
|
|
||||||
if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) {
|
if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) {
|
||||||
/*
|
/*
|
||||||
* Check if eirp txpower exceed txpower_limit.
|
* Check if eirp txpower exceed txpower_limit.
|
||||||
|
@ -2542,11 +2559,13 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
|
||||||
* .11b data rate need add additional 4dbm
|
* .11b data rate need add additional 4dbm
|
||||||
* when calculating eirp txpower.
|
* when calculating eirp txpower.
|
||||||
*/
|
*/
|
||||||
rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, ®);
|
rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + 1,
|
||||||
criterion = rt2x00_get_field32(reg, TX_PWR_CFG_0_6MBS);
|
&eeprom);
|
||||||
|
criterion = rt2x00_get_field16(eeprom,
|
||||||
|
EEPROM_TXPOWER_BYRATE_RATE0);
|
||||||
|
|
||||||
rt2x00_eeprom_read(rt2x00dev,
|
rt2x00_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER,
|
||||||
EEPROM_EIRP_MAX_TX_POWER, &eeprom);
|
&eeprom);
|
||||||
|
|
||||||
if (band == IEEE80211_BAND_2GHZ)
|
if (band == IEEE80211_BAND_2GHZ)
|
||||||
eirp_txpower_criterion = rt2x00_get_field16(eeprom,
|
eirp_txpower_criterion = rt2x00_get_field16(eeprom,
|
||||||
|
@ -2563,36 +2582,71 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b,
|
||||||
} else
|
} else
|
||||||
reg_limit = 0;
|
reg_limit = 0;
|
||||||
|
|
||||||
return txpower + delta - reg_limit;
|
txpower = max(0, txpower + delta - reg_limit);
|
||||||
|
return min_t(u8, txpower, 0xc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We configure transmit power using MAC TX_PWR_CFG_{0,...,N} registers and
|
||||||
|
* BBP R1 register. TX_PWR_CFG_X allow to configure per rate TX power values,
|
||||||
|
* 4 bits for each rate (tune from 0 to 15 dBm). BBP_R1 controls transmit power
|
||||||
|
* for all rates, but allow to set only 4 discrete values: -12, -6, 0 and 6 dBm.
|
||||||
|
* Reference per rate transmit power values are located in the EEPROM at
|
||||||
|
* EEPROM_TXPOWER_BYRATE offset. We adjust them and BBP R1 settings according to
|
||||||
|
* current conditions (i.e. band, bandwidth, temperature, user settings).
|
||||||
|
*/
|
||||||
static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
|
static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
|
||||||
enum ieee80211_band band,
|
struct ieee80211_channel *chan,
|
||||||
int power_level)
|
int power_level)
|
||||||
{
|
{
|
||||||
u8 txpower;
|
u8 txpower, r1;
|
||||||
u16 eeprom;
|
u16 eeprom;
|
||||||
int i, is_rate_b;
|
u32 reg, offset;
|
||||||
u32 reg;
|
int i, is_rate_b, delta, power_ctrl;
|
||||||
u8 r1;
|
enum ieee80211_band band = chan->band;
|
||||||
u32 offset;
|
|
||||||
int delta;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Calculate HT40 compensation delta
|
* Calculate HT40 compensation. For 40MHz we need to add or subtract
|
||||||
|
* value read from EEPROM (different for 2GHz and for 5GHz).
|
||||||
*/
|
*/
|
||||||
delta = rt2800_get_txpower_bw_comp(rt2x00dev, band);
|
delta = rt2800_get_txpower_bw_comp(rt2x00dev, band);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* calculate temperature compensation delta
|
* Calculate temperature compensation. Depends on measurement of current
|
||||||
|
* TSSI (Transmitter Signal Strength Indication) we know TX power (due
|
||||||
|
* to temperature or maybe other factors) is smaller or bigger than
|
||||||
|
* expected. We adjust it, based on TSSI reference and boundaries values
|
||||||
|
* provided in EEPROM.
|
||||||
*/
|
*/
|
||||||
delta += rt2800_get_gain_calibration_delta(rt2x00dev);
|
delta += rt2800_get_gain_calibration_delta(rt2x00dev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set to normal bbp tx power control mode: +/- 0dBm
|
* Decrease power according to user settings, on devices with unknown
|
||||||
|
* maximum tx power. For other devices we take user power_level into
|
||||||
|
* consideration on rt2800_compensate_txpower().
|
||||||
|
*/
|
||||||
|
delta += rt2800_get_txpower_reg_delta(rt2x00dev, power_level,
|
||||||
|
chan->max_power);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BBP_R1 controls TX power for all rates, it allow to set the following
|
||||||
|
* gains -12, -6, 0, +6 dBm by setting values 2, 1, 0, 3 respectively.
|
||||||
|
*
|
||||||
|
* TODO: we do not use +6 dBm option to do not increase power beyond
|
||||||
|
* regulatory limit, however this could be utilized for devices with
|
||||||
|
* CAPABILITY_POWER_LIMIT.
|
||||||
*/
|
*/
|
||||||
rt2800_bbp_read(rt2x00dev, 1, &r1);
|
rt2800_bbp_read(rt2x00dev, 1, &r1);
|
||||||
rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, 0);
|
if (delta <= -12) {
|
||||||
|
power_ctrl = 2;
|
||||||
|
delta += 12;
|
||||||
|
} else if (delta <= -6) {
|
||||||
|
power_ctrl = 1;
|
||||||
|
delta += 6;
|
||||||
|
} else {
|
||||||
|
power_ctrl = 0;
|
||||||
|
}
|
||||||
|
rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl);
|
||||||
rt2800_bbp_write(rt2x00dev, 1, r1);
|
rt2800_bbp_write(rt2x00dev, 1, r1);
|
||||||
offset = TX_PWR_CFG_0;
|
offset = TX_PWR_CFG_0;
|
||||||
|
|
||||||
|
@ -2710,7 +2764,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
|
||||||
|
|
||||||
void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev)
|
void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev)
|
||||||
{
|
{
|
||||||
rt2800_config_txpower(rt2x00dev, rt2x00dev->curr_band,
|
rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.channel,
|
||||||
rt2x00dev->tx_power);
|
rt2x00dev->tx_power);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(rt2800_gain_calibration);
|
EXPORT_SYMBOL_GPL(rt2800_gain_calibration);
|
||||||
|
@ -2845,11 +2899,11 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev,
|
||||||
if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {
|
if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||||
rt2800_config_channel(rt2x00dev, libconf->conf,
|
rt2800_config_channel(rt2x00dev, libconf->conf,
|
||||||
&libconf->rf, &libconf->channel);
|
&libconf->rf, &libconf->channel);
|
||||||
rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band,
|
rt2800_config_txpower(rt2x00dev, libconf->conf->channel,
|
||||||
libconf->conf->power_level);
|
libconf->conf->power_level);
|
||||||
}
|
}
|
||||||
if (flags & IEEE80211_CONF_CHANGE_POWER)
|
if (flags & IEEE80211_CONF_CHANGE_POWER)
|
||||||
rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band,
|
rt2800_config_txpower(rt2x00dev, libconf->conf->channel,
|
||||||
libconf->conf->power_level);
|
libconf->conf->power_level);
|
||||||
if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
|
if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
|
||||||
rt2800_config_retry_limit(rt2x00dev, libconf);
|
rt2800_config_retry_limit(rt2x00dev, libconf);
|
||||||
|
|
|
@ -52,11 +52,8 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no,
|
||||||
u32 target_content = 0;
|
u32 target_content = 0;
|
||||||
u8 entry_i;
|
u8 entry_i;
|
||||||
|
|
||||||
RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
|
RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "key_cont_128: %6phC\n",
|
||||||
"key_cont_128:\n %x:%x:%x:%x:%x:%x\n",
|
key_cont_128);
|
||||||
key_cont_128[0], key_cont_128[1],
|
|
||||||
key_cont_128[2], key_cont_128[3],
|
|
||||||
key_cont_128[4], key_cont_128[5]);
|
|
||||||
|
|
||||||
for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
|
for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
|
||||||
target_command = entry_i + CAM_CONTENT_COUNT * entry_no;
|
target_command = entry_i + CAM_CONTENT_COUNT * entry_no;
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue