Merge remote-tracking branch 'wireless-next/master' into mac80211-next
This commit is contained in:
commit
6fb47de9cf
175 changed files with 8268 additions and 2967 deletions
|
@ -7477,6 +7477,12 @@ S: Maintained
|
|||
F: Documentation/usb/acm.txt
|
||||
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
|
||||
M: Matthew Wilcox <willy@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
|
||||
case BCM47XX_BUS_TYPE_SSB:
|
||||
mcore_ssb = &bcm47xx_bus.ssb.mipscore;
|
||||
base = mcore_ssb->flash_window;
|
||||
lim = mcore_ssb->flash_window_size;
|
||||
base = mcore_ssb->pflash.window;
|
||||
lim = mcore_ssb->pflash.window_size;
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_BCM47XX_BCMA
|
||||
|
|
|
@ -156,10 +156,10 @@ static int __init wgt634u_init(void)
|
|||
SSB_CHIPCO_IRQ_GPIO);
|
||||
}
|
||||
|
||||
wgt634u_flash_data.width = mcore->flash_buswidth;
|
||||
wgt634u_flash_resource.start = mcore->flash_window;
|
||||
wgt634u_flash_resource.end = mcore->flash_window
|
||||
+ mcore->flash_window_size
|
||||
wgt634u_flash_data.width = mcore->pflash.buswidth;
|
||||
wgt634u_flash_resource.start = mcore->pflash.window;
|
||||
wgt634u_flash_resource.end = mcore->pflash.window
|
||||
+ mcore->pflash.window_size
|
||||
- 1;
|
||||
return platform_add_devices(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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
u32 leddc_on = 10;
|
||||
|
@ -30,11 +47,7 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc)
|
|||
if (cc->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);
|
||||
bcma_core_chipcommon_early_init(cc);
|
||||
|
||||
if (cc->core->id.rev >= 20) {
|
||||
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;
|
||||
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,
|
||||
* 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;
|
||||
|
||||
|
@ -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",
|
||||
cc->pmu.rev, pmucap);
|
||||
}
|
||||
|
||||
void bcma_pmu_init(struct bcma_drv_cc *cc)
|
||||
{
|
||||
if (cc->pmu.rev == 1)
|
||||
bcma_cc_mask32(cc, BCMA_CC_PMU_CTL,
|
||||
~BCMA_CC_PMU_CTL_NOILPONW);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
static struct resource bcma_sflash_resource = {
|
||||
.name = "bcma_sflash",
|
||||
.start = BCMA_SFLASH,
|
||||
.start = BCMA_SOC_FLASH2,
|
||||
.end = 0,
|
||||
.flags = IORESOURCE_MEM | IORESOURCE_READONLY,
|
||||
};
|
||||
|
@ -31,15 +31,42 @@ struct bcma_sflash_tbl_e {
|
|||
};
|
||||
|
||||
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 },
|
||||
};
|
||||
|
||||
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 },
|
||||
};
|
||||
|
||||
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 },
|
||||
};
|
||||
|
||||
|
@ -84,6 +111,8 @@ int bcma_sflash_init(struct bcma_drv_cc *cc)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case 0x13:
|
||||
return -ENOTSUPP;
|
||||
default:
|
||||
for (e = bcma_sflash_st_tbl; e->name; e++) {
|
||||
if (e->id == id)
|
||||
|
@ -116,7 +145,7 @@ int bcma_sflash_init(struct bcma_drv_cc *cc)
|
|||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
sflash->window = BCMA_SFLASH;
|
||||
sflash->window = BCMA_SOC_FLASH2;
|
||||
sflash->blocksize = e->blocksize;
|
||||
sflash->numblocks = e->numblocks;
|
||||
sflash->size = sflash->blocksize * sflash->numblocks;
|
||||
|
|
|
@ -181,47 +181,66 @@ EXPORT_SYMBOL(bcma_cpu_clock);
|
|||
static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
|
||||
{
|
||||
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_ATSER:
|
||||
bcma_debug(bus, "Found serial flash\n");
|
||||
bcma_sflash_init(&bus->drv_cc);
|
||||
bcma_sflash_init(cc);
|
||||
break;
|
||||
case BCMA_CC_FLASHT_PARA:
|
||||
bcma_debug(bus, "Found parallel flash\n");
|
||||
bus->drv_cc.pflash.window = 0x1c000000;
|
||||
bus->drv_cc.pflash.window_size = 0x02000000;
|
||||
cc->pflash.present = true;
|
||||
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)
|
||||
bus->drv_cc.pflash.buswidth = 1;
|
||||
cc->pflash.buswidth = 1;
|
||||
else
|
||||
bus->drv_cc.pflash.buswidth = 2;
|
||||
cc->pflash.buswidth = 2;
|
||||
break;
|
||||
default:
|
||||
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) {
|
||||
if (bus->drv_cc.capabilities & BCMA_CC_CAP_NFLASH) {
|
||||
if (cc->capabilities & BCMA_CC_CAP_NFLASH) {
|
||||
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)
|
||||
{
|
||||
struct bcma_bus *bus;
|
||||
struct bcma_device *core;
|
||||
bus = mcore->core->bus;
|
||||
|
||||
if (mcore->setup_done)
|
||||
return;
|
||||
|
||||
bcma_info(bus, "Initializing MIPS core...\n");
|
||||
|
||||
if (!mcore->setup_done)
|
||||
mcore->assigned_irqs = 1;
|
||||
bcma_core_mips_early_init(mcore);
|
||||
|
||||
mcore->assigned_irqs = 1;
|
||||
|
||||
/* Assign IRQs to all cores on the bus */
|
||||
list_for_each_entry(core, &bus->cores, list) {
|
||||
|
@ -256,10 +275,5 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore)
|
|||
bcma_info(bus, "IRQ reconfiguration done\n");
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -35,11 +35,6 @@ bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc)
|
|||
chipid_top != 0x5300)
|
||||
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);
|
||||
|
||||
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");
|
||||
|
||||
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);
|
||||
if (!pc_host) {
|
||||
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.end = BCMA_SOC_PCI_MEM +
|
||||
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;
|
||||
pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0,
|
||||
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.end = BCMA_SOC_PCI1_MEM +
|
||||
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;
|
||||
pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG;
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static int bcma_host_pci_suspend(struct device *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);
|
||||
#define BCMA_PM_OPS (&bcma_pm_ops)
|
||||
|
||||
#else /* CONFIG_PM */
|
||||
#else /* CONFIG_PM_SLEEP */
|
||||
|
||||
#define BCMA_PM_OPS NULL
|
||||
|
||||
#endif /* CONFIG_PM */
|
||||
#endif /* CONFIG_PM_SLEEP */
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = {
|
||||
{ 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);
|
||||
|
||||
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)
|
||||
{
|
||||
struct bcma_device *core = container_of(dev, struct bcma_device, dev);
|
||||
|
@ -158,9 +170,10 @@ static int bcma_register_cores(struct bcma_bus *bus)
|
|||
|
||||
static void bcma_unregister_cores(struct bcma_bus *bus)
|
||||
{
|
||||
struct bcma_device *core;
|
||||
struct bcma_device *core, *tmp;
|
||||
|
||||
list_for_each_entry(core, &bus->cores, list) {
|
||||
list_for_each_entry_safe(core, tmp, &bus->cores, list) {
|
||||
list_del(&core->list);
|
||||
if (core->dev_registered)
|
||||
device_unregister(&core->dev);
|
||||
}
|
||||
|
@ -182,6 +195,20 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
|
|||
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 */
|
||||
core = bcma_find_core(bus, bcma_cc_core_id(bus));
|
||||
if (core) {
|
||||
|
@ -197,10 +224,17 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
|
|||
}
|
||||
|
||||
/* Init PCIE core */
|
||||
core = bcma_find_core(bus, BCMA_CORE_PCIE);
|
||||
core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 0);
|
||||
if (core) {
|
||||
bus->drv_pci.core = core;
|
||||
bcma_core_pci_init(&bus->drv_pci);
|
||||
bus->drv_pci[0].core = core;
|
||||
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 */
|
||||
|
@ -210,13 +244,6 @@ int __devinit bcma_bus_register(struct bcma_bus *bus)
|
|||
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 */
|
||||
bcma_register_cores(bus);
|
||||
|
||||
|
@ -274,18 +301,18 @@ int __init bcma_bus_early_register(struct bcma_bus *bus,
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Init CC core */
|
||||
/* Early init CC core */
|
||||
core = bcma_find_core(bus, bcma_cc_core_id(bus));
|
||||
if (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);
|
||||
if (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");
|
||||
|
|
|
@ -595,8 +595,11 @@ int bcma_sprom_get(struct bcma_bus *bus)
|
|||
bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
u16 buf_len = 0;
|
||||
int ret, buf_block_len, blksz;
|
||||
int ret, num_blocks, blksz;
|
||||
struct sk_buff *skb = NULL;
|
||||
u32 type;
|
||||
u8 *payload = NULL;
|
||||
|
@ -514,18 +514,17 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
|||
}
|
||||
|
||||
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
|
||||
|| (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
|
||||
|| (num_blocks * blksz) > ALLOC_BUF_SIZE) {
|
||||
BT_ERR("invalid packet length: %d", buf_len);
|
||||
ret = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Allocate buffer */
|
||||
skb = bt_skb_alloc(buf_block_len * blksz + BTSDIO_DMA_ALIGN,
|
||||
GFP_ATOMIC);
|
||||
skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC);
|
||||
if (skb == NULL) {
|
||||
BT_ERR("No free skb");
|
||||
goto exit;
|
||||
|
@ -541,7 +540,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
|||
payload = skb->data;
|
||||
|
||||
ret = sdio_readsb(card->func, payload, card->ioport,
|
||||
buf_block_len * blksz);
|
||||
num_blocks * blksz);
|
||||
if (ret < 0) {
|
||||
BT_ERR("readsb failed: %d", ret);
|
||||
ret = -EIO;
|
||||
|
@ -553,7 +552,16 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
|||
*/
|
||||
|
||||
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];
|
||||
|
||||
switch (type) {
|
||||
|
@ -589,8 +597,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv)
|
|||
|
||||
default:
|
||||
BT_ERR("Unknown packet type:%d", type);
|
||||
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload,
|
||||
blksz * buf_block_len);
|
||||
BT_ERR("hex: %*ph", blksz * num_blocks, payload);
|
||||
|
||||
kfree_skb(skb);
|
||||
skb = NULL;
|
||||
|
@ -849,8 +856,7 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv,
|
|||
if (ret < 0) {
|
||||
i++;
|
||||
BT_ERR("i=%d writesb failed: %d", i, ret);
|
||||
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET,
|
||||
payload, nb);
|
||||
BT_ERR("hex: %*ph", nb, payload);
|
||||
ret = -EIO;
|
||||
if (i > MAX_WRITE_IOMEM_RETRY)
|
||||
goto exit;
|
||||
|
|
|
@ -26,5 +26,6 @@ source "drivers/net/wireless/ath/ath5k/Kconfig"
|
|||
source "drivers/net/wireless/ath/ath9k/Kconfig"
|
||||
source "drivers/net/wireless/ath/carl9170/Kconfig"
|
||||
source "drivers/net/wireless/ath/ath6kl/Kconfig"
|
||||
source "drivers/net/wireless/ath/ar5523/Kconfig"
|
||||
|
||||
endif
|
||||
|
|
|
@ -2,6 +2,7 @@ obj-$(CONFIG_ATH5K) += ath5k/
|
|||
obj-$(CONFIG_ATH9K_HW) += ath9k/
|
||||
obj-$(CONFIG_CARL9170) += carl9170/
|
||||
obj-$(CONFIG_ATH6KL) += ath6kl/
|
||||
obj-$(CONFIG_AR5523) += ar5523/
|
||||
|
||||
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;
|
||||
|
||||
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)
|
|
@ -534,107 +534,107 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
|
|||
|
||||
static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
|
||||
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
|
||||
{0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
|
||||
{0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
|
||||
{0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||
{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
|
||||
{0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
|
||||
{0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
|
||||
{0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
|
||||
{0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202},
|
||||
{0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400},
|
||||
{0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402},
|
||||
{0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404},
|
||||
{0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603},
|
||||
{0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02},
|
||||
{0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04},
|
||||
{0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20},
|
||||
{0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20},
|
||||
{0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22},
|
||||
{0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24},
|
||||
{0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640},
|
||||
{0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660},
|
||||
{0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861},
|
||||
{0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81},
|
||||
{0x0000a54c, 0x5a08442e, 0x5a08442e, 0x47001a83, 0x47001a83},
|
||||
{0x0000a550, 0x5e0a4431, 0x5e0a4431, 0x4a001c84, 0x4a001c84},
|
||||
{0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3},
|
||||
{0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5},
|
||||
{0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9},
|
||||
{0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb},
|
||||
{0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
|
||||
{0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
|
||||
{0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
|
||||
{0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
|
||||
{0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
|
||||
{0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
|
||||
{0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
|
||||
{0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
|
||||
{0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
|
||||
{0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
|
||||
{0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
|
||||
{0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
|
||||
{0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
|
||||
{0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861},
|
||||
{0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81},
|
||||
{0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83},
|
||||
{0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84},
|
||||
{0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3},
|
||||
{0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5},
|
||||
{0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9},
|
||||
{0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb},
|
||||
{0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
|
||||
{0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
|
||||
{0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
|
||||
{0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
|
||||
{0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
|
||||
{0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202},
|
||||
{0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400},
|
||||
{0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402},
|
||||
{0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404},
|
||||
{0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603},
|
||||
{0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02},
|
||||
{0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04},
|
||||
{0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20},
|
||||
{0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20},
|
||||
{0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22},
|
||||
{0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24},
|
||||
{0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640},
|
||||
{0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660},
|
||||
{0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861},
|
||||
{0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81},
|
||||
{0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83},
|
||||
{0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84},
|
||||
{0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3},
|
||||
{0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5},
|
||||
{0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9},
|
||||
{0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb},
|
||||
{0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
|
||||
{0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
|
||||
{0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
|
||||
{0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
|
||||
{0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
|
||||
{0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
|
||||
{0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec},
|
||||
{0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
|
||||
{0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
|
||||
{0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402},
|
||||
{0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
|
||||
{0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
|
||||
{0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
|
||||
{0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
|
||||
{0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
|
||||
{0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
|
||||
{0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
|
||||
{0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
|
||||
{0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
|
||||
{0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
|
||||
{0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861},
|
||||
{0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81},
|
||||
{0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83},
|
||||
{0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84},
|
||||
{0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3},
|
||||
{0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5},
|
||||
{0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9},
|
||||
{0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb},
|
||||
{0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
|
||||
{0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
|
||||
{0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
|
||||
{0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
|
||||
{0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
|
||||
{0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
|
||||
{0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
|
||||
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
|
||||
{0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
|
||||
{0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000},
|
||||
{0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000},
|
||||
{0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501},
|
||||
{0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501},
|
||||
{0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03},
|
||||
{0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04},
|
||||
{0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04},
|
||||
{0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
|
||||
{0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
|
||||
{0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
|
||||
{0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
|
||||
{0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005},
|
||||
{0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
|
||||
{0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
|
||||
{0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000},
|
||||
{0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501},
|
||||
{0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501},
|
||||
{0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03},
|
||||
{0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04},
|
||||
{0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04},
|
||||
{0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||
{0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||
{0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||
{0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||
{0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
|
||||
{0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
|
||||
{0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||
{0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352},
|
||||
{0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
|
||||
{0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
|
||||
{0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
|
||||
{0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
|
||||
{0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
||||
{0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
|
||||
{0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
|
||||
{0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
{0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
||||
{0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
|
||||
{0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
|
||||
{0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
{0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
|
||||
{0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001},
|
||||
{0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
|
||||
{0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
|
||||
};
|
||||
|
||||
|
|
|
@ -276,6 +276,11 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains)
|
|||
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],
|
||||
AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF,
|
||||
iCoff);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "hw.h"
|
||||
#include "ar9003_phy.h"
|
||||
#include "ar9003_eeprom.h"
|
||||
#include "ar9003_mci.h"
|
||||
|
||||
#define COMP_HDR_LEN 4
|
||||
#define COMP_CKSUM_LEN 2
|
||||
|
@ -41,7 +42,6 @@
|
|||
static int ar9003_hw_power_interpolate(int32_t x,
|
||||
int32_t *px, int32_t *py, u_int16_t np);
|
||||
|
||||
|
||||
static const struct ar9300_eeprom ar9300_default = {
|
||||
.eepromVersion = 2,
|
||||
.templateVersion = 2,
|
||||
|
@ -2989,7 +2989,7 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
|
|||
case EEP_PAPRD:
|
||||
if (AR_SREV_9462(ah))
|
||||
return false;
|
||||
if (!ah->config.enable_paprd);
|
||||
if (!ah->config.enable_paprd)
|
||||
return false;
|
||||
return !!(pBase->featureEnable & BIT(5));
|
||||
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
|
||||
* 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);
|
||||
REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL,
|
||||
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_2GHT20:
|
||||
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],
|
||||
minCtlPower);
|
||||
if (ath9k_hw_mci_is_enabled(ah))
|
||||
pPwrArray[i] =
|
||||
(u8)min((u16)pPwrArray[i],
|
||||
ar9003_mci_get_max_txpower(ah,
|
||||
pCtlMode[ctlMode]));
|
||||
}
|
||||
break;
|
||||
case CTL_5GHT40:
|
||||
case CTL_2GHT40:
|
||||
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],
|
||||
minCtlPower);
|
||||
if (ath9k_hw_mci_is_enabled(ah))
|
||||
pPwrArray[i] =
|
||||
(u8)min((u16)pPwrArray[i],
|
||||
ar9003_mci_get_max_txpower(ah,
|
||||
pCtlMode[ctlMode]));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -219,10 +219,10 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
|
|||
|
||||
/* Awake -> Sleep Setting */
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
||||
ar9462_pciephy_pll_on_clkreq_disable_L1_2p0);
|
||||
ar9462_pciephy_clkreq_disable_L1_2p0);
|
||||
/* Sleep -> Awake Setting */
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
|
||||
ar9462_pciephy_pll_on_clkreq_disable_L1_2p0);
|
||||
ar9462_pciephy_clkreq_disable_L1_2p0);
|
||||
|
||||
/* Fast clock modal settings */
|
||||
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);
|
||||
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdes,
|
||||
ar9565_1p0_pciephy_pll_on_clkreq_disable_L1);
|
||||
ar9565_1p0_pciephy_clkreq_disable_L1);
|
||||
INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
|
||||
ar9565_1p0_pciephy_pll_on_clkreq_disable_L1);
|
||||
ar9565_1p0_pciephy_clkreq_disable_L1);
|
||||
|
||||
INIT_INI_ARRAY(&ah->iniModesFastClock,
|
||||
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;
|
||||
|
||||
REG_CLR_BIT(ah, AR_PHY_TIMING4,
|
||||
1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT);
|
||||
|
||||
if (caldata) {
|
||||
caldata->done_txiqcal_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))
|
||||
return -EIO;
|
||||
|
||||
REG_SET_BIT(ah, AR_PHY_TIMING4,
|
||||
1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT);
|
||||
|
||||
exit:
|
||||
ar9003_mci_enable_interrupt(ah);
|
||||
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,
|
||||
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)) {
|
||||
thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH);
|
||||
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 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",
|
||||
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_PA_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_BCN) |
|
||||
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);
|
||||
|
||||
|
@ -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,
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
|
@ -910,6 +941,9 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
|
|||
mci->ready = true;
|
||||
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)
|
||||
ar9003_mci_enable_interrupt(ah);
|
||||
|
||||
|
@ -1028,7 +1062,9 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force)
|
|||
|
||||
if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA))
|
||||
ar9003_mci_osla_setup(ah, true);
|
||||
REG_WRITE(ah, AR_SELFGEN_MASK, 0x02);
|
||||
|
||||
if (AR_SREV_9462(ah))
|
||||
REG_WRITE(ah, AR_SELFGEN_MASK, 0x02);
|
||||
} else {
|
||||
ar9003_mci_send_lna_take(ah, true);
|
||||
udelay(5);
|
||||
|
@ -1170,7 +1206,7 @@ EXPORT_SYMBOL(ar9003_mci_cleanup);
|
|||
u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type)
|
||||
{
|
||||
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
|
||||
u32 value = 0;
|
||||
u32 value = 0, tsf;
|
||||
u8 query_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);
|
||||
break;
|
||||
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);
|
||||
mci->query_bt = 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);
|
||||
}
|
||||
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 MCI_FLAG_DISABLE_TIMESTAMP 0x00000001 /* Disable time stamp */
|
||||
#define MCI_RECOVERY_DUR_TSF (100 * 1000) /* 100 ms */
|
||||
|
||||
/* Default remote BT device MCI COEX version */
|
||||
#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_BNEP,
|
||||
MCI_GPM_COEX_PROFILE_VOICE,
|
||||
MCI_GPM_COEX_PROFILE_A2DPVO,
|
||||
MCI_GPM_COEX_PROFILE_MAX
|
||||
};
|
||||
|
||||
|
@ -196,7 +198,6 @@ enum mci_state_type {
|
|||
MCI_STATE_SEND_WLAN_COEX_VERSION,
|
||||
MCI_STATE_SEND_VERSION_QUERY,
|
||||
MCI_STATE_SEND_STATUS_QUERY,
|
||||
MCI_STATE_SET_CONCUR_TX_PRI,
|
||||
MCI_STATE_RECOVER_RX,
|
||||
MCI_STATE_NEED_FTP_STOMP,
|
||||
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_set_power_awake(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
|
||||
|
||||
|
@ -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 u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#define AR_PHY_SPUR_REG (AR_CHAN_BASE + 0x1c)
|
||||
#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_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT 16
|
||||
|
||||
#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000
|
||||
#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},
|
||||
};
|
||||
|
||||
static const u32 ar9565_1p0_pciephy_pll_on_clkreq_disable_L1[][2] = {
|
||||
static const u32 ar9565_1p0_pciephy_clkreq_disable_L1[][2] = {
|
||||
/* Addr allmodes */
|
||||
{0x00018c00, 0x18212ede},
|
||||
{0x00018c00, 0x18213ede},
|
||||
{0x00018c04, 0x000801d8},
|
||||
{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 30000 /* 30 seconds */
|
||||
#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */
|
||||
#define ATH_ANI_MAX_SKIP_COUNT 10
|
||||
|
||||
#define ATH_PAPRD_TIMEOUT 100 /* msecs */
|
||||
#define ATH_PLL_WORK_INTERVAL 100
|
||||
|
@ -478,6 +479,7 @@ struct ath_btcoex {
|
|||
u32 btscan_no_stomp; /* in usec */
|
||||
u32 duty_cycle;
|
||||
u32 bt_wait_time;
|
||||
int rssi_count;
|
||||
struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */
|
||||
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);
|
||||
u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen);
|
||||
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
|
||||
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 int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf,
|
||||
u32 len, u32 size)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */
|
||||
|
||||
struct ath9k_wow_pattern {
|
||||
|
@ -642,6 +650,7 @@ enum sc_op_flags {
|
|||
#define PS_WAIT_FOR_PSPOLL_DATA BIT(2)
|
||||
#define PS_WAIT_FOR_TX_ACK BIT(3)
|
||||
#define PS_BEACON_SYNC BIT(4)
|
||||
#define PS_WAIT_FOR_ANI BIT(5)
|
||||
|
||||
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.wlan_cal_seq = 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);
|
||||
|
||||
|
@ -218,27 +218,45 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
|
|||
enum ath_stomp_type stomp_type)
|
||||
{
|
||||
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
|
||||
struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci;
|
||||
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];
|
||||
int i;
|
||||
|
||||
if (AR_SREV_9300_20_OR_LATER(ah)) {
|
||||
const u32 *weight = ar9003_wlan_weights[stomp_type];
|
||||
int i;
|
||||
|
||||
if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) {
|
||||
if ((stomp_type == ATH_BTCOEX_STOMP_LOW) &&
|
||||
btcoex_hw->mci.stomp_ftp)
|
||||
stomp_type = ATH_BTCOEX_STOMP_LOW_FTP;
|
||||
weight = mci_wlan_weights[stomp_type];
|
||||
}
|
||||
|
||||
for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) {
|
||||
btcoex_hw->bt_weight[i] = AR9300_BT_WGHT;
|
||||
btcoex_hw->wlan_weight[i] = weight[i];
|
||||
}
|
||||
} else {
|
||||
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)) {
|
||||
enum ath_stomp_type stype =
|
||||
((stomp_type == ATH_BTCOEX_STOMP_LOW) &&
|
||||
btcoex_hw->mci.stomp_ftp) ?
|
||||
ATH_BTCOEX_STOMP_LOW_FTP : stomp_type;
|
||||
weight = mci_wlan_weights[stype];
|
||||
}
|
||||
|
||||
for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) {
|
||||
btcoex_hw->bt_weight[i] = AR9300_BT_WGHT;
|
||||
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]);
|
||||
}
|
||||
}
|
||||
/* 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);
|
||||
|
||||
|
@ -385,3 +403,13 @@ void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
|
|||
}
|
||||
}
|
||||
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_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_WLAN_WEIGHTS 4
|
||||
/* Defines the BT AR_BT_COEX_WGHT used */
|
||||
|
@ -84,6 +87,8 @@ struct ath9k_hw_mci {
|
|||
u8 bt_ver_minor;
|
||||
u8 bt_state;
|
||||
u8 stomp_ftp;
|
||||
bool concur_tx;
|
||||
u32 last_recovery;
|
||||
};
|
||||
|
||||
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_weight[AR9300_NUM_BT_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);
|
||||
|
@ -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_bt_stomp(struct ath_hw *ah,
|
||||
enum ath_stomp_type stomp_type);
|
||||
void ath9k_hw_btcoex_set_concur_txprio(struct ath_hw *ah, u8 *stomp_txprio);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -410,6 +410,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
|
|||
|
||||
ah->caldata->channel = chan->channel;
|
||||
ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT;
|
||||
ah->caldata->chanmode = chan->chanmode;
|
||||
h = ah->caldata->nfCalHist;
|
||||
default_nf = ath9k_hw_get_default_nf(ah, chan);
|
||||
for (i = 0; i < NUM_NF_READINGS; i++) {
|
||||
|
|
|
@ -1586,6 +1586,35 @@ static const struct file_operations fops_samps = {
|
|||
|
||||
#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)
|
||||
{
|
||||
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);
|
||||
debugfs_create_file("diversity", S_IRUSR | S_IWUSR,
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -187,34 +187,12 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
static void ath_mci_ftp_adjust(struct ath_softc *sc)
|
||||
{
|
||||
struct ath_softc *sc = (struct ath_softc *) data;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
struct ath_btcoex *btcoex = &sc->btcoex;
|
||||
struct ath_mci_profile *mci = &btcoex->mci;
|
||||
u32 timer_period;
|
||||
bool is_btscan;
|
||||
unsigned long flags;
|
||||
struct ath_hw *ah = sc->sc_ah;
|
||||
|
||||
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 (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) &&
|
||||
(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;
|
||||
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);
|
||||
|
||||
ath9k_hw_btcoex_bt_stomp(ah, is_btscan ? ATH_BTCOEX_STOMP_ALL :
|
||||
btcoex->bt_stomp_type);
|
||||
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);
|
||||
|
||||
spin_unlock_bh(&btcoex->btcoex_lock);
|
||||
|
||||
/*
|
||||
|
@ -243,17 +263,16 @@ static void ath_btcoex_period_timer(unsigned long data)
|
|||
if (btcoex->hw_timer_enabled)
|
||||
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,
|
||||
timer_period * 10);
|
||||
btcoex->hw_timer_enabled = true;
|
||||
}
|
||||
|
||||
ath9k_ps_restore(sc);
|
||||
|
||||
skip_hw_wakeup:
|
||||
timer_period = btcoex->btcoex_period;
|
||||
mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period));
|
||||
mod_timer(&btcoex->period_timer,
|
||||
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);
|
||||
|
||||
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);
|
||||
else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
|
||||
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
|
||||
|
@ -474,4 +494,52 @@ int ath9k_init_btcoex(struct ath_softc *sc)
|
|||
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 */
|
||||
|
|
|
@ -38,6 +38,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = {
|
|||
{ USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */
|
||||
{ USB_DEVICE(0x040D, 0x3801) }, /* VIA */
|
||||
{ USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */
|
||||
{ USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */
|
||||
{ USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */
|
||||
|
||||
{ USB_DEVICE(0x0cf3, 0x7015),
|
||||
|
|
|
@ -694,6 +694,20 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
|
|||
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,
|
||||
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_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_IBSS_RSN |
|
||||
|
|
|
@ -1036,26 +1036,6 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
|
|||
|
||||
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);
|
||||
memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
|
||||
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);
|
||||
udelay(50);
|
||||
|
||||
if (ath9k_hw_mci_is_enabled(ah))
|
||||
ar9003_mci_set_power_awake(ah);
|
||||
|
||||
for (i = POWER_UP_TIME / 50; i > 0; i--) {
|
||||
val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M;
|
||||
if (val == AR_RTC_STATUS_ON)
|
||||
|
@ -2171,6 +2168,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah)
|
|||
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);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -401,6 +401,7 @@ enum ath9k_int {
|
|||
struct ath9k_hw_cal_data {
|
||||
u16 channel;
|
||||
u32 channelFlags;
|
||||
u32 chanmode;
|
||||
int32_t CalValid;
|
||||
int8_t iCoff;
|
||||
int8_t qCoff;
|
||||
|
@ -834,6 +835,7 @@ struct ath_hw {
|
|||
int coarse_low[5];
|
||||
int firpwr[5];
|
||||
enum ath9k_ani_cmd ani_function;
|
||||
u32 ani_skip_count;
|
||||
|
||||
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
|
||||
struct ath_btcoex_hw btcoex_hw;
|
||||
|
|
|
@ -687,6 +687,7 @@ static const struct ieee80211_iface_combination if_comb = {
|
|||
.n_limits = ARRAY_SIZE(if_limits),
|
||||
.max_interfaces = 2048,
|
||||
.num_different_channels = 1,
|
||||
.beacon_int_infra_match = true,
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
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);
|
||||
|
||||
|
|
|
@ -131,7 +131,8 @@ void ath9k_ps_restore(struct ath_softc *sc)
|
|||
!(sc->ps_flags & (PS_WAIT_FOR_BEACON |
|
||||
PS_WAIT_FOR_CAB |
|
||||
PS_WAIT_FOR_PSPOLL_DATA |
|
||||
PS_WAIT_FOR_TX_ACK))) {
|
||||
PS_WAIT_FOR_TX_ACK |
|
||||
PS_WAIT_FOR_ANI))) {
|
||||
mode = ATH9K_PM_NETWORK_SLEEP;
|
||||
if (ath9k_hw_btcoex_is_enabled(sc->sc_ah))
|
||||
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;
|
||||
}
|
||||
|
||||
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))
|
||||
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;
|
||||
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,
|
||||
"Primary Station interface: %pM, BSSID: %pM\n",
|
||||
vif->addr, common->curbssid);
|
||||
|
@ -1505,6 +1513,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
|
|||
memset(common->curbssid, 0, ETH_ALEN);
|
||||
common->curaid = 0;
|
||||
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 *entry;
|
||||
u8 voice_priority[] = { 110, 110, 110, 112, 110, 110, 114, 116, 118 };
|
||||
|
||||
if ((mci->num_sco == ATH_MCI_MAX_SCO_PROFILE) &&
|
||||
(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);
|
||||
INC_PROF(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;
|
||||
}
|
||||
|
@ -150,7 +157,7 @@ static void ath_mci_update_scheme(struct ath_softc *sc)
|
|||
* For single PAN/FTP profile, allocate 35% for BT
|
||||
* to improve WLAN throughput.
|
||||
*/
|
||||
btcoex->duty_cycle = 35;
|
||||
btcoex->duty_cycle = AR_SREV_9565(sc->sc_ah) ? 40 : 35;
|
||||
btcoex->btcoex_period = 53;
|
||||
ath_dbg(common, MCI,
|
||||
"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);
|
||||
}
|
||||
|
||||
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,
|
||||
struct ath_mci_profile_info *info)
|
||||
{
|
||||
|
@ -281,6 +339,7 @@ static u8 ath_mci_process_profile(struct ath_softc *sc,
|
|||
} else
|
||||
ath_mci_del_profile(common, mci, entry);
|
||||
|
||||
ath_mci_set_concur_txprio(sc);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -314,6 +373,7 @@ static u8 ath_mci_process_status(struct ath_softc *sc,
|
|||
mci->num_mgmt++;
|
||||
} while (++i < ATH_MCI_MAX_PROFILE);
|
||||
|
||||
ath_mci_set_concur_txprio(sc);
|
||||
if (old_num_mgmt != mci->num_mgmt)
|
||||
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)
|
||||
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 +\
|
||||
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 { \
|
||||
switch (_info->type) { \
|
||||
case MCI_GPM_COEX_PROFILE_RFCOMM:\
|
||||
|
@ -49,6 +70,7 @@
|
|||
_mci->num_pan++; \
|
||||
break; \
|
||||
case MCI_GPM_COEX_PROFILE_VOICE: \
|
||||
case MCI_GPM_COEX_PROFILE_A2DPVO:\
|
||||
_mci->num_sco++; \
|
||||
break; \
|
||||
default: \
|
||||
|
@ -73,6 +95,7 @@
|
|||
_mci->num_pan--; \
|
||||
break; \
|
||||
case MCI_GPM_COEX_PROFILE_VOICE: \
|
||||
case MCI_GPM_COEX_PROFILE_A2DPVO:\
|
||||
_mci->num_sco--; \
|
||||
break; \
|
||||
default: \
|
||||
|
@ -113,6 +136,7 @@ struct ath_mci_profile {
|
|||
u8 num_pan;
|
||||
u8 num_other_acl;
|
||||
u8 num_bdr;
|
||||
u8 voice_priority;
|
||||
};
|
||||
|
||||
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);
|
||||
void ath_mci_cleanup(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
|
||||
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
|
||||
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 /* MCI_H*/
|
||||
|
|
|
@ -1105,7 +1105,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
|
|||
else
|
||||
rs.is_mybeacon = false;
|
||||
|
||||
sc->rx.num_pkts++;
|
||||
if (ieee80211_is_data_present(hdr->frame_control) &&
|
||||
!ieee80211_is_qos_nullfunc(hdr->frame_control))
|
||||
sc->rx.num_pkts++;
|
||||
|
||||
ath_debug_stat_rx(sc, &rs);
|
||||
|
||||
/*
|
||||
|
|
|
@ -907,10 +907,6 @@
|
|||
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
|
||||
((_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) \
|
||||
(((_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_WL_LNA 0x1940
|
||||
#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_TXPWR_THRESH 0x0007F800
|
||||
|
@ -2360,4 +2358,11 @@ enum {
|
|||
#define AR_GLB_SWREG_DISCONT_MODE 0x2002c
|
||||
#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
|
||||
|
|
|
@ -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]);
|
||||
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
|
||||
* discard) compared to other chips */
|
||||
REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0);
|
||||
|
|
|
@ -312,6 +312,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)
|
|||
}
|
||||
|
||||
bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list);
|
||||
bf->bf_next = NULL;
|
||||
list_del(&bf->list);
|
||||
|
||||
spin_unlock_bh(&sc->tx.txbuflock);
|
||||
|
@ -1774,6 +1775,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
|
|||
list_add_tail(&bf->list, &bf_head);
|
||||
bf->bf_state.bf_type = 0;
|
||||
|
||||
bf->bf_next = NULL;
|
||||
bf->bf_lastbf = bf;
|
||||
ath_tx_fill_desc(sc, bf, txq, fi->framelen);
|
||||
ath_tx_txqaddbuf(sc, txq, &bf_head, false);
|
||||
|
|
|
@ -343,7 +343,24 @@ int carl9170_set_operating_mode(struct ar9170 *ar)
|
|||
break;
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
@ -355,8 +372,6 @@ int carl9170_set_operating_mode(struct ar9170 *ar)
|
|||
enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -164,9 +164,6 @@ void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
|
|||
struct carl9170_rsp *cmd = buf;
|
||||
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_CMD_ASYNC_FLAG))
|
||||
carl9170_cmd_callback(ar, len, buf);
|
||||
|
@ -663,6 +660,35 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms,
|
|||
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
|
||||
* 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,
|
||||
* this is non-trivial.
|
||||
*/
|
||||
|
||||
static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
|
||||
static void carl9170_rx_untie_data(struct ar9170 *ar, u8 *buf, int len)
|
||||
{
|
||||
struct ar9170_rx_head *head;
|
||||
struct ar9170_rx_macstatus *mac;
|
||||
struct ar9170_rx_phystatus *phy = NULL;
|
||||
struct ieee80211_rx_status status;
|
||||
struct sk_buff *skb;
|
||||
int mpdu_len;
|
||||
u8 mac_status;
|
||||
|
||||
|
@ -791,18 +815,10 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
|
|||
if (phy)
|
||||
carl9170_rx_phy_status(ar, phy, &status);
|
||||
|
||||
carl9170_ps_beacon(ar, buf, mpdu_len);
|
||||
|
||||
carl9170_ba_check(ar, buf, mpdu_len);
|
||||
|
||||
skb = carl9170_rx_copy_data(buf, mpdu_len);
|
||||
if (!skb)
|
||||
if (carl9170_handle_mpdu(ar, buf, mpdu_len, &status))
|
||||
goto drop;
|
||||
|
||||
memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
|
||||
ieee80211_rx(ar->hw, skb);
|
||||
return;
|
||||
|
||||
drop:
|
||||
ar->rx_dropped++;
|
||||
}
|
||||
|
@ -820,6 +836,9 @@ static void carl9170_rx_untie_cmds(struct ar9170 *ar, const u8 *respbuf,
|
|||
if (unlikely(i > resplen))
|
||||
break;
|
||||
|
||||
if (carl9170_check_sequence(ar, cmd->hdr.seq))
|
||||
break;
|
||||
|
||||
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)
|
||||
carl9170_rx_untie_cmds(ar, buf, len);
|
||||
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)
|
||||
|
|
|
@ -295,6 +295,13 @@ static void carl9170_usb_rx_irq_complete(struct urb *urb)
|
|||
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,
|
||||
urb->actual_length);
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@
|
|||
#include "ath.h"
|
||||
#include "reg.h"
|
||||
|
||||
#define REG_READ (common->ops->read)
|
||||
#define REG_WRITE (common->ops->write)
|
||||
#define REG_READ (common->ops->read)
|
||||
#define REG_WRITE(_ah, _reg, _val) (common->ops->write)(_ah, _val, _reg)
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
REG_WRITE(ah, get_unaligned_le32(common->bssidmask), AR_BSSMSKL);
|
||||
REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU);
|
||||
REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(common->bssidmask));
|
||||
REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(common->bssidmask + 4));
|
||||
}
|
||||
EXPORT_SYMBOL(ath_hw_setbssidmask);
|
||||
|
||||
|
@ -139,7 +139,7 @@ void ath_hw_cycle_counters_update(struct ath_common *common)
|
|||
void *ah = common->ah;
|
||||
|
||||
/* freeze */
|
||||
REG_WRITE(ah, AR_MIBC_FMC, AR_MIBC);
|
||||
REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);
|
||||
|
||||
/* read */
|
||||
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);
|
||||
|
||||
/* clear */
|
||||
REG_WRITE(ah, 0, AR_CCCNT);
|
||||
REG_WRITE(ah, 0, AR_RFCNT);
|
||||
REG_WRITE(ah, 0, AR_RCCNT);
|
||||
REG_WRITE(ah, 0, AR_TFCNT);
|
||||
REG_WRITE(ah, AR_CCCNT, 0);
|
||||
REG_WRITE(ah, AR_RFCNT, 0);
|
||||
REG_WRITE(ah, AR_RCCNT, 0);
|
||||
REG_WRITE(ah, AR_TFCNT, 0);
|
||||
|
||||
/* unfreeze */
|
||||
REG_WRITE(ah, 0, AR_MIBC);
|
||||
REG_WRITE(ah, AR_MIBC, 0);
|
||||
|
||||
/* update all cycle counters here */
|
||||
common->cc_ani.cycles += cycles;
|
||||
|
|
|
@ -4652,7 +4652,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
|
|||
switch (dev->dev->bus_type) {
|
||||
#ifdef CONFIG_B43_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);
|
||||
break;
|
||||
#endif
|
||||
|
@ -5404,6 +5404,8 @@ static void b43_bcma_remove(struct bcma_device *core)
|
|||
cancel_work_sync(&wldev->restart_work);
|
||||
|
||||
B43_WARN_ON(!wl);
|
||||
if (!wldev->fw.ucode.data)
|
||||
return; /* NULL if firmware never loaded */
|
||||
if (wl->current_dev == wldev && wl->hw_registred) {
|
||||
b43_leds_stop(wldev);
|
||||
ieee80211_unregister_hw(wl->hw);
|
||||
|
@ -5478,6 +5480,8 @@ static void b43_ssb_remove(struct ssb_device *sdev)
|
|||
cancel_work_sync(&wldev->restart_work);
|
||||
|
||||
B43_WARN_ON(!wl);
|
||||
if (!wldev->fw.ucode.data)
|
||||
return; /* NULL if firmware never loaded */
|
||||
if (wl->current_dev == wldev && wl->hw_registred) {
|
||||
b43_leds_stop(wldev);
|
||||
ieee80211_unregister_hw(wl->hw);
|
||||
|
|
|
@ -24,6 +24,7 @@ ccflags-y += -D__CHECK_ENDIAN__
|
|||
obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
|
||||
brcmfmac-objs += \
|
||||
wl_cfg80211.o \
|
||||
fwil.o \
|
||||
dhd_cdc.o \
|
||||
dhd_common.o \
|
||||
dhd_linux.o
|
||||
|
|
|
@ -318,6 +318,12 @@ struct brcmf_event {
|
|||
#define BRCMF_E_LINK_ASSOC_REC 3
|
||||
#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
|
||||
* start matching, the pattern to match, the size of the pattern, and a bitmask
|
||||
* that indicates which bits within the pattern should be matched.
|
||||
|
@ -623,7 +629,6 @@ struct brcmf_pub {
|
|||
u8 wme_dp; /* wme discard priority */
|
||||
|
||||
/* Dongle media info */
|
||||
bool iswl; /* Dongle-resident driver is wl */
|
||||
unsigned long drv_version; /* Version of dongle-resident driver */
|
||||
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 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 mutex proto_block;
|
||||
unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
|
||||
|
||||
struct work_struct setmacaddr_work;
|
||||
struct work_struct multicast_work;
|
||||
|
@ -671,6 +670,11 @@ struct brcmf_pub {
|
|||
#endif
|
||||
};
|
||||
|
||||
struct bcmevent_name {
|
||||
uint event;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct brcmf_if_event {
|
||||
u8 ifidx;
|
||||
u8 action;
|
||||
|
@ -678,47 +682,60 @@ struct brcmf_if_event {
|
|||
u8 bssidx;
|
||||
};
|
||||
|
||||
struct bcmevent_name {
|
||||
uint event;
|
||||
const char *name;
|
||||
/* forward declaration */
|
||||
struct brcmf_cfg80211_vif;
|
||||
|
||||
/**
|
||||
* 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 uint brcmf_c_mkiovar(char *name, char *data, uint datalen,
|
||||
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 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 */
|
||||
extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx);
|
||||
|
||||
/* Query dongle */
|
||||
extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx,
|
||||
uint cmd, void *buf, uint len);
|
||||
|
||||
#ifdef DEBUG
|
||||
extern int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size);
|
||||
#endif /* DEBUG */
|
||||
extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
|
||||
void *buf, uint len);
|
||||
|
||||
extern int brcmf_ifname2idx(struct brcmf_pub *drvr, char *name);
|
||||
extern int brcmf_c_host_event(struct brcmf_pub *drvr, int *idx,
|
||||
void *pktdata, struct brcmf_event_msg *,
|
||||
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_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_ */
|
||||
|
|
|
@ -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_add_if(struct device *dev, int ifidx,
|
||||
char *name, u8 *mac_addr);
|
||||
|
||||
#ifdef CONFIG_BRCMFMAC_SDIO
|
||||
extern void brcmf_sdio_exit(void);
|
||||
extern void brcmf_sdio_init(void);
|
||||
|
|
|
@ -458,35 +458,6 @@ void brcmf_proto_detach(struct brcmf_pub *drvr)
|
|||
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)
|
||||
{
|
||||
/* Nothing to do for CDC */
|
||||
|
|
|
@ -28,12 +28,17 @@
|
|||
#include "dhd_bus.h"
|
||||
#include "dhd_proto.h"
|
||||
#include "dhd_dbg.h"
|
||||
#include "fwil.h"
|
||||
|
||||
#define BRCM_OUI "\x00\x10\x18"
|
||||
#define DOT11_OUI_LEN 3
|
||||
#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_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
|
||||
|
||||
|
@ -88,52 +93,6 @@ brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen)
|
|||
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,
|
||||
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 */
|
||||
struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata;
|
||||
struct brcmf_if_event *ifevent;
|
||||
struct brcmf_if *ifp;
|
||||
char *event_data;
|
||||
u32 type, status;
|
||||
u16 flags;
|
||||
|
@ -525,12 +485,17 @@ brcmf_c_host_event(struct brcmf_pub *drvr, int *ifidx, void *pktdata,
|
|||
brcmf_dbg(TRACE, "if event\n");
|
||||
|
||||
if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) {
|
||||
if (ifevent->action == BRCMF_E_IF_ADD)
|
||||
brcmf_add_if(drvr->dev, ifevent->ifidx,
|
||||
event->ifname,
|
||||
pvt_data->eth.h_dest);
|
||||
else
|
||||
if (ifevent->action == BRCMF_E_IF_ADD) {
|
||||
ifp = brcmf_add_if(drvr->dev, ifevent->ifidx,
|
||||
ifevent->bssidx,
|
||||
event->ifname,
|
||||
pvt_data->eth.h_dest);
|
||||
if (IS_ERR(ifp))
|
||||
return PTR_ERR(ifp);
|
||||
brcmf_net_attach(ifp);
|
||||
} else {
|
||||
brcmf_del_if(drvr, ifevent->ifidx);
|
||||
}
|
||||
} else {
|
||||
brcmf_dbg(ERROR, "Invalid ifidx %d for %s\n",
|
||||
ifevent->ifidx, event->ifname);
|
||||
|
@ -603,90 +568,57 @@ static int brcmf_c_pattern_atoh(char *src, char *dst)
|
|||
return i;
|
||||
}
|
||||
|
||||
void
|
||||
brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable,
|
||||
int master_mode)
|
||||
static void
|
||||
brcmf_c_pktfilter_offload_enable(struct brcmf_if *ifp, char *arg, int enable,
|
||||
int master_mode)
|
||||
{
|
||||
unsigned long res;
|
||||
char *argv[8];
|
||||
int i = 0;
|
||||
const char *str;
|
||||
int buf_len;
|
||||
int str_len;
|
||||
char *argv;
|
||||
char *arg_save = NULL, *arg_org = NULL;
|
||||
int rc;
|
||||
char buf[128];
|
||||
s32 err;
|
||||
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)
|
||||
goto fail;
|
||||
|
||||
arg_org = arg_save;
|
||||
memcpy(arg_save, arg, strlen(arg) + 1);
|
||||
|
||||
argv[i] = strsep(&arg_save, " ");
|
||||
argv = strsep(&arg_save, " ");
|
||||
|
||||
i = 0;
|
||||
if (NULL == argv[i]) {
|
||||
if (argv == NULL) {
|
||||
brcmf_dbg(ERROR, "No args provided\n");
|
||||
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. */
|
||||
enable_parm.id = 0;
|
||||
if (!kstrtoul(argv[i], 0, &res))
|
||||
if (!kstrtoul(argv, 0, &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);
|
||||
|
||||
buf_len += sizeof(enable_parm);
|
||||
memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm));
|
||||
err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_enable", &enable_parm,
|
||||
sizeof(enable_parm));
|
||||
if (err)
|
||||
brcmf_dbg(ERROR, "Set pkt_filter_enable error (%d)\n", err);
|
||||
|
||||
/* Enable/disable the specified filter. */
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
/* Control the master mode */
|
||||
err = brcmf_fil_iovar_int_set(ifp, "pkt_filter_mode", master_mode);
|
||||
if (err)
|
||||
brcmf_dbg(ERROR, "Set pkt_filter_mode error (%d)\n", err);
|
||||
|
||||
fail:
|
||||
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_filterp;
|
||||
struct brcmf_pkt_filter_le *pkt_filter;
|
||||
unsigned long res;
|
||||
int buf_len;
|
||||
int str_len;
|
||||
int rc;
|
||||
s32 err;
|
||||
u32 mask_size;
|
||||
u32 pattern_size;
|
||||
char *argv[8], *buf = NULL;
|
||||
|
@ -704,104 +636,64 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
|
|||
goto fail;
|
||||
|
||||
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, " ");
|
||||
}
|
||||
|
||||
i = 0;
|
||||
if (NULL == argv[i]) {
|
||||
brcmf_dbg(ERROR, "No args provided\n");
|
||||
if (i != 6) {
|
||||
brcmf_dbg(ERROR, "Not enough args provided %d\n", i);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
str = "pkt_filter_add";
|
||||
strcpy(buf, str);
|
||||
str_len = strlen(str);
|
||||
buf_len = str_len + 1;
|
||||
|
||||
pkt_filterp = (struct brcmf_pkt_filter_le *) (buf + str_len + 1);
|
||||
pkt_filter = (struct brcmf_pkt_filter_le *)buf;
|
||||
|
||||
/* Parse packet filter id. */
|
||||
pkt_filter.id = 0;
|
||||
if (!kstrtoul(argv[i], 0, &res))
|
||||
pkt_filter.id = cpu_to_le32((u32)res);
|
||||
|
||||
if (NULL == argv[++i]) {
|
||||
brcmf_dbg(ERROR, "Polarity not provided\n");
|
||||
goto fail;
|
||||
}
|
||||
pkt_filter->id = 0;
|
||||
if (!kstrtoul(argv[0], 0, &res))
|
||||
pkt_filter->id = cpu_to_le32((u32)res);
|
||||
|
||||
/* Parse filter polarity. */
|
||||
pkt_filter.negate_match = 0;
|
||||
if (!kstrtoul(argv[i], 0, &res))
|
||||
pkt_filter.negate_match = cpu_to_le32((u32)res);
|
||||
|
||||
if (NULL == argv[++i]) {
|
||||
brcmf_dbg(ERROR, "Filter type not provided\n");
|
||||
goto fail;
|
||||
}
|
||||
pkt_filter->negate_match = 0;
|
||||
if (!kstrtoul(argv[1], 0, &res))
|
||||
pkt_filter->negate_match = cpu_to_le32((u32)res);
|
||||
|
||||
/* Parse filter type. */
|
||||
pkt_filter.type = 0;
|
||||
if (!kstrtoul(argv[i], 0, &res))
|
||||
pkt_filter.type = cpu_to_le32((u32)res);
|
||||
|
||||
if (NULL == argv[++i]) {
|
||||
brcmf_dbg(ERROR, "Offset not provided\n");
|
||||
goto fail;
|
||||
}
|
||||
pkt_filter->type = 0;
|
||||
if (!kstrtoul(argv[2], 0, &res))
|
||||
pkt_filter->type = cpu_to_le32((u32)res);
|
||||
|
||||
/* Parse pattern filter offset. */
|
||||
pkt_filter.u.pattern.offset = 0;
|
||||
if (!kstrtoul(argv[i], 0, &res))
|
||||
pkt_filter.u.pattern.offset = cpu_to_le32((u32)res);
|
||||
|
||||
if (NULL == argv[++i]) {
|
||||
brcmf_dbg(ERROR, "Bitmask not provided\n");
|
||||
goto fail;
|
||||
}
|
||||
pkt_filter->u.pattern.offset = 0;
|
||||
if (!kstrtoul(argv[3], 0, &res))
|
||||
pkt_filter->u.pattern.offset = cpu_to_le32((u32)res);
|
||||
|
||||
/* Parse pattern filter mask. */
|
||||
mask_size =
|
||||
brcmf_c_pattern_atoh
|
||||
(argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern);
|
||||
|
||||
if (NULL == argv[++i]) {
|
||||
brcmf_dbg(ERROR, "Pattern not provided\n");
|
||||
goto fail;
|
||||
}
|
||||
mask_size = brcmf_c_pattern_atoh(argv[4],
|
||||
(char *)pkt_filter->u.pattern.mask_and_pattern);
|
||||
|
||||
/* Parse pattern filter pattern. */
|
||||
pattern_size =
|
||||
brcmf_c_pattern_atoh(argv[i],
|
||||
(char *)&pkt_filterp->u.pattern.
|
||||
mask_and_pattern[mask_size]);
|
||||
pattern_size = brcmf_c_pattern_atoh(argv[5],
|
||||
(char *)&pkt_filter->u.pattern.mask_and_pattern[mask_size]);
|
||||
|
||||
if (mask_size != pattern_size) {
|
||||
brcmf_dbg(ERROR, "Mask and pattern not the same size\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pkt_filter.u.pattern.size_bytes = cpu_to_le32(mask_size);
|
||||
buf_len += BRCMF_PKT_FILTER_FIXED_LEN;
|
||||
buf_len += (BRCMF_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size);
|
||||
pkt_filter->u.pattern.size_bytes = cpu_to_le32(mask_size);
|
||||
buf_len = sizeof(*pkt_filter);
|
||||
buf_len -= sizeof(pkt_filter->u.pattern.mask_and_pattern);
|
||||
buf_len += mask_size + pattern_size;
|
||||
|
||||
/* Keep-alive attributes are set in local
|
||||
* variable (keep_alive_pkt), and
|
||||
** then memcpy'ed into buffer (keep_alive_pktp) since there is no
|
||||
** guarantee that the buffer is properly aligned.
|
||||
*/
|
||||
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);
|
||||
err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_add", pkt_filter,
|
||||
buf_len);
|
||||
if (err)
|
||||
brcmf_dbg(ERROR, "Set pkt_filter_add error (%d)\n", err);
|
||||
|
||||
fail:
|
||||
kfree(arg_org);
|
||||
|
@ -809,130 +701,125 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg)
|
|||
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];
|
||||
int retcode;
|
||||
__le32 arp_mode_le;
|
||||
|
||||
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;
|
||||
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
|
||||
u8 buf[BRCMF_DCMD_SMLEN];
|
||||
char *ptr;
|
||||
s32 err;
|
||||
struct brcmf_bus_dcmd *cmdlst;
|
||||
struct list_head *cur, *q;
|
||||
|
||||
mutex_lock(&drvr->proto_block);
|
||||
|
||||
/* Set Country code */
|
||||
if (drvr->country_code[0] != 0) {
|
||||
if (brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_COUNTRY,
|
||||
drvr->country_code,
|
||||
sizeof(drvr->country_code)) < 0)
|
||||
brcmf_dbg(ERROR, "country code setting failed\n");
|
||||
/* retreive mac address */
|
||||
err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
|
||||
sizeof(ifp->mac_addr));
|
||||
if (err < 0) {
|
||||
brcmf_dbg(ERROR, "Retreiving cur_etheraddr failed, %d\n",
|
||||
err);
|
||||
goto done;
|
||||
}
|
||||
memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
|
||||
|
||||
/* query for 'ver' to get version info from firmware */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
ptr = buf;
|
||||
brcmf_c_mkiovar("ver", NULL, 0, buf, sizeof(buf));
|
||||
brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, buf, sizeof(buf));
|
||||
strcpy(buf, "ver");
|
||||
err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
|
||||
if (err < 0) {
|
||||
brcmf_dbg(ERROR, "Retreiving version information failed, %d\n",
|
||||
err);
|
||||
goto done;
|
||||
}
|
||||
ptr = (char *)buf;
|
||||
strsep(&ptr, "\n");
|
||||
/* Print fw version info */
|
||||
brcmf_dbg(ERROR, "Firmware version = %s\n", buf);
|
||||
|
||||
/* Setup timeout if Beacons are lost and roam is off to report
|
||||
link down */
|
||||
brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout_le, 4, iovbuf,
|
||||
sizeof(iovbuf));
|
||||
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
|
||||
sizeof(iovbuf));
|
||||
|
||||
/* Enable/Disable build-in roaming to allowed ext supplicant to take
|
||||
of romaing */
|
||||
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);
|
||||
/*
|
||||
* Setup timeout if Beacons are lost and roam is off to report
|
||||
* link down
|
||||
*/
|
||||
err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout",
|
||||
BRCMF_DEFAULT_BCN_TIMEOUT);
|
||||
if (err) {
|
||||
brcmf_dbg(ERROR, "bcn_timeout error (%d)\n", err);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
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);
|
||||
if (cmdlst->name && cmdlst->param && cmdlst->param_len) {
|
||||
brcmf_c_mkiovar(cmdlst->name, cmdlst->param,
|
||||
cmdlst->param_len, iovbuf,
|
||||
sizeof(iovbuf));
|
||||
brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
|
||||
iovbuf, sizeof(iovbuf));
|
||||
brcmf_fil_iovar_data_set(ifp, cmdlst->name,
|
||||
cmdlst->param,
|
||||
cmdlst->param_len);
|
||||
}
|
||||
list_del(cur);
|
||||
kfree(cmdlst);
|
||||
}
|
||||
|
||||
mutex_unlock(&drvr->proto_block);
|
||||
|
||||
return 0;
|
||||
done:
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -16,8 +16,10 @@
|
|||
#include <linux/debugfs.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <linux/if.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/ieee80211.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
|
||||
#include <defs.h>
|
||||
#include <brcmu_wifi.h>
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#define BRCMF_EVENT_VAL 0x0800
|
||||
#define BRCMF_BTA_VAL 0x1000
|
||||
#define BRCMF_ISCAN_VAL 0x2000
|
||||
#define BRCMF_FIL_VAL 0x4000
|
||||
|
||||
#if defined(DEBUG)
|
||||
|
||||
|
@ -56,6 +57,7 @@ do { \
|
|||
#define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL)
|
||||
#define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_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) */
|
||||
|
||||
|
@ -67,6 +69,7 @@ do { \
|
|||
#define BRCMF_BYTES_ON() 0
|
||||
#define BRCMF_GLOM_ON() 0
|
||||
#define BRCMF_EVENT_ON() 0
|
||||
#define BRCMF_FIL_ON() 0
|
||||
|
||||
#endif /* defined(DEBUG) */
|
||||
|
||||
|
|
|
@ -52,16 +52,6 @@ MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards");
|
|||
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 */
|
||||
int brcmf_msg_level = BRCMF_ERROR_VAL;
|
||||
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");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* finally, report dongle driver type */
|
||||
else if (drvr->iswl)
|
||||
sprintf(info.driver, "wl");
|
||||
else
|
||||
sprintf(info.driver, "xx");
|
||||
sprintf(info.driver, "wl");
|
||||
|
||||
sprintf(info.version, "%lu", drvr->drv_version);
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
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
|
||||
};
|
||||
|
||||
static int brcmf_net_attach(struct brcmf_if *ifp)
|
||||
int brcmf_net_attach(struct brcmf_if *ifp)
|
||||
{
|
||||
struct brcmf_pub *drvr = ifp->drvr;
|
||||
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);
|
||||
|
||||
/* 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) {
|
||||
brcmf_dbg(ERROR, "couldn't register the net device\n");
|
||||
goto fail;
|
||||
|
@ -905,11 +824,12 @@ static int brcmf_net_attach(struct brcmf_if *ifp)
|
|||
|
||||
fail:
|
||||
ndev->netdev_ops = NULL;
|
||||
free_netdev(ndev);
|
||||
return -EBADE;
|
||||
}
|
||||
|
||||
int
|
||||
brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr)
|
||||
struct brcmf_if *brcmf_add_if(struct device *dev, int ifidx, s32 bssidx,
|
||||
char *name, u8 *mac_addr)
|
||||
{
|
||||
struct brcmf_if *ifp;
|
||||
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);
|
||||
if (!ndev) {
|
||||
brcmf_dbg(ERROR, "OOM - alloc_netdev\n");
|
||||
return -ENOMEM;
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
ifp = netdev_priv(ndev);
|
||||
|
@ -944,20 +864,14 @@ brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr)
|
|||
ifp->drvr = drvr;
|
||||
drvr->iflist[ifidx] = ifp;
|
||||
ifp->idx = ifidx;
|
||||
ifp->bssidx = bssidx;
|
||||
if (mac_addr != NULL)
|
||||
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",
|
||||
current->pid, ifp->ndev->name);
|
||||
|
||||
return 0;
|
||||
return ifp;
|
||||
}
|
||||
|
||||
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 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_pub *drvr = bus_if->drvr;
|
||||
struct brcmf_if *ifp;
|
||||
|
||||
brcmf_dbg(TRACE, "\n");
|
||||
|
||||
|
@ -1050,49 +963,30 @@ int brcmf_bus_start(struct device *dev)
|
|||
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 */
|
||||
ret = brcmf_add_if(dev, 0, "wlan%d", drvr->mac);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
ifp = brcmf_add_if(dev, 0, 0, "wlan%d", NULL);
|
||||
if (IS_ERR(ifp))
|
||||
return PTR_ERR(ifp);
|
||||
|
||||
/* signal bus ready */
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1163,42 +1057,6 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev)
|
|||
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)
|
||||
{
|
||||
brcmf_debugfs_init();
|
||||
|
|
|
@ -27,11 +27,6 @@ extern int brcmf_proto_attach(struct brcmf_pub *drvr);
|
|||
/* Unlink, frees allocated protocol memory (including brcmf_proto) */
|
||||
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. */
|
||||
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,
|
||||
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,
|
||||
uint cmd, void *buf, uint len);
|
||||
|
|
|
@ -614,6 +614,12 @@ static const uint max_roundup = 512;
|
|||
|
||||
#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)
|
||||
{
|
||||
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,
|
||||
struct brcmf_sdio_read *rd)
|
||||
struct brcmf_sdio_read *rd,
|
||||
enum brcmf_sdio_frmtype type)
|
||||
{
|
||||
u16 len, checksum;
|
||||
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");
|
||||
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;
|
||||
|
||||
/*
|
||||
|
@ -1071,9 +1087,16 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
|||
* Byte 5: Maximum Sequence number allow for Tx
|
||||
* 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]);
|
||||
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");
|
||||
bus->sdiodev->bus_if->dstats.rx_errors++;
|
||||
bus->sdcnt.rx_toolong++;
|
||||
|
@ -1081,6 +1104,17 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header,
|
|||
rd->len = 0;
|
||||
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]);
|
||||
if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) {
|
||||
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++;
|
||||
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];
|
||||
if (rd->len_nxtfrm << 4 > MAX_RX_DATASZ) {
|
||||
/* only warm for NON glom packet */
|
||||
|
@ -1126,16 +1163,16 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
|||
u16 dlen, totlen;
|
||||
u8 *dptr, num = 0;
|
||||
|
||||
u16 sublen, check;
|
||||
u16 sublen;
|
||||
struct sk_buff *pfirst, *pnext;
|
||||
|
||||
int errcode;
|
||||
u8 chan, seq, doff, sfdoff;
|
||||
u8 txmax;
|
||||
u8 doff, sfdoff;
|
||||
|
||||
int ifidx = 0;
|
||||
bool usechain = bus->use_rxchain;
|
||||
u16 next_len;
|
||||
|
||||
struct brcmf_sdio_read rd_new;
|
||||
|
||||
/* If packets, issue read(s) and send up packet chain */
|
||||
/* 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),
|
||||
"SUPERFRAME:\n");
|
||||
|
||||
/* Validate the superframe header */
|
||||
dptr = (u8 *) (pfirst->data);
|
||||
sublen = get_unaligned_le16(dptr);
|
||||
check = get_unaligned_le16(dptr + sizeof(u16));
|
||||
|
||||
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;
|
||||
rd_new.seq_num = rxseq;
|
||||
rd_new.len = dlen;
|
||||
errcode = -!brcmf_sdio_hdparser(bus, pfirst->data, &rd_new,
|
||||
BRCMF_SDIO_FT_SUPER);
|
||||
bus->cur_read.len = rd_new.len_nxtfrm << 4;
|
||||
|
||||
/* Remove superframe header, remember offset */
|
||||
skb_pull(pfirst, doff);
|
||||
sfdoff = doff;
|
||||
skb_pull(pfirst, rd_new.dat_offset);
|
||||
sfdoff = rd_new.dat_offset;
|
||||
num = 0;
|
||||
|
||||
/* Validate all the subframe headers */
|
||||
|
@ -1349,34 +1333,14 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
|||
if (errcode)
|
||||
break;
|
||||
|
||||
dptr = (u8 *) (pnext->data);
|
||||
dlen = (u16) (pnext->len);
|
||||
sublen = get_unaligned_le16(dptr);
|
||||
check = get_unaligned_le16(dptr + sizeof(u16));
|
||||
chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
|
||||
doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
|
||||
rd_new.len = pnext->len;
|
||||
rd_new.seq_num = rxseq++;
|
||||
errcode = -!brcmf_sdio_hdparser(bus, pnext->data,
|
||||
&rd_new,
|
||||
BRCMF_SDIO_FT_SUB);
|
||||
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++;
|
||||
}
|
||||
|
||||
|
@ -1402,27 +1366,11 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq)
|
|||
skb_queue_walk_safe(&bus->glom, pfirst, pnext) {
|
||||
dptr = (u8 *) (pfirst->data);
|
||||
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]);
|
||||
|
||||
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(),
|
||||
dptr, dlen, "Rx Subframe Data:\n");
|
||||
dptr, pfirst->len,
|
||||
"Rx Subframe Data:\n");
|
||||
|
||||
__skb_trim(pfirst, sublen);
|
||||
skb_pull(pfirst, doff);
|
||||
|
@ -1642,7 +1590,8 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
|||
bus->rxhdr, SDPCM_HDRLEN,
|
||||
"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)
|
||||
break;
|
||||
else
|
||||
|
@ -1701,7 +1650,8 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)
|
|||
} else {
|
||||
memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN);
|
||||
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;
|
||||
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 BRCMF_USB_SYNC_TIMEOUT 300 /* ms */
|
||||
#define BRCMF_USB_DLIMAGE_SPINWAIT 100 /* in unit of 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 */
|
||||
int image_len;
|
||||
|
||||
wait_queue_head_t wait;
|
||||
bool waitdone;
|
||||
int sync_urb_status;
|
||||
|
||||
struct usb_device *usbdev;
|
||||
struct device *dev;
|
||||
|
||||
|
@ -131,7 +126,6 @@ struct brcmf_usbdev_info {
|
|||
int ctl_urb_status;
|
||||
int ctl_completed;
|
||||
wait_queue_head_t ioctl_resp_wait;
|
||||
wait_queue_head_t ctrl_wait;
|
||||
ulong ctl_op;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
brcmf_usb_sync_complete(struct urb *urb)
|
||||
{
|
||||
struct brcmf_usbdev_info *devinfo =
|
||||
(struct brcmf_usbdev_info *)urb->context;
|
||||
|
||||
devinfo->waitdone = true;
|
||||
wake_up_interruptible(&devinfo->wait);
|
||||
devinfo->sync_urb_status = urb->status;
|
||||
devinfo->ctl_completed = true;
|
||||
brcmf_usb_ioctl_resp_wake(devinfo);
|
||||
}
|
||||
|
||||
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,
|
||||
(usb_complete_t)brcmf_usb_sync_complete, devinfo);
|
||||
|
||||
devinfo->ctl_completed = false;
|
||||
ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC);
|
||||
if (ret < 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT);
|
||||
ret = brcmf_usb_ioctl_resp_wait(devinfo);
|
||||
memcpy(buffer, tmpbuf, buflen);
|
||||
kfree(tmpbuf);
|
||||
|
||||
return (ret == 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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->ctl_completed = false;
|
||||
ret = usb_submit_urb(devinfo->bulk_urb, GFP_ATOMIC);
|
||||
if (ret) {
|
||||
brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT);
|
||||
return ret;
|
||||
ret = brcmf_usb_ioctl_resp_wait(devinfo);
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1284,7 +1260,6 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
|
|||
goto error;
|
||||
}
|
||||
|
||||
init_waitqueue_head(&devinfo->wait);
|
||||
if (!brcmf_usb_dlneeded(devinfo))
|
||||
return &devinfo->bus_pub;
|
||||
|
||||
|
@ -1339,7 +1314,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,
|
|||
}
|
||||
|
||||
ret = brcmf_bus_start(dev);
|
||||
if (ret == -ENOLINK) {
|
||||
if (ret) {
|
||||
brcmf_dbg(ERROR, "dongle is not responding\n");
|
||||
brcmf_detach(dev);
|
||||
goto fail;
|
||||
|
|
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 IE_MAX_LEN 512
|
||||
|
||||
/* dongle status */
|
||||
enum wl_status {
|
||||
WL_STATUS_READY,
|
||||
WL_STATUS_SCANNING,
|
||||
WL_STATUS_SCAN_ABORTING,
|
||||
WL_STATUS_CONNECTING,
|
||||
WL_STATUS_CONNECTED,
|
||||
WL_STATUS_AP_CREATING,
|
||||
WL_STATUS_AP_CREATED
|
||||
/**
|
||||
* enum brcmf_scan_status - dongle scan status
|
||||
*
|
||||
* @BRCMF_SCAN_STATUS_BUSY: scanning in progress on dongle.
|
||||
* @BRCMF_SCAN_STATUS_ABORT: scan being aborted on dongle.
|
||||
*/
|
||||
enum brcmf_scan_status {
|
||||
BRCMF_SCAN_STATUS_BUSY,
|
||||
BRCMF_SCAN_STATUS_ABORT,
|
||||
};
|
||||
|
||||
/* wi-fi mode */
|
||||
|
@ -145,19 +145,6 @@ enum wl_mode {
|
|||
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 */
|
||||
enum wl_iscan_state {
|
||||
WL_ISCAN_STATE_IDLE,
|
||||
|
@ -214,25 +201,73 @@ struct brcmf_cfg80211_security {
|
|||
u32 wpa_auth;
|
||||
};
|
||||
|
||||
/* ibss information for currently joined ibss network */
|
||||
struct brcmf_cfg80211_ibss {
|
||||
u8 beacon_interval; /* in millisecond */
|
||||
u8 atim; /* in millisecond */
|
||||
s8 join_only;
|
||||
u8 band;
|
||||
u8 channel;
|
||||
};
|
||||
|
||||
/* dongle profile */
|
||||
/**
|
||||
* struct brcmf_cfg80211_profile - profile information.
|
||||
*
|
||||
* @ssid: ssid of associated/associating ap.
|
||||
* @bssid: bssid of joined/joining ibss.
|
||||
* @sec: security information.
|
||||
*/
|
||||
struct brcmf_cfg80211_profile {
|
||||
u32 mode;
|
||||
struct brcmf_ssid ssid;
|
||||
u8 bssid[ETH_ALEN];
|
||||
u16 beacon_interval;
|
||||
u8 dtim_period;
|
||||
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 */
|
||||
|
@ -383,7 +418,7 @@ struct brcmf_pno_scanresults_le {
|
|||
/**
|
||||
* struct brcmf_cfg80211_info - dongle private data of cfg80211 interface
|
||||
*
|
||||
* @wdev: representing wl cfg80211 device.
|
||||
* @wiphy: wiphy object for cfg80211 interface.
|
||||
* @conf: dongle configuration.
|
||||
* @scan_request: cfg80211 scan request object.
|
||||
* @el: main event loop.
|
||||
|
@ -395,12 +430,11 @@ struct brcmf_pno_scanresults_le {
|
|||
* @scan_req_int: internal scan request object.
|
||||
* @bss_info: bss information for cfg80211 layer.
|
||||
* @ie: information element object for internal purpose.
|
||||
* @profile: holding dongle profile.
|
||||
* @iscan: iscan controller information.
|
||||
* @conn_info: association info.
|
||||
* @pmk_list: wpa2 pmk list.
|
||||
* @event_work: event handler work struct.
|
||||
* @status: current dongle status.
|
||||
* @scan_status: scan activity on the dongle.
|
||||
* @pub: common driver information.
|
||||
* @channel: current channel.
|
||||
* @iscan_on: iscan on/off switch.
|
||||
|
@ -422,10 +456,11 @@ struct brcmf_pno_scanresults_le {
|
|||
* @escan_timeout_work: scan timeout worker.
|
||||
* @escan_ioctl_buf: dongle command buffer for escan commands.
|
||||
* @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 wireless_dev *wdev;
|
||||
struct wiphy *wiphy;
|
||||
struct brcmf_cfg80211_conf *conf;
|
||||
struct cfg80211_scan_request *scan_request;
|
||||
struct brcmf_cfg80211_event_loop el;
|
||||
|
@ -437,12 +472,11 @@ struct brcmf_cfg80211_info {
|
|||
struct brcmf_cfg80211_scan_req *scan_req_int;
|
||||
struct wl_cfg80211_bss_info *bss_info;
|
||||
struct brcmf_cfg80211_ie ie;
|
||||
struct brcmf_cfg80211_profile *profile;
|
||||
struct brcmf_cfg80211_iscan_ctrl *iscan;
|
||||
struct brcmf_cfg80211_connect_info conn_info;
|
||||
struct brcmf_cfg80211_pmk_list *pmk_list;
|
||||
struct work_struct event_work;
|
||||
unsigned long status;
|
||||
unsigned long scan_status;
|
||||
struct brcmf_pub *pub;
|
||||
u32 channel;
|
||||
bool iscan_on;
|
||||
|
@ -464,11 +498,13 @@ struct brcmf_cfg80211_info {
|
|||
struct work_struct escan_timeout_work;
|
||||
u8 *escan_ioctl_buf;
|
||||
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)
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -491,6 +530,12 @@ static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev)
|
|||
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 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;
|
||||
}
|
||||
|
||||
struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct net_device *ndev,
|
||||
struct device *busdev,
|
||||
struct brcmf_pub *drvr);
|
||||
struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr);
|
||||
void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg);
|
||||
|
||||
/* event handler from dongle */
|
||||
|
|
|
@ -692,7 +692,7 @@ void ai_pci_up(struct si_pub *sih)
|
|||
sii = container_of(sih, struct si_info, pub);
|
||||
|
||||
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 */
|
||||
|
@ -703,7 +703,7 @@ void ai_pci_down(struct si_pub *sih)
|
|||
sii = container_of(sih, struct si_info, pub);
|
||||
|
||||
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 */
|
||||
|
|
|
@ -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()
|
||||
* 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);
|
||||
|
||||
/*
|
||||
|
|
|
@ -10472,7 +10472,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv,
|
|||
} else
|
||||
len = src->len;
|
||||
|
||||
dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC);
|
||||
dst = alloc_skb(len + sizeof(*rt_hdr) + sizeof(u16)*2, GFP_ATOMIC);
|
||||
if (!dst)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
|||
* See iwlagn_mac_channel_switch.
|
||||
*/
|
||||
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
|
||||
struct iwl6000_channel_switch_cmd cmd;
|
||||
struct iwl6000_channel_switch_cmd *cmd;
|
||||
u32 switch_time_in_usec, ucode_switch_time;
|
||||
u16 ch;
|
||||
u32 tsf_low;
|
||||
|
@ -527,18 +527,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
|||
struct ieee80211_vif *vif = ctx->vif;
|
||||
struct iwl_host_cmd hcmd = {
|
||||
.id = REPLY_CHANNEL_SWITCH,
|
||||
.len = { sizeof(cmd), },
|
||||
.len = { sizeof(*cmd), },
|
||||
.flags = CMD_SYNC,
|
||||
.data = { &cmd, },
|
||||
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
|
||||
};
|
||||
int err;
|
||||
|
||||
cmd.band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
hcmd.data[0] = cmd;
|
||||
|
||||
cmd->band = priv->band == IEEE80211_BAND_2GHZ;
|
||||
ch = ch_switch->channel->hw_value;
|
||||
IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
|
||||
ctx->active.channel, ch);
|
||||
cmd.channel = cpu_to_le16(ch);
|
||||
cmd.rxon_flags = ctx->staging.flags;
|
||||
cmd.rxon_filter_flags = ctx->staging.filter_flags;
|
||||
cmd->channel = cpu_to_le16(ch);
|
||||
cmd->rxon_flags = ctx->staging.flags;
|
||||
cmd->rxon_filter_flags = ctx->staging.filter_flags;
|
||||
switch_count = ch_switch->count;
|
||||
tsf_low = ch_switch->timestamp & 0x0ffffffff;
|
||||
/*
|
||||
|
@ -554,23 +561,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
|
|||
switch_count = 0;
|
||||
}
|
||||
if (switch_count <= 1)
|
||||
cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||
cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time);
|
||||
else {
|
||||
switch_time_in_usec =
|
||||
vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
|
||||
ucode_switch_time = iwl_usecs_to_beacons(priv,
|
||||
switch_time_in_usec,
|
||||
beacon_interval);
|
||||
cmd.switch_time = iwl_add_beacon_time(priv,
|
||||
priv->ucode_beacon_time,
|
||||
ucode_switch_time,
|
||||
beacon_interval);
|
||||
cmd->switch_time = iwl_add_beacon_time(priv,
|
||||
priv->ucode_beacon_time,
|
||||
ucode_switch_time,
|
||||
beacon_interval);
|
||||
}
|
||||
IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
|
||||
cmd.switch_time);
|
||||
cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
|
||||
cmd->switch_time);
|
||||
cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR;
|
||||
|
||||
return iwl_dvm_send_cmd(priv, &hcmd);
|
||||
err = iwl_dvm_send_cmd(priv, &hcmd);
|
||||
kfree(cmd);
|
||||
return err;
|
||||
}
|
||||
|
||||
struct iwl_lib_ops iwl6000_lib = {
|
||||
|
|
|
@ -1191,8 +1191,6 @@ static void iwl_option_config(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;
|
||||
|
||||
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);
|
||||
|
||||
radio_cfg = priv->eeprom_data->radio_cfg;
|
||||
|
||||
priv->hw_params.tx_chains_num =
|
||||
num_of_ant(priv->eeprom_data->valid_tx_ant);
|
||||
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 */
|
||||
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. */
|
||||
|
||||
SET_IEEE80211_DEV(priv->hw, priv->trans->dev);
|
||||
|
@ -2152,8 +2151,6 @@ static int __init iwl_init(void)
|
|||
{
|
||||
|
||||
int ret;
|
||||
pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
|
||||
pr_info(DRV_COPYRIGHT "\n");
|
||||
|
||||
ret = iwlagn_rate_control_register();
|
||||
if (ret) {
|
||||
|
|
|
@ -25,6 +25,39 @@
|
|||
*****************************************************************************/
|
||||
|
||||
#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
|
||||
|
||||
#include <linux/tracepoint.h>
|
||||
|
@ -234,6 +267,48 @@ TRACE_EVENT(iwlwifi_dbg,
|
|||
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
|
||||
#define TRACE_SYSTEM iwlwifi
|
||||
|
||||
|
@ -270,25 +345,28 @@ TRACE_EVENT(iwlwifi_dev_hcmd,
|
|||
);
|
||||
|
||||
TRACE_EVENT(iwlwifi_dev_rx,
|
||||
TP_PROTO(const struct device *dev, void *rxbuf, size_t len),
|
||||
TP_ARGS(dev, rxbuf, len),
|
||||
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, rxbuf, len)
|
||||
__dynamic_array(u8, rxbuf, iwl_rx_trace_len(trans, rxbuf, len))
|
||||
),
|
||||
TP_fast_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",
|
||||
__get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4])
|
||||
);
|
||||
|
||||
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 *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(
|
||||
DEV_ENTRY
|
||||
|
||||
|
@ -301,14 +379,15 @@ TRACE_EVENT(iwlwifi_dev_tx,
|
|||
* for the possible padding).
|
||||
*/
|
||||
__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(
|
||||
DEV_ASSIGN;
|
||||
__entry->framelen = buf0_len + buf1_len;
|
||||
memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
|
||||
memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
|
||||
memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
|
||||
if (!iwl_trace_data(skb))
|
||||
memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
|
||||
),
|
||||
TP_printk("[%s] TX %.2x (%zu bytes)",
|
||||
__get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0],
|
||||
|
|
|
@ -327,11 +327,11 @@ u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr)
|
|||
EXPORT_SYMBOL_GPL(iwl_read_targ_mem);
|
||||
|
||||
int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr,
|
||||
void *buf, int dwords)
|
||||
const void *buf, int dwords)
|
||||
{
|
||||
unsigned long flags;
|
||||
int offs, result = 0;
|
||||
u32 *vals = buf;
|
||||
const u32 *vals = buf;
|
||||
|
||||
spin_lock_irqsave(&trans->reg_lock, flags);
|
||||
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)
|
||||
|
||||
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);
|
||||
int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val);
|
||||
|
|
|
@ -213,6 +213,9 @@
|
|||
#define SCD_CONTEXT_QUEUE_OFFSET(x)\
|
||||
(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) \
|
||||
((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
|
||||
* device_cmd for Tx - for internal use only
|
||||
* 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 {
|
||||
const struct iwl_trans_ops *ops;
|
||||
|
@ -457,6 +461,8 @@ struct iwl_trans {
|
|||
u32 hw_id;
|
||||
char hw_id_str[52];
|
||||
|
||||
u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size;
|
||||
|
||||
bool pm_support;
|
||||
|
||||
wait_queue_head_t wait_command_queue;
|
||||
|
@ -516,6 +522,8 @@ static inline int iwl_trans_start_fw(struct iwl_trans *trans,
|
|||
{
|
||||
might_sleep();
|
||||
|
||||
WARN_ON_ONCE(!trans->rx_mpdu_cmd);
|
||||
|
||||
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 += 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
|
||||
* 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 *trans = iwl_trans_pcie_get_trans(trans_pcie);
|
||||
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];
|
||||
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_BIDIRECTIONAL);
|
||||
|
||||
trace_iwlwifi_dev_tx(trans->dev,
|
||||
trace_iwlwifi_dev_tx(trans->dev, skb,
|
||||
&txq->tfds[txq->q.write_ptr],
|
||||
sizeof(struct iwl_tfd),
|
||||
&dev_cmd->hdr, firstlen,
|
||||
skb->data + hdr_len, secondlen);
|
||||
trace_iwlwifi_dev_tx_data(trans->dev, skb,
|
||||
skb->data + hdr_len, secondlen);
|
||||
|
||||
/* start timer if queue currently empty */
|
||||
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];
|
||||
/* n_bd is usually 256 => n_bd - 1 = 0xff */
|
||||
int tfd_num = ssn & (txq->q.n_bd - 1);
|
||||
int freed = 0;
|
||||
|
||||
spin_lock(&txq->lock);
|
||||
|
||||
if (txq->q.read_ptr != tfd_num) {
|
||||
IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n",
|
||||
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)
|
||||
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)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
u16 rd_ptr, wr_ptr;
|
||||
int n_bd = trans_pcie->txq[txq_id].q.n_bd;
|
||||
u32 stts_addr = trans_pcie->scd_base_addr +
|
||||
SCD_TX_STTS_QUEUE_OFFSET(txq_id);
|
||||
static const u32 zero_val[4] = {};
|
||||
|
||||
if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) {
|
||||
WARN_ONCE(1, "queue %d not used", txq_id);
|
||||
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_write_targ_mem_dwords(trans, stts_addr,
|
||||
zero_val, ARRAY_SIZE(zero_val));
|
||||
|
||||
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
|
||||
* 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;
|
||||
|
||||
spin_lock_bh(&txq->lock);
|
||||
|
|
|
@ -58,8 +58,7 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv,
|
|||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||
mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
|
||||
else
|
||||
mwifiex_process_rx_packet(priv->adapter,
|
||||
rx_tmp_ptr);
|
||||
mwifiex_process_rx_packet(priv, rx_tmp_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,7 +105,7 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
|
|||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||
mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
|
||||
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);
|
||||
|
@ -442,8 +441,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
|
|||
if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
|
||||
mwifiex_handle_uap_rx_forward(priv, payload);
|
||||
else
|
||||
mwifiex_process_rx_packet(priv->adapter,
|
||||
payload);
|
||||
mwifiex_process_rx_packet(priv, payload);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -471,13 +471,13 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
|
|||
flag = 1;
|
||||
first_chan = (u32) ch->hw_value;
|
||||
next_chan = first_chan;
|
||||
max_pwr = ch->max_reg_power;
|
||||
max_pwr = ch->max_power;
|
||||
no_of_parsed_chan = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ch->hw_value == next_chan + 1 &&
|
||||
ch->max_reg_power == max_pwr) {
|
||||
ch->max_power == max_pwr) {
|
||||
next_chan++;
|
||||
no_of_parsed_chan++;
|
||||
} else {
|
||||
|
@ -488,7 +488,7 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy)
|
|||
no_of_triplet++;
|
||||
first_chan = (u32) ch->hw_value;
|
||||
next_chan = first_chan;
|
||||
max_pwr = ch->max_reg_power;
|
||||
max_pwr = ch->max_power;
|
||||
no_of_parsed_chan = 1;
|
||||
}
|
||||
}
|
||||
|
@ -1819,13 +1819,17 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
|
|||
|
||||
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) {
|
||||
dev_dbg(priv->adapter->dev, "scan rejected due to traffic\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
priv->scan_request = request;
|
||||
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),
|
||||
GFP_KERNEL);
|
||||
|
@ -1834,6 +1838,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
priv->scan_request = request;
|
||||
|
||||
priv->user_scan_cfg->num_ssids = request->n_ssids;
|
||||
priv->user_scan_cfg->ssid_list = request->ssids;
|
||||
|
||||
|
@ -1870,6 +1876,9 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
|
|||
ret = mwifiex_scan_networks(priv, priv->user_scan_cfg);
|
||||
if (ret) {
|
||||
dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
|
||||
priv->scan_request = NULL;
|
||||
kfree(priv->user_scan_cfg);
|
||||
priv->user_scan_cfg = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -2113,7 +2122,6 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy,
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
|
@ -2251,7 +2259,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter)
|
|||
wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1;
|
||||
|
||||
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 */
|
||||
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",
|
||||
adapter->dbg.last_cmd_index);
|
||||
print_hex_dump_bytes("last_cmd_id: ", DUMP_PREFIX_OFFSET,
|
||||
adapter->dbg.last_cmd_id, DBG_CMD_NUM);
|
||||
print_hex_dump_bytes("last_cmd_act: ", DUMP_PREFIX_OFFSET,
|
||||
adapter->dbg.last_cmd_act, DBG_CMD_NUM);
|
||||
dev_err(adapter->dev, "last_cmd_id: %*ph\n",
|
||||
(int)sizeof(adapter->dbg.last_cmd_id),
|
||||
adapter->dbg.last_cmd_id);
|
||||
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",
|
||||
adapter->dbg.last_cmd_resp_index);
|
||||
print_hex_dump_bytes("last_cmd_resp_id: ", DUMP_PREFIX_OFFSET,
|
||||
adapter->dbg.last_cmd_resp_id,
|
||||
DBG_CMD_NUM);
|
||||
dev_err(adapter->dev, "last_cmd_resp_id: %*ph\n",
|
||||
(int)sizeof(adapter->dbg.last_cmd_resp_id),
|
||||
adapter->dbg.last_cmd_resp_id);
|
||||
|
||||
dev_err(adapter->dev, "last_event_index = %d\n",
|
||||
adapter->dbg.last_event_index);
|
||||
print_hex_dump_bytes("last_event: ", DUMP_PREFIX_OFFSET,
|
||||
adapter->dbg.last_event, DBG_CMD_NUM);
|
||||
dev_err(adapter->dev, "last_event: %*ph\n",
|
||||
(int)sizeof(adapter->dbg.last_event),
|
||||
adapter->dbg.last_event);
|
||||
|
||||
dev_err(adapter->dev, "data_sent=%d cmd_sent=%d\n",
|
||||
adapter->data_sent, adapter->cmd_sent);
|
||||
|
|
|
@ -84,18 +84,19 @@ static void scan_delay_timer_fn(unsigned long data)
|
|||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||
|
||||
if (priv->user_scan_cfg) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: %s: scan aborted\n", __func__);
|
||||
cfg80211_scan_done(priv->scan_request, 1);
|
||||
priv->scan_request = NULL;
|
||||
if (priv->scan_request) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: aborting scan\n");
|
||||
cfg80211_scan_done(priv->scan_request, 1);
|
||||
priv->scan_request = NULL;
|
||||
} else {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: scan already aborted\n");
|
||||
}
|
||||
|
||||
kfree(priv->user_scan_cfg);
|
||||
priv->user_scan_cfg = NULL;
|
||||
}
|
||||
|
||||
if (priv->scan_pending_on_block) {
|
||||
priv->scan_pending_on_block = false;
|
||||
up(&priv->async_sem);
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
|
|
@ -472,6 +472,14 @@ mwifiex_open(struct net_device *dev)
|
|||
static int
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -115,8 +115,6 @@ enum {
|
|||
#define MWIFIEX_TYPE_DATA 0
|
||||
#define MWIFIEX_TYPE_EVENT 3
|
||||
|
||||
#define DBG_CMD_NUM 5
|
||||
|
||||
#define MAX_BITMAP_RATES_SIZE 10
|
||||
|
||||
#define MAX_CHANNEL_BAND_BG 14
|
||||
|
@ -484,7 +482,6 @@ struct mwifiex_private {
|
|||
u8 nick_name[16];
|
||||
u16 current_key_index;
|
||||
struct semaphore async_sem;
|
||||
u8 scan_pending_on_block;
|
||||
u8 report_scan_result;
|
||||
struct cfg80211_scan_request *scan_request;
|
||||
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_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);
|
||||
|
||||
int mwifiex_process_event(struct mwifiex_adapter *adapter);
|
||||
|
@ -809,7 +806,7 @@ void mwifiex_hs_activated_event(struct mwifiex_private *priv,
|
|||
u8 activated);
|
||||
int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv,
|
||||
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);
|
||||
int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no,
|
||||
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);
|
||||
int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no,
|
||||
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);
|
||||
int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
|
||||
int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv,
|
||||
struct sk_buff *skb);
|
||||
int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
|
||||
struct sk_buff *skb);
|
||||
|
|
|
@ -941,6 +941,11 @@ mwifiex_config_scan(struct mwifiex_private *priv,
|
|||
chan_idx)->chan_scan_mode_bitmap
|
||||
&= ~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) {
|
||||
scan_dur = (u16) user_scan_in->
|
||||
chan_list[chan_idx].scan_time;
|
||||
|
@ -1762,26 +1767,39 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
|
|||
}
|
||||
if (priv->report_scan_result)
|
||||
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) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: %s: sending scan results\n", __func__);
|
||||
cfg80211_scan_done(priv->scan_request, 0);
|
||||
priv->scan_request = NULL;
|
||||
if (priv->scan_request) {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: notifying scan done\n");
|
||||
cfg80211_scan_done(priv->scan_request, 0);
|
||||
priv->scan_request = NULL;
|
||||
} else {
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: scan already aborted\n");
|
||||
}
|
||||
|
||||
kfree(priv->user_scan_cfg);
|
||||
priv->user_scan_cfg = NULL;
|
||||
}
|
||||
} 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,
|
||||
flags);
|
||||
adapter->scan_delay_cnt = 1;
|
||||
mod_timer(&priv->scan_delay_timer, jiffies +
|
||||
msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
|
||||
dev_dbg(priv->adapter->dev,
|
||||
"info: %s: deferring scan\n", __func__);
|
||||
} else {
|
||||
/* Get scan command from scan_pending_q and put to
|
||||
cmd_pending_q */
|
||||
|
@ -1846,21 +1864,18 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
|
|||
struct cfg80211_ssid *req_ssid)
|
||||
{
|
||||
struct mwifiex_adapter *adapter = priv->adapter;
|
||||
int ret = 0;
|
||||
int ret;
|
||||
struct mwifiex_user_scan_cfg *scan_cfg;
|
||||
|
||||
if (!req_ssid)
|
||||
return -1;
|
||||
|
||||
if (adapter->scan_processing) {
|
||||
dev_dbg(adapter->dev, "cmd: Scan already in process...\n");
|
||||
return ret;
|
||||
dev_err(adapter->dev, "cmd: Scan already in process...\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
if (priv->scan_block) {
|
||||
dev_dbg(adapter->dev,
|
||||
dev_err(adapter->dev,
|
||||
"cmd: Scan is blocked during association...\n");
|
||||
return ret;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
|
||||
|
@ -1897,7 +1912,6 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
|
|||
__func__);
|
||||
return -1;
|
||||
}
|
||||
priv->scan_pending_on_block = true;
|
||||
|
||||
priv->adapter->scan_wait_q_woken = false;
|
||||
|
||||
|
@ -1911,10 +1925,7 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
|
|||
if (!ret)
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -85,10 +85,6 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
|
|||
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
|
||||
if (priv->report_scan_result)
|
||||
priv->report_scan_result = false;
|
||||
if (priv->scan_pending_on_block) {
|
||||
priv->scan_pending_on_block = false;
|
||||
up(&priv->async_sem);
|
||||
}
|
||||
break;
|
||||
|
||||
case HostCmd_CMD_MAC_CONTROL:
|
||||
|
|
|
@ -38,14 +38,10 @@
|
|||
*
|
||||
* 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)
|
||||
{
|
||||
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 rxpd *local_rx_pd;
|
||||
int hdr_chop;
|
||||
|
@ -98,9 +94,9 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
|
|||
|
||||
priv->rxpd_htinfo = local_rx_pd->ht_info;
|
||||
|
||||
ret = mwifiex_recv_packet(adapter, skb);
|
||||
ret = mwifiex_recv_packet(priv, skb);
|
||||
if (ret == -1)
|
||||
dev_err(adapter->dev, "recv packet failed\n");
|
||||
dev_err(priv->adapter->dev, "recv packet failed\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -117,21 +113,15 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
|
|||
*
|
||||
* 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 mwifiex_adapter *adapter = priv->adapter;
|
||||
int ret = 0;
|
||||
struct rxpd *local_rx_pd;
|
||||
struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
|
||||
struct rx_packet_hdr *rx_pkt_hdr;
|
||||
u8 ta[ETH_ALEN];
|
||||
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);
|
||||
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)) {
|
||||
rx_skb = __skb_dequeue(&list);
|
||||
ret = mwifiex_recv_packet(adapter, rx_skb);
|
||||
ret = mwifiex_recv_packet(priv, rx_skb);
|
||||
if (ret == -1)
|
||||
dev_err(adapter->dev, "Rx of A-MSDU failed");
|
||||
}
|
||||
return 0;
|
||||
} else if (rx_pkt_type == PKT_TYPE_MGMT) {
|
||||
ret = mwifiex_process_mgmt_packet(adapter, skb);
|
||||
ret = mwifiex_process_mgmt_packet(priv, skb);
|
||||
if (ret)
|
||||
dev_err(adapter->dev, "Rx of mgmt packet failed");
|
||||
dev_kfree_skb_any(skb);
|
||||
|
@ -188,7 +178,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
|
|||
*/
|
||||
if (!IS_11N_ENABLED(priv) ||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,13 +48,19 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
|
|||
if (!priv)
|
||||
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_type = priv->bss_type;
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
const u8 *var_pos = params->beacon.head + 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);
|
||||
if (rate_ie)
|
||||
if (rate_ie) {
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
|
|||
}
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
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 mwifiex_adapter *adapter = priv->adapter;
|
||||
int ret;
|
||||
struct uap_rxpd *uap_rx_pd;
|
||||
struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
|
||||
struct rx_packet_hdr *rx_pkt_hdr;
|
||||
u16 rx_pkt_type;
|
||||
u8 ta[ETH_ALEN], pkt_type;
|
||||
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);
|
||||
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);
|
||||
|
@ -210,7 +203,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
|
|||
|
||||
while (!skb_queue_empty(&list)) {
|
||||
rx_skb = __skb_dequeue(&list);
|
||||
ret = mwifiex_recv_packet(adapter, rx_skb);
|
||||
ret = mwifiex_recv_packet(priv, rx_skb);
|
||||
if (ret)
|
||||
dev_err(adapter->dev,
|
||||
"AP:Rx A-MSDU failed");
|
||||
|
@ -218,7 +211,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
|
|||
|
||||
return 0;
|
||||
} else if (rx_pkt_type == PKT_TYPE_MGMT) {
|
||||
ret = mwifiex_process_mgmt_packet(adapter, skb);
|
||||
ret = mwifiex_process_mgmt_packet(priv, skb);
|
||||
if (ret)
|
||||
dev_err(adapter->dev, "Rx of mgmt packet failed");
|
||||
dev_kfree_skb_any(skb);
|
||||
|
|
|
@ -146,20 +146,16 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv,
|
|||
* to the kernel.
|
||||
*/
|
||||
int
|
||||
mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter,
|
||||
mwifiex_process_mgmt_packet(struct mwifiex_private *priv,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct rxpd *rx_pd;
|
||||
struct mwifiex_private *priv;
|
||||
u16 pkt_len;
|
||||
|
||||
if (!skb)
|
||||
return -1;
|
||||
|
||||
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, 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
|
||||
* 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)
|
||||
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->protocol = eth_type_trans(skb, priv->netdev);
|
||||
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
|
||||
* 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 += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE);
|
||||
|
||||
|
|
|
@ -865,7 +865,7 @@ static int ezusb_firmware_download(struct ezusb_priv *upriv,
|
|||
static int ezusb_access_ltv(struct ezusb_priv *upriv,
|
||||
struct request_context *ctx,
|
||||
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 retval = 0;
|
||||
|
@ -933,7 +933,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv,
|
|||
}
|
||||
if (ctx->in_rid) {
|
||||
struct ezusb_packet *ans = ctx->buf;
|
||||
int exp_len;
|
||||
unsigned exp_len;
|
||||
|
||||
if (ans->hermes_len != 0)
|
||||
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)
|
||||
memcpy(ans_buff, ans->data,
|
||||
min_t(int, exp_len, ans_size));
|
||||
memcpy(ans_buff, ans->data, min(exp_len, ans_size));
|
||||
if (ans_length)
|
||||
*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 request_context *ctx;
|
||||
|
||||
if ((bufsize < 0) || (bufsize % 2))
|
||||
if (bufsize % 2)
|
||||
return -EINVAL;
|
||||
|
||||
ctx = ezusb_alloc_ctx(upriv, rid, rid);
|
||||
|
|
|
@ -1988,6 +1988,7 @@ static struct usb_driver rt2500usb_driver = {
|
|||
.disconnect = rt2x00usb_disconnect,
|
||||
.suspend = rt2x00usb_suspend,
|
||||
.resume = rt2x00usb_resume,
|
||||
.reset_resume = rt2x00usb_resume,
|
||||
.disable_hub_initiated_lpm = 1,
|
||||
};
|
||||
|
||||
|
|
|
@ -2520,20 +2520,37 @@ static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev,
|
|||
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,
|
||||
enum ieee80211_band band, int power_level,
|
||||
u8 txpower, int delta)
|
||||
{
|
||||
u32 reg;
|
||||
u16 eeprom;
|
||||
u8 criterion;
|
||||
u8 eirp_txpower;
|
||||
u8 eirp_txpower_criterion;
|
||||
u8 reg_limit;
|
||||
|
||||
if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b))
|
||||
return txpower;
|
||||
|
||||
if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) {
|
||||
/*
|
||||
* 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
|
||||
* when calculating eirp txpower.
|
||||
*/
|
||||
rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, ®);
|
||||
criterion = rt2x00_get_field32(reg, TX_PWR_CFG_0_6MBS);
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + 1,
|
||||
&eeprom);
|
||||
criterion = rt2x00_get_field16(eeprom,
|
||||
EEPROM_TXPOWER_BYRATE_RATE0);
|
||||
|
||||
rt2x00_eeprom_read(rt2x00dev,
|
||||
EEPROM_EIRP_MAX_TX_POWER, &eeprom);
|
||||
rt2x00_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER,
|
||||
&eeprom);
|
||||
|
||||
if (band == IEEE80211_BAND_2GHZ)
|
||||
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
|
||||
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,
|
||||
enum ieee80211_band band,
|
||||
struct ieee80211_channel *chan,
|
||||
int power_level)
|
||||
{
|
||||
u8 txpower;
|
||||
u8 txpower, r1;
|
||||
u16 eeprom;
|
||||
int i, is_rate_b;
|
||||
u32 reg;
|
||||
u8 r1;
|
||||
u32 offset;
|
||||
int delta;
|
||||
u32 reg, offset;
|
||||
int i, is_rate_b, delta, power_ctrl;
|
||||
enum ieee80211_band band = chan->band;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
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);
|
||||
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)
|
||||
{
|
||||
rt2800_config_txpower(rt2x00dev, rt2x00dev->curr_band,
|
||||
rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.channel,
|
||||
rt2x00dev->tx_power);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rt2800_gain_calibration);
|
||||
|
@ -2845,11 +2899,11 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev,
|
|||
if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {
|
||||
rt2800_config_channel(rt2x00dev, libconf->conf,
|
||||
&libconf->rf, &libconf->channel);
|
||||
rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band,
|
||||
rt2800_config_txpower(rt2x00dev, libconf->conf->channel,
|
||||
libconf->conf->power_level);
|
||||
}
|
||||
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);
|
||||
if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
|
||||
rt2800_config_retry_limit(rt2x00dev, libconf);
|
||||
|
|
|
@ -1282,6 +1282,7 @@ static struct usb_driver rt2800usb_driver = {
|
|||
.disconnect = rt2x00usb_disconnect,
|
||||
.suspend = rt2x00usb_suspend,
|
||||
.resume = rt2x00usb_resume,
|
||||
.reset_resume = rt2x00usb_resume,
|
||||
.disable_hub_initiated_lpm = 1,
|
||||
};
|
||||
|
||||
|
|
|
@ -2535,6 +2535,7 @@ static struct usb_driver rt73usb_driver = {
|
|||
.disconnect = rt2x00usb_disconnect,
|
||||
.suspend = rt2x00usb_suspend,
|
||||
.resume = rt2x00usb_resume,
|
||||
.reset_resume = rt2x00usb_resume,
|
||||
.disable_hub_initiated_lpm = 1,
|
||||
};
|
||||
|
||||
|
|
|
@ -52,11 +52,8 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no,
|
|||
u32 target_content = 0;
|
||||
u8 entry_i;
|
||||
|
||||
RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
|
||||
"key_cont_128:\n %x:%x:%x:%x:%x:%x\n",
|
||||
key_cont_128[0], key_cont_128[1],
|
||||
key_cont_128[2], key_cont_128[3],
|
||||
key_cont_128[4], key_cont_128[5]);
|
||||
RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "key_cont_128: %6phC\n",
|
||||
key_cont_128);
|
||||
|
||||
for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) {
|
||||
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