Unified · Split
| @@ -7509,6 +7509,12 @@ S: Maintained · 7508 unmodified lines | ||
| 7509 | 7509 | F: Documentation/usb/acm.txt |
| 7510 | 7510 | F: drivers/usb/class/cdc-acm.* |
| 7511 | 7511 | |
| 7512 | +USB AR5523 WIRELESS DRIVER | |
| 7513 | +M: Pontus Fuchs <pontus.fuchs@gmail.com> | |
| 7514 | +L: linux-wireless@vger.kernel.org | |
| 7515 | +S: Maintained | |
| 7516 | +F: drivers/net/wireless/ath/ar5523/ | |
| 7517 | + | |
| 7512 | 7518 | USB ATTACHED SCSI |
| 7513 | 7519 | M: Matthew Wilcox <willy@linux.intel.com> |
| 7514 | 7520 | M: Sarah Sharp <sarah.a.sharp@linux.intel.com> |
| @@ -43,8 +43,8 @@ static void early_nvram_init(void) · 42 unmodified lines | ||
| 43 | 43 | #ifdef CONFIG_BCM47XX_SSB |
| 44 | 44 | case BCM47XX_BUS_TYPE_SSB: |
| 45 | 45 | mcore_ssb = &bcm47xx_bus.ssb.mipscore; |
| 46 | − base = mcore_ssb->flash_window; | |
| 47 | − lim = mcore_ssb->flash_window_size; | |
| 46 | + base = mcore_ssb->pflash.window; | |
| 47 | + lim = mcore_ssb->pflash.window_size; | |
| 48 | 48 | break; |
| 49 | 49 | #endif |
| 50 | 50 | #ifdef CONFIG_BCM47XX_BCMA |
| @@ -156,10 +156,10 @@ static int __init wgt634u_init(void) · 155 unmodified lines | ||
| 156 | 156 | SSB_CHIPCO_IRQ_GPIO); |
| 157 | 157 | } |
| 158 | 158 | |
| 159 | − wgt634u_flash_data.width = mcore->flash_buswidth; | |
| 160 | − wgt634u_flash_resource.start = mcore->flash_window; | |
| 161 | − wgt634u_flash_resource.end = mcore->flash_window | |
| 162 | − + mcore->flash_window_size | |
| 159 | + wgt634u_flash_data.width = mcore->pflash.buswidth; | |
| 160 | + wgt634u_flash_resource.start = mcore->pflash.window; | |
| 161 | + wgt634u_flash_resource.end = mcore->pflash.window | |
| 162 | + + mcore->pflash.window_size | |
| 163 | 163 | - 1; |
| 164 | 164 | return platform_add_devices(wgt634u_devices, |
| 165 | 165 | ARRAY_SIZE(wgt634u_devices)); |
| @@ -22,12 +22,9 @@ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, · 21 unmodified lines | ||
| 22 | 22 | return value; |
| 23 | 23 | } |
| 24 | 24 | |
| 25 | −void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) | |
| 25 | +void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc) | |
| 26 | 26 | { |
| 27 | − u32 leddc_on = 10; | |
| 28 | − u32 leddc_off = 90; | |
| 29 | − | |
| 30 | − if (cc->setup_done) | |
| 27 | + if (cc->early_setup_done) | |
| 31 | 28 | return; |
| 32 | 29 | |
| 33 | 30 | if (cc->core->id.rev >= 11) |
| @@ -36,6 +33,22 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) · 2 unmodified lines | ||
| 36 | 33 | if (cc->core->id.rev >= 35) |
| 37 | 34 | cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT); |
| 38 | 35 | |
| 36 | + if (cc->capabilities & BCMA_CC_CAP_PMU) | |
| 37 | + bcma_pmu_early_init(cc); | |
| 38 | + | |
| 39 | + cc->early_setup_done = true; | |
| 40 | +} | |
| 41 | + | |
| 42 | +void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) | |
| 43 | +{ | |
| 44 | + u32 leddc_on = 10; | |
| 45 | + u32 leddc_off = 90; | |
| 46 | + | |
| 47 | + if (cc->setup_done) | |
| 48 | + return; | |
| 49 | + | |
| 50 | + bcma_core_chipcommon_early_init(cc); | |
| 51 | + | |
| 39 | 52 | if (cc->core->id.rev >= 20) { |
| 40 | 53 | bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0); |
| 41 | 54 | bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0); |
| @@ -32,6 +32,9 @@ int bcma_nflash_init(struct bcma_drv_cc *cc) · 31 unmodified lines | ||
| 32 | 32 | } |
| 33 | 33 | |
| 34 | 34 | cc->nflash.present = true; |
| 35 | + if (cc->core->id.rev == 38 && | |
| 36 | + (cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT)) | |
| 37 | + cc->nflash.boot = true; | |
| 35 | 38 | |
| 36 | 39 | /* Prepare platform device, but don't register it yet. It's too early, |
| 37 | 40 | * malloc (required by device_private_init) is not available yet. */ |
| @@ -144,7 +144,7 @@ static void bcma_pmu_workarounds(struct bcma_drv_cc *cc) · 143 unmodified lines | ||
| 144 | 144 | } |
| 145 | 145 | } |
| 146 | 146 | |
| 147 | −void bcma_pmu_init(struct bcma_drv_cc *cc) | |
| 147 | +void bcma_pmu_early_init(struct bcma_drv_cc *cc) | |
| 148 | 148 | { |
| 149 | 149 | u32 pmucap; |
| 150 | 150 | |
| @@ -153,7 +153,10 @@ void bcma_pmu_init(struct bcma_drv_cc *cc) · 2 unmodified lines | ||
| 153 | 153 | |
| 154 | 154 | bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n", |
| 155 | 155 | cc->pmu.rev, pmucap); |
| 156 | +} | |
| 156 | 157 | |
| 158 | +void bcma_pmu_init(struct bcma_drv_cc *cc) | |
| 159 | +{ | |
| 157 | 160 | if (cc->pmu.rev == 1) |
| 158 | 161 | bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, |
| 159 | 162 | ~BCMA_CC_PMU_CTL_NOILPONW); |
| @@ -12,7 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | static struct resource bcma_sflash_resource = { |
| 14 | 14 | .name = "bcma_sflash", |
| 15 | − .start = BCMA_SFLASH, | |
| 15 | + .start = BCMA_SOC_FLASH2, | |
| 16 | 16 | .end = 0, |
| 17 | 17 | .flags = IORESOURCE_MEM | IORESOURCE_READONLY, |
| 18 | 18 | }; |
| @@ -31,15 +31,42 @@ struct bcma_sflash_tbl_e { · 12 unmodified lines | ||
| 31 | 31 | }; |
| 32 | 32 | |
| 33 | 33 | static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { |
| 34 | − { "", 0x14, 0x10000, 32, }, | |
| 34 | + { "M25P20", 0x11, 0x10000, 4, }, | |
| 35 | + { "M25P40", 0x12, 0x10000, 8, }, | |
| 36 | + | |
| 37 | + { "M25P16", 0x14, 0x10000, 32, }, | |
| 38 | + { "M25P32", 0x14, 0x10000, 64, }, | |
| 39 | + { "M25P64", 0x16, 0x10000, 128, }, | |
| 40 | + { "M25FL128", 0x17, 0x10000, 256, }, | |
| 35 | 41 | { 0 }, |
| 36 | 42 | }; |
| 37 | 43 | |
| 38 | 44 | static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { |
| 45 | + { "SST25WF512", 1, 0x1000, 16, }, | |
| 46 | + { "SST25VF512", 0x48, 0x1000, 16, }, | |
| 47 | + { "SST25WF010", 2, 0x1000, 32, }, | |
| 48 | + { "SST25VF010", 0x49, 0x1000, 32, }, | |
| 49 | + { "SST25WF020", 3, 0x1000, 64, }, | |
| 50 | + { "SST25VF020", 0x43, 0x1000, 64, }, | |
| 51 | + { "SST25WF040", 4, 0x1000, 128, }, | |
| 52 | + { "SST25VF040", 0x44, 0x1000, 128, }, | |
| 53 | + { "SST25VF040B", 0x8d, 0x1000, 128, }, | |
| 54 | + { "SST25WF080", 5, 0x1000, 256, }, | |
| 55 | + { "SST25VF080B", 0x8e, 0x1000, 256, }, | |
| 56 | + { "SST25VF016", 0x41, 0x1000, 512, }, | |
| 57 | + { "SST25VF032", 0x4a, 0x1000, 1024, }, | |
| 58 | + { "SST25VF064", 0x4b, 0x1000, 2048, }, | |
| 39 | 59 | { 0 }, |
| 40 | 60 | }; |
| 41 | 61 | |
| 42 | 62 | static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { |
| 63 | + { "AT45DB011", 0xc, 256, 512, }, | |
| 64 | + { "AT45DB021", 0x14, 256, 1024, }, | |
| 65 | + { "AT45DB041", 0x1c, 256, 2048, }, | |
| 66 | + { "AT45DB081", 0x24, 256, 4096, }, | |
| 67 | + { "AT45DB161", 0x2c, 512, 4096, }, | |
| 68 | + { "AT45DB321", 0x34, 512, 8192, }, | |
| 69 | + { "AT45DB642", 0x3c, 1024, 8192, }, | |
| 43 | 70 | { 0 }, |
| 44 | 71 | }; |
| 45 | 72 | |
| @@ -84,6 +111,8 @@ int bcma_sflash_init(struct bcma_drv_cc *cc) · 38 unmodified lines | ||
| 84 | 111 | break; |
| 85 | 112 | } |
| 86 | 113 | break; |
| 114 | + case 0x13: | |
| 115 | + return -ENOTSUPP; | |
| 87 | 116 | default: |
| 88 | 117 | for (e = bcma_sflash_st_tbl; e->name; e++) { |
| 89 | 118 | if (e->id == id) |
| @@ -116,7 +145,7 @@ int bcma_sflash_init(struct bcma_drv_cc *cc) · 26 unmodified lines | ||
| 116 | 145 | return -ENOTSUPP; |
| 117 | 146 | } |
| 118 | 147 | |
| 119 | − sflash->window = BCMA_SFLASH; | |
| 148 | + sflash->window = BCMA_SOC_FLASH2; | |
| 120 | 149 | sflash->blocksize = e->blocksize; |
| 121 | 150 | sflash->numblocks = e->numblocks; |
| 122 | 151 | sflash->size = sflash->blocksize * sflash->numblocks; |
| @@ -181,47 +181,66 @@ EXPORT_SYMBOL(bcma_cpu_clock); · 180 unmodified lines | ||
| 181 | 181 | static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) |
| 182 | 182 | { |
| 183 | 183 | struct bcma_bus *bus = mcore->core->bus; |
| 184 | + struct bcma_drv_cc *cc = &bus->drv_cc; | |
| 184 | 185 | |
| 185 | − switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) { | |
| 186 | + switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { | |
| 186 | 187 | case BCMA_CC_FLASHT_STSER: |
| 187 | 188 | case BCMA_CC_FLASHT_ATSER: |
| 188 | 189 | bcma_debug(bus, "Found serial flash\n"); |
| 189 | − bcma_sflash_init(&bus->drv_cc); | |
| 190 | + bcma_sflash_init(cc); | |
| 190 | 191 | break; |
| 191 | 192 | case BCMA_CC_FLASHT_PARA: |
| 192 | 193 | bcma_debug(bus, "Found parallel flash\n"); |
| 193 | − bus->drv_cc.pflash.window = 0x1c000000; | |
| 194 | − bus->drv_cc.pflash.window_size = 0x02000000; | |
| 194 | + cc->pflash.present = true; | |
| 195 | + cc->pflash.window = BCMA_SOC_FLASH2; | |
| 196 | + cc->pflash.window_size = BCMA_SOC_FLASH2_SZ; | |
| 195 | 197 | |
| 196 | − if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) & | |
| 198 | + if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) & | |
| 197 | 199 | BCMA_CC_FLASH_CFG_DS) == 0) |
| 198 | − bus->drv_cc.pflash.buswidth = 1; | |
| 200 | + cc->pflash.buswidth = 1; | |
| 199 | 201 | else |
| 200 | − bus->drv_cc.pflash.buswidth = 2; | |
| 202 | + cc->pflash.buswidth = 2; | |
| 201 | 203 | break; |
| 202 | 204 | default: |
| 203 | 205 | bcma_err(bus, "Flash type not supported\n"); |
| 204 | 206 | } |
| 205 | 207 | |
| 206 | − if (bus->drv_cc.core->id.rev == 38 || | |
| 208 | + if (cc->core->id.rev == 38 || | |
| 207 | 209 | bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) { |
| 208 | − if (bus->drv_cc.capabilities & BCMA_CC_CAP_NFLASH) { | |
| 210 | + if (cc->capabilities & BCMA_CC_CAP_NFLASH) { | |
| 209 | 211 | bcma_debug(bus, "Found NAND flash\n"); |
| 210 | − bcma_nflash_init(&bus->drv_cc); | |
| 212 | + bcma_nflash_init(cc); | |
| 211 | 213 | } |
| 212 | 214 | } |
| 213 | 215 | } |
| 214 | 216 | |
| 217 | +void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) | |
| 218 | +{ | |
| 219 | + struct bcma_bus *bus = mcore->core->bus; | |
| 220 | + | |
| 221 | + if (mcore->early_setup_done) | |
| 222 | + return; | |
| 223 | + | |
| 224 | + bcma_chipco_serial_init(&bus->drv_cc); | |
| 225 | + bcma_core_mips_flash_detect(mcore); | |
| 226 | + | |
| 227 | + mcore->early_setup_done = true; | |
| 228 | +} | |
| 229 | + | |
| 215 | 230 | void bcma_core_mips_init(struct bcma_drv_mips *mcore) |
| 216 | 231 | { |
| 217 | 232 | struct bcma_bus *bus; |
| 218 | 233 | struct bcma_device *core; |
| 219 | 234 | bus = mcore->core->bus; |
| 220 | 235 | |
| 236 | + if (mcore->setup_done) | |
| 237 | + return; | |
| 238 | + | |
| 221 | 239 | bcma_info(bus, "Initializing MIPS core...\n"); |
| 222 | 240 | |
| 223 | − if (!mcore->setup_done) | |
| 224 | − mcore->assigned_irqs = 1; | |
| 241 | + bcma_core_mips_early_init(mcore); | |
| 242 | + | |
| 243 | + mcore->assigned_irqs = 1; | |
| 225 | 244 | |
| 226 | 245 | /* Assign IRQs to all cores on the bus */ |
| 227 | 246 | list_for_each_entry(core, &bus->cores, list) { |
| @@ -256,10 +275,5 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore) · 28 unmodified lines | ||
| 256 | 275 | bcma_info(bus, "IRQ reconfiguration done\n"); |
| 257 | 276 | bcma_core_mips_dump_irq(bus); |
| 258 | 277 | |
| 259 | − if (mcore->setup_done) | |
| 260 | − return; | |
| 261 | − | |
| 262 | − bcma_chipco_serial_init(&bus->drv_cc); | |
| 263 | − bcma_core_mips_flash_detect(mcore); | |
| 264 | 278 | mcore->setup_done = true; |
| 265 | 279 | } |
| @@ -35,11 +35,6 @@ bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) · 34 unmodified lines | ||
| 35 | 35 | chipid_top != 0x5300) |
| 36 | 36 | return false; |
| 37 | 37 | |
| 38 | − if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) { | |
| 39 | − bcma_info(bus, "This PCI core is disabled and not working\n"); | |
| 40 | − return false; | |
| 41 | − } | |
| 42 | − | |
| 43 | 38 | bcma_core_enable(pc->core, 0); |
| 44 | 39 | |
| 45 | 40 | return !mips_busprobe32(tmp, pc->core->io_addr); |
| @@ -396,6 +391,11 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) · 350 unmodified lines | ||
| 396 | 391 | |
| 397 | 392 | bcma_info(bus, "PCIEcore in host mode found\n"); |
| 398 | 393 | |
| 394 | + if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) { | |
| 395 | + bcma_info(bus, "This PCIE core is disabled and not working\n"); | |
| 396 | + return; | |
| 397 | + } | |
| 398 | + | |
| 399 | 399 | pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL); |
| 400 | 400 | if (!pc_host) { |
| 401 | 401 | bcma_err(bus, "can not allocate memory"); |
| @@ -452,6 +452,8 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) · 50 unmodified lines | ||
| 452 | 452 | pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; |
| 453 | 453 | pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + |
| 454 | 454 | BCMA_SOC_PCI_MEM_SZ - 1; |
| 455 | + pc_host->io_resource.start = 0x100; | |
| 456 | + pc_host->io_resource.end = 0x47F; | |
| 455 | 457 | pci_membase_1G = BCMA_SOC_PCIE_DMA_H32; |
| 456 | 458 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, |
| 457 | 459 | tmp | BCMA_SOC_PCI_MEM); |
| @@ -459,6 +461,8 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) · 1 unmodified line | ||
| 459 | 461 | pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM; |
| 460 | 462 | pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM + |
| 461 | 463 | BCMA_SOC_PCI_MEM_SZ - 1; |
| 464 | + pc_host->io_resource.start = 0x480; | |
| 465 | + pc_host->io_resource.end = 0x7FF; | |
| 462 | 466 | pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32; |
| 463 | 467 | pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG; |
| 464 | 468 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, |
| @@ -238,7 +238,7 @@ static void __devexit bcma_host_pci_remove(struct pci_dev *dev) · 237 unmodified lines | ||
| 238 | 238 | pci_set_drvdata(dev, NULL); |
| 239 | 239 | } |
| 240 | 240 | |
| 241 | −#ifdef CONFIG_PM | |
| 241 | +#ifdef CONFIG_PM_SLEEP | |
| 242 | 242 | static int bcma_host_pci_suspend(struct device *dev) |
| 243 | 243 | { |
| 244 | 244 | struct pci_dev *pdev = to_pci_dev(dev); |
| @@ -261,11 +261,11 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend, · 16 unmodified lines | ||
| 261 | 261 | bcma_host_pci_resume); |
| 262 | 262 | #define BCMA_PM_OPS (&bcma_pm_ops) |
| 263 | 263 | |
| 264 | −#else /* CONFIG_PM */ | |
| 264 | +#else /* CONFIG_PM_SLEEP */ | |
| 265 | 265 | |
| 266 | 266 | #define BCMA_PM_OPS NULL |
| 267 | 267 | |
| 268 | −#endif /* CONFIG_PM */ | |
| 268 | +#endif /* CONFIG_PM_SLEEP */ | |
| 269 | 269 | |
| 270 | 270 | static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { |
| 271 | 271 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, |
| @@ -81,6 +81,18 @@ struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid) · 80 unmodified lines | ||
| 81 | 81 | } |
| 82 | 82 | EXPORT_SYMBOL_GPL(bcma_find_core); |
| 83 | 83 | |
| 84 | +static struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid, | |
| 85 | + u8 unit) | |
| 86 | +{ | |
| 87 | + struct bcma_device *core; | |
| 88 | + | |
| 89 | + list_for_each_entry(core, &bus->cores, list) { | |
| 90 | + if (core->id.id == coreid && core->core_unit == unit) | |
| 91 | + return core; | |
| 92 | + } | |
| 93 | + return NULL; | |
| 94 | +} | |
| 95 | + | |
| 84 | 96 | static void bcma_release_core_dev(struct device *dev) |
| 85 | 97 | { |
| 86 | 98 | struct bcma_device *core = container_of(dev, struct bcma_device, dev); |
| @@ -183,6 +195,20 @@ int __devinit bcma_bus_register(struct bcma_bus *bus) · 96 unmodified lines | ||
| 183 | 195 | return -1; |
| 184 | 196 | } |
| 185 | 197 | |
| 198 | + /* Early init CC core */ | |
| 199 | + core = bcma_find_core(bus, bcma_cc_core_id(bus)); | |
| 200 | + if (core) { | |
| 201 | + bus->drv_cc.core = core; | |
| 202 | + bcma_core_chipcommon_early_init(&bus->drv_cc); | |
| 203 | + } | |
| 204 | + | |
| 205 | + /* Try to get SPROM */ | |
| 206 | + err = bcma_sprom_get(bus); | |
| 207 | + if (err == -ENOENT) { | |
| 208 | + bcma_err(bus, "No SPROM available\n"); | |
| 209 | + } else if (err) | |
| 210 | + bcma_err(bus, "Failed to get SPROM: %d\n", err); | |
| 211 | + | |
| 186 | 212 | /* Init CC core */ |
| 187 | 213 | core = bcma_find_core(bus, bcma_cc_core_id(bus)); |
| 188 | 214 | if (core) { |
| @@ -198,10 +224,17 @@ int __devinit bcma_bus_register(struct bcma_bus *bus) · 9 unmodified lines | ||
| 198 | 224 | } |
| 199 | 225 | |
| 200 | 226 | /* Init PCIE core */ |
| 201 | − core = bcma_find_core(bus, BCMA_CORE_PCIE); | |
| 227 | + core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 0); | |
| 202 | 228 | if (core) { |
| 203 | − bus->drv_pci.core = core; | |
| 204 | − bcma_core_pci_init(&bus->drv_pci); | |
| 229 | + bus->drv_pci[0].core = core; | |
| 230 | + bcma_core_pci_init(&bus->drv_pci[0]); | |
| 231 | + } | |
| 232 | + | |
| 233 | + /* Init PCIE core */ | |
| 234 | + core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 1); | |
| 235 | + if (core) { | |
| 236 | + bus->drv_pci[1].core = core; | |
| 237 | + bcma_core_pci_init(&bus->drv_pci[1]); | |
| 205 | 238 | } |
| 206 | 239 | |
| 207 | 240 | /* Init GBIT MAC COMMON core */ |
| @@ -211,13 +244,6 @@ int __devinit bcma_bus_register(struct bcma_bus *bus) · 3 unmodified lines | ||
| 211 | 244 | bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn); |
| 212 | 245 | } |
| 213 | 246 | |
| 214 | − /* Try to get SPROM */ | |
| 215 | − err = bcma_sprom_get(bus); | |
| 216 | − if (err == -ENOENT) { | |
| 217 | − bcma_err(bus, "No SPROM available\n"); | |
| 218 | − } else if (err) | |
| 219 | − bcma_err(bus, "Failed to get SPROM: %d\n", err); | |
| 220 | − | |
| 221 | 247 | /* Register found cores */ |
| 222 | 248 | bcma_register_cores(bus); |
| 223 | 249 | |
| @@ -275,18 +301,18 @@ int __init bcma_bus_early_register(struct bcma_bus *bus, · 51 unmodified lines | ||
| 275 | 301 | return -1; |
| 276 | 302 | } |
| 277 | 303 | |
| 278 | − /* Init CC core */ | |
| 304 | + /* Early init CC core */ | |
| 279 | 305 | core = bcma_find_core(bus, bcma_cc_core_id(bus)); |
| 280 | 306 | if (core) { |
| 281 | 307 | bus->drv_cc.core = core; |
| 282 | − bcma_core_chipcommon_init(&bus->drv_cc); | |
| 308 | + bcma_core_chipcommon_early_init(&bus->drv_cc); | |
| 283 | 309 | } |
| 284 | 310 | |
| 285 | − /* Init MIPS core */ | |
| 311 | + /* Early init MIPS core */ | |
| 286 | 312 | core = bcma_find_core(bus, BCMA_CORE_MIPS_74K); |
| 287 | 313 | if (core) { |
| 288 | 314 | bus->drv_mips.core = core; |
| 289 | − bcma_core_mips_init(&bus->drv_mips); | |
| 315 | + bcma_core_mips_early_init(&bus->drv_mips); | |
| 290 | 316 | } |
| 291 | 317 | |
| 292 | 318 | bcma_info(bus, "Early bus registered\n"); |
| @@ -595,8 +595,11 @@ int bcma_sprom_get(struct bcma_bus *bus) · 594 unmodified lines | ||
| 595 | 595 | bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); |
| 596 | 596 | |
| 597 | 597 | err = bcma_sprom_valid(sprom); |
| 598 | − if (err) | |
| 598 | + if (err) { | |
| 599 | + bcma_warn(bus, "invalid sprom read from the PCIe card, try to use fallback sprom\n"); | |
| 600 | + err = bcma_fill_sprom_with_fallback(bus, &bus->sprom); | |
| 599 | 601 | goto out; |
| 602 | + } | |
| 600 | 603 | |
| 601 | 604 | bcma_sprom_extract_r8(bus, sprom); |
| 602 | 605 | |
| @@ -492,7 +492,7 @@ done: · 491 unmodified lines | ||
| 492 | 492 | static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) |
| 493 | 493 | { |
| 494 | 494 | u16 buf_len = 0; |
| 495 | − int ret, buf_block_len, blksz; | |
| 495 | + int ret, num_blocks, blksz; | |
| 496 | 496 | struct sk_buff *skb = NULL; |
| 497 | 497 | u32 type; |
| 498 | 498 | u8 *payload = NULL; |
| @@ -514,18 +514,17 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) · 15 unmodified lines | ||
| 514 | 514 | } |
| 515 | 515 | |
| 516 | 516 | blksz = SDIO_BLOCK_SIZE; |
| 517 | − buf_block_len = (buf_len + blksz - 1) / blksz; | |
| 517 | + num_blocks = DIV_ROUND_UP(buf_len, blksz); | |
| 518 | 518 | |
| 519 | 519 | if (buf_len <= SDIO_HEADER_LEN |
| 520 | − || (buf_block_len * blksz) > ALLOC_BUF_SIZE) { | |
| 520 | + || (num_blocks * blksz) > ALLOC_BUF_SIZE) { | |
| 521 | 521 | BT_ERR("invalid packet length: %d", buf_len); |
| 522 | 522 | ret = -EINVAL; |
| 523 | 523 | goto exit; |
| 524 | 524 | } |
| 525 | 525 | |
| 526 | 526 | /* Allocate buffer */ |
| 527 | − skb = bt_skb_alloc(buf_block_len * blksz + BTSDIO_DMA_ALIGN, | |
| 528 | − GFP_ATOMIC); | |
| 527 | + skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC); | |
| 529 | 528 | if (skb == NULL) { |
| 530 | 529 | BT_ERR("No free skb"); |
| 531 | 530 | goto exit; |
| @@ -541,7 +540,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) · 9 unmodified lines | ||
| 541 | 540 | payload = skb->data; |
| 542 | 541 | |
| 543 | 542 | ret = sdio_readsb(card->func, payload, card->ioport, |
| 544 | − buf_block_len * blksz); | |
| 543 | + num_blocks * blksz); | |
| 545 | 544 | if (ret < 0) { |
| 546 | 545 | BT_ERR("readsb failed: %d", ret); |
| 547 | 546 | ret = -EIO; |
| @@ -553,7 +552,16 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) · 5 unmodified lines | ||
| 553 | 552 | */ |
| 554 | 553 | |
| 555 | 554 | buf_len = payload[0]; |
| 556 | − buf_len |= (u16) payload[1] << 8; | |
| 555 | + buf_len |= payload[1] << 8; | |
| 556 | + buf_len |= payload[2] << 16; | |
| 557 | + | |
| 558 | + if (buf_len > blksz * num_blocks) { | |
| 559 | + BT_ERR("Skip incorrect packet: hdrlen %d buffer %d", | |
| 560 | + buf_len, blksz * num_blocks); | |
| 561 | + ret = -EIO; | |
| 562 | + goto exit; | |
| 563 | + } | |
| 564 | + | |
| 557 | 565 | type = payload[3]; |
| 558 | 566 | |
| 559 | 567 | switch (type) { |
| @@ -589,8 +597,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) · 29 unmodified lines | ||
| 589 | 597 | |
| 590 | 598 | default: |
| 591 | 599 | BT_ERR("Unknown packet type:%d", type); |
| 592 | − print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload, | |
| 593 | − blksz * buf_block_len); | |
| 600 | + BT_ERR("hex: %*ph", blksz * num_blocks, payload); | |
| 594 | 601 | |
| 595 | 602 | kfree_skb(skb); |
| 596 | 603 | skb = NULL; |
| @@ -849,8 +856,7 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv, · 252 unmodified lines | ||
| 849 | 856 | if (ret < 0) { |
| 850 | 857 | i++; |
| 851 | 858 | BT_ERR("i=%d writesb failed: %d", i, ret); |
| 852 | − print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, | |
| 853 | − payload, nb); | |
| 859 | + BT_ERR("hex: %*ph", nb, payload); | |
| 854 | 860 | ret = -EIO; |
| 855 | 861 | if (i > MAX_WRITE_IOMEM_RETRY) |
| 856 | 862 | goto exit; |
| @@ -452,7 +452,7 @@ static size_t gelic_wl_synthesize_ie(u8 *buf, · 451 unmodified lines | ||
| 452 | 452 | if (rsn) |
| 453 | 453 | *buf++ = WLAN_EID_RSN; |
| 454 | 454 | else |
| 455 | − *buf++ = WLAN_EID_GENERIC; | |
| 455 | + *buf++ = WLAN_EID_VENDOR_SPECIFIC; | |
| 456 | 456 | |
| 457 | 457 | /* length filed; set later */ |
| 458 | 458 | buf++; |
| @@ -540,7 +540,7 @@ static void gelic_wl_parse_ie(u8 *data, size_t len, · 81 unmodified lines | ||
| 540 | 540 | break; |
| 541 | 541 | |
| 542 | 542 | switch (item_id) { |
| 543 | − case WLAN_EID_GENERIC: | |
| 543 | + case WLAN_EID_VENDOR_SPECIFIC: | |
| 544 | 544 | if ((OUI_LEN + 1 <= item_len) && |
| 545 | 545 | !memcmp(pos, wpa_oui, OUI_LEN) && |
| 546 | 546 | pos[OUI_LEN] == 0x01) { |
| @@ -7433,7 +7433,7 @@ static inline char *airo_translate_scan(struct net_device *dev, · 7432 unmodified lines | ||
| 7433 | 7433 | num_null_ies++; |
| 7434 | 7434 | break; |
| 7435 | 7435 | |
| 7436 | − case WLAN_EID_GENERIC: | |
| 7436 | + case WLAN_EID_VENDOR_SPECIFIC: | |
| 7437 | 7437 | if (ie[1] >= 4 && |
| 7438 | 7438 | ie[2] == 0x00 && |
| 7439 | 7439 | ie[3] == 0x50 && |
| @@ -26,5 +26,6 @@ source "drivers/net/wireless/ath/ath5k/Kconfig" · 25 unmodified lines | ||
| 26 | 26 | source "drivers/net/wireless/ath/ath9k/Kconfig" |
| 27 | 27 | source "drivers/net/wireless/ath/carl9170/Kconfig" |
| 28 | 28 | source "drivers/net/wireless/ath/ath6kl/Kconfig" |
| 29 | +source "drivers/net/wireless/ath/ar5523/Kconfig" | |
| 29 | 30 | |
| 30 | 31 | endif |
| @@ -2,6 +2,7 @@ obj-$(CONFIG_ATH5K) += ath5k/ · 1 unmodified line | ||
| 2 | 2 | obj-$(CONFIG_ATH9K_HW) += ath9k/ |
| 3 | 3 | obj-$(CONFIG_CARL9170) += carl9170/ |
| 4 | 4 | obj-$(CONFIG_ATH6KL) += ath6kl/ |
| 5 | +obj-$(CONFIG_AR5523) += ar5523/ | |
| 5 | 6 | |
| 6 | 7 | obj-$(CONFIG_ATH_COMMON) += ath.o |
| 7 | 8 | |
| @@ -0,0 +1,7 @@ | ||
| 1 | +config AR5523 | |
| 2 | + tristate "Atheros AR5523 wireless driver support" | |
| 3 | + depends on MAC80211 && USB | |
| 4 | + select FW_LOADER | |
| 5 | + ---help--- | |
| 6 | + This module add support for AR5523 based USB dongles such as D-Link | |
| 7 | + DWL-G132, Netgear WPN111 and many more. | |
| @@ -0,0 +1 @@ | ||
| 1 | +obj-$(CONFIG_AR5523) := ar5523.o | |
| @@ -0,0 +1,1806 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr> | |
| 3 | + * Copyright (c) 2006 Sam Leffler, Errno Consulting | |
| 4 | + * Copyright (c) 2007 Christoph Hellwig <hch@lst.de> | |
| 5 | + * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org> | |
| 6 | + * Copyright (c) 2012 Pontus Fuchs <pontus.fuchs@gmail.com> | |
| 7 | + * | |
| 8 | + * Permission to use, copy, modify, and/or distribute this software for any | |
| 9 | + * purpose with or without fee is hereby granted, provided that the above | |
| 10 | + * copyright notice and this permission notice appear in all copies. | |
| 11 | + * | |
| 12 | + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
| 13 | + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
| 14 | + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
| 15 | + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
| 16 | + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
| 17 | + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
| 18 | + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
| 19 | + */ | |
| 20 | + | |
| 21 | +/* | |
| 22 | + * This driver is based on the uath driver written by Damien Bergamini for | |
| 23 | + * OpenBSD, who did black-box analysis of the Windows binary driver to find | |
| 24 | + * out how the hardware works. It contains a lot magic numbers because of | |
| 25 | + * that and only has minimal functionality. | |
| 26 | + */ | |
| 27 | +#include <linux/compiler.h> | |
| 28 | +#include <linux/init.h> | |
| 29 | +#include <linux/kernel.h> | |
| 30 | +#include <linux/module.h> | |
| 31 | +#include <linux/list.h> | |
| 32 | +#include <linux/completion.h> | |
| 33 | +#include <linux/firmware.h> | |
| 34 | +#include <linux/skbuff.h> | |
| 35 | +#include <linux/usb.h> | |
| 36 | +#include <net/mac80211.h> | |
| 37 | + | |
| 38 | +#include "ar5523.h" | |
| 39 | +#include "ar5523_hw.h" | |
| 40 | + | |
| 41 | +/* | |
| 42 | + * Various supported device vendors/products. | |
| 43 | + * UB51: AR5005UG 802.11b/g, UB52: AR5005UX 802.11a/b/g | |
| 44 | + */ | |
| 45 | + | |
| 46 | +static int ar5523_submit_rx_cmd(struct ar5523 *ar); | |
| 47 | +static void ar5523_data_tx_pkt_put(struct ar5523 *ar); | |
| 48 | + | |
| 49 | +static void ar5523_read_reply(struct ar5523 *ar, struct ar5523_cmd_hdr *hdr, | |
| 50 | + struct ar5523_tx_cmd *cmd) | |
| 51 | +{ | |
| 52 | + int dlen, olen; | |
| 53 | + u32 *rp; | |
| 54 | + | |
| 55 | + dlen = hdr->len - sizeof(*hdr); | |
| 56 | + | |
| 57 | + if (dlen < 0) { | |
| 58 | + WARN_ON(1); | |
| 59 | + goto out; | |
| 60 | + } | |
| 61 | + | |
| 62 | + ar5523_dbg(ar, "Code = %d len = %d\n", hdr->code & 0xff, dlen); | |
| 63 | + | |
| 64 | + rp = (u32 *)(hdr + 1); | |
| 65 | + if (dlen >= sizeof(u32)) { | |
| 66 | + olen = be32_to_cpu(rp[0]); | |
| 67 | + dlen -= sizeof(u32); | |
| 68 | + if (olen == 0) { | |
| 69 | + /* convention is 0 =>'s one word */ | |
| 70 | + olen = sizeof(u32); | |
| 71 | + } | |
| 72 | + } else | |
| 73 | + olen = 0; | |
| 74 | + | |
| 75 | + if (cmd->odata) { | |
| 76 | + if (cmd->olen < olen) { | |
| 77 | + ar5523_err(ar, "olen to small %d < %d\n", | |
| 78 | + cmd->olen, olen); | |
| 79 | + cmd->olen = 0; | |
| 80 | + cmd->res = -EOVERFLOW; | |
| 81 | + } else { | |
| 82 | + cmd->olen = olen; | |
| 83 | + memcpy(cmd->odata, &rp[1], olen); | |
| 84 | + cmd->res = 0; | |
| 85 | + } | |
| 86 | + } | |
| 87 | + | |
| 88 | +out: | |
| 89 | + complete(&cmd->done); | |
| 90 | +} | |
| 91 | + | |
| 92 | +static void ar5523_cmd_rx_cb(struct urb *urb) | |
| 93 | +{ | |
| 94 | + struct ar5523 *ar = urb->context; | |
| 95 | + struct ar5523_tx_cmd *cmd = &ar->tx_cmd; | |
| 96 | + struct ar5523_cmd_hdr *hdr = ar->rx_cmd_buf; | |
| 97 | + int dlen; | |
| 98 | + | |
| 99 | + if (urb->status) { | |
| 100 | + if (urb->status != -ESHUTDOWN) | |
| 101 | + ar5523_err(ar, "RX USB error %d.\n", urb->status); | |
| 102 | + goto skip; | |
| 103 | + } | |
| 104 | + | |
| 105 | + if (urb->actual_length < sizeof(struct ar5523_cmd_hdr)) { | |
| 106 | + ar5523_err(ar, "RX USB to short.\n"); | |
| 107 | + goto skip; | |
| 108 | + } | |
| 109 | + | |
| 110 | + ar5523_dbg(ar, "%s code %02x priv %d\n", __func__, | |
| 111 | + be32_to_cpu(hdr->code) & 0xff, hdr->priv); | |
| 112 | + | |
| 113 | + hdr->code = be32_to_cpu(hdr->code); | |
| 114 | + hdr->len = be32_to_cpu(hdr->len); | |
| 115 | + | |
| 116 | + switch (hdr->code & 0xff) { | |
| 117 | + default: | |
| 118 | + /* reply to a read command */ | |
| 119 | + if (hdr->priv != AR5523_CMD_ID) { | |
| 120 | + ar5523_err(ar, "Unexpected command id: %02x\n", | |
| 121 | + hdr->code & 0xff); | |
| 122 | + goto skip; | |
| 123 | + } | |
| 124 | + ar5523_read_reply(ar, hdr, cmd); | |
| 125 | + break; | |
| 126 | + | |
| 127 | + case WDCMSG_DEVICE_AVAIL: | |
| 128 | + ar5523_dbg(ar, "WDCMSG_DEVICE_AVAIL\n"); | |
| 129 | + cmd->res = 0; | |
| 130 | + cmd->olen = 0; | |
| 131 | + complete(&cmd->done); | |
| 132 | + break; | |
| 133 | + | |
| 134 | + case WDCMSG_SEND_COMPLETE: | |
| 135 | + ar5523_dbg(ar, "WDCMSG_SEND_COMPLETE: %d pending\n", | |
| 136 | + atomic_read(&ar->tx_nr_pending)); | |
| 137 | + if (!test_bit(AR5523_HW_UP, &ar->flags)) | |
| 138 | + ar5523_dbg(ar, "Unexpected WDCMSG_SEND_COMPLETE\n"); | |
| 139 | + else { | |
| 140 | + mod_timer(&ar->tx_wd_timer, | |
| 141 | + jiffies + AR5523_TX_WD_TIMEOUT); | |
| 142 | + ar5523_data_tx_pkt_put(ar); | |
| 143 | + | |
| 144 | + } | |
| 145 | + break; | |
| 146 | + | |
| 147 | + case WDCMSG_TARGET_START: | |
| 148 | + /* This command returns a bogus id so it needs special | |
| 149 | + handling */ | |
| 150 | + dlen = hdr->len - sizeof(*hdr); | |
| 151 | + if (dlen != (int)sizeof(u32)) { | |
| 152 | + ar5523_err(ar, "Invalid reply to WDCMSG_TARGET_START"); | |
| 153 | + return; | |
| 154 | + } | |
| 155 | + memcpy(cmd->odata, hdr + 1, sizeof(u32)); | |
| 156 | + cmd->olen = sizeof(u32); | |
| 157 | + cmd->res = 0; | |
| 158 | + complete(&cmd->done); | |
| 159 | + break; | |
| 160 | + | |
| 161 | + case WDCMSG_STATS_UPDATE: | |
| 162 | + ar5523_dbg(ar, "WDCMSG_STATS_UPDATE\n"); | |
| 163 | + break; | |
| 164 | + } | |
| 165 | + | |
| 166 | +skip: | |
| 167 | + ar5523_submit_rx_cmd(ar); | |
| 168 | +} | |
| 169 | + | |
| 170 | +static int ar5523_alloc_rx_cmd(struct ar5523 *ar) | |
| 171 | +{ | |
| 172 | + ar->rx_cmd_urb = usb_alloc_urb(0, GFP_KERNEL); | |
| 173 | + if (!ar->rx_cmd_urb) | |
| 174 | + return -ENOMEM; | |
| 175 | + | |
| 176 | + ar->rx_cmd_buf = usb_alloc_coherent(ar->dev, AR5523_MAX_RXCMDSZ, | |
| 177 | + GFP_KERNEL, | |
| 178 | + &ar->rx_cmd_urb->transfer_dma); | |
| 179 | + if (!ar->rx_cmd_buf) { | |
| 180 | + usb_free_urb(ar->rx_cmd_urb); | |
| 181 | + return -ENOMEM; | |
| 182 | + } | |
| 183 | + return 0; | |
| 184 | +} | |
| 185 | + | |
| 186 | +static void ar5523_cancel_rx_cmd(struct ar5523 *ar) | |
| 187 | +{ | |
| 188 | + usb_kill_urb(ar->rx_cmd_urb); | |
| 189 | +} | |
| 190 | + | |
| 191 | +static void ar5523_free_rx_cmd(struct ar5523 *ar) | |
| 192 | +{ | |
| 193 | + usb_free_coherent(ar->dev, AR5523_MAX_RXCMDSZ, | |
| 194 | + ar->rx_cmd_buf, ar->rx_cmd_urb->transfer_dma); | |
| 195 | + usb_free_urb(ar->rx_cmd_urb); | |
| 196 | +} | |
| 197 | + | |
| 198 | +static int ar5523_submit_rx_cmd(struct ar5523 *ar) | |
| 199 | +{ | |
| 200 | + int error; | |
| 201 | + | |
| 202 | + usb_fill_bulk_urb(ar->rx_cmd_urb, ar->dev, | |
| 203 | + ar5523_cmd_rx_pipe(ar->dev), ar->rx_cmd_buf, | |
| 204 | + AR5523_MAX_RXCMDSZ, ar5523_cmd_rx_cb, ar); | |
| 205 | + ar->rx_cmd_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | |
| 206 | + | |
| 207 | + error = usb_submit_urb(ar->rx_cmd_urb, GFP_ATOMIC); | |
| 208 | + if (error) { | |
| 209 | + if (error != -ENODEV) | |
| 210 | + ar5523_err(ar, "error %d when submitting rx urb\n", | |
| 211 | + error); | |
| 212 | + return error; | |
| 213 | + } | |
| 214 | + return 0; | |
| 215 | +} | |
| 216 | + | |
| 217 | +/* | |
| 218 | + * Command submitted cb | |
| 219 | + */ | |
| 220 | +static void ar5523_cmd_tx_cb(struct urb *urb) | |
| 221 | +{ | |
| 222 | + struct ar5523_tx_cmd *cmd = urb->context; | |
| 223 | + struct ar5523 *ar = cmd->ar; | |
| 224 | + | |
| 225 | + if (urb->status) { | |
| 226 | + ar5523_err(ar, "Failed to TX command. Status = %d\n", | |
| 227 | + urb->status); | |
| 228 | + cmd->res = urb->status; | |
| 229 | + complete(&cmd->done); | |
| 230 | + return; | |
| 231 | + } | |
| 232 | + | |
| 233 | + if (!(cmd->flags & AR5523_CMD_FLAG_READ)) { | |
| 234 | + cmd->res = 0; | |
| 235 | + complete(&cmd->done); | |
| 236 | + } | |
| 237 | +} | |
| 238 | + | |
| 239 | +static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata, | |
| 240 | + int ilen, void *odata, int olen, int flags) | |
| 241 | +{ | |
| 242 | + struct ar5523_cmd_hdr *hdr; | |
| 243 | + struct ar5523_tx_cmd *cmd = &ar->tx_cmd; | |
| 244 | + int xferlen, error; | |
| 245 | + | |
| 246 | + /* always bulk-out a multiple of 4 bytes */ | |
| 247 | + xferlen = (sizeof(struct ar5523_cmd_hdr) + ilen + 3) & ~3; | |
| 248 | + | |
| 249 | + hdr = (struct ar5523_cmd_hdr *)cmd->buf_tx; | |
| 250 | + memset(hdr, 0, sizeof(struct ar5523_cmd_hdr)); | |
| 251 | + hdr->len = cpu_to_be32(xferlen); | |
| 252 | + hdr->code = cpu_to_be32(code); | |
| 253 | + hdr->priv = AR5523_CMD_ID; | |
| 254 | + | |
| 255 | + if (flags & AR5523_CMD_FLAG_MAGIC) | |
| 256 | + hdr->magic = cpu_to_be32(1 << 24); | |
| 257 | + memcpy(hdr + 1, idata, ilen); | |
| 258 | + | |
| 259 | + cmd->odata = odata; | |
| 260 | + cmd->olen = olen; | |
| 261 | + cmd->flags = flags; | |
| 262 | + | |
| 263 | + ar5523_dbg(ar, "do cmd %02x\n", code); | |
| 264 | + | |
| 265 | + usb_fill_bulk_urb(cmd->urb_tx, ar->dev, ar5523_cmd_tx_pipe(ar->dev), | |
| 266 | + cmd->buf_tx, xferlen, ar5523_cmd_tx_cb, cmd); | |
| 267 | + cmd->urb_tx->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | |
| 268 | + | |
| 269 | + error = usb_submit_urb(cmd->urb_tx, GFP_KERNEL); | |
| 270 | + if (error) { | |
| 271 | + ar5523_err(ar, "could not send command 0x%x, error=%d\n", | |
| 272 | + code, error); | |
| 273 | + return error; | |
| 274 | + } | |
| 275 | + | |
| 276 | + if (!wait_for_completion_timeout(&cmd->done, 2 * HZ)) { | |
| 277 | + cmd->odata = NULL; | |
| 278 | + ar5523_err(ar, "timeout waiting for command %02x reply\n", | |
| 279 | + code); | |
| 280 | + cmd->res = -ETIMEDOUT; | |
| 281 | + } | |
| 282 | + return cmd->res; | |
| 283 | +} | |
| 284 | + | |
| 285 | +static int ar5523_cmd_write(struct ar5523 *ar, u32 code, const void *data, | |
| 286 | + int len, int flags) | |
| 287 | +{ | |
| 288 | + flags &= ~AR5523_CMD_FLAG_READ; | |
| 289 | + return ar5523_cmd(ar, code, data, len, NULL, 0, flags); | |
| 290 | +} | |
| 291 | + | |
| 292 | +static int ar5523_cmd_read(struct ar5523 *ar, u32 code, const void *idata, | |
| 293 | + int ilen, void *odata, int olen, int flags) | |
| 294 | +{ | |
| 295 | + flags |= AR5523_CMD_FLAG_READ; | |
| 296 | + return ar5523_cmd(ar, code, idata, ilen, odata, olen, flags); | |
| 297 | +} | |
| 298 | + | |
| 299 | +static int ar5523_config(struct ar5523 *ar, u32 reg, u32 val) | |
| 300 | +{ | |
| 301 | + struct ar5523_write_mac write; | |
| 302 | + int error; | |
| 303 | + | |
| 304 | + write.reg = cpu_to_be32(reg); | |
| 305 | + write.len = cpu_to_be32(0); /* 0 = single write */ | |
| 306 | + *(u32 *)write.data = cpu_to_be32(val); | |
| 307 | + | |
| 308 | + error = ar5523_cmd_write(ar, WDCMSG_TARGET_SET_CONFIG, &write, | |
| 309 | + 3 * sizeof(u32), 0); | |
| 310 | + if (error != 0) | |
| 311 | + ar5523_err(ar, "could not write register 0x%02x\n", reg); | |
| 312 | + return error; | |
| 313 | +} | |
| 314 | + | |
| 315 | +static int ar5523_config_multi(struct ar5523 *ar, u32 reg, const void *data, | |
| 316 | + int len) | |
| 317 | +{ | |
| 318 | + struct ar5523_write_mac write; | |
| 319 | + int error; | |
| 320 | + | |
| 321 | + write.reg = cpu_to_be32(reg); | |
| 322 | + write.len = cpu_to_be32(len); | |
| 323 | + memcpy(write.data, data, len); | |
| 324 | + | |
| 325 | + /* properly handle the case where len is zero (reset) */ | |
| 326 | + error = ar5523_cmd_write(ar, WDCMSG_TARGET_SET_CONFIG, &write, | |
| 327 | + (len == 0) ? sizeof(u32) : 2 * sizeof(u32) + len, 0); | |
| 328 | + if (error != 0) | |
| 329 | + ar5523_err(ar, "could not write %d bytes to register 0x%02x\n", | |
| 330 | + len, reg); | |
| 331 | + return error; | |
| 332 | +} | |
| 333 | + | |
| 334 | +static int ar5523_get_status(struct ar5523 *ar, u32 which, void *odata, | |
| 335 | + int olen) | |
| 336 | +{ | |
| 337 | + int error; | |
| 338 | + | |
| 339 | + which = cpu_to_be32(which); | |
| 340 | + error = ar5523_cmd_read(ar, WDCMSG_TARGET_GET_STATUS, | |
| 341 | + &which, sizeof(which), odata, olen, AR5523_CMD_FLAG_MAGIC); | |
| 342 | + if (error != 0) | |
| 343 | + ar5523_err(ar, "could not read EEPROM offset 0x%02x\n", | |
| 344 | + be32_to_cpu(which)); | |
| 345 | + return error; | |
| 346 | +} | |
| 347 | + | |
| 348 | +static int ar5523_get_capability(struct ar5523 *ar, u32 cap, u32 *val) | |
| 349 | +{ | |
| 350 | + int error; | |
| 351 | + | |
| 352 | + cap = cpu_to_be32(cap); | |
| 353 | + error = ar5523_cmd_read(ar, WDCMSG_TARGET_GET_CAPABILITY, | |
| 354 | + &cap, sizeof(cap), val, sizeof(u32), AR5523_CMD_FLAG_MAGIC); | |
| 355 | + if (error != 0) { | |
| 356 | + ar5523_err(ar, "could not read capability %u\n", | |
| 357 | + be32_to_cpu(cap)); | |
| 358 | + return error; | |
| 359 | + } | |
| 360 | + *val = be32_to_cpu(*val); | |
| 361 | + return error; | |
| 362 | +} | |
| 363 | + | |
| 364 | +static int ar5523_get_devcap(struct ar5523 *ar) | |
| 365 | +{ | |
| 366 | +#define GETCAP(x) do { \ | |
| 367 | + error = ar5523_get_capability(ar, x, &cap); \ | |
| 368 | + if (error != 0) \ | |
| 369 | + return error; \ | |
| 370 | + ar5523_info(ar, "Cap: " \ | |
| 371 | + "%s=0x%08x\n", #x, cap); \ | |
| 372 | +} while (0) | |
| 373 | + int error; | |
| 374 | + u32 cap; | |
| 375 | + | |
| 376 | + /* collect device capabilities */ | |
| 377 | + GETCAP(CAP_TARGET_VERSION); | |
| 378 | + GETCAP(CAP_TARGET_REVISION); | |
| 379 | + GETCAP(CAP_MAC_VERSION); | |
| 380 | + GETCAP(CAP_MAC_REVISION); | |
| 381 | + GETCAP(CAP_PHY_REVISION); | |
| 382 | + GETCAP(CAP_ANALOG_5GHz_REVISION); | |
| 383 | + GETCAP(CAP_ANALOG_2GHz_REVISION); | |
| 384 | + | |
| 385 | + GETCAP(CAP_REG_DOMAIN); | |
| 386 | + GETCAP(CAP_REG_CAP_BITS); | |
| 387 | + GETCAP(CAP_WIRELESS_MODES); | |
| 388 | + GETCAP(CAP_CHAN_SPREAD_SUPPORT); | |
| 389 | + GETCAP(CAP_COMPRESS_SUPPORT); | |
| 390 | + GETCAP(CAP_BURST_SUPPORT); | |
| 391 | + GETCAP(CAP_FAST_FRAMES_SUPPORT); | |
| 392 | + GETCAP(CAP_CHAP_TUNING_SUPPORT); | |
| 393 | + GETCAP(CAP_TURBOG_SUPPORT); | |
| 394 | + GETCAP(CAP_TURBO_PRIME_SUPPORT); | |
| 395 | + GETCAP(CAP_DEVICE_TYPE); | |
| 396 | + GETCAP(CAP_WME_SUPPORT); | |
| 397 | + GETCAP(CAP_TOTAL_QUEUES); | |
| 398 | + GETCAP(CAP_CONNECTION_ID_MAX); | |
| 399 | + | |
| 400 | + GETCAP(CAP_LOW_5GHZ_CHAN); | |
| 401 | + GETCAP(CAP_HIGH_5GHZ_CHAN); | |
| 402 | + GETCAP(CAP_LOW_2GHZ_CHAN); | |
| 403 | + GETCAP(CAP_HIGH_2GHZ_CHAN); | |
| 404 | + GETCAP(CAP_TWICE_ANTENNAGAIN_5G); | |
| 405 | + GETCAP(CAP_TWICE_ANTENNAGAIN_2G); | |
| 406 | + | |
| 407 | + GETCAP(CAP_CIPHER_AES_CCM); | |
| 408 | + GETCAP(CAP_CIPHER_TKIP); | |
| 409 | + GETCAP(CAP_MIC_TKIP); | |
| 410 | + return 0; | |
| 411 | +} | |
| 412 | + | |
| 413 | +static int ar5523_set_ledsteady(struct ar5523 *ar, int lednum, int ledmode) | |
| 414 | +{ | |
| 415 | + struct ar5523_cmd_ledsteady led; | |
| 416 | + | |
| 417 | + led.lednum = cpu_to_be32(lednum); | |
| 418 | + led.ledmode = cpu_to_be32(ledmode); | |
| 419 | + | |
| 420 | + ar5523_dbg(ar, "set %s led %s (steady)\n", | |
| 421 | + (lednum == UATH_LED_LINK) ? "link" : "activity", | |
| 422 | + ledmode ? "on" : "off"); | |
| 423 | + return ar5523_cmd_write(ar, WDCMSG_SET_LED_STEADY, &led, sizeof(led), | |
| 424 | + 0); | |
| 425 | +} | |
| 426 | + | |
| 427 | +static int ar5523_set_rxfilter(struct ar5523 *ar, u32 bits, u32 op) | |
| 428 | +{ | |
| 429 | + struct ar5523_cmd_rx_filter rxfilter; | |
| 430 | + | |
| 431 | + rxfilter.bits = cpu_to_be32(bits); | |
| 432 | + rxfilter.op = cpu_to_be32(op); | |
| 433 | + | |
| 434 | + ar5523_dbg(ar, "setting Rx filter=0x%x flags=0x%x\n", bits, op); | |
| 435 | + return ar5523_cmd_write(ar, WDCMSG_RX_FILTER, &rxfilter, | |
| 436 | + sizeof(rxfilter), 0); | |
| 437 | +} | |
| 438 | + | |
| 439 | +static int ar5523_reset_tx_queues(struct ar5523 *ar) | |
| 440 | +{ | |
| 441 | + __be32 qid = cpu_to_be32(0); | |
| 442 | + | |
| 443 | + ar5523_dbg(ar, "resetting Tx queue\n"); | |
| 444 | + return ar5523_cmd_write(ar, WDCMSG_RELEASE_TX_QUEUE, | |
| 445 | + &qid, sizeof(qid), 0); | |
| 446 | +} | |
| 447 | + | |
| 448 | +static int ar5523_set_chan(struct ar5523 *ar) | |
| 449 | +{ | |
| 450 | + struct ieee80211_conf *conf = &ar->hw->conf; | |
| 451 | + | |
| 452 | + struct ar5523_cmd_reset reset; | |
| 453 | + | |
| 454 | + memset(&reset, 0, sizeof(reset)); | |
| 455 | + reset.flags |= cpu_to_be32(UATH_CHAN_2GHZ); | |
| 456 | + reset.flags |= cpu_to_be32(UATH_CHAN_OFDM); | |
| 457 | + reset.freq = cpu_to_be32(conf->channel->center_freq); | |
| 458 | + reset.maxrdpower = cpu_to_be32(50); /* XXX */ | |
| 459 | + reset.channelchange = cpu_to_be32(1); | |
| 460 | + reset.keeprccontent = cpu_to_be32(0); | |
| 461 | + | |
| 462 | + ar5523_dbg(ar, "set chan flags 0x%x freq %d\n", | |
| 463 | + be32_to_cpu(reset.flags), | |
| 464 | + conf->channel->center_freq); | |
| 465 | + return ar5523_cmd_write(ar, WDCMSG_RESET, &reset, sizeof(reset), 0); | |
| 466 | +} | |
| 467 | + | |
| 468 | +static int ar5523_queue_init(struct ar5523 *ar) | |
| 469 | +{ | |
| 470 | + struct ar5523_cmd_txq_setup qinfo; | |
| 471 | + | |
| 472 | + ar5523_dbg(ar, "setting up Tx queue\n"); | |
| 473 | + qinfo.qid = cpu_to_be32(0); | |
| 474 | + qinfo.len = cpu_to_be32(sizeof(qinfo.attr)); | |
| 475 | + qinfo.attr.priority = cpu_to_be32(0); /* XXX */ | |
| 476 | + qinfo.attr.aifs = cpu_to_be32(3); | |
| 477 | + qinfo.attr.logcwmin = cpu_to_be32(4); | |
| 478 | + qinfo.attr.logcwmax = cpu_to_be32(10); | |
| 479 | + qinfo.attr.bursttime = cpu_to_be32(0); | |
| 480 | + qinfo.attr.mode = cpu_to_be32(0); | |
| 481 | + qinfo.attr.qflags = cpu_to_be32(1); /* XXX? */ | |
| 482 | + return ar5523_cmd_write(ar, WDCMSG_SETUP_TX_QUEUE, &qinfo, | |
| 483 | + sizeof(qinfo), 0); | |
| 484 | +} | |
| 485 | + | |
| 486 | +static int ar5523_switch_chan(struct ar5523 *ar) | |
| 487 | +{ | |
| 488 | + int error; | |
| 489 | + | |
| 490 | + error = ar5523_set_chan(ar); | |
| 491 | + if (error) { | |
| 492 | + ar5523_err(ar, "could not set chan, error %d\n", error); | |
| 493 | + goto out_err; | |
| 494 | + } | |
| 495 | + | |
| 496 | + /* reset Tx rings */ | |
| 497 | + error = ar5523_reset_tx_queues(ar); | |
| 498 | + if (error) { | |
| 499 | + ar5523_err(ar, "could not reset Tx queues, error %d\n", | |
| 500 | + error); | |
| 501 | + goto out_err; | |
| 502 | + } | |
| 503 | + /* set Tx rings WME properties */ | |
| 504 | + error = ar5523_queue_init(ar); | |
| 505 | + if (error) | |
| 506 | + ar5523_err(ar, "could not init wme, error %d\n", error); | |
| 507 | + | |
| 508 | +out_err: | |
| 509 | + return error; | |
| 510 | +} | |
| 511 | + | |
| 512 | +static void ar5523_rx_data_put(struct ar5523 *ar, | |
| 513 | + struct ar5523_rx_data *data) | |
| 514 | +{ | |
| 515 | + unsigned long flags; | |
| 516 | + spin_lock_irqsave(&ar->rx_data_list_lock, flags); | |
| 517 | + list_move(&data->list, &ar->rx_data_free); | |
| 518 | + spin_unlock_irqrestore(&ar->rx_data_list_lock, flags); | |
| 519 | +} | |
| 520 | + | |
| 521 | +static void ar5523_data_rx_cb(struct urb *urb) | |
| 522 | +{ | |
| 523 | + struct ar5523_rx_data *data = urb->context; | |
| 524 | + struct ar5523 *ar = data->ar; | |
| 525 | + struct ar5523_rx_desc *desc; | |
| 526 | + struct ar5523_chunk *chunk; | |
| 527 | + struct ieee80211_hw *hw = ar->hw; | |
| 528 | + struct ieee80211_rx_status *rx_status; | |
| 529 | + u32 rxlen; | |
| 530 | + int usblen = urb->actual_length; | |
| 531 | + int hdrlen, pad; | |
| 532 | + | |
| 533 | + ar5523_dbg(ar, "%s\n", __func__); | |
| 534 | + /* sync/async unlink faults aren't errors */ | |
| 535 | + if (urb->status) { | |
| 536 | + if (urb->status != -ESHUTDOWN) | |
| 537 | + ar5523_err(ar, "%s: USB err: %d\n", __func__, | |
| 538 | + urb->status); | |
| 539 | + goto skip; | |
| 540 | + } | |
| 541 | + | |
| 542 | + if (usblen < AR5523_MIN_RXBUFSZ) { | |
| 543 | + ar5523_err(ar, "RX: wrong xfer size (usblen=%d)\n", usblen); | |
| 544 | + goto skip; | |
| 545 | + } | |
| 546 | + | |
| 547 | + chunk = (struct ar5523_chunk *) data->skb->data; | |
| 548 | + | |
| 549 | + if (((chunk->flags & UATH_CFLAGS_FINAL) == 0) || | |
| 550 | + chunk->seqnum != 0) { | |
| 551 | + ar5523_dbg(ar, "RX: No final flag. s: %d f: %02x l: %d\n", | |
| 552 | + chunk->seqnum, chunk->flags, | |
| 553 | + be16_to_cpu(chunk->length)); | |
| 554 | + goto skip; | |
| 555 | + } | |
| 556 | + | |
| 557 | + /* Rx descriptor is located at the end, 32-bit aligned */ | |
| 558 | + desc = (struct ar5523_rx_desc *) | |
| 559 | + (data->skb->data + usblen - sizeof(struct ar5523_rx_desc)); | |
| 560 | + | |
| 561 | + rxlen = be32_to_cpu(desc->len); | |
| 562 | + if (rxlen > ar->rxbufsz) { | |
| 563 | + ar5523_dbg(ar, "RX: Bad descriptor (len=%d)\n", | |
| 564 | + be32_to_cpu(desc->len)); | |
| 565 | + goto skip; | |
| 566 | + } | |
| 567 | + | |
| 568 | + if (!rxlen) { | |
| 569 | + ar5523_dbg(ar, "RX: rxlen is 0\n"); | |
| 570 | + goto skip; | |
| 571 | + } | |
| 572 | + | |
| 573 | + if (be32_to_cpu(desc->status) != 0) { | |
| 574 | + ar5523_dbg(ar, "Bad RX status (0x%x len = %d). Skip\n", | |
| 575 | + be32_to_cpu(desc->status), be32_to_cpu(desc->len)); | |
| 576 | + goto skip; | |
| 577 | + } | |
| 578 | + | |
| 579 | + skb_reserve(data->skb, sizeof(*chunk)); | |
| 580 | + skb_put(data->skb, rxlen - sizeof(struct ar5523_rx_desc)); | |
| 581 | + | |
| 582 | + hdrlen = ieee80211_get_hdrlen_from_skb(data->skb); | |
| 583 | + if (!IS_ALIGNED(hdrlen, 4)) { | |
| 584 | + ar5523_dbg(ar, "eek, alignment workaround activated\n"); | |
| 585 | + pad = ALIGN(hdrlen, 4) - hdrlen; | |
| 586 | + memmove(data->skb->data + pad, data->skb->data, hdrlen); | |
| 587 | + skb_pull(data->skb, pad); | |
| 588 | + skb_put(data->skb, pad); | |
| 589 | + } | |
| 590 | + | |
| 591 | + rx_status = IEEE80211_SKB_RXCB(data->skb); | |
| 592 | + memset(rx_status, 0, sizeof(*rx_status)); | |
| 593 | + rx_status->freq = be32_to_cpu(desc->channel); | |
| 594 | + rx_status->band = hw->conf.channel->band; | |
| 595 | + rx_status->signal = -95 + be32_to_cpu(desc->rssi); | |
| 596 | + | |
| 597 | + ieee80211_rx_irqsafe(hw, data->skb); | |
| 598 | + data->skb = NULL; | |
| 599 | + | |
| 600 | +skip: | |
| 601 | + if (data->skb) { | |
| 602 | + dev_kfree_skb_irq(data->skb); | |
| 603 | + data->skb = NULL; | |
| 604 | + } | |
| 605 | + | |
| 606 | + ar5523_rx_data_put(ar, data); | |
| 607 | + if (atomic_inc_return(&ar->rx_data_free_cnt) >= | |
| 608 | + AR5523_RX_DATA_REFILL_COUNT && | |
| 609 | + test_bit(AR5523_HW_UP, &ar->flags)) | |
| 610 | + queue_work(ar->wq, &ar->rx_refill_work); | |
| 611 | +} | |
| 612 | + | |
| 613 | +static void ar5523_rx_refill_work(struct work_struct *work) | |
| 614 | +{ | |
| 615 | + struct ar5523 *ar = container_of(work, struct ar5523, rx_refill_work); | |
| 616 | + struct ar5523_rx_data *data; | |
| 617 | + unsigned long flags; | |
| 618 | + int error; | |
| 619 | + | |
| 620 | + ar5523_dbg(ar, "%s\n", __func__); | |
| 621 | + do { | |
| 622 | + spin_lock_irqsave(&ar->rx_data_list_lock, flags); | |
| 623 | + | |
| 624 | + if (!list_empty(&ar->rx_data_free)) | |
| 625 | + data = (struct ar5523_rx_data *) ar->rx_data_free.next; | |
| 626 | + else | |
| 627 | + data = NULL; | |
| 628 | + spin_unlock_irqrestore(&ar->rx_data_list_lock, flags); | |
| 629 | + | |
| 630 | + if (!data) | |
| 631 | + goto done; | |
| 632 | + | |
| 633 | + data->skb = alloc_skb(ar->rxbufsz, GFP_KERNEL); | |
| 634 | + if (!data->skb) { | |
| 635 | + ar5523_err(ar, "could not allocate rx skbuff\n"); | |
| 636 | + return; | |
| 637 | + } | |
| 638 | + | |
| 639 | + usb_fill_bulk_urb(data->urb, ar->dev, | |
| 640 | + ar5523_data_rx_pipe(ar->dev), data->skb->data, | |
| 641 | + ar->rxbufsz, ar5523_data_rx_cb, data); | |
| 642 | + | |
| 643 | + spin_lock_irqsave(&ar->rx_data_list_lock, flags); | |
| 644 | + list_move(&data->list, &ar->rx_data_used); | |
| 645 | + spin_unlock_irqrestore(&ar->rx_data_list_lock, flags); | |
| 646 | + atomic_dec(&ar->rx_data_free_cnt); | |
| 647 | + | |
| 648 | + error = usb_submit_urb(data->urb, GFP_KERNEL); | |
| 649 | + if (error) { | |
| 650 | + kfree_skb(data->skb); | |
| 651 | + if (error != -ENODEV) | |
| 652 | + ar5523_err(ar, "Err sending rx data urb %d\n", | |
| 653 | + error); | |
| 654 | + ar5523_rx_data_put(ar, data); | |
| 655 | + atomic_inc(&ar->rx_data_free_cnt); | |
| 656 | + return; | |
| 657 | + } | |
| 658 | + | |
| 659 | + } while (true); | |
| 660 | +done: | |
| 661 | + return; | |
| 662 | +} | |
| 663 | + | |
| 664 | +static void ar5523_cancel_rx_bufs(struct ar5523 *ar) | |
| 665 | +{ | |
| 666 | + struct ar5523_rx_data *data; | |
| 667 | + unsigned long flags; | |
| 668 | + | |
| 669 | + do { | |
| 670 | + spin_lock_irqsave(&ar->rx_data_list_lock, flags); | |
| 671 | + if (!list_empty(&ar->rx_data_used)) | |
| 672 | + data = (struct ar5523_rx_data *) ar->rx_data_used.next; | |
| 673 | + else | |
| 674 | + data = NULL; | |
| 675 | + spin_unlock_irqrestore(&ar->rx_data_list_lock, flags); | |
| 676 | + | |
| 677 | + if (!data) | |
| 678 | + break; | |
| 679 | + | |
| 680 | + usb_kill_urb(data->urb); | |
| 681 | + list_move(&data->list, &ar->rx_data_free); | |
| 682 | + atomic_inc(&ar->rx_data_free_cnt); | |
| 683 | + } while (data); | |
| 684 | +} | |
| 685 | + | |
| 686 | +static void ar5523_free_rx_bufs(struct ar5523 *ar) | |
| 687 | +{ | |
| 688 | + struct ar5523_rx_data *data; | |
| 689 | + | |
| 690 | + ar5523_cancel_rx_bufs(ar); | |
| 691 | + while (!list_empty(&ar->rx_data_free)) { | |
| 692 | + data = (struct ar5523_rx_data *) ar->rx_data_free.next; | |
| 693 | + list_del(&data->list); | |
| 694 | + usb_free_urb(data->urb); | |
| 695 | + } | |
| 696 | +} | |
| 697 | + | |
| 698 | +static int ar5523_alloc_rx_bufs(struct ar5523 *ar) | |
| 699 | +{ | |
| 700 | + int i; | |
| 701 | + | |
| 702 | + for (i = 0; i < AR5523_RX_DATA_COUNT; i++) { | |
| 703 | + struct ar5523_rx_data *data = &ar->rx_data[i]; | |
| 704 | + | |
| 705 | + data->ar = ar; | |
| 706 | + data->urb = usb_alloc_urb(0, GFP_KERNEL); | |
| 707 | + if (!data->urb) { | |
| 708 | + ar5523_err(ar, "could not allocate rx data urb\n"); | |
| 709 | + goto err; | |
| 710 | + } | |
| 711 | + list_add_tail(&data->list, &ar->rx_data_free); | |
| 712 | + atomic_inc(&ar->rx_data_free_cnt); | |
| 713 | + } | |
| 714 | + return 0; | |
| 715 | + | |
| 716 | +err: | |
| 717 | + ar5523_free_rx_bufs(ar); | |
| 718 | + return -ENOMEM; | |
| 719 | +} | |
| 720 | + | |
| 721 | +static void ar5523_data_tx_pkt_put(struct ar5523 *ar) | |
| 722 | +{ | |
| 723 | + atomic_dec(&ar->tx_nr_total); | |
| 724 | + if (!atomic_dec_return(&ar->tx_nr_pending)) { | |
| 725 | + del_timer(&ar->tx_wd_timer); | |
| 726 | + wake_up(&ar->tx_flush_waitq); | |
| 727 | + } | |
| 728 | + | |
| 729 | + if (atomic_read(&ar->tx_nr_total) < AR5523_TX_DATA_RESTART_COUNT) { | |
| 730 | + ar5523_dbg(ar, "restart tx queue\n"); | |
| 731 | + ieee80211_wake_queues(ar->hw); | |
| 732 | + } | |
| 733 | +} | |
| 734 | + | |
| 735 | +static void ar5523_data_tx_cb(struct urb *urb) | |
| 736 | +{ | |
| 737 | + struct sk_buff *skb = urb->context; | |
| 738 | + struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb); | |
| 739 | + struct ar5523_tx_data *data = (struct ar5523_tx_data *) | |
| 740 | + txi->driver_data; | |
| 741 | + struct ar5523 *ar = data->ar; | |
| 742 | + unsigned long flags; | |
| 743 | + | |
| 744 | + ar5523_dbg(ar, "data tx urb completed: %d\n", urb->status); | |
| 745 | + | |
| 746 | + spin_lock_irqsave(&ar->tx_data_list_lock, flags); | |
| 747 | + list_del(&data->list); | |
| 748 | + spin_unlock_irqrestore(&ar->tx_data_list_lock, flags); | |
| 749 | + | |
| 750 | + if (urb->status) { | |
| 751 | + ar5523_dbg(ar, "%s: urb status: %d\n", __func__, urb->status); | |
| 752 | + ar5523_data_tx_pkt_put(ar); | |
| 753 | + ieee80211_free_txskb(ar->hw, skb); | |
| 754 | + } else { | |
| 755 | + skb_pull(skb, sizeof(struct ar5523_tx_desc) + sizeof(__be32)); | |
| 756 | + ieee80211_tx_status_irqsafe(ar->hw, skb); | |
| 757 | + } | |
| 758 | + usb_free_urb(urb); | |
| 759 | +} | |
| 760 | + | |
| 761 | +static void ar5523_tx(struct ieee80211_hw *hw, | |
| 762 | + struct ieee80211_tx_control *control, | |
| 763 | + struct sk_buff *skb) | |
| 764 | +{ | |
| 765 | + struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb); | |
| 766 | + struct ar5523_tx_data *data = (struct ar5523_tx_data *) | |
| 767 | + txi->driver_data; | |
| 768 | + struct ar5523 *ar = hw->priv; | |
| 769 | + unsigned long flags; | |
| 770 | + | |
| 771 | + ar5523_dbg(ar, "tx called\n"); | |
| 772 | + if (atomic_inc_return(&ar->tx_nr_total) >= AR5523_TX_DATA_COUNT) { | |
| 773 | + ar5523_dbg(ar, "tx queue full\n"); | |
| 774 | + ar5523_dbg(ar, "stop queues (tot %d pend %d)\n", | |
| 775 | + atomic_read(&ar->tx_nr_total), | |
| 776 | + atomic_read(&ar->tx_nr_pending)); | |
| 777 | + ieee80211_stop_queues(hw); | |
| 778 | + } | |
| 779 | + | |
| 780 | + data->skb = skb; | |
| 781 | + | |
| 782 | + spin_lock_irqsave(&ar->tx_data_list_lock, flags); | |
| 783 | + list_add_tail(&data->list, &ar->tx_queue_pending); | |
| 784 | + spin_unlock_irqrestore(&ar->tx_data_list_lock, flags); | |
| 785 | + | |
| 786 | + ieee80211_queue_work(ar->hw, &ar->tx_work); | |
| 787 | +} | |
| 788 | + | |
| 789 | +static void ar5523_tx_work_locked(struct ar5523 *ar) | |
| 790 | +{ | |
| 791 | + struct ar5523_tx_data *data; | |
| 792 | + struct ar5523_tx_desc *desc; | |
| 793 | + struct ar5523_chunk *chunk; | |
| 794 | + struct ieee80211_tx_info *txi; | |
| 795 | + struct urb *urb; | |
| 796 | + struct sk_buff *skb; | |
| 797 | + int error = 0, paylen; | |
| 798 | + u32 txqid; | |
| 799 | + unsigned long flags; | |
| 800 | + | |
| 801 | + BUILD_BUG_ON(sizeof(struct ar5523_tx_data) > | |
| 802 | + IEEE80211_TX_INFO_DRIVER_DATA_SIZE); | |
| 803 | + | |
| 804 | + ar5523_dbg(ar, "%s\n", __func__); | |
| 805 | + do { | |
| 806 | + spin_lock_irqsave(&ar->tx_data_list_lock, flags); | |
| 807 | + if (!list_empty(&ar->tx_queue_pending)) { | |
| 808 | + data = (struct ar5523_tx_data *) | |
| 809 | + ar->tx_queue_pending.next; | |
| 810 | + list_del(&data->list); | |
| 811 | + } else | |
| 812 | + data = NULL; | |
| 813 | + spin_unlock_irqrestore(&ar->tx_data_list_lock, flags); | |
| 814 | + | |
| 815 | + if (!data) | |
| 816 | + break; | |
| 817 | + | |
| 818 | + skb = data->skb; | |
| 819 | + txqid = 0; | |
| 820 | + txi = IEEE80211_SKB_CB(skb); | |
| 821 | + paylen = skb->len; | |
| 822 | + urb = usb_alloc_urb(0, GFP_KERNEL); | |
| 823 | + if (!urb) { | |
| 824 | + ar5523_err(ar, "Failed to allocate TX urb\n"); | |
| 825 | + ieee80211_free_txskb(ar->hw, skb); | |
| 826 | + continue; | |
| 827 | + } | |
| 828 | + | |
| 829 | + data->ar = ar; | |
| 830 | + data->urb = urb; | |
| 831 | + | |
| 832 | + desc = (struct ar5523_tx_desc *)skb_push(skb, sizeof(*desc)); | |
| 833 | + chunk = (struct ar5523_chunk *)skb_push(skb, sizeof(*chunk)); | |
| 834 | + | |
| 835 | + chunk->seqnum = 0; | |
| 836 | + chunk->flags = UATH_CFLAGS_FINAL; | |
| 837 | + chunk->length = cpu_to_be16(skb->len); | |
| 838 | + | |
| 839 | + desc->msglen = cpu_to_be32(skb->len); | |
| 840 | + desc->msgid = AR5523_DATA_ID; | |
| 841 | + desc->buflen = cpu_to_be32(paylen); | |
| 842 | + desc->type = cpu_to_be32(WDCMSG_SEND); | |
| 843 | + desc->flags = cpu_to_be32(UATH_TX_NOTIFY); | |
| 844 | + | |
| 845 | + if (test_bit(AR5523_CONNECTED, &ar->flags)) | |
| 846 | + desc->connid = cpu_to_be32(AR5523_ID_BSS); | |
| 847 | + else | |
| 848 | + desc->connid = cpu_to_be32(AR5523_ID_BROADCAST); | |
| 849 | + | |
| 850 | + if (txi->flags & IEEE80211_TX_CTL_USE_MINRATE) | |
| 851 | + txqid |= UATH_TXQID_MINRATE; | |
| 852 | + | |
| 853 | + desc->txqid = cpu_to_be32(txqid); | |
| 854 | + | |
| 855 | + urb->transfer_flags = URB_ZERO_PACKET; | |
| 856 | + usb_fill_bulk_urb(urb, ar->dev, ar5523_data_tx_pipe(ar->dev), | |
| 857 | + skb->data, skb->len, ar5523_data_tx_cb, skb); | |
| 858 | + | |
| 859 | + spin_lock_irqsave(&ar->tx_data_list_lock, flags); | |
| 860 | + list_add_tail(&data->list, &ar->tx_queue_submitted); | |
| 861 | + spin_unlock_irqrestore(&ar->tx_data_list_lock, flags); | |
| 862 | + mod_timer(&ar->tx_wd_timer, jiffies + AR5523_TX_WD_TIMEOUT); | |
| 863 | + atomic_inc(&ar->tx_nr_pending); | |
| 864 | + | |
| 865 | + ar5523_dbg(ar, "TX Frame (%d pending)\n", | |
| 866 | + atomic_read(&ar->tx_nr_pending)); | |
| 867 | + error = usb_submit_urb(urb, GFP_KERNEL); | |
| 868 | + if (error) { | |
| 869 | + ar5523_err(ar, "error %d when submitting tx urb\n", | |
| 870 | + error); | |
| 871 | + spin_lock_irqsave(&ar->tx_data_list_lock, flags); | |
| 872 | + list_del(&data->list); | |
| 873 | + spin_unlock_irqrestore(&ar->tx_data_list_lock, flags); | |
| 874 | + atomic_dec(&ar->tx_nr_pending); | |
| 875 | + ar5523_data_tx_pkt_put(ar); | |
| 876 | + usb_free_urb(urb); | |
| 877 | + ieee80211_free_txskb(ar->hw, skb); | |
| 878 | + } | |
| 879 | + } while (true); | |
| 880 | +} | |
| 881 | + | |
| 882 | +static void ar5523_tx_work(struct work_struct *work) | |
| 883 | +{ | |
| 884 | + struct ar5523 *ar = container_of(work, struct ar5523, tx_work); | |
| 885 | + | |
| 886 | + ar5523_dbg(ar, "%s\n", __func__); | |
| 887 | + mutex_lock(&ar->mutex); | |
| 888 | + ar5523_tx_work_locked(ar); | |
| 889 | + mutex_unlock(&ar->mutex); | |
| 890 | +} | |
| 891 | + | |
| 892 | +static void ar5523_tx_wd_timer(unsigned long arg) | |
| 893 | +{ | |
| 894 | + struct ar5523 *ar = (struct ar5523 *) arg; | |
| 895 | + | |
| 896 | + ar5523_dbg(ar, "TX watchdog timer triggered\n"); | |
| 897 | + ieee80211_queue_work(ar->hw, &ar->tx_wd_work); | |
| 898 | +} | |
| 899 | + | |
| 900 | +static void ar5523_tx_wd_work(struct work_struct *work) | |
| 901 | +{ | |
| 902 | + struct ar5523 *ar = container_of(work, struct ar5523, tx_wd_work); | |
| 903 | + | |
| 904 | + /* Occasionally the TX queues stop responding. The only way to | |
| 905 | + * recover seems to be to reset the dongle. | |
| 906 | + */ | |
| 907 | + | |
| 908 | + mutex_lock(&ar->mutex); | |
| 909 | + ar5523_err(ar, "TX queue stuck (tot %d pend %d)\n", | |
| 910 | + atomic_read(&ar->tx_nr_total), | |
| 911 | + atomic_read(&ar->tx_nr_pending)); | |
| 912 | + | |
| 913 | + ar5523_err(ar, "Will restart dongle.\n"); | |
| 914 | + ar5523_cmd_write(ar, WDCMSG_TARGET_RESET, NULL, 0, 0); | |
| 915 | + mutex_unlock(&ar->mutex); | |
| 916 | +} | |
| 917 | + | |
| 918 | +static void ar5523_flush_tx(struct ar5523 *ar) | |
| 919 | +{ | |
| 920 | + ar5523_tx_work_locked(ar); | |
| 921 | + | |
| 922 | + /* Don't waste time trying to flush if USB is disconnected */ | |
| 923 | + if (test_bit(AR5523_USB_DISCONNECTED, &ar->flags)) | |
| 924 | + return; | |
| 925 | + if (!wait_event_timeout(ar->tx_flush_waitq, | |
| 926 | + !atomic_read(&ar->tx_nr_pending), AR5523_FLUSH_TIMEOUT)) | |
| 927 | + ar5523_err(ar, "flush timeout (tot %d pend %d)\n", | |
| 928 | + atomic_read(&ar->tx_nr_total), | |
| 929 | + atomic_read(&ar->tx_nr_pending)); | |
| 930 | +} | |
| 931 | + | |
| 932 | +static void ar5523_free_tx_cmd(struct ar5523 *ar) | |
| 933 | +{ | |
| 934 | + struct ar5523_tx_cmd *cmd = &ar->tx_cmd; | |
| 935 | + | |
| 936 | + usb_free_coherent(ar->dev, AR5523_MAX_RXCMDSZ, cmd->buf_tx, | |
| 937 | + cmd->urb_tx->transfer_dma); | |
| 938 | + usb_free_urb(cmd->urb_tx); | |
| 939 | +} | |
| 940 | + | |
| 941 | +static int ar5523_alloc_tx_cmd(struct ar5523 *ar) | |
| 942 | +{ | |
| 943 | + struct ar5523_tx_cmd *cmd = &ar->tx_cmd; | |
| 944 | + | |
| 945 | + cmd->ar = ar; | |
| 946 | + init_completion(&cmd->done); | |
| 947 | + | |
| 948 | + cmd->urb_tx = usb_alloc_urb(0, GFP_KERNEL); | |
| 949 | + if (!cmd->urb_tx) { | |
| 950 | + ar5523_err(ar, "could not allocate urb\n"); | |
| 951 | + return -ENOMEM; | |
| 952 | + } | |
| 953 | + cmd->buf_tx = usb_alloc_coherent(ar->dev, AR5523_MAX_TXCMDSZ, | |
| 954 | + GFP_KERNEL, | |
| 955 | + &cmd->urb_tx->transfer_dma); | |
| 956 | + if (!cmd->buf_tx) { | |
| 957 | + usb_free_urb(cmd->urb_tx); | |
| 958 | + return -ENOMEM; | |
| 959 | + } | |
| 960 | + return 0; | |
| 961 | +} | |
| 962 | + | |
| 963 | +/* | |
| 964 | + * This function is called periodically (every second) when associated to | |
| 965 | + * query device statistics. | |
| 966 | + */ | |
| 967 | +static void ar5523_stat_work(struct work_struct *work) | |
| 968 | +{ | |
| 969 | + struct ar5523 *ar = container_of(work, struct ar5523, stat_work.work); | |
| 970 | + int error; | |
| 971 | + | |
| 972 | + ar5523_dbg(ar, "%s\n", __func__); | |
| 973 | + mutex_lock(&ar->mutex); | |
| 974 | + | |
| 975 | + /* | |
| 976 | + * Send request for statistics asynchronously once a second. This | |
| 977 | + * seems to be important. Throughput is a lot better if this is done. | |
| 978 | + */ | |
| 979 | + error = ar5523_cmd_write(ar, WDCMSG_TARGET_GET_STATS, NULL, 0, 0); | |
| 980 | + if (error) | |
| 981 | + ar5523_err(ar, "could not query stats, error %d\n", error); | |
| 982 | + mutex_unlock(&ar->mutex); | |
| 983 | + ieee80211_queue_delayed_work(ar->hw, &ar->stat_work, HZ); | |
| 984 | +} | |
| 985 | + | |
| 986 | +/* | |
| 987 | + * Interface routines to the mac80211 stack. | |
| 988 | + */ | |
| 989 | +static int ar5523_start(struct ieee80211_hw *hw) | |
| 990 | +{ | |
| 991 | + struct ar5523 *ar = hw->priv; | |
| 992 | + int error; | |
| 993 | + __be32 val; | |
| 994 | + | |
| 995 | + ar5523_dbg(ar, "start called\n"); | |
| 996 | + | |
| 997 | + mutex_lock(&ar->mutex); | |
| 998 | + val = cpu_to_be32(0); | |
| 999 | + ar5523_cmd_write(ar, WDCMSG_BIND, &val, sizeof(val), 0); | |
| 1000 | + | |
| 1001 | + /* set MAC address */ | |
| 1002 | + ar5523_config_multi(ar, CFG_MAC_ADDR, &ar->hw->wiphy->perm_addr, | |
| 1003 | + ETH_ALEN); | |
| 1004 | + | |
| 1005 | + /* XXX honor net80211 state */ | |
| 1006 | + ar5523_config(ar, CFG_RATE_CONTROL_ENABLE, 0x00000001); | |
| 1007 | + ar5523_config(ar, CFG_DIVERSITY_CTL, 0x00000001); | |
| 1008 | + ar5523_config(ar, CFG_ABOLT, 0x0000003f); | |
| 1009 | + ar5523_config(ar, CFG_WME_ENABLED, 0x00000000); | |
| 1010 | + | |
| 1011 | + ar5523_config(ar, CFG_SERVICE_TYPE, 1); | |
| 1012 | + ar5523_config(ar, CFG_TP_SCALE, 0x00000000); | |
| 1013 | + ar5523_config(ar, CFG_TPC_HALF_DBM5, 0x0000003c); | |
| 1014 | + ar5523_config(ar, CFG_TPC_HALF_DBM2, 0x0000003c); | |
| 1015 | + ar5523_config(ar, CFG_OVERRD_TX_POWER, 0x00000000); | |
| 1016 | + ar5523_config(ar, CFG_GMODE_PROTECTION, 0x00000000); | |
| 1017 | + ar5523_config(ar, CFG_GMODE_PROTECT_RATE_INDEX, 0x00000003); | |
| 1018 | + ar5523_config(ar, CFG_PROTECTION_TYPE, 0x00000000); | |
| 1019 | + ar5523_config(ar, CFG_MODE_CTS, 0x00000002); | |
| 1020 | + | |
| 1021 | + error = ar5523_cmd_read(ar, WDCMSG_TARGET_START, NULL, 0, | |
| 1022 | + &val, sizeof(val), AR5523_CMD_FLAG_MAGIC); | |
| 1023 | + if (error) { | |
| 1024 | + ar5523_dbg(ar, "could not start target, error %d\n", error); | |
| 1025 | + goto err; | |
| 1026 | + } | |
| 1027 | + ar5523_dbg(ar, "WDCMSG_TARGET_START returns handle: 0x%x\n", | |
| 1028 | + be32_to_cpu(val)); | |
| 1029 | + | |
| 1030 | + ar5523_switch_chan(ar); | |
| 1031 | + | |
| 1032 | + val = cpu_to_be32(TARGET_DEVICE_AWAKE); | |
| 1033 | + ar5523_cmd_write(ar, WDCMSG_SET_PWR_MODE, &val, sizeof(val), 0); | |
| 1034 | + /* XXX? check */ | |
| 1035 | + ar5523_cmd_write(ar, WDCMSG_RESET_KEY_CACHE, NULL, 0, 0); | |
| 1036 | + | |
| 1037 | + set_bit(AR5523_HW_UP, &ar->flags); | |
| 1038 | + queue_work(ar->wq, &ar->rx_refill_work); | |
| 1039 | + | |
| 1040 | + /* enable Rx */ | |
| 1041 | + ar5523_set_rxfilter(ar, 0, UATH_FILTER_OP_INIT); | |
| 1042 | + ar5523_set_rxfilter(ar, | |
| 1043 | + UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST | | |
| 1044 | + UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON, | |
| 1045 | + UATH_FILTER_OP_SET); | |
| 1046 | + | |
| 1047 | + ar5523_set_ledsteady(ar, UATH_LED_ACTIVITY, UATH_LED_ON); | |
| 1048 | + ar5523_dbg(ar, "start OK\n"); | |
| 1049 | + | |
| 1050 | +err: | |
| 1051 | + mutex_unlock(&ar->mutex); | |
| 1052 | + return error; | |
| 1053 | +} | |
| 1054 | + | |
| 1055 | +static void ar5523_stop(struct ieee80211_hw *hw) | |
| 1056 | +{ | |
| 1057 | + struct ar5523 *ar = hw->priv; | |
| 1058 | + | |
| 1059 | + ar5523_dbg(ar, "stop called\n"); | |
| 1060 | + | |
| 1061 | + cancel_delayed_work_sync(&ar->stat_work); | |
| 1062 | + mutex_lock(&ar->mutex); | |
| 1063 | + clear_bit(AR5523_HW_UP, &ar->flags); | |
| 1064 | + | |
| 1065 | + ar5523_set_ledsteady(ar, UATH_LED_LINK, UATH_LED_OFF); | |
| 1066 | + ar5523_set_ledsteady(ar, UATH_LED_ACTIVITY, UATH_LED_OFF); | |
| 1067 | + | |
| 1068 | + ar5523_cmd_write(ar, WDCMSG_TARGET_STOP, NULL, 0, 0); | |
| 1069 | + | |
| 1070 | + del_timer_sync(&ar->tx_wd_timer); | |
| 1071 | + cancel_work_sync(&ar->tx_wd_work); | |
| 1072 | + cancel_work_sync(&ar->rx_refill_work); | |
| 1073 | + ar5523_cancel_rx_bufs(ar); | |
| 1074 | + mutex_unlock(&ar->mutex); | |
| 1075 | +} | |
| 1076 | + | |
| 1077 | +static int ar5523_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | |
| 1078 | +{ | |
| 1079 | + struct ar5523 *ar = hw->priv; | |
| 1080 | + int ret; | |
| 1081 | + | |
| 1082 | + ar5523_dbg(ar, "set_rts_threshold called\n"); | |
| 1083 | + mutex_lock(&ar->mutex); | |
| 1084 | + | |
| 1085 | + ret = ar5523_config(ar, CFG_USER_RTS_THRESHOLD, value); | |
| 1086 | + | |
| 1087 | + mutex_unlock(&ar->mutex); | |
| 1088 | + return ret; | |
| 1089 | +} | |
| 1090 | + | |
| 1091 | +static void ar5523_flush(struct ieee80211_hw *hw, bool drop) | |
| 1092 | +{ | |
| 1093 | + struct ar5523 *ar = hw->priv; | |
| 1094 | + | |
| 1095 | + ar5523_dbg(ar, "flush called\n"); | |
| 1096 | + ar5523_flush_tx(ar); | |
| 1097 | +} | |
| 1098 | + | |
| 1099 | +static int ar5523_add_interface(struct ieee80211_hw *hw, | |
| 1100 | + struct ieee80211_vif *vif) | |
| 1101 | +{ | |
| 1102 | + struct ar5523 *ar = hw->priv; | |
| 1103 | + | |
| 1104 | + ar5523_dbg(ar, "add interface called\n"); | |
| 1105 | + | |
| 1106 | + if (ar->vif) { | |
| 1107 | + ar5523_dbg(ar, "invalid add_interface\n"); | |
| 1108 | + return -EOPNOTSUPP; | |
| 1109 | + } | |
| 1110 | + | |
| 1111 | + switch (vif->type) { | |
| 1112 | + case NL80211_IFTYPE_STATION: | |
| 1113 | + ar->vif = vif; | |
| 1114 | + break; | |
| 1115 | + default: | |
| 1116 | + return -EOPNOTSUPP; | |
| 1117 | + } | |
| 1118 | + return 0; | |
| 1119 | +} | |
| 1120 | + | |
| 1121 | +static void ar5523_remove_interface(struct ieee80211_hw *hw, | |
| 1122 | + struct ieee80211_vif *vif) | |
| 1123 | +{ | |
| 1124 | + struct ar5523 *ar = hw->priv; | |
| 1125 | + | |
| 1126 | + ar5523_dbg(ar, "remove interface called\n"); | |
| 1127 | + ar->vif = NULL; | |
| 1128 | +} | |
| 1129 | + | |
| 1130 | +static int ar5523_hwconfig(struct ieee80211_hw *hw, u32 changed) | |
| 1131 | +{ | |
| 1132 | + struct ar5523 *ar = hw->priv; | |
| 1133 | + | |
| 1134 | + ar5523_dbg(ar, "config called\n"); | |
| 1135 | + mutex_lock(&ar->mutex); | |
| 1136 | + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | |
| 1137 | + ar5523_dbg(ar, "Do channel switch\n"); | |
| 1138 | + ar5523_flush_tx(ar); | |
| 1139 | + ar5523_switch_chan(ar); | |
| 1140 | + } | |
| 1141 | + mutex_unlock(&ar->mutex); | |
| 1142 | + return 0; | |
| 1143 | +} | |
| 1144 | + | |
| 1145 | +static int ar5523_get_wlan_mode(struct ar5523 *ar, | |
| 1146 | + struct ieee80211_bss_conf *bss_conf) | |
| 1147 | +{ | |
| 1148 | + struct ieee80211_supported_band *band; | |
| 1149 | + int bit; | |
| 1150 | + struct ieee80211_sta *sta; | |
| 1151 | + u32 sta_rate_set; | |
| 1152 | + | |
| 1153 | + band = ar->hw->wiphy->bands[ar->hw->conf.channel->band]; | |
| 1154 | + sta = ieee80211_find_sta(ar->vif, bss_conf->bssid); | |
| 1155 | + if (!sta) { | |
| 1156 | + ar5523_info(ar, "STA not found!\n"); | |
| 1157 | + return WLAN_MODE_11b; | |
| 1158 | + } | |
| 1159 | + sta_rate_set = sta->supp_rates[ar->hw->conf.channel->band]; | |
| 1160 | + | |
| 1161 | + for (bit = 0; bit < band->n_bitrates; bit++) { | |
| 1162 | + if (sta_rate_set & 1) { | |
| 1163 | + int rate = band->bitrates[bit].bitrate; | |
| 1164 | + switch (rate) { | |
| 1165 | + case 60: | |
| 1166 | + case 90: | |
| 1167 | + case 120: | |
| 1168 | + case 180: | |
| 1169 | + case 240: | |
| 1170 | + case 360: | |
| 1171 | + case 480: | |
| 1172 | + case 540: | |
| 1173 | + return WLAN_MODE_11g; | |
| 1174 | + } | |
| 1175 | + } | |
| 1176 | + sta_rate_set >>= 1; | |
| 1177 | + } | |
| 1178 | + return WLAN_MODE_11b; | |
| 1179 | +} | |
| 1180 | + | |
| 1181 | +static void ar5523_create_rateset(struct ar5523 *ar, | |
| 1182 | + struct ieee80211_bss_conf *bss_conf, | |
| 1183 | + struct ar5523_cmd_rateset *rs, | |
| 1184 | + bool basic) | |
| 1185 | +{ | |
| 1186 | + struct ieee80211_supported_band *band; | |
| 1187 | + struct ieee80211_sta *sta; | |
| 1188 | + int bit, i = 0; | |
| 1189 | + u32 sta_rate_set, basic_rate_set; | |
| 1190 | + | |
| 1191 | + sta = ieee80211_find_sta(ar->vif, bss_conf->bssid); | |
| 1192 | + basic_rate_set = bss_conf->basic_rates; | |
| 1193 | + if (!sta) { | |
| 1194 | + ar5523_info(ar, "STA not found. Cannot set rates\n"); | |
| 1195 | + sta_rate_set = bss_conf->basic_rates; | |
| 1196 | + } | |
| 1197 | + sta_rate_set = sta->supp_rates[ar->hw->conf.channel->band]; | |
| 1198 | + | |
| 1199 | + ar5523_dbg(ar, "sta rate_set = %08x\n", sta_rate_set); | |
| 1200 | + | |
| 1201 | + band = ar->hw->wiphy->bands[ar->hw->conf.channel->band]; | |
| 1202 | + for (bit = 0; bit < band->n_bitrates; bit++) { | |
| 1203 | + BUG_ON(i >= AR5523_MAX_NRATES); | |
| 1204 | + ar5523_dbg(ar, "Considering rate %d : %d\n", | |
| 1205 | + band->bitrates[bit].hw_value, sta_rate_set & 1); | |
| 1206 | + if (sta_rate_set & 1) { | |
| 1207 | + rs->set[i] = band->bitrates[bit].hw_value; | |
| 1208 | + if (basic_rate_set & 1 && basic) | |
| 1209 | + rs->set[i] |= 0x80; | |
| 1210 | + i++; | |
| 1211 | + } | |
| 1212 | + sta_rate_set >>= 1; | |
| 1213 | + basic_rate_set >>= 1; | |
| 1214 | + } | |
| 1215 | + | |
| 1216 | + rs->length = i; | |
| 1217 | +} | |
| 1218 | + | |
| 1219 | +static int ar5523_set_basic_rates(struct ar5523 *ar, | |
| 1220 | + struct ieee80211_bss_conf *bss) | |
| 1221 | +{ | |
| 1222 | + struct ar5523_cmd_rates rates; | |
| 1223 | + | |
| 1224 | + memset(&rates, 0, sizeof(rates)); | |
| 1225 | + rates.connid = cpu_to_be32(2); /* XXX */ | |
| 1226 | + rates.size = cpu_to_be32(sizeof(struct ar5523_cmd_rateset)); | |
| 1227 | + ar5523_create_rateset(ar, bss, &rates.rateset, true); | |
| 1228 | + | |
| 1229 | + return ar5523_cmd_write(ar, WDCMSG_SET_BASIC_RATE, &rates, | |
| 1230 | + sizeof(rates), 0); | |
| 1231 | +} | |
| 1232 | + | |
| 1233 | +static int ar5523_create_connection(struct ar5523 *ar, | |
| 1234 | + struct ieee80211_vif *vif, | |
| 1235 | + struct ieee80211_bss_conf *bss) | |
| 1236 | +{ | |
| 1237 | + struct ar5523_cmd_create_connection create; | |
| 1238 | + int wlan_mode; | |
| 1239 | + | |
| 1240 | + memset(&create, 0, sizeof(create)); | |
| 1241 | + create.connid = cpu_to_be32(2); | |
| 1242 | + create.bssid = cpu_to_be32(0); | |
| 1243 | + /* XXX packed or not? */ | |
| 1244 | + create.size = cpu_to_be32(sizeof(struct ar5523_cmd_rateset)); | |
| 1245 | + | |
| 1246 | + ar5523_create_rateset(ar, bss, &create.connattr.rateset, false); | |
| 1247 | + | |
| 1248 | + wlan_mode = ar5523_get_wlan_mode(ar, bss); | |
| 1249 | + create.connattr.wlanmode = cpu_to_be32(wlan_mode); | |
| 1250 | + | |
| 1251 | + return ar5523_cmd_write(ar, WDCMSG_CREATE_CONNECTION, &create, | |
| 1252 | + sizeof(create), 0); | |
| 1253 | +} | |
| 1254 | + | |
| 1255 | +static int ar5523_write_associd(struct ar5523 *ar, | |
| 1256 | + struct ieee80211_bss_conf *bss) | |
| 1257 | +{ | |
| 1258 | + struct ar5523_cmd_set_associd associd; | |
| 1259 | + | |
| 1260 | + memset(&associd, 0, sizeof(associd)); | |
| 1261 | + associd.defaultrateix = cpu_to_be32(0); /* XXX */ | |
| 1262 | + associd.associd = cpu_to_be32(bss->aid); | |
| 1263 | + associd.timoffset = cpu_to_be32(0x3b); /* XXX */ | |
| 1264 | + memcpy(associd.bssid, bss->bssid, ETH_ALEN); | |
| 1265 | + return ar5523_cmd_write(ar, WDCMSG_WRITE_ASSOCID, &associd, | |
| 1266 | + sizeof(associd), 0); | |
| 1267 | +} | |
| 1268 | + | |
| 1269 | +static void ar5523_bss_info_changed(struct ieee80211_hw *hw, | |
| 1270 | + struct ieee80211_vif *vif, | |
| 1271 | + struct ieee80211_bss_conf *bss, | |
| 1272 | + u32 changed) | |
| 1273 | +{ | |
| 1274 | + struct ar5523 *ar = hw->priv; | |
| 1275 | + int error; | |
| 1276 | + | |
| 1277 | + ar5523_dbg(ar, "bss_info_changed called\n"); | |
| 1278 | + mutex_lock(&ar->mutex); | |
| 1279 | + | |
| 1280 | + if (!(changed & BSS_CHANGED_ASSOC)) | |
| 1281 | + goto out_unlock; | |
| 1282 | + | |
| 1283 | + if (bss->assoc) { | |
| 1284 | + error = ar5523_create_connection(ar, vif, bss); | |
| 1285 | + if (error) { | |
| 1286 | + ar5523_err(ar, "could not create connection\n"); | |
| 1287 | + goto out_unlock; | |
| 1288 | + } | |
| 1289 | + | |
| 1290 | + error = ar5523_set_basic_rates(ar, bss); | |
| 1291 | + if (error) { | |
| 1292 | + ar5523_err(ar, "could not set negotiated rate set\n"); | |
| 1293 | + goto out_unlock; | |
| 1294 | + } | |
| 1295 | + | |
| 1296 | + error = ar5523_write_associd(ar, bss); | |
| 1297 | + if (error) { | |
| 1298 | + ar5523_err(ar, "could not set association\n"); | |
| 1299 | + goto out_unlock; | |
| 1300 | + } | |
| 1301 | + | |
| 1302 | + /* turn link LED on */ | |
| 1303 | + ar5523_set_ledsteady(ar, UATH_LED_LINK, UATH_LED_ON); | |
| 1304 | + set_bit(AR5523_CONNECTED, &ar->flags); | |
| 1305 | + ieee80211_queue_delayed_work(hw, &ar->stat_work, HZ); | |
| 1306 | + | |
| 1307 | + } else { | |
| 1308 | + cancel_delayed_work(&ar->stat_work); | |
| 1309 | + clear_bit(AR5523_CONNECTED, &ar->flags); | |
| 1310 | + ar5523_set_ledsteady(ar, UATH_LED_LINK, UATH_LED_OFF); | |
| 1311 | + } | |
| 1312 | + | |
| 1313 | +out_unlock: | |
| 1314 | + mutex_unlock(&ar->mutex); | |
| 1315 | + | |
| 1316 | +} | |
| 1317 | + | |
| 1318 | +#define AR5523_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \ | |
| 1319 | + FIF_ALLMULTI | \ | |
| 1320 | + FIF_FCSFAIL | \ | |
| 1321 | + FIF_OTHER_BSS) | |
| 1322 | + | |
| 1323 | +static void ar5523_configure_filter(struct ieee80211_hw *hw, | |
| 1324 | + unsigned int changed_flags, | |
| 1325 | + unsigned int *total_flags, | |
| 1326 | + u64 multicast) | |
| 1327 | +{ | |
| 1328 | + struct ar5523 *ar = hw->priv; | |
| 1329 | + u32 filter = 0; | |
| 1330 | + | |
| 1331 | + ar5523_dbg(ar, "configure_filter called\n"); | |
| 1332 | + mutex_lock(&ar->mutex); | |
| 1333 | + ar5523_flush_tx(ar); | |
| 1334 | + | |
| 1335 | + *total_flags &= AR5523_SUPPORTED_FILTERS; | |
| 1336 | + | |
| 1337 | + /* The filters seems strange. UATH_FILTER_RX_BCAST and | |
| 1338 | + * UATH_FILTER_RX_MCAST does not result in those frames being RXed. | |
| 1339 | + * The only way I have found to get [mb]cast frames seems to be | |
| 1340 | + * to set UATH_FILTER_RX_PROM. */ | |
| 1341 | + filter |= UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST | | |
| 1342 | + UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON | | |
| 1343 | + UATH_FILTER_RX_PROM; | |
| 1344 | + | |
| 1345 | + ar5523_set_rxfilter(ar, 0, UATH_FILTER_OP_INIT); | |
| 1346 | + ar5523_set_rxfilter(ar, filter, UATH_FILTER_OP_SET); | |
| 1347 | + | |
| 1348 | + mutex_unlock(&ar->mutex); | |
| 1349 | +} | |
| 1350 | + | |
| 1351 | +static const struct ieee80211_ops ar5523_ops = { | |
| 1352 | + .start = ar5523_start, | |
| 1353 | + .stop = ar5523_stop, | |
| 1354 | + .tx = ar5523_tx, | |
| 1355 | + .set_rts_threshold = ar5523_set_rts_threshold, | |
| 1356 | + .add_interface = ar5523_add_interface, | |
| 1357 | + .remove_interface = ar5523_remove_interface, | |
| 1358 | + .config = ar5523_hwconfig, | |
| 1359 | + .bss_info_changed = ar5523_bss_info_changed, | |
| 1360 | + .configure_filter = ar5523_configure_filter, | |
| 1361 | + .flush = ar5523_flush, | |
| 1362 | +}; | |
| 1363 | + | |
| 1364 | +static int ar5523_host_available(struct ar5523 *ar) | |
| 1365 | +{ | |
| 1366 | + struct ar5523_cmd_host_available setup; | |
| 1367 | + | |
| 1368 | + /* inform target the host is available */ | |
| 1369 | + setup.sw_ver_major = cpu_to_be32(ATH_SW_VER_MAJOR); | |
| 1370 | + setup.sw_ver_minor = cpu_to_be32(ATH_SW_VER_MINOR); | |
| 1371 | + setup.sw_ver_patch = cpu_to_be32(ATH_SW_VER_PATCH); | |
| 1372 | + setup.sw_ver_build = cpu_to_be32(ATH_SW_VER_BUILD); | |
| 1373 | + return ar5523_cmd_read(ar, WDCMSG_HOST_AVAILABLE, | |
| 1374 | + &setup, sizeof(setup), NULL, 0, 0); | |
| 1375 | +} | |
| 1376 | + | |
| 1377 | +static int ar5523_get_devstatus(struct ar5523 *ar) | |
| 1378 | +{ | |
| 1379 | + u8 macaddr[ETH_ALEN]; | |
| 1380 | + int error; | |
| 1381 | + | |
| 1382 | + /* retrieve MAC address */ | |
| 1383 | + error = ar5523_get_status(ar, ST_MAC_ADDR, macaddr, ETH_ALEN); | |
| 1384 | + if (error) { | |
| 1385 | + ar5523_err(ar, "could not read MAC address\n"); | |
| 1386 | + return error; | |
| 1387 | + } | |
| 1388 | + | |
| 1389 | + SET_IEEE80211_PERM_ADDR(ar->hw, macaddr); | |
| 1390 | + | |
| 1391 | + error = ar5523_get_status(ar, ST_SERIAL_NUMBER, | |
| 1392 | + &ar->serial[0], sizeof(ar->serial)); | |
| 1393 | + if (error) { | |
| 1394 | + ar5523_err(ar, "could not read device serial number\n"); | |
| 1395 | + return error; | |
| 1396 | + } | |
| 1397 | + return 0; | |
| 1398 | +} | |
| 1399 | + | |
| 1400 | +#define AR5523_SANE_RXBUFSZ 2000 | |
| 1401 | + | |
| 1402 | +static int ar5523_get_max_rxsz(struct ar5523 *ar) | |
| 1403 | +{ | |
| 1404 | + int error; | |
| 1405 | + __be32 rxsize; | |
| 1406 | + | |
| 1407 | + /* Get max rx size */ | |
| 1408 | + error = ar5523_get_status(ar, ST_WDC_TRANSPORT_CHUNK_SIZE, &rxsize, | |
| 1409 | + sizeof(rxsize)); | |
| 1410 | + if (error != 0) { | |
| 1411 | + ar5523_err(ar, "could not read max RX size\n"); | |
| 1412 | + return error; | |
| 1413 | + } | |
| 1414 | + | |
| 1415 | + ar->rxbufsz = be32_to_cpu(rxsize); | |
| 1416 | + | |
| 1417 | + if (!ar->rxbufsz || ar->rxbufsz > AR5523_SANE_RXBUFSZ) { | |
| 1418 | + ar5523_err(ar, "Bad rxbufsz from device. Using %d instead\n", | |
| 1419 | + AR5523_SANE_RXBUFSZ); | |
| 1420 | + ar->rxbufsz = AR5523_SANE_RXBUFSZ; | |
| 1421 | + } | |
| 1422 | + | |
| 1423 | + ar5523_dbg(ar, "Max RX buf size: %d\n", ar->rxbufsz); | |
| 1424 | + return 0; | |
| 1425 | +} | |
| 1426 | + | |
| 1427 | +/* | |
| 1428 | + * This is copied from rtl818x, but we should probably move this | |
| 1429 | + * to common code as in OpenBSD. | |
| 1430 | + */ | |
| 1431 | +static const struct ieee80211_rate ar5523_rates[] = { | |
| 1432 | + { .bitrate = 10, .hw_value = 2, }, | |
| 1433 | + { .bitrate = 20, .hw_value = 4 }, | |
| 1434 | + { .bitrate = 55, .hw_value = 11, }, | |
| 1435 | + { .bitrate = 110, .hw_value = 22, }, | |
| 1436 | + { .bitrate = 60, .hw_value = 12, }, | |
| 1437 | + { .bitrate = 90, .hw_value = 18, }, | |
| 1438 | + { .bitrate = 120, .hw_value = 24, }, | |
| 1439 | + { .bitrate = 180, .hw_value = 36, }, | |
| 1440 | + { .bitrate = 240, .hw_value = 48, }, | |
| 1441 | + { .bitrate = 360, .hw_value = 72, }, | |
| 1442 | + { .bitrate = 480, .hw_value = 96, }, | |
| 1443 | + { .bitrate = 540, .hw_value = 108, }, | |
| 1444 | +}; | |
| 1445 | + | |
| 1446 | +static const struct ieee80211_channel ar5523_channels[] = { | |
| 1447 | + { .center_freq = 2412 }, | |
| 1448 | + { .center_freq = 2417 }, | |
| 1449 | + { .center_freq = 2422 }, | |
| 1450 | + { .center_freq = 2427 }, | |
| 1451 | + { .center_freq = 2432 }, | |
| 1452 | + { .center_freq = 2437 }, | |
| 1453 | + { .center_freq = 2442 }, | |
| 1454 | + { .center_freq = 2447 }, | |
| 1455 | + { .center_freq = 2452 }, | |
| 1456 | + { .center_freq = 2457 }, | |
| 1457 | + { .center_freq = 2462 }, | |
| 1458 | + { .center_freq = 2467 }, | |
| 1459 | + { .center_freq = 2472 }, | |
| 1460 | + { .center_freq = 2484 }, | |
| 1461 | +}; | |
| 1462 | + | |
| 1463 | +static int ar5523_init_modes(struct ar5523 *ar) | |
| 1464 | +{ | |
| 1465 | + BUILD_BUG_ON(sizeof(ar->channels) != sizeof(ar5523_channels)); | |
| 1466 | + BUILD_BUG_ON(sizeof(ar->rates) != sizeof(ar5523_rates)); | |
| 1467 | + | |
| 1468 | + memcpy(ar->channels, ar5523_channels, sizeof(ar5523_channels)); | |
| 1469 | + memcpy(ar->rates, ar5523_rates, sizeof(ar5523_rates)); | |
| 1470 | + | |
| 1471 | + ar->band.band = IEEE80211_BAND_2GHZ; | |
| 1472 | + ar->band.channels = ar->channels; | |
| 1473 | + ar->band.n_channels = ARRAY_SIZE(ar5523_channels); | |
| 1474 | + ar->band.bitrates = ar->rates; | |
| 1475 | + ar->band.n_bitrates = ARRAY_SIZE(ar5523_rates); | |
| 1476 | + ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar->band; | |
| 1477 | + return 0; | |
| 1478 | +} | |
| 1479 | + | |
| 1480 | +/* | |
| 1481 | + * Load the MIPS R4000 microcode into the device. Once the image is loaded, | |
| 1482 | + * the device will detach itself from the bus and reattach later with a new | |
| 1483 | + * product Id (a la ezusb). | |
| 1484 | + */ | |
| 1485 | +static int ar5523_load_firmware(struct usb_device *dev) | |
| 1486 | +{ | |
| 1487 | + struct ar5523_fwblock *txblock, *rxblock; | |
| 1488 | + const struct firmware *fw; | |
| 1489 | + void *fwbuf; | |
| 1490 | + int len, offset; | |
| 1491 | + int foolen; /* XXX(hch): handle short transfers */ | |
| 1492 | + int error = -ENXIO; | |
| 1493 | + | |
| 1494 | + if (request_firmware(&fw, AR5523_FIRMWARE_FILE, &dev->dev)) { | |
| 1495 | + dev_err(&dev->dev, "no firmware found: %s\n", | |
| 1496 | + AR5523_FIRMWARE_FILE); | |
| 1497 | + return -ENOENT; | |
| 1498 | + } | |
| 1499 | + | |
| 1500 | + txblock = kmalloc(sizeof(*txblock), GFP_KERNEL); | |
| 1501 | + if (!txblock) | |
| 1502 | + goto out; | |
| 1503 | + | |
| 1504 | + rxblock = kmalloc(sizeof(*rxblock), GFP_KERNEL); | |
| 1505 | + if (!rxblock) | |
| 1506 | + goto out_free_txblock; | |
| 1507 | + | |
| 1508 | + fwbuf = kmalloc(AR5523_MAX_FWBLOCK_SIZE, GFP_KERNEL); | |
| 1509 | + if (!fwbuf) | |
| 1510 | + goto out_free_rxblock; | |
| 1511 | + | |
| 1512 | + memset(txblock, 0, sizeof(struct ar5523_fwblock)); | |
| 1513 | + txblock->flags = cpu_to_be32(AR5523_WRITE_BLOCK); | |
| 1514 | + txblock->total = cpu_to_be32(fw->size); | |
| 1515 | + | |
| 1516 | + offset = 0; | |
| 1517 | + len = fw->size; | |
| 1518 | + while (len > 0) { | |
| 1519 | + int mlen = min(len, AR5523_MAX_FWBLOCK_SIZE); | |
| 1520 | + | |
| 1521 | + txblock->remain = cpu_to_be32(len - mlen); | |
| 1522 | + txblock->len = cpu_to_be32(mlen); | |
| 1523 | + | |
| 1524 | + /* send firmware block meta-data */ | |
| 1525 | + error = usb_bulk_msg(dev, ar5523_cmd_tx_pipe(dev), | |
| 1526 | + txblock, sizeof(*txblock), &foolen, | |
| 1527 | + AR5523_CMD_TIMEOUT); | |
| 1528 | + if (error) { | |
| 1529 | + dev_err(&dev->dev, | |
| 1530 | + "could not send firmware block info\n"); | |
| 1531 | + goto out_free_fwbuf; | |
| 1532 | + } | |
| 1533 | + | |
| 1534 | + /* send firmware block data */ | |
| 1535 | + memcpy(fwbuf, fw->data + offset, mlen); | |
| 1536 | + error = usb_bulk_msg(dev, ar5523_data_tx_pipe(dev), | |
| 1537 | + fwbuf, mlen, &foolen, | |
| 1538 | + AR5523_DATA_TIMEOUT); | |
| 1539 | + if (error) { | |
| 1540 | + dev_err(&dev->dev, | |
| 1541 | + "could not send firmware block data\n"); | |
| 1542 | + goto out_free_fwbuf; | |
| 1543 | + } | |
| 1544 | + | |
| 1545 | + /* wait for ack from firmware */ | |
| 1546 | + error = usb_bulk_msg(dev, ar5523_cmd_rx_pipe(dev), | |
| 1547 | + rxblock, sizeof(*rxblock), &foolen, | |
| 1548 | + AR5523_CMD_TIMEOUT); | |
| 1549 | + if (error) { | |
| 1550 | + dev_err(&dev->dev, | |
| 1551 | + "could not read firmware answer\n"); | |
| 1552 | + goto out_free_fwbuf; | |
| 1553 | + } | |
| 1554 | + | |
| 1555 | + len -= mlen; | |
| 1556 | + offset += mlen; | |
| 1557 | + } | |
| 1558 | + | |
| 1559 | + /* | |
| 1560 | + * Set the error to -ENXIO to make sure we continue probing for | |
| 1561 | + * a driver. | |
| 1562 | + */ | |
| 1563 | + error = -ENXIO; | |
| 1564 | + | |
| 1565 | + out_free_fwbuf: | |
| 1566 | + kfree(fwbuf); | |
| 1567 | + out_free_rxblock: | |
| 1568 | + kfree(rxblock); | |
| 1569 | + out_free_txblock: | |
| 1570 | + kfree(txblock); | |
| 1571 | + out: | |
| 1572 | + release_firmware(fw); | |
| 1573 | + return error; | |
| 1574 | +} | |
| 1575 | + | |
| 1576 | +static int ar5523_probe(struct usb_interface *intf, | |
| 1577 | + const struct usb_device_id *id) | |
| 1578 | +{ | |
| 1579 | + struct usb_device *dev = interface_to_usbdev(intf); | |
| 1580 | + struct ieee80211_hw *hw; | |
| 1581 | + struct ar5523 *ar; | |
| 1582 | + int error = -ENOMEM; | |
| 1583 | + | |
| 1584 | + /* | |
| 1585 | + * Load firmware if the device requires it. This will return | |
| 1586 | + * -ENXIO on success and we'll get called back afer the usb | |
| 1587 | + * id changes to indicate that the firmware is present. | |
| 1588 | + */ | |
| 1589 | + if (id->driver_info & AR5523_FLAG_PRE_FIRMWARE) | |
| 1590 | + return ar5523_load_firmware(dev); | |
| 1591 | + | |
| 1592 | + | |
| 1593 | + hw = ieee80211_alloc_hw(sizeof(*ar), &ar5523_ops); | |
| 1594 | + if (!hw) | |
| 1595 | + goto out; | |
| 1596 | + SET_IEEE80211_DEV(hw, &intf->dev); | |
| 1597 | + | |
| 1598 | + ar = hw->priv; | |
| 1599 | + ar->hw = hw; | |
| 1600 | + ar->dev = dev; | |
| 1601 | + mutex_init(&ar->mutex); | |
| 1602 | + | |
| 1603 | + INIT_DELAYED_WORK(&ar->stat_work, ar5523_stat_work); | |
| 1604 | + init_timer(&ar->tx_wd_timer); | |
| 1605 | + setup_timer(&ar->tx_wd_timer, ar5523_tx_wd_timer, (unsigned long) ar); | |
| 1606 | + INIT_WORK(&ar->tx_wd_work, ar5523_tx_wd_work); | |
| 1607 | + INIT_WORK(&ar->tx_work, ar5523_tx_work); | |
| 1608 | + INIT_LIST_HEAD(&ar->tx_queue_pending); | |
| 1609 | + INIT_LIST_HEAD(&ar->tx_queue_submitted); | |
| 1610 | + spin_lock_init(&ar->tx_data_list_lock); | |
| 1611 | + atomic_set(&ar->tx_nr_total, 0); | |
| 1612 | + atomic_set(&ar->tx_nr_pending, 0); | |
| 1613 | + init_waitqueue_head(&ar->tx_flush_waitq); | |
| 1614 | + | |
| 1615 | + atomic_set(&ar->rx_data_free_cnt, 0); | |
| 1616 | + INIT_WORK(&ar->rx_refill_work, ar5523_rx_refill_work); | |
| 1617 | + INIT_LIST_HEAD(&ar->rx_data_free); | |
| 1618 | + INIT_LIST_HEAD(&ar->rx_data_used); | |
| 1619 | + spin_lock_init(&ar->rx_data_list_lock); | |
| 1620 | + | |
| 1621 | + ar->wq = create_singlethread_workqueue("ar5523"); | |
| 1622 | + if (!ar->wq) { | |
| 1623 | + ar5523_err(ar, "Could not create wq\n"); | |
| 1624 | + goto out_free_ar; | |
| 1625 | + } | |
| 1626 | + | |
| 1627 | + error = ar5523_alloc_rx_bufs(ar); | |
| 1628 | + if (error) { | |
| 1629 | + ar5523_err(ar, "Could not allocate rx buffers\n"); | |
| 1630 | + goto out_free_wq; | |
| 1631 | + } | |
| 1632 | + | |
| 1633 | + error = ar5523_alloc_rx_cmd(ar); | |
| 1634 | + if (error) { | |
| 1635 | + ar5523_err(ar, "Could not allocate rx command buffers\n"); | |
| 1636 | + goto out_free_rx_bufs; | |
| 1637 | + } | |
| 1638 | + | |
| 1639 | + error = ar5523_alloc_tx_cmd(ar); | |
| 1640 | + if (error) { | |
| 1641 | + ar5523_err(ar, "Could not allocate tx command buffers\n"); | |
| 1642 | + goto out_free_rx_cmd; | |
| 1643 | + } | |
| 1644 | + | |
| 1645 | + error = ar5523_submit_rx_cmd(ar); | |
| 1646 | + if (error) { | |
| 1647 | + ar5523_err(ar, "Failed to submit rx cmd\n"); | |
| 1648 | + goto out_free_tx_cmd; | |
| 1649 | + } | |
| 1650 | + | |
| 1651 | + /* | |
| 1652 | + * We're now ready to send/receive firmware commands. | |
| 1653 | + */ | |
| 1654 | + error = ar5523_host_available(ar); | |
| 1655 | + if (error) { | |
| 1656 | + ar5523_err(ar, "could not initialize adapter\n"); | |
| 1657 | + goto out_cancel_rx_cmd; | |
| 1658 | + } | |
| 1659 | + | |
| 1660 | + error = ar5523_get_max_rxsz(ar); | |
| 1661 | + if (error) { | |
| 1662 | + ar5523_err(ar, "could not get caps from adapter\n"); | |
| 1663 | + goto out_cancel_rx_cmd; | |
| 1664 | + } | |
| 1665 | + | |
| 1666 | + error = ar5523_get_devcap(ar); | |
| 1667 | + if (error) { | |
| 1668 | + ar5523_err(ar, "could not get caps from adapter\n"); | |
| 1669 | + goto out_cancel_rx_cmd; | |
| 1670 | + } | |
| 1671 | + | |
| 1672 | + error = ar5523_get_devstatus(ar); | |
| 1673 | + if (error != 0) { | |
| 1674 | + ar5523_err(ar, "could not get device status\n"); | |
| 1675 | + goto out_cancel_rx_cmd; | |
| 1676 | + } | |
| 1677 | + | |
| 1678 | + ar5523_info(ar, "MAC/BBP AR5523, RF AR%c112\n", | |
| 1679 | + (id->driver_info & AR5523_FLAG_ABG) ? '5' : '2'); | |
| 1680 | + | |
| 1681 | + ar->vif = NULL; | |
| 1682 | + hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | | |
| 1683 | + IEEE80211_HW_SIGNAL_DBM | | |
| 1684 | + IEEE80211_HW_HAS_RATE_CONTROL; | |
| 1685 | + hw->extra_tx_headroom = sizeof(struct ar5523_tx_desc) + | |
| 1686 | + sizeof(struct ar5523_chunk); | |
| 1687 | + hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | |
| 1688 | + hw->queues = 1; | |
| 1689 | + | |
| 1690 | + error = ar5523_init_modes(ar); | |
| 1691 | + if (error) | |
| 1692 | + goto out_cancel_rx_cmd; | |
| 1693 | + | |
| 1694 | + usb_set_intfdata(intf, hw); | |
| 1695 | + | |
| 1696 | + error = ieee80211_register_hw(hw); | |
| 1697 | + if (error) { | |
| 1698 | + ar5523_err(ar, "could not register device\n"); | |
| 1699 | + goto out_cancel_rx_cmd; | |
| 1700 | + } | |
| 1701 | + | |
| 1702 | + ar5523_info(ar, "Found and initialized AR5523 device\n"); | |
| 1703 | + return 0; | |
| 1704 | + | |
| 1705 | +out_cancel_rx_cmd: | |
| 1706 | + ar5523_cancel_rx_cmd(ar); | |
| 1707 | +out_free_tx_cmd: | |
| 1708 | + ar5523_free_tx_cmd(ar); | |
| 1709 | +out_free_rx_cmd: | |
| 1710 | + ar5523_free_rx_cmd(ar); | |
| 1711 | +out_free_rx_bufs: | |
| 1712 | + ar5523_free_rx_bufs(ar); | |
| 1713 | +out_free_wq: | |
| 1714 | + destroy_workqueue(ar->wq); | |
| 1715 | +out_free_ar: | |
| 1716 | + ieee80211_free_hw(hw); | |
| 1717 | +out: | |
| 1718 | + return error; | |
| 1719 | +} | |
| 1720 | + | |
| 1721 | +static void ar5523_disconnect(struct usb_interface *intf) | |
| 1722 | +{ | |
| 1723 | + struct ieee80211_hw *hw = usb_get_intfdata(intf); | |
| 1724 | + struct ar5523 *ar = hw->priv; | |
| 1725 | + | |
| 1726 | + ar5523_dbg(ar, "detaching\n"); | |
| 1727 | + set_bit(AR5523_USB_DISCONNECTED, &ar->flags); | |
| 1728 | + | |
| 1729 | + ieee80211_unregister_hw(hw); | |
| 1730 | + | |
| 1731 | + ar5523_cancel_rx_cmd(ar); | |
| 1732 | + ar5523_free_tx_cmd(ar); | |
| 1733 | + ar5523_free_rx_cmd(ar); | |
| 1734 | + ar5523_free_rx_bufs(ar); | |
| 1735 | + | |
| 1736 | + destroy_workqueue(ar->wq); | |
| 1737 | + | |
| 1738 | + ieee80211_free_hw(hw); | |
| 1739 | + usb_set_intfdata(intf, NULL); | |
| 1740 | +} | |
| 1741 | + | |
| 1742 | +#define AR5523_DEVICE_UG(vendor, device) \ | |
| 1743 | + { USB_DEVICE((vendor), (device)) }, \ | |
| 1744 | + { USB_DEVICE((vendor), (device) + 1), \ | |
| 1745 | + .driver_info = AR5523_FLAG_PRE_FIRMWARE } | |
| 1746 | +#define AR5523_DEVICE_UX(vendor, device) \ | |
| 1747 | + { USB_DEVICE((vendor), (device)), \ | |
| 1748 | + .driver_info = AR5523_FLAG_ABG }, \ | |
| 1749 | + { USB_DEVICE((vendor), (device) + 1), \ | |
| 1750 | + .driver_info = AR5523_FLAG_ABG|AR5523_FLAG_PRE_FIRMWARE } | |
| 1751 | + | |
| 1752 | +static struct usb_device_id ar5523_id_table[] = { | |
| 1753 | + AR5523_DEVICE_UG(0x168c, 0x0001), /* Atheros / AR5523 */ | |
| 1754 | + AR5523_DEVICE_UG(0x0cf3, 0x0001), /* Atheros2 / AR5523_1 */ | |
| 1755 | + AR5523_DEVICE_UG(0x0cf3, 0x0003), /* Atheros2 / AR5523_2 */ | |
| 1756 | + AR5523_DEVICE_UX(0x0cf3, 0x0005), /* Atheros2 / AR5523_3 */ | |
| 1757 | + AR5523_DEVICE_UG(0x0d8e, 0x7801), /* Conceptronic / AR5523_1 */ | |
| 1758 | + AR5523_DEVICE_UX(0x0d8e, 0x7811), /* Conceptronic / AR5523_2 */ | |
| 1759 | + AR5523_DEVICE_UX(0x2001, 0x3a00), /* Dlink / DWLAG132 */ | |
| 1760 | + AR5523_DEVICE_UG(0x2001, 0x3a02), /* Dlink / DWLG132 */ | |
| 1761 | + AR5523_DEVICE_UX(0x2001, 0x3a04), /* Dlink / DWLAG122 */ | |
| 1762 | + AR5523_DEVICE_UG(0x1690, 0x0712), /* Gigaset / AR5523 */ | |
| 1763 | + AR5523_DEVICE_UG(0x1690, 0x0710), /* Gigaset / SMCWUSBTG */ | |
| 1764 | + AR5523_DEVICE_UG(0x129b, 0x160c), /* Gigaset / USB stick 108 | |
| 1765 | + (CyberTAN Technology) */ | |
| 1766 | + AR5523_DEVICE_UG(0x16ab, 0x7801), /* Globalsun / AR5523_1 */ | |
| 1767 | + AR5523_DEVICE_UX(0x16ab, 0x7811), /* Globalsun / AR5523_2 */ | |
| 1768 | + AR5523_DEVICE_UG(0x0d8e, 0x7802), /* Globalsun / AR5523_3 */ | |
| 1769 | + AR5523_DEVICE_UX(0x0846, 0x4300), /* Netgear / WG111U */ | |
| 1770 | + AR5523_DEVICE_UG(0x0846, 0x4250), /* Netgear / WG111T */ | |
| 1771 | + AR5523_DEVICE_UG(0x0846, 0x5f00), /* Netgear / WPN111 */ | |
| 1772 | + AR5523_DEVICE_UG(0x157e, 0x3006), /* Umedia / AR5523_1 */ | |
| 1773 | + AR5523_DEVICE_UX(0x157e, 0x3205), /* Umedia / AR5523_2 */ | |
| 1774 | + AR5523_DEVICE_UG(0x157e, 0x3006), /* Umedia / TEW444UBEU */ | |
| 1775 | + AR5523_DEVICE_UG(0x1435, 0x0826), /* Wistronneweb / AR5523_1 */ | |
| 1776 | + AR5523_DEVICE_UX(0x1435, 0x0828), /* Wistronneweb / AR5523_2 */ | |
| 1777 | + AR5523_DEVICE_UG(0x0cde, 0x0012), /* Zcom / AR5523 */ | |
| 1778 | + AR5523_DEVICE_UG(0x1385, 0x4250), /* Netgear3 / WG111T (2) */ | |
| 1779 | + AR5523_DEVICE_UG(0x1385, 0x5f00), /* Netgear / WPN111 */ | |
| 1780 | + AR5523_DEVICE_UG(0x1385, 0x5f02), /* Netgear / WPN111 */ | |
| 1781 | + { } | |
| 1782 | +}; | |
| 1783 | +MODULE_DEVICE_TABLE(usb, ar5523_id_table); | |
| 1784 | + | |
| 1785 | +static struct usb_driver ar5523_driver = { | |
| 1786 | + .name = "ar5523", | |
| 1787 | + .id_table = ar5523_id_table, | |
| 1788 | + .probe = ar5523_probe, | |
| 1789 | + .disconnect = ar5523_disconnect, | |
| 1790 | +}; | |
| 1791 | + | |
| 1792 | +static int __init ar5523_init(void) | |
| 1793 | +{ | |
| 1794 | + return usb_register(&ar5523_driver); | |
| 1795 | +} | |
| 1796 | + | |
| 1797 | +static void __exit ar5523_exit(void) | |
| 1798 | +{ | |
| 1799 | + usb_deregister(&ar5523_driver); | |
| 1800 | +} | |
| 1801 | + | |
| 1802 | +MODULE_LICENSE("Dual BSD/GPL"); | |
| 1803 | +MODULE_FIRMWARE(AR5523_FIRMWARE_FILE); | |
| 1804 | + | |
| 1805 | +module_init(ar5523_init); | |
| 1806 | +module_exit(ar5523_exit); | |
| @@ -0,0 +1,152 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr> | |
| 3 | + * Copyright (c) 2006 Sam Leffler, Errno Consulting | |
| 4 | + * Copyright (c) 2007 Christoph Hellwig <hch@lst.de> | |
| 5 | + * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org> | |
| 6 | + * Copyright (c) 2012 Pontus Fuchs <pontus.fuchs@gmail.com> | |
| 7 | + * | |
| 8 | + * Permission to use, copy, modify, and/or distribute this software for any | |
| 9 | + * purpose with or without fee is hereby granted, provided that the above | |
| 10 | + * copyright notice and this permission notice appear in all copies. | |
| 11 | + * | |
| 12 | + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
| 13 | + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
| 14 | + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
| 15 | + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
| 16 | + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
| 17 | + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
| 18 | + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
| 19 | + */ | |
| 20 | + | |
| 21 | +#define AR5523_FLAG_PRE_FIRMWARE (1 << 0) | |
| 22 | +#define AR5523_FLAG_ABG (1 << 1) | |
| 23 | + | |
| 24 | +#define AR5523_FIRMWARE_FILE "ar5523.bin" | |
| 25 | + | |
| 26 | +#define AR5523_CMD_TX_PIPE 0x01 | |
| 27 | +#define AR5523_DATA_TX_PIPE 0x02 | |
| 28 | +#define AR5523_CMD_RX_PIPE 0x81 | |
| 29 | +#define AR5523_DATA_RX_PIPE 0x82 | |
| 30 | + | |
| 31 | +#define ar5523_cmd_tx_pipe(dev) \ | |
| 32 | + usb_sndbulkpipe((dev), AR5523_CMD_TX_PIPE) | |
| 33 | +#define ar5523_data_tx_pipe(dev) \ | |
| 34 | + usb_sndbulkpipe((dev), AR5523_DATA_TX_PIPE) | |
| 35 | +#define ar5523_cmd_rx_pipe(dev) \ | |
| 36 | + usb_rcvbulkpipe((dev), AR5523_CMD_RX_PIPE) | |
| 37 | +#define ar5523_data_rx_pipe(dev) \ | |
| 38 | + usb_rcvbulkpipe((dev), AR5523_DATA_RX_PIPE) | |
| 39 | + | |
| 40 | +#define AR5523_DATA_TIMEOUT 10000 | |
| 41 | +#define AR5523_CMD_TIMEOUT 1000 | |
| 42 | + | |
| 43 | +#define AR5523_TX_DATA_COUNT 8 | |
| 44 | +#define AR5523_TX_DATA_RESTART_COUNT 2 | |
| 45 | +#define AR5523_RX_DATA_COUNT 16 | |
| 46 | +#define AR5523_RX_DATA_REFILL_COUNT 8 | |
| 47 | + | |
| 48 | +#define AR5523_CMD_ID 1 | |
| 49 | +#define AR5523_DATA_ID 2 | |
| 50 | + | |
| 51 | +#define AR5523_TX_WD_TIMEOUT (HZ * 2) | |
| 52 | +#define AR5523_FLUSH_TIMEOUT (HZ * 3) | |
| 53 | + | |
| 54 | +enum AR5523_flags { | |
| 55 | + AR5523_HW_UP, | |
| 56 | + AR5523_USB_DISCONNECTED, | |
| 57 | + AR5523_CONNECTED | |
| 58 | +}; | |
| 59 | + | |
| 60 | +struct ar5523_tx_cmd { | |
| 61 | + struct ar5523 *ar; | |
| 62 | + struct urb *urb_tx; | |
| 63 | + void *buf_tx; | |
| 64 | + void *odata; | |
| 65 | + int olen; | |
| 66 | + int flags; | |
| 67 | + int res; | |
| 68 | + struct completion done; | |
| 69 | +}; | |
| 70 | + | |
| 71 | +/* This struct is placed in tx_info->driver_data. It must not be larger | |
| 72 | + * than IEEE80211_TX_INFO_DRIVER_DATA_SIZE. | |
| 73 | + */ | |
| 74 | +struct ar5523_tx_data { | |
| 75 | + struct list_head list; | |
| 76 | + struct ar5523 *ar; | |
| 77 | + struct sk_buff *skb; | |
| 78 | + struct urb *urb; | |
| 79 | +}; | |
| 80 | + | |
| 81 | +struct ar5523_rx_data { | |
| 82 | + struct list_head list; | |
| 83 | + struct ar5523 *ar; | |
| 84 | + struct urb *urb; | |
| 85 | + struct sk_buff *skb; | |
| 86 | +}; | |
| 87 | + | |
| 88 | +struct ar5523 { | |
| 89 | + struct usb_device *dev; | |
| 90 | + struct ieee80211_hw *hw; | |
| 91 | + | |
| 92 | + unsigned long flags; | |
| 93 | + struct mutex mutex; | |
| 94 | + struct workqueue_struct *wq; | |
| 95 | + | |
| 96 | + struct ar5523_tx_cmd tx_cmd; | |
| 97 | + | |
| 98 | + struct delayed_work stat_work; | |
| 99 | + | |
| 100 | + struct timer_list tx_wd_timer; | |
| 101 | + struct work_struct tx_wd_work; | |
| 102 | + struct work_struct tx_work; | |
| 103 | + struct list_head tx_queue_pending; | |
| 104 | + struct list_head tx_queue_submitted; | |
| 105 | + spinlock_t tx_data_list_lock; | |
| 106 | + wait_queue_head_t tx_flush_waitq; | |
| 107 | + | |
| 108 | + /* Queued + Submitted TX frames */ | |
| 109 | + atomic_t tx_nr_total; | |
| 110 | + | |
| 111 | + /* Submitted TX frames */ | |
| 112 | + atomic_t tx_nr_pending; | |
| 113 | + | |
| 114 | + void *rx_cmd_buf; | |
| 115 | + struct urb *rx_cmd_urb; | |
| 116 | + | |
| 117 | + struct ar5523_rx_data rx_data[AR5523_RX_DATA_COUNT]; | |
| 118 | + spinlock_t rx_data_list_lock; | |
| 119 | + struct list_head rx_data_free; | |
| 120 | + struct list_head rx_data_used; | |
| 121 | + atomic_t rx_data_free_cnt; | |
| 122 | + | |
| 123 | + struct work_struct rx_refill_work; | |
| 124 | + | |
| 125 | + unsigned int rxbufsz; | |
| 126 | + u8 serial[16]; | |
| 127 | + | |
| 128 | + struct ieee80211_channel channels[14]; | |
| 129 | + struct ieee80211_rate rates[12]; | |
| 130 | + struct ieee80211_supported_band band; | |
| 131 | + struct ieee80211_vif *vif; | |
| 132 | +}; | |
| 133 | + | |
| 134 | +/* flags for sending firmware commands */ | |
| 135 | +#define AR5523_CMD_FLAG_READ (1 << 1) | |
| 136 | +#define AR5523_CMD_FLAG_MAGIC (1 << 2) | |
| 137 | + | |
| 138 | +#define ar5523_dbg(ar, format, arg...) \ | |
| 139 | + dev_dbg(&(ar)->dev->dev, format, ## arg) | |
| 140 | + | |
| 141 | +/* On USB hot-unplug there can be a lot of URBs in flight and they'll all | |
| 142 | + * fail. Instead of dealing with them in every possible place just surpress | |
| 143 | + * any messages on USB disconnect. | |
| 144 | + */ | |
| 145 | +#define ar5523_err(ar, format, arg...) \ | |
| 146 | +do { \ | |
| 147 | + if (!test_bit(AR5523_USB_DISCONNECTED, &ar->flags)) { \ | |
| 148 | + dev_err(&(ar)->dev->dev, format, ## arg); \ | |
| 149 | + } \ | |
| 150 | +} while (0) | |
| 151 | +#define ar5523_info(ar, format, arg...) \ | |
| 152 | + dev_info(&(ar)->dev->dev, format, ## arg) | |
| @@ -0,0 +1,431 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr> | |
| 3 | + * Copyright (c) 2006 Sam Leffler, Errno Consulting | |
| 4 | + * Copyright (c) 2007 Christoph Hellwig <hch@lst.de> | |
| 5 | + * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org> | |
| 6 | + * Copyright (c) 2012 Pontus Fuchs <pontus.fuchs@gmail.com> | |
| 7 | + * | |
| 8 | + * Permission to use, copy, modify, and/or distribute this software for any | |
| 9 | + * purpose with or without fee is hereby granted, provided that the above | |
| 10 | + * copyright notice and this permission notice appear in all copies. | |
| 11 | + * | |
| 12 | + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
| 13 | + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
| 14 | + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
| 15 | + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
| 16 | + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
| 17 | + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
| 18 | + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
| 19 | + */ | |
| 20 | + | |
| 21 | +/* all fields are big endian */ | |
| 22 | +struct ar5523_fwblock { | |
| 23 | + __be32 flags; | |
| 24 | +#define AR5523_WRITE_BLOCK (1 << 4) | |
| 25 | + | |
| 26 | + __be32 len; | |
| 27 | +#define AR5523_MAX_FWBLOCK_SIZE 2048 | |
| 28 | + | |
| 29 | + __be32 total; | |
| 30 | + __be32 remain; | |
| 31 | + __be32 rxtotal; | |
| 32 | + __be32 pad[123]; | |
| 33 | +} __packed; | |
| 34 | + | |
| 35 | +#define AR5523_MAX_RXCMDSZ 1024 | |
| 36 | +#define AR5523_MAX_TXCMDSZ 1024 | |
| 37 | + | |
| 38 | +struct ar5523_cmd_hdr { | |
| 39 | + __be32 len; | |
| 40 | + __be32 code; | |
| 41 | +/* NB: these are defined for rev 1.5 firmware; rev 1.6 is different */ | |
| 42 | +/* messages from Host -> Target */ | |
| 43 | +#define WDCMSG_HOST_AVAILABLE 0x01 | |
| 44 | +#define WDCMSG_BIND 0x02 | |
| 45 | +#define WDCMSG_TARGET_RESET 0x03 | |
| 46 | +#define WDCMSG_TARGET_GET_CAPABILITY 0x04 | |
| 47 | +#define WDCMSG_TARGET_SET_CONFIG 0x05 | |
| 48 | +#define WDCMSG_TARGET_GET_STATUS 0x06 | |
| 49 | +#define WDCMSG_TARGET_GET_STATS 0x07 | |
| 50 | +#define WDCMSG_TARGET_START 0x08 | |
| 51 | +#define WDCMSG_TARGET_STOP 0x09 | |
| 52 | +#define WDCMSG_TARGET_ENABLE 0x0a | |
| 53 | +#define WDCMSG_TARGET_DISABLE 0x0b | |
| 54 | +#define WDCMSG_CREATE_CONNECTION 0x0c | |
| 55 | +#define WDCMSG_UPDATE_CONNECT_ATTR 0x0d | |
| 56 | +#define WDCMSG_DELETE_CONNECT 0x0e | |
| 57 | +#define WDCMSG_SEND 0x0f | |
| 58 | +#define WDCMSG_FLUSH 0x10 | |
| 59 | +/* messages from Target -> Host */ | |
| 60 | +#define WDCMSG_STATS_UPDATE 0x11 | |
| 61 | +#define WDCMSG_BMISS 0x12 | |
| 62 | +#define WDCMSG_DEVICE_AVAIL 0x13 | |
| 63 | +#define WDCMSG_SEND_COMPLETE 0x14 | |
| 64 | +#define WDCMSG_DATA_AVAIL 0x15 | |
| 65 | +#define WDCMSG_SET_PWR_MODE 0x16 | |
| 66 | +#define WDCMSG_BMISS_ACK 0x17 | |
| 67 | +#define WDCMSG_SET_LED_STEADY 0x18 | |
| 68 | +#define WDCMSG_SET_LED_BLINK 0x19 | |
| 69 | +/* more messages */ | |
| 70 | +#define WDCMSG_SETUP_BEACON_DESC 0x1a | |
| 71 | +#define WDCMSG_BEACON_INIT 0x1b | |
| 72 | +#define WDCMSG_RESET_KEY_CACHE 0x1c | |
| 73 | +#define WDCMSG_RESET_KEY_CACHE_ENTRY 0x1d | |
| 74 | +#define WDCMSG_SET_KEY_CACHE_ENTRY 0x1e | |
| 75 | +#define WDCMSG_SET_DECOMP_MASK 0x1f | |
| 76 | +#define WDCMSG_SET_REGULATORY_DOMAIN 0x20 | |
| 77 | +#define WDCMSG_SET_LED_STATE 0x21 | |
| 78 | +#define WDCMSG_WRITE_ASSOCID 0x22 | |
| 79 | +#define WDCMSG_SET_STA_BEACON_TIMERS 0x23 | |
| 80 | +#define WDCMSG_GET_TSF 0x24 | |
| 81 | +#define WDCMSG_RESET_TSF 0x25 | |
| 82 | +#define WDCMSG_SET_ADHOC_MODE 0x26 | |
| 83 | +#define WDCMSG_SET_BASIC_RATE 0x27 | |
| 84 | +#define WDCMSG_MIB_CONTROL 0x28 | |
| 85 | +#define WDCMSG_GET_CHANNEL_DATA 0x29 | |
| 86 | +#define WDCMSG_GET_CUR_RSSI 0x2a | |
| 87 | +#define WDCMSG_SET_ANTENNA_SWITCH 0x2b | |
| 88 | +#define WDCMSG_USE_SHORT_SLOT_TIME 0x2f | |
| 89 | +#define WDCMSG_SET_POWER_MODE 0x30 | |
| 90 | +#define WDCMSG_SETUP_PSPOLL_DESC 0x31 | |
| 91 | +#define WDCMSG_SET_RX_MULTICAST_FILTER 0x32 | |
| 92 | +#define WDCMSG_RX_FILTER 0x33 | |
| 93 | +#define WDCMSG_PER_CALIBRATION 0x34 | |
| 94 | +#define WDCMSG_RESET 0x35 | |
| 95 | +#define WDCMSG_DISABLE 0x36 | |
| 96 | +#define WDCMSG_PHY_DISABLE 0x37 | |
| 97 | +#define WDCMSG_SET_TX_POWER_LIMIT 0x38 | |
| 98 | +#define WDCMSG_SET_TX_QUEUE_PARAMS 0x39 | |
| 99 | +#define WDCMSG_SETUP_TX_QUEUE 0x3a | |
| 100 | +#define WDCMSG_RELEASE_TX_QUEUE 0x3b | |
| 101 | +#define WDCMSG_SET_DEFAULT_KEY 0x43 | |
| 102 | + | |
| 103 | + __u32 priv; /* driver private data, | |
| 104 | + don't care about endianess */ | |
| 105 | + __be32 magic; | |
| 106 | + __be32 reserved2[4]; | |
| 107 | +}; | |
| 108 | + | |
| 109 | +struct ar5523_cmd_host_available { | |
| 110 | + __be32 sw_ver_major; | |
| 111 | + __be32 sw_ver_minor; | |
| 112 | + __be32 sw_ver_patch; | |
| 113 | + __be32 sw_ver_build; | |
| 114 | +} __packed; | |
| 115 | + | |
| 116 | +#define ATH_SW_VER_MAJOR 1 | |
| 117 | +#define ATH_SW_VER_MINOR 5 | |
| 118 | +#define ATH_SW_VER_PATCH 0 | |
| 119 | +#define ATH_SW_VER_BUILD 9999 | |
| 120 | + | |
| 121 | +struct ar5523_chunk { | |
| 122 | + u8 seqnum; /* sequence number for ordering */ | |
| 123 | + u8 flags; | |
| 124 | +#define UATH_CFLAGS_FINAL 0x01 /* final chunk of a msg */ | |
| 125 | +#define UATH_CFLAGS_RXMSG 0x02 /* chunk contains rx completion */ | |
| 126 | +#define UATH_CFLAGS_DEBUG 0x04 /* for debugging */ | |
| 127 | + __be16 length; /* chunk size in bytes */ | |
| 128 | + /* chunk data follows */ | |
| 129 | +} __packed; | |
| 130 | + | |
| 131 | +/* | |
| 132 | + * Message format for a WDCMSG_DATA_AVAIL message from Target to Host. | |
| 133 | + */ | |
| 134 | +struct ar5523_rx_desc { | |
| 135 | + __be32 len; /* msg length including header */ | |
| 136 | + __be32 code; /* WDCMSG_DATA_AVAIL */ | |
| 137 | + __be32 gennum; /* generation number */ | |
| 138 | + __be32 status; /* start of RECEIVE_INFO */ | |
| 139 | +#define UATH_STATUS_OK 0 | |
| 140 | +#define UATH_STATUS_STOP_IN_PROGRESS 1 | |
| 141 | +#define UATH_STATUS_CRC_ERR 2 | |
| 142 | +#define UATH_STATUS_PHY_ERR 3 | |
| 143 | +#define UATH_STATUS_DECRYPT_CRC_ERR 4 | |
| 144 | +#define UATH_STATUS_DECRYPT_MIC_ERR 5 | |
| 145 | +#define UATH_STATUS_DECOMP_ERR 6 | |
| 146 | +#define UATH_STATUS_KEY_ERR 7 | |
| 147 | +#define UATH_STATUS_ERR 8 | |
| 148 | + __be32 tstamp_low; /* low-order 32-bits of rx timestamp */ | |
| 149 | + __be32 tstamp_high; /* high-order 32-bits of rx timestamp */ | |
| 150 | + __be32 framelen; /* frame length */ | |
| 151 | + __be32 rate; /* rx rate code */ | |
| 152 | + __be32 antenna; | |
| 153 | + __be32 rssi; | |
| 154 | + __be32 channel; | |
| 155 | + __be32 phyerror; | |
| 156 | + __be32 connix; /* key table ix for bss traffic */ | |
| 157 | + __be32 decrypterror; | |
| 158 | + __be32 keycachemiss; | |
| 159 | + __be32 pad; /* XXX? */ | |
| 160 | +} __packed; | |
| 161 | + | |
| 162 | +struct ar5523_tx_desc { | |
| 163 | + __be32 msglen; | |
| 164 | + __be32 msgid; /* msg id (supplied by host) */ | |
| 165 | + __be32 type; /* opcode: WDMSG_SEND or WDCMSG_FLUSH */ | |
| 166 | + __be32 txqid; /* tx queue id and flags */ | |
| 167 | +#define UATH_TXQID_MASK 0x0f | |
| 168 | +#define UATH_TXQID_MINRATE 0x10 /* use min tx rate */ | |
| 169 | +#define UATH_TXQID_FF 0x20 /* content is fast frame */ | |
| 170 | + __be32 connid; /* tx connection id */ | |
| 171 | +#define UATH_ID_INVALID 0xffffffff /* for sending prior to connection */ | |
| 172 | + __be32 flags; /* non-zero if response desired */ | |
| 173 | +#define UATH_TX_NOTIFY (1 << 24) /* f/w will send a UATH_NOTIF_TX */ | |
| 174 | + __be32 buflen; /* payload length */ | |
| 175 | +} __packed; | |
| 176 | + | |
| 177 | + | |
| 178 | +#define AR5523_ID_BSS 2 | |
| 179 | +#define AR5523_ID_BROADCAST 0xffffffff | |
| 180 | + | |
| 181 | +/* structure for command UATH_CMD_WRITE_MAC */ | |
| 182 | +struct ar5523_write_mac { | |
| 183 | + __be32 reg; | |
| 184 | + __be32 len; | |
| 185 | + u8 data[32]; | |
| 186 | +} __packed; | |
| 187 | + | |
| 188 | +struct ar5523_cmd_rateset { | |
| 189 | + __u8 length; | |
| 190 | +#define AR5523_MAX_NRATES 32 | |
| 191 | + __u8 set[AR5523_MAX_NRATES]; | |
| 192 | +}; | |
| 193 | + | |
| 194 | +struct ar5523_cmd_set_associd { /* AR5523_WRITE_ASSOCID */ | |
| 195 | + __be32 defaultrateix; | |
| 196 | + __be32 associd; | |
| 197 | + __be32 timoffset; | |
| 198 | + __be32 turboprime; | |
| 199 | + __u8 bssid[6]; | |
| 200 | +} __packed; | |
| 201 | + | |
| 202 | +/* structure for command WDCMSG_RESET */ | |
| 203 | +struct ar5523_cmd_reset { | |
| 204 | + __be32 flags; /* channel flags */ | |
| 205 | +#define UATH_CHAN_TURBO 0x0100 | |
| 206 | +#define UATH_CHAN_CCK 0x0200 | |
| 207 | +#define UATH_CHAN_OFDM 0x0400 | |
| 208 | +#define UATH_CHAN_2GHZ 0x1000 | |
| 209 | +#define UATH_CHAN_5GHZ 0x2000 | |
| 210 | + __be32 freq; /* channel frequency */ | |
| 211 | + __be32 maxrdpower; | |
| 212 | + __be32 cfgctl; | |
| 213 | + __be32 twiceantennareduction; | |
| 214 | + __be32 channelchange; | |
| 215 | + __be32 keeprccontent; | |
| 216 | +} __packed; | |
| 217 | + | |
| 218 | +/* structure for command WDCMSG_SET_BASIC_RATE */ | |
| 219 | +struct ar5523_cmd_rates { | |
| 220 | + __be32 connid; | |
| 221 | + __be32 keeprccontent; | |
| 222 | + __be32 size; | |
| 223 | + struct ar5523_cmd_rateset rateset; | |
| 224 | +} __packed; | |
| 225 | + | |
| 226 | +enum { | |
| 227 | + WLAN_MODE_NONE = 0, | |
| 228 | + WLAN_MODE_11b, | |
| 229 | + WLAN_MODE_11a, | |
| 230 | + WLAN_MODE_11g, | |
| 231 | + WLAN_MODE_11a_TURBO, | |
| 232 | + WLAN_MODE_11g_TURBO, | |
| 233 | + WLAN_MODE_11a_TURBO_PRIME, | |
| 234 | + WLAN_MODE_11g_TURBO_PRIME, | |
| 235 | + WLAN_MODE_11a_XR, | |
| 236 | + WLAN_MODE_11g_XR, | |
| 237 | +}; | |
| 238 | + | |
| 239 | +struct ar5523_cmd_connection_attr { | |
| 240 | + __be32 longpreambleonly; | |
| 241 | + struct ar5523_cmd_rateset rateset; | |
| 242 | + __be32 wlanmode; | |
| 243 | +} __packed; | |
| 244 | + | |
| 245 | +/* structure for command AR5523_CREATE_CONNECTION */ | |
| 246 | +struct ar5523_cmd_create_connection { | |
| 247 | + __be32 connid; | |
| 248 | + __be32 bssid; | |
| 249 | + __be32 size; | |
| 250 | + struct ar5523_cmd_connection_attr connattr; | |
| 251 | +} __packed; | |
| 252 | + | |
| 253 | +struct ar5523_cmd_ledsteady { /* WDCMSG_SET_LED_STEADY */ | |
| 254 | + __be32 lednum; | |
| 255 | +#define UATH_LED_LINK 0 | |
| 256 | +#define UATH_LED_ACTIVITY 1 | |
| 257 | + __be32 ledmode; | |
| 258 | +#define UATH_LED_OFF 0 | |
| 259 | +#define UATH_LED_ON 1 | |
| 260 | +} __packed; | |
| 261 | + | |
| 262 | +struct ar5523_cmd_ledblink { /* WDCMSG_SET_LED_BLINK */ | |
| 263 | + __be32 lednum; | |
| 264 | + __be32 ledmode; | |
| 265 | + __be32 blinkrate; | |
| 266 | + __be32 slowmode; | |
| 267 | +} __packed; | |
| 268 | + | |
| 269 | +struct ar5523_cmd_ledstate { /* WDCMSG_SET_LED_STATE */ | |
| 270 | + __be32 connected; | |
| 271 | +} __packed; | |
| 272 | + | |
| 273 | +struct ar5523_cmd_txq_attr { | |
| 274 | + __be32 priority; | |
| 275 | + __be32 aifs; | |
| 276 | + __be32 logcwmin; | |
| 277 | + __be32 logcwmax; | |
| 278 | + __be32 bursttime; | |
| 279 | + __be32 mode; | |
| 280 | + __be32 qflags; | |
| 281 | +} __packed; | |
| 282 | + | |
| 283 | +struct ar5523_cmd_txq_setup { /* WDCMSG_SETUP_TX_QUEUE */ | |
| 284 | + __be32 qid; | |
| 285 | + __be32 len; | |
| 286 | + struct ar5523_cmd_txq_attr attr; | |
| 287 | +} __packed; | |
| 288 | + | |
| 289 | +struct ar5523_cmd_rx_filter { /* WDCMSG_RX_FILTER */ | |
| 290 | + __be32 bits; | |
| 291 | +#define UATH_FILTER_RX_UCAST 0x00000001 | |
| 292 | +#define UATH_FILTER_RX_MCAST 0x00000002 | |
| 293 | +#define UATH_FILTER_RX_BCAST 0x00000004 | |
| 294 | +#define UATH_FILTER_RX_CONTROL 0x00000008 | |
| 295 | +#define UATH_FILTER_RX_BEACON 0x00000010 /* beacon frames */ | |
| 296 | +#define UATH_FILTER_RX_PROM 0x00000020 /* promiscuous mode */ | |
| 297 | +#define UATH_FILTER_RX_PHY_ERR 0x00000040 /* phy errors */ | |
| 298 | +#define UATH_FILTER_RX_PHY_RADAR 0x00000080 /* radar phy errors */ | |
| 299 | +#define UATH_FILTER_RX_XR_POOL 0x00000400 /* XR group polls */ | |
| 300 | +#define UATH_FILTER_RX_PROBE_REQ 0x00000800 | |
| 301 | + __be32 op; | |
| 302 | +#define UATH_FILTER_OP_INIT 0x0 | |
| 303 | +#define UATH_FILTER_OP_SET 0x1 | |
| 304 | +#define UATH_FILTER_OP_CLEAR 0x2 | |
| 305 | +#define UATH_FILTER_OP_TEMP 0x3 | |
| 306 | +#define UATH_FILTER_OP_RESTORE 0x4 | |
| 307 | +} __packed; | |
| 308 | + | |
| 309 | +enum { | |
| 310 | + CFG_NONE, /* Sentinal to indicate "no config" */ | |
| 311 | + CFG_REG_DOMAIN, /* Regulatory Domain */ | |
| 312 | + CFG_RATE_CONTROL_ENABLE, | |
| 313 | + CFG_DEF_XMIT_DATA_RATE, /* NB: if rate control is not enabled */ | |
| 314 | + CFG_HW_TX_RETRIES, | |
| 315 | + CFG_SW_TX_RETRIES, | |
| 316 | + CFG_SLOW_CLOCK_ENABLE, | |
| 317 | + CFG_COMP_PROC, | |
| 318 | + CFG_USER_RTS_THRESHOLD, | |
| 319 | + CFG_XR2NORM_RATE_THRESHOLD, | |
| 320 | + CFG_XRMODE_SWITCH_COUNT, | |
| 321 | + CFG_PROTECTION_TYPE, | |
| 322 | + CFG_BURST_SEQ_THRESHOLD, | |
| 323 | + CFG_ABOLT, | |
| 324 | + CFG_IQ_LOG_COUNT_MAX, | |
| 325 | + CFG_MODE_CTS, | |
| 326 | + CFG_WME_ENABLED, | |
| 327 | + CFG_GPRS_CBR_PERIOD, | |
| 328 | + CFG_SERVICE_TYPE, | |
| 329 | + /* MAC Address to use. Overrides EEPROM */ | |
| 330 | + CFG_MAC_ADDR, | |
| 331 | + CFG_DEBUG_EAR, | |
| 332 | + CFG_INIT_REGS, | |
| 333 | + /* An ID for use in error & debug messages */ | |
| 334 | + CFG_DEBUG_ID, | |
| 335 | + CFG_COMP_WIN_SZ, | |
| 336 | + CFG_DIVERSITY_CTL, | |
| 337 | + CFG_TP_SCALE, | |
| 338 | + CFG_TPC_HALF_DBM5, | |
| 339 | + CFG_TPC_HALF_DBM2, | |
| 340 | + CFG_OVERRD_TX_POWER, | |
| 341 | + CFG_USE_32KHZ_CLOCK, | |
| 342 | + CFG_GMODE_PROTECTION, | |
| 343 | + CFG_GMODE_PROTECT_RATE_INDEX, | |
| 344 | + CFG_GMODE_NON_ERP_PREAMBLE, | |
| 345 | + CFG_WDC_TRANSPORT_CHUNK_SIZE, | |
| 346 | +}; | |
| 347 | + | |
| 348 | +enum { | |
| 349 | + /* Sentinal to indicate "no capability" */ | |
| 350 | + CAP_NONE, | |
| 351 | + CAP_ALL, /* ALL capabilities */ | |
| 352 | + CAP_TARGET_VERSION, | |
| 353 | + CAP_TARGET_REVISION, | |
| 354 | + CAP_MAC_VERSION, | |
| 355 | + CAP_MAC_REVISION, | |
| 356 | + CAP_PHY_REVISION, | |
| 357 | + CAP_ANALOG_5GHz_REVISION, | |
| 358 | + CAP_ANALOG_2GHz_REVISION, | |
| 359 | + /* Target supports WDC message debug features */ | |
| 360 | + CAP_DEBUG_WDCMSG_SUPPORT, | |
| 361 | + | |
| 362 | + CAP_REG_DOMAIN, | |
| 363 | + CAP_COUNTRY_CODE, | |
| 364 | + CAP_REG_CAP_BITS, | |
| 365 | + | |
| 366 | + CAP_WIRELESS_MODES, | |
| 367 | + CAP_CHAN_SPREAD_SUPPORT, | |
| 368 | + CAP_SLEEP_AFTER_BEACON_BROKEN, | |
| 369 | + CAP_COMPRESS_SUPPORT, | |
| 370 | + CAP_BURST_SUPPORT, | |
| 371 | + CAP_FAST_FRAMES_SUPPORT, | |
| 372 | + CAP_CHAP_TUNING_SUPPORT, | |
| 373 | + CAP_TURBOG_SUPPORT, | |
| 374 | + CAP_TURBO_PRIME_SUPPORT, | |
| 375 | + CAP_DEVICE_TYPE, | |
| 376 | + CAP_XR_SUPPORT, | |
| 377 | + CAP_WME_SUPPORT, | |
| 378 | + CAP_TOTAL_QUEUES, | |
| 379 | + CAP_CONNECTION_ID_MAX, /* Should absorb CAP_KEY_CACHE_SIZE */ | |
| 380 | + | |
| 381 | + CAP_LOW_5GHZ_CHAN, | |
| 382 | + CAP_HIGH_5GHZ_CHAN, | |
| 383 | + CAP_LOW_2GHZ_CHAN, | |
| 384 | + CAP_HIGH_2GHZ_CHAN, | |
| 385 | + | |
| 386 | + CAP_MIC_AES_CCM, | |
| 387 | + CAP_MIC_CKIP, | |
| 388 | + CAP_MIC_TKIP, | |
| 389 | + CAP_MIC_TKIP_WME, | |
| 390 | + CAP_CIPHER_AES_CCM, | |
| 391 | + CAP_CIPHER_CKIP, | |
| 392 | + CAP_CIPHER_TKIP, | |
| 393 | + | |
| 394 | + CAP_TWICE_ANTENNAGAIN_5G, | |
| 395 | + CAP_TWICE_ANTENNAGAIN_2G, | |
| 396 | +}; | |
| 397 | + | |
| 398 | +enum { | |
| 399 | + ST_NONE, /* Sentinal to indicate "no status" */ | |
| 400 | + ST_ALL, | |
| 401 | + ST_SERVICE_TYPE, | |
| 402 | + ST_WLAN_MODE, | |
| 403 | + ST_FREQ, | |
| 404 | + ST_BAND, | |
| 405 | + ST_LAST_RSSI, | |
| 406 | + ST_PS_FRAMES_DROPPED, | |
| 407 | + ST_CACHED_DEF_ANT, | |
| 408 | + ST_COUNT_OTHER_RX_ANT, | |
| 409 | + ST_USE_FAST_DIVERSITY, | |
| 410 | + ST_MAC_ADDR, | |
| 411 | + ST_RX_GENERATION_NUM, | |
| 412 | + ST_TX_QUEUE_DEPTH, | |
| 413 | + ST_SERIAL_NUMBER, | |
| 414 | + ST_WDC_TRANSPORT_CHUNK_SIZE, | |
| 415 | +}; | |
| 416 | + | |
| 417 | +enum { | |
| 418 | + TARGET_DEVICE_AWAKE, | |
| 419 | + TARGET_DEVICE_SLEEP, | |
| 420 | + TARGET_DEVICE_PWRDN, | |
| 421 | + TARGET_DEVICE_PWRSAVE, | |
| 422 | + TARGET_DEVICE_SUSPEND, | |
| 423 | + TARGET_DEVICE_RESUME, | |
| 424 | +}; | |
| 425 | + | |
| 426 | +/* this is in net/ieee80211.h, but that conflicts with the mac80211 headers */ | |
| 427 | +#define IEEE80211_2ADDR_LEN 16 | |
| 428 | + | |
| 429 | +#define AR5523_MIN_RXBUFSZ \ | |
| 430 | + (((sizeof(__be32) + IEEE80211_2ADDR_LEN + \ | |
| 431 | + sizeof(struct ar5523_rx_desc)) + 3) & ~3) | |
| @@ -301,7 +301,7 @@ static bool ath6kl_cfg80211_ready(struct ath6kl_vif *vif) · 300 unmodified lines | ||
| 301 | 301 | |
| 302 | 302 | static bool ath6kl_is_wpa_ie(const u8 *pos) |
| 303 | 303 | { |
| 304 | − return pos[0] == WLAN_EID_WPA && pos[1] >= 4 && | |
| 304 | + return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && | |
| 305 | 305 | pos[2] == 0x00 && pos[3] == 0x50 && |
| 306 | 306 | pos[4] == 0xf2 && pos[5] == 0x01; |
| 307 | 307 | } |
| @@ -3651,7 +3651,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) · 3343 unmodified lines | ||
| 3651 | 3651 | |
| 3652 | 3652 | if (test_bit(ATH6KL_FW_CAPABILITY_INACTIVITY_TIMEOUT, |
| 3653 | 3653 | ar->fw_capabilities)) |
| 3654 | − ar->wiphy->features = NL80211_FEATURE_INACTIVITY_TIMER; | |
| 3654 | + ar->wiphy->features |= NL80211_FEATURE_INACTIVITY_TIMER; | |
| 3655 | 3655 | |
| 3656 | 3656 | ar->wiphy->probe_resp_offload = |
| 3657 | 3657 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | |
| @@ -276,6 +276,11 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) · 275 unmodified lines | ||
| 276 | 276 | offset_array[i], |
| 277 | 277 | REG_READ(ah, offset_array[i])); |
| 278 | 278 | |
| 279 | + if (AR_SREV_9565(ah) && | |
| 280 | + (iCoff == 63 || qCoff == 63 || | |
| 281 | + iCoff == -63 || qCoff == -63)) | |
| 282 | + return; | |
| 283 | + | |
| 279 | 284 | REG_RMW_FIELD(ah, offset_array[i], |
| 280 | 285 | AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, |
| 281 | 286 | iCoff); |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | #include "hw.h" |
| 19 | 19 | #include "ar9003_phy.h" |
| 20 | 20 | #include "ar9003_eeprom.h" |
| 21 | +#include "ar9003_mci.h" | |
| 21 | 22 | |
| 22 | 23 | #define COMP_HDR_LEN 4 |
| 23 | 24 | #define COMP_CKSUM_LEN 2 |
| @@ -41,7 +42,6 @@ · 17 unmodified lines | ||
| 41 | 42 | static int ar9003_hw_power_interpolate(int32_t x, |
| 42 | 43 | int32_t *px, int32_t *py, u_int16_t np); |
| 43 | 44 | |
| 44 | − | |
| 45 | 45 | static const struct ar9300_eeprom ar9300_default = { |
| 46 | 46 | .eepromVersion = 2, |
| 47 | 47 | .templateVersion = 2, |
| @@ -2989,7 +2989,7 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, · 2941 unmodified lines | ||
| 2989 | 2989 | case EEP_PAPRD: |
| 2990 | 2990 | if (AR_SREV_9462(ah)) |
| 2991 | 2991 | return false; |
| 2992 | − if (!ah->config.enable_paprd); | |
| 2992 | + if (!ah->config.enable_paprd) | |
| 2993 | 2993 | return false; |
| 2994 | 2994 | return !!(pBase->featureEnable & BIT(5)); |
| 2995 | 2995 | case EEP_CHAIN_MASK_REDUCE: |
| @@ -3601,7 +3601,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) · 605 unmodified lines | ||
| 3601 | 3601 | * 7:4 R/W SWITCH_TABLE_COM_SPDT_WLAN_IDLE |
| 3602 | 3602 | * SWITCH_TABLE_COM_SPDT_WLAN_IDLE |
| 3603 | 3603 | */ |
| 3604 | − if (AR_SREV_9462_20_OR_LATER(ah)) { | |
| 3604 | + if (AR_SREV_9462_20(ah) || AR_SREV_9565(ah)) { | |
| 3605 | 3605 | value = ar9003_switch_com_spdt_get(ah, is2ghz); |
| 3606 | 3606 | REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, |
| 3607 | 3607 | AR_SWITCH_TABLE_COM_SPDT_ALL, value); |
| @@ -5037,16 +5037,28 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, · 1429 unmodified lines | ||
| 5037 | 5037 | case CTL_5GHT20: |
| 5038 | 5038 | case CTL_2GHT20: |
| 5039 | 5039 | for (i = ALL_TARGET_HT20_0_8_16; |
| 5040 | − i <= ALL_TARGET_HT20_23; i++) | |
| 5040 | + i <= ALL_TARGET_HT20_23; i++) { | |
| 5041 | 5041 | pPwrArray[i] = (u8)min((u16)pPwrArray[i], |
| 5042 | 5042 | minCtlPower); |
| 5043 | + if (ath9k_hw_mci_is_enabled(ah)) | |
| 5044 | + pPwrArray[i] = | |
| 5045 | + (u8)min((u16)pPwrArray[i], | |
| 5046 | + ar9003_mci_get_max_txpower(ah, | |
| 5047 | + pCtlMode[ctlMode])); | |
| 5048 | + } | |
| 5043 | 5049 | break; |
| 5044 | 5050 | case CTL_5GHT40: |
| 5045 | 5051 | case CTL_2GHT40: |
| 5046 | 5052 | for (i = ALL_TARGET_HT40_0_8_16; |
| 5047 | − i <= ALL_TARGET_HT40_23; i++) | |
| 5053 | + i <= ALL_TARGET_HT40_23; i++) { | |
| 5048 | 5054 | pPwrArray[i] = (u8)min((u16)pPwrArray[i], |
| 5049 | 5055 | minCtlPower); |
| 5056 | + if (ath9k_hw_mci_is_enabled(ah)) | |
| 5057 | + pPwrArray[i] = | |
| 5058 | + (u8)min((u16)pPwrArray[i], | |
| 5059 | + ar9003_mci_get_max_txpower(ah, | |
| 5060 | + pCtlMode[ctlMode])); | |
| 5061 | + } | |
| 5050 | 5062 | break; |
| 5051 | 5063 | default: |
| 5052 | 5064 | break; |
| @@ -219,10 +219,10 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) · 218 unmodified lines | ||
| 219 | 219 | |
| 220 | 220 | /* Awake -> Sleep Setting */ |
| 221 | 221 | INIT_INI_ARRAY(&ah->iniPcieSerdes, |
| 222 | − ar9462_pciephy_pll_on_clkreq_disable_L1_2p0); | |
| 222 | + ar9462_pciephy_clkreq_disable_L1_2p0); | |
| 223 | 223 | /* Sleep -> Awake Setting */ |
| 224 | 224 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, |
| 225 | − ar9462_pciephy_pll_on_clkreq_disable_L1_2p0); | |
| 225 | + ar9462_pciephy_clkreq_disable_L1_2p0); | |
| 226 | 226 | |
| 227 | 227 | /* Fast clock modal settings */ |
| 228 | 228 | INIT_INI_ARRAY(&ah->iniModesFastClock, |
| @@ -328,9 +328,9 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) · 99 unmodified lines | ||
| 328 | 328 | ar9565_1p0_Modes_lowest_ob_db_tx_gain_table); |
| 329 | 329 | |
| 330 | 330 | INIT_INI_ARRAY(&ah->iniPcieSerdes, |
| 331 | − ar9565_1p0_pciephy_pll_on_clkreq_disable_L1); | |
| 331 | + ar9565_1p0_pciephy_clkreq_disable_L1); | |
| 332 | 332 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, |
| 333 | − ar9565_1p0_pciephy_pll_on_clkreq_disable_L1); | |
| 333 | + ar9565_1p0_pciephy_clkreq_disable_L1); | |
| 334 | 334 | |
| 335 | 335 | INIT_INI_ARRAY(&ah->iniModesFastClock, |
| 336 | 336 | ar9565_1p0_modes_fast_clock); |
| @@ -750,6 +750,9 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, · 749 unmodified lines | ||
| 750 | 750 | |
| 751 | 751 | mci_hw->bt_state = MCI_BT_AWAKE; |
| 752 | 752 | |
| 753 | + REG_CLR_BIT(ah, AR_PHY_TIMING4, | |
| 754 | + 1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT); | |
| 755 | + | |
| 753 | 756 | if (caldata) { |
| 754 | 757 | caldata->done_txiqcal_once = false; |
| 755 | 758 | caldata->done_txclcal_once = false; |
| @@ -759,6 +762,9 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, · 3 unmodified lines | ||
| 759 | 762 | if (!ath9k_hw_init_cal(ah, chan)) |
| 760 | 763 | return -EIO; |
| 761 | 764 | |
| 765 | + REG_SET_BIT(ah, AR_PHY_TIMING4, | |
| 766 | + 1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT); | |
| 767 | + | |
| 762 | 768 | exit: |
| 763 | 769 | ar9003_mci_enable_interrupt(ah); |
| 764 | 770 | return 0; |
| @@ -799,6 +805,9 @@ static void ar9003_mci_osla_setup(struct ath_hw *ah, bool enable) · 34 unmodified lines | ||
| 799 | 805 | REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, |
| 800 | 806 | AR_MCI_SCHD_TABLE_2_MEM_BASED, 1); |
| 801 | 807 | |
| 808 | + if (AR_SREV_9565(ah)) | |
| 809 | + REG_RMW_FIELD(ah, AR_MCI_MISC, AR_MCI_MISC_HW_FIX_EN, 1); | |
| 810 | + | |
| 802 | 811 | if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) { |
| 803 | 812 | thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH); |
| 804 | 813 | 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, · 13 unmodified lines | ||
| 818 | 827 | { |
| 819 | 828 | struct ath_common *common = ath9k_hw_common(ah); |
| 820 | 829 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; |
| 821 | − u32 regval; | |
| 830 | + u32 regval, i; | |
| 822 | 831 | |
| 823 | 832 | ath_dbg(common, MCI, "MCI Reset (full_sleep = %d, is_2g = %d)\n", |
| 824 | 833 | is_full_sleep, is_2g); |
| @@ -847,11 +856,18 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, · 22 unmodified lines | ||
| 847 | 856 | SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) | |
| 848 | 857 | SM(1, AR_BTCOEX_CTRL_PA_SHARED) | |
| 849 | 858 | SM(1, AR_BTCOEX_CTRL_LNA_SHARED) | |
| 850 | − SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) | | |
| 851 | − SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) | | |
| 852 | 859 | SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) | |
| 853 | 860 | SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) | |
| 854 | 861 | SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); |
| 862 | + if (AR_SREV_9565(ah)) { | |
| 863 | + regval |= SM(1, AR_BTCOEX_CTRL_NUM_ANTENNAS) | | |
| 864 | + SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK); | |
| 865 | + REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, | |
| 866 | + AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x1); | |
| 867 | + } else { | |
| 868 | + regval |= SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) | | |
| 869 | + SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK); | |
| 870 | + } | |
| 855 | 871 | |
| 856 | 872 | REG_WRITE(ah, AR_BTCOEX_CTRL, regval); |
| 857 | 873 | |
| @@ -865,9 +881,24 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, · 7 unmodified lines | ||
| 865 | 881 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3, |
| 866 | 882 | AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20); |
| 867 | 883 | |
| 868 | − REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 1); | |
| 884 | + REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 0); | |
| 869 | 885 | REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); |
| 870 | 886 | |
| 887 | + /* Set the time out to 3.125ms (5 BT slots) */ | |
| 888 | + REG_RMW_FIELD(ah, AR_BTCOEX_WL_LNA, AR_BTCOEX_WL_LNA_TIMEOUT, 0x3D090); | |
| 889 | + | |
| 890 | + /* concurrent tx priority */ | |
| 891 | + if (mci->config & ATH_MCI_CONFIG_CONCUR_TX) { | |
| 892 | + REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, | |
| 893 | + AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE, 0); | |
| 894 | + REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, | |
| 895 | + AR_BTCOEX_CTRL2_TXPWR_THRESH, 0x7f); | |
| 896 | + REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, | |
| 897 | + AR_BTCOEX_CTRL_REDUCE_TXPWR, 0); | |
| 898 | + for (i = 0; i < 8; i++) | |
| 899 | + REG_WRITE(ah, AR_BTCOEX_MAX_TXPWR(i), 0x7f7f7f7f); | |
| 900 | + } | |
| 901 | + | |
| 871 | 902 | regval = MS(mci->config, ATH_MCI_CONFIG_CLK_DIV); |
| 872 | 903 | REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, regval); |
| 873 | 904 | 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, · 36 unmodified lines | ||
| 910 | 941 | mci->ready = true; |
| 911 | 942 | ar9003_mci_prep_interface(ah); |
| 912 | 943 | |
| 944 | + if (AR_SREV_9565(ah)) | |
| 945 | + REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL, | |
| 946 | + AR_MCI_DBG_CNT_CTRL_ENABLE, 0); | |
| 913 | 947 | if (en_int) |
| 914 | 948 | ar9003_mci_enable_interrupt(ah); |
| 915 | 949 | |
| @@ -1028,7 +1062,9 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force) · 112 unmodified lines | ||
| 1028 | 1062 | |
| 1029 | 1063 | if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) |
| 1030 | 1064 | ar9003_mci_osla_setup(ah, true); |
| 1031 | − REG_WRITE(ah, AR_SELFGEN_MASK, 0x02); | |
| 1065 | + | |
| 1066 | + if (AR_SREV_9462(ah)) | |
| 1067 | + REG_WRITE(ah, AR_SELFGEN_MASK, 0x02); | |
| 1032 | 1068 | } else { |
| 1033 | 1069 | ar9003_mci_send_lna_take(ah, true); |
| 1034 | 1070 | udelay(5); |
| @@ -1170,7 +1206,7 @@ EXPORT_SYMBOL(ar9003_mci_cleanup); · 135 unmodified lines | ||
| 1170 | 1206 | u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type) |
| 1171 | 1207 | { |
| 1172 | 1208 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; |
| 1173 | − u32 value = 0; | |
| 1209 | + u32 value = 0, tsf; | |
| 1174 | 1210 | u8 query_type; |
| 1175 | 1211 | |
| 1176 | 1212 | switch (state_type) { |
| @@ -1228,6 +1264,14 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type) · 51 unmodified lines | ||
| 1228 | 1264 | ar9003_mci_send_coex_bt_status_query(ah, true, query_type); |
| 1229 | 1265 | break; |
| 1230 | 1266 | case MCI_STATE_RECOVER_RX: |
| 1267 | + tsf = ath9k_hw_gettsf32(ah); | |
| 1268 | + if ((tsf - mci->last_recovery) <= MCI_RECOVERY_DUR_TSF) { | |
| 1269 | + ath_dbg(ath9k_hw_common(ah), MCI, | |
| 1270 | + "(MCI) ignore Rx recovery\n"); | |
| 1271 | + break; | |
| 1272 | + } | |
| 1273 | + ath_dbg(ath9k_hw_common(ah), MCI, "(MCI) RECOVER RX\n"); | |
| 1274 | + mci->last_recovery = tsf; | |
| 1231 | 1275 | ar9003_mci_prep_interface(ah); |
| 1232 | 1276 | mci->query_bt = true; |
| 1233 | 1277 | mci->need_flush_btinfo = true; |
| @@ -1426,3 +1470,17 @@ void ar9003_mci_send_wlan_channels(struct ath_hw *ah) · 192 unmodified lines | ||
| 1426 | 1470 | ar9003_mci_send_coex_wlan_channels(ah, true); |
| 1427 | 1471 | } |
| 1428 | 1472 | EXPORT_SYMBOL(ar9003_mci_send_wlan_channels); |
| 1473 | + | |
| 1474 | +u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode) | |
| 1475 | +{ | |
| 1476 | + if (!ah->btcoex_hw.mci.concur_tx) | |
| 1477 | + goto out; | |
| 1478 | + | |
| 1479 | + if (ctlmode == CTL_2GHT20) | |
| 1480 | + return ATH_BTCOEX_HT20_MAX_TXPOWER; | |
| 1481 | + else if (ctlmode == CTL_2GHT40) | |
| 1482 | + return ATH_BTCOEX_HT40_MAX_TXPOWER; | |
| 1483 | + | |
| 1484 | +out: | |
| 1485 | + return -1; | |
| 1486 | +} | |
| @@ -18,6 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | #define AR9003_MCI_H |
| 19 | 19 | |
| 20 | 20 | #define MCI_FLAG_DISABLE_TIMESTAMP 0x00000001 /* Disable time stamp */ |
| 21 | +#define MCI_RECOVERY_DUR_TSF (100 * 1000) /* 100 ms */ | |
| 21 | 22 | |
| 22 | 23 | /* Default remote BT device MCI COEX version */ |
| 23 | 24 | #define MCI_GPM_COEX_MAJOR_VERSION_DEFAULT 3 |
| @@ -125,6 +126,7 @@ enum ath_mci_gpm_coex_profile_type { · 101 unmodified lines | ||
| 125 | 126 | MCI_GPM_COEX_PROFILE_HID, |
| 126 | 127 | MCI_GPM_COEX_PROFILE_BNEP, |
| 127 | 128 | MCI_GPM_COEX_PROFILE_VOICE, |
| 129 | + MCI_GPM_COEX_PROFILE_A2DPVO, | |
| 128 | 130 | MCI_GPM_COEX_PROFILE_MAX |
| 129 | 131 | }; |
| 130 | 132 | |
| @@ -196,7 +198,6 @@ enum mci_state_type { · 65 unmodified lines | ||
| 196 | 198 | MCI_STATE_SEND_WLAN_COEX_VERSION, |
| 197 | 199 | MCI_STATE_SEND_VERSION_QUERY, |
| 198 | 200 | MCI_STATE_SEND_STATUS_QUERY, |
| 199 | − MCI_STATE_SET_CONCUR_TX_PRI, | |
| 200 | 201 | MCI_STATE_RECOVER_RX, |
| 201 | 202 | MCI_STATE_NEED_FTP_STOMP, |
| 202 | 203 | MCI_STATE_DEBUG, |
| @@ -278,6 +279,7 @@ void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked); · 75 unmodified lines | ||
| 278 | 279 | void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah); |
| 279 | 280 | void ar9003_mci_set_power_awake(struct ath_hw *ah); |
| 280 | 281 | void ar9003_mci_check_gpm_offset(struct ath_hw *ah); |
| 282 | +u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode); | |
| 281 | 283 | |
| 282 | 284 | #else |
| 283 | 285 | |
| @@ -324,6 +326,10 @@ static inline void ar9003_mci_set_power_awake(struct ath_hw *ah) · 40 unmodified lines | ||
| 324 | 326 | static inline void ar9003_mci_check_gpm_offset(struct ath_hw *ah) |
| 325 | 327 | { |
| 326 | 328 | } |
| 329 | +static inline u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode) | |
| 330 | +{ | |
| 331 | + return -1; | |
| 332 | +} | |
| 327 | 333 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ |
| 328 | 334 | |
| 329 | 335 | #endif |
| @@ -32,6 +32,7 @@ · 31 unmodified lines | ||
| 32 | 32 | #define AR_PHY_SPUR_REG (AR_CHAN_BASE + 0x1c) |
| 33 | 33 | #define AR_PHY_RX_IQCAL_CORR_B0 (AR_CHAN_BASE + 0xdc) |
| 34 | 34 | #define AR_PHY_TX_IQCAL_CONTROL_3 (AR_CHAN_BASE + 0xb0) |
| 35 | +#define AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT 16 | |
| 35 | 36 | |
| 36 | 37 | #define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 |
| 37 | 38 | #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] = { · 767 unmodified lines | ||
| 768 | 768 | {0x00016054, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
| 769 | 769 | }; |
| 770 | 770 | |
| 771 | −static const u32 ar9565_1p0_pciephy_pll_on_clkreq_disable_L1[][2] = { | |
| 771 | +static const u32 ar9565_1p0_pciephy_clkreq_disable_L1[][2] = { | |
| 772 | 772 | /* Addr allmodes */ |
| 773 | − {0x00018c00, 0x18212ede}, | |
| 773 | + {0x00018c00, 0x18213ede}, | |
| 774 | 774 | {0x00018c04, 0x000801d8}, |
| 775 | 775 | {0x00018c08, 0x0003780c}, |
| 776 | 776 | }; |
| @@ -437,6 +437,7 @@ void ath9k_set_beacon(struct ath_softc *sc); · 436 unmodified lines | ||
| 437 | 437 | #define ATH_LONG_CALINTERVAL_INT 1000 /* 1000 ms */ |
| 438 | 438 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ |
| 439 | 439 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ |
| 440 | +#define ATH_ANI_MAX_SKIP_COUNT 10 | |
| 440 | 441 | |
| 441 | 442 | #define ATH_PAPRD_TIMEOUT 100 /* msecs */ |
| 442 | 443 | #define ATH_PLL_WORK_INTERVAL 100 |
| @@ -478,6 +479,7 @@ struct ath_btcoex { · 35 unmodified lines | ||
| 478 | 479 | u32 btscan_no_stomp; /* in usec */ |
| 479 | 480 | u32 duty_cycle; |
| 480 | 481 | u32 bt_wait_time; |
| 482 | + int rssi_count; | |
| 481 | 483 | struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */ |
| 482 | 484 | struct ath_mci_profile mci; |
| 483 | 485 | }; |
| @@ -492,6 +494,7 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc); · 8 unmodified lines | ||
| 492 | 494 | void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status); |
| 493 | 495 | u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen); |
| 494 | 496 | void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc); |
| 497 | +int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 len, u32 size); | |
| 495 | 498 | #else |
| 496 | 499 | static inline int ath9k_init_btcoex(struct ath_softc *sc) |
| 497 | 500 | { |
| @@ -518,6 +521,11 @@ static inline u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, · 20 unmodified lines | ||
| 518 | 521 | static inline void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc) |
| 519 | 522 | { |
| 520 | 523 | } |
| 524 | +static inline int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, | |
| 525 | + u32 len, u32 size) | |
| 526 | +{ | |
| 527 | + return 0; | |
| 528 | +} | |
| 521 | 529 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ |
| 522 | 530 | |
| 523 | 531 | struct ath9k_wow_pattern { |
| @@ -642,6 +650,7 @@ enum sc_op_flags { · 118 unmodified lines | ||
| 642 | 650 | #define PS_WAIT_FOR_PSPOLL_DATA BIT(2) |
| 643 | 651 | #define PS_WAIT_FOR_TX_ACK BIT(3) |
| 644 | 652 | #define PS_BEACON_SYNC BIT(4) |
| 653 | +#define PS_WAIT_FOR_ANI BIT(5) | |
| 645 | 654 | |
| 646 | 655 | struct ath_rate_table; |
| 647 | 656 | |
| @@ -195,7 +195,7 @@ void ath9k_hw_btcoex_init_mci(struct ath_hw *ah) · 194 unmodified lines | ||
| 195 | 195 | ah->btcoex_hw.mci.need_flush_btinfo = false; |
| 196 | 196 | ah->btcoex_hw.mci.wlan_cal_seq = 0; |
| 197 | 197 | ah->btcoex_hw.mci.wlan_cal_done = 0; |
| 198 | − ah->btcoex_hw.mci.config = 0x2201; | |
| 198 | + ah->btcoex_hw.mci.config = (AR_SREV_9462(ah)) ? 0x2201 : 0xa4c1; | |
| 199 | 199 | } |
| 200 | 200 | EXPORT_SYMBOL(ath9k_hw_btcoex_init_mci); |
| 201 | 201 | |
| @@ -218,27 +218,45 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, · 16 unmodified lines | ||
| 218 | 218 | enum ath_stomp_type stomp_type) |
| 219 | 219 | { |
| 220 | 220 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; |
| 221 | + struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; | |
| 222 | + u8 txprio_shift[] = { 24, 16, 16, 0 }; /* tx priority weight */ | |
| 223 | + bool concur_tx = (mci_hw->concur_tx && btcoex_hw->tx_prio[stomp_type]); | |
| 224 | + const u32 *weight = ar9003_wlan_weights[stomp_type]; | |
| 225 | + int i; | |
| 221 | 226 | |
| 222 | − if (AR_SREV_9300_20_OR_LATER(ah)) { | |
| 223 | − const u32 *weight = ar9003_wlan_weights[stomp_type]; | |
| 224 | − int i; | |
| 225 | − | |
| 226 | − if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { | |
| 227 | − if ((stomp_type == ATH_BTCOEX_STOMP_LOW) && | |
| 228 | − btcoex_hw->mci.stomp_ftp) | |
| 229 | − stomp_type = ATH_BTCOEX_STOMP_LOW_FTP; | |
| 230 | − weight = mci_wlan_weights[stomp_type]; | |
| 231 | − } | |
| 232 | − | |
| 233 | − for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) { | |
| 234 | − btcoex_hw->bt_weight[i] = AR9300_BT_WGHT; | |
| 235 | − btcoex_hw->wlan_weight[i] = weight[i]; | |
| 236 | − } | |
| 237 | − } else { | |
| 227 | + if (!AR_SREV_9300_20_OR_LATER(ah)) { | |
| 238 | 228 | btcoex_hw->bt_coex_weights = |
| 239 | 229 | SM(bt_weight, AR_BTCOEX_BT_WGHT) | |
| 240 | 230 | SM(wlan_weight, AR_BTCOEX_WL_WGHT); |
| 231 | + return; | |
| 232 | + } | |
| 233 | + | |
| 234 | + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { | |
| 235 | + enum ath_stomp_type stype = | |
| 236 | + ((stomp_type == ATH_BTCOEX_STOMP_LOW) && | |
| 237 | + btcoex_hw->mci.stomp_ftp) ? | |
| 238 | + ATH_BTCOEX_STOMP_LOW_FTP : stomp_type; | |
| 239 | + weight = mci_wlan_weights[stype]; | |
| 241 | 240 | } |
| 241 | + | |
| 242 | + for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) { | |
| 243 | + btcoex_hw->bt_weight[i] = AR9300_BT_WGHT; | |
| 244 | + btcoex_hw->wlan_weight[i] = weight[i]; | |
| 245 | + if (concur_tx && i) { | |
| 246 | + btcoex_hw->wlan_weight[i] &= | |
| 247 | + ~(0xff << txprio_shift[i-1]); | |
| 248 | + btcoex_hw->wlan_weight[i] |= | |
| 249 | + (btcoex_hw->tx_prio[stomp_type] << | |
| 250 | + txprio_shift[i-1]); | |
| 251 | + } | |
| 252 | + } | |
| 253 | + /* Last WLAN weight has to be adjusted wrt tx priority */ | |
| 254 | + if (concur_tx) { | |
| 255 | + btcoex_hw->wlan_weight[i-1] &= ~(0xff << txprio_shift[i-1]); | |
| 256 | + btcoex_hw->wlan_weight[i-1] |= (btcoex_hw->tx_prio[stomp_type] | |
| 257 | + << txprio_shift[i-1]); | |
| 258 | + } | |
| 259 | + | |
| 242 | 260 | } |
| 243 | 261 | EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); |
| 244 | 262 | |
| @@ -385,3 +403,13 @@ void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, · 140 unmodified lines | ||
| 385 | 403 | } |
| 386 | 404 | } |
| 387 | 405 | EXPORT_SYMBOL(ath9k_hw_btcoex_bt_stomp); |
| 406 | + | |
| 407 | +void ath9k_hw_btcoex_set_concur_txprio(struct ath_hw *ah, u8 *stomp_txprio) | |
| 408 | +{ | |
| 409 | + struct ath_btcoex_hw *btcoex = &ah->btcoex_hw; | |
| 410 | + int i; | |
| 411 | + | |
| 412 | + for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++) | |
| 413 | + btcoex->tx_prio[i] = stomp_txprio[i]; | |
| 414 | +} | |
| 415 | +EXPORT_SYMBOL(ath9k_hw_btcoex_set_concur_txprio); | |
| @@ -39,6 +39,9 @@ · 38 unmodified lines | ||
| 39 | 39 | #define ATH_BTCOEX_RX_WAIT_TIME 100 |
| 40 | 40 | #define ATH_BTCOEX_STOMP_FTP_THRESH 5 |
| 41 | 41 | |
| 42 | +#define ATH_BTCOEX_HT20_MAX_TXPOWER 0x14 | |
| 43 | +#define ATH_BTCOEX_HT40_MAX_TXPOWER 0x10 | |
| 44 | + | |
| 42 | 45 | #define AR9300_NUM_BT_WEIGHTS 4 |
| 43 | 46 | #define AR9300_NUM_WLAN_WEIGHTS 4 |
| 44 | 47 | /* Defines the BT AR_BT_COEX_WGHT used */ |
| @@ -84,6 +87,8 @@ struct ath9k_hw_mci { · 39 unmodified lines | ||
| 84 | 87 | u8 bt_ver_minor; |
| 85 | 88 | u8 bt_state; |
| 86 | 89 | u8 stomp_ftp; |
| 90 | + bool concur_tx; | |
| 91 | + u32 last_recovery; | |
| 87 | 92 | }; |
| 88 | 93 | |
| 89 | 94 | struct ath_btcoex_hw { |
| @@ -98,6 +103,7 @@ struct ath_btcoex_hw { · 8 unmodified lines | ||
| 98 | 103 | u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ |
| 99 | 104 | u32 bt_weight[AR9300_NUM_BT_WEIGHTS]; |
| 100 | 105 | u32 wlan_weight[AR9300_NUM_WLAN_WEIGHTS]; |
| 106 | + u8 tx_prio[ATH_BTCOEX_STOMP_MAX]; | |
| 101 | 107 | }; |
| 102 | 108 | |
| 103 | 109 | void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah); |
| @@ -112,5 +118,6 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, · 8 unmodified lines | ||
| 112 | 118 | void ath9k_hw_btcoex_disable(struct ath_hw *ah); |
| 113 | 119 | void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, |
| 114 | 120 | enum ath_stomp_type stomp_type); |
| 121 | +void ath9k_hw_btcoex_set_concur_txprio(struct ath_hw *ah, u8 *stomp_txprio); | |
| 115 | 122 | |
| 116 | 123 | #endif |
| @@ -410,6 +410,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, · 409 unmodified lines | ||
| 410 | 410 | |
| 411 | 411 | ah->caldata->channel = chan->channel; |
| 412 | 412 | ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT; |
| 413 | + ah->caldata->chanmode = chan->chanmode; | |
| 413 | 414 | h = ah->caldata->nfCalHist; |
| 414 | 415 | default_nf = ath9k_hw_get_default_nf(ah, chan); |
| 415 | 416 | for (i = 0; i < NUM_NF_READINGS; i++) { |
| @@ -1586,6 +1586,35 @@ static const struct file_operations fops_samps = { · 1585 unmodified lines | ||
| 1586 | 1586 | |
| 1587 | 1587 | #endif |
| 1588 | 1588 | |
| 1589 | +#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | |
| 1590 | +static ssize_t read_file_btcoex(struct file *file, char __user *user_buf, | |
| 1591 | + size_t count, loff_t *ppos) | |
| 1592 | +{ | |
| 1593 | + struct ath_softc *sc = file->private_data; | |
| 1594 | + u32 len = 0, size = 1500; | |
| 1595 | + char *buf; | |
| 1596 | + size_t retval; | |
| 1597 | + | |
| 1598 | + buf = kzalloc(size, GFP_KERNEL); | |
| 1599 | + if (buf == NULL) | |
| 1600 | + return -ENOMEM; | |
| 1601 | + | |
| 1602 | + len = ath9k_dump_btcoex(sc, buf, len, size); | |
| 1603 | + | |
| 1604 | + retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | |
| 1605 | + kfree(buf); | |
| 1606 | + | |
| 1607 | + return retval; | |
| 1608 | +} | |
| 1609 | + | |
| 1610 | +static const struct file_operations fops_btcoex = { | |
| 1611 | + .read = read_file_btcoex, | |
| 1612 | + .open = simple_open, | |
| 1613 | + .owner = THIS_MODULE, | |
| 1614 | + .llseek = default_llseek, | |
| 1615 | +}; | |
| 1616 | +#endif | |
| 1617 | + | |
| 1589 | 1618 | int ath9k_init_debug(struct ath_hw *ah) |
| 1590 | 1619 | { |
| 1591 | 1620 | struct ath_common *common = ath9k_hw_common(ah); |
| @@ -1658,6 +1687,9 @@ int ath9k_init_debug(struct ath_hw *ah) · 66 unmodified lines | ||
| 1658 | 1687 | sc->debug.debugfs_phy, &sc->sc_ah->gpio_val); |
| 1659 | 1688 | debugfs_create_file("diversity", S_IRUSR | S_IWUSR, |
| 1660 | 1689 | sc->debug.debugfs_phy, sc, &fops_ant_diversity); |
| 1661 | − | |
| 1690 | +#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | |
| 1691 | + debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc, | |
| 1692 | + &fops_btcoex); | |
| 1693 | +#endif | |
| 1662 | 1694 | return 0; |
| 1663 | 1695 | } |
| @@ -187,6 +187,24 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) · 186 unmodified lines | ||
| 187 | 187 | } |
| 188 | 188 | } |
| 189 | 189 | |
| 190 | +static void ath_mci_ftp_adjust(struct ath_softc *sc) | |
| 191 | +{ | |
| 192 | + struct ath_btcoex *btcoex = &sc->btcoex; | |
| 193 | + struct ath_mci_profile *mci = &btcoex->mci; | |
| 194 | + struct ath_hw *ah = sc->sc_ah; | |
| 195 | + | |
| 196 | + if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) { | |
| 197 | + if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) && | |
| 198 | + (mci->num_pan || mci->num_other_acl)) | |
| 199 | + ah->btcoex_hw.mci.stomp_ftp = | |
| 200 | + (sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH); | |
| 201 | + else | |
| 202 | + ah->btcoex_hw.mci.stomp_ftp = false; | |
| 203 | + btcoex->bt_wait_time = 0; | |
| 204 | + sc->rx.num_pkts = 0; | |
| 205 | + } | |
| 206 | +} | |
| 207 | + | |
| 190 | 208 | /* |
| 191 | 209 | * This is the master bt coex timer which runs for every |
| 192 | 210 | * 45ms, bt traffic will be given priority during 55% of this |
| @@ -197,41 +215,43 @@ static void ath_btcoex_period_timer(unsigned long data) · 4 unmodified lines | ||
| 197 | 215 | struct ath_softc *sc = (struct ath_softc *) data; |
| 198 | 216 | struct ath_hw *ah = sc->sc_ah; |
| 199 | 217 | struct ath_btcoex *btcoex = &sc->btcoex; |
| 200 | − struct ath_mci_profile *mci = &btcoex->mci; | |
| 218 | + enum ath_stomp_type stomp_type; | |
| 201 | 219 | u32 timer_period; |
| 202 | − bool is_btscan; | |
| 203 | 220 | unsigned long flags; |
| 204 | 221 | |
| 205 | 222 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
| 206 | 223 | if (sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP) { |
| 224 | + btcoex->bt_wait_time += btcoex->btcoex_period; | |
| 207 | 225 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
| 208 | 226 | goto skip_hw_wakeup; |
| 209 | 227 | } |
| 210 | 228 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
| 211 | 229 | |
| 230 | + ath9k_mci_update_rssi(sc); | |
| 231 | + | |
| 212 | 232 | ath9k_ps_wakeup(sc); |
| 233 | + | |
| 213 | 234 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) |
| 214 | 235 | ath_detect_bt_priority(sc); |
| 215 | − is_btscan = test_bit(BT_OP_SCAN, &btcoex->op_flags); | |
| 216 | 236 | |
| 217 | − btcoex->bt_wait_time += btcoex->btcoex_period; | |
| 218 | − if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) { | |
| 219 | − if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) && | |
| 220 | − (mci->num_pan || mci->num_other_acl)) | |
| 221 | − ah->btcoex_hw.mci.stomp_ftp = | |
| 222 | − (sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH); | |
| 223 | − else | |
| 224 | − ah->btcoex_hw.mci.stomp_ftp = false; | |
| 225 | − btcoex->bt_wait_time = 0; | |
| 226 | − sc->rx.num_pkts = 0; | |
| 227 | − } | |
| 237 | + if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) | |
| 238 | + ath_mci_ftp_adjust(sc); | |
| 228 | 239 | |
| 229 | 240 | spin_lock_bh(&btcoex->btcoex_lock); |
| 230 | 241 | |
| 231 | − ath9k_hw_btcoex_bt_stomp(ah, is_btscan ? ATH_BTCOEX_STOMP_ALL : | |
| 232 | − btcoex->bt_stomp_type); | |
| 242 | + stomp_type = btcoex->bt_stomp_type; | |
| 243 | + timer_period = btcoex->btcoex_no_stomp; | |
| 244 | + | |
| 245 | + if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) { | |
| 246 | + if (test_bit(BT_OP_SCAN, &btcoex->op_flags)) { | |
| 247 | + stomp_type = ATH_BTCOEX_STOMP_ALL; | |
| 248 | + timer_period = btcoex->btscan_no_stomp; | |
| 249 | + } | |
| 250 | + } | |
| 233 | 251 | |
| 252 | + ath9k_hw_btcoex_bt_stomp(ah, stomp_type); | |
| 234 | 253 | ath9k_hw_btcoex_enable(ah); |
| 254 | + | |
| 235 | 255 | spin_unlock_bh(&btcoex->btcoex_lock); |
| 236 | 256 | |
| 237 | 257 | /* |
| @@ -243,17 +263,16 @@ static void ath_btcoex_period_timer(unsigned long data) · 5 unmodified lines | ||
| 243 | 263 | if (btcoex->hw_timer_enabled) |
| 244 | 264 | ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); |
| 245 | 265 | |
| 246 | − timer_period = is_btscan ? btcoex->btscan_no_stomp : | |
| 247 | − btcoex->btcoex_no_stomp; | |
| 248 | 266 | ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period, |
| 249 | 267 | timer_period * 10); |
| 250 | 268 | btcoex->hw_timer_enabled = true; |
| 251 | 269 | } |
| 252 | 270 | |
| 253 | 271 | ath9k_ps_restore(sc); |
| 272 | + | |
| 254 | 273 | skip_hw_wakeup: |
| 255 | − timer_period = btcoex->btcoex_period; | |
| 256 | − mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period)); | |
| 274 | + mod_timer(&btcoex->period_timer, | |
| 275 | + jiffies + msecs_to_jiffies(btcoex->btcoex_period)); | |
| 257 | 276 | } |
| 258 | 277 | |
| 259 | 278 | /* |
| @@ -273,7 +292,8 @@ static void ath_btcoex_no_stomp_timer(void *arg) · 13 unmodified lines | ||
| 273 | 292 | spin_lock_bh(&btcoex->btcoex_lock); |
| 274 | 293 | |
| 275 | 294 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || |
| 276 | − test_bit(BT_OP_SCAN, &btcoex->op_flags)) | |
| 295 | + (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && | |
| 296 | + test_bit(BT_OP_SCAN, &btcoex->op_flags))) | |
| 277 | 297 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); |
| 278 | 298 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) |
| 279 | 299 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); |
| @@ -474,4 +494,52 @@ int ath9k_init_btcoex(struct ath_softc *sc) · 194 unmodified lines | ||
| 474 | 494 | return 0; |
| 475 | 495 | } |
| 476 | 496 | |
| 497 | +int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 len, u32 size) | |
| 498 | +{ | |
| 499 | +#define ATH_DUMP_BTCOEX(_s, _val) \ | |
| 500 | + do { \ | |
| 501 | + len += snprintf(buf + len, size - len, \ | |
| 502 | + "%20s : %10d\n", _s, (_val)); \ | |
| 503 | + } while (0) | |
| 504 | + | |
| 505 | + struct ath_btcoex *btcoex = &sc->btcoex; | |
| 506 | + struct ath_mci_profile *mci = &btcoex->mci; | |
| 507 | + struct ath_hw *ah = sc->sc_ah; | |
| 508 | + struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; | |
| 509 | + int i; | |
| 510 | + | |
| 511 | + ATH_DUMP_BTCOEX("Total BT profiles", NUM_PROF(mci)); | |
| 512 | + ATH_DUMP_BTCOEX("Number of MGMT", mci->num_mgmt); | |
| 513 | + ATH_DUMP_BTCOEX("Number of SCO", mci->num_sco); | |
| 514 | + ATH_DUMP_BTCOEX("Number of A2DP", mci->num_a2dp); | |
| 515 | + ATH_DUMP_BTCOEX("Number of HID", mci->num_hid); | |
| 516 | + ATH_DUMP_BTCOEX("Number of PAN", mci->num_pan); | |
| 517 | + ATH_DUMP_BTCOEX("Number of ACL", mci->num_other_acl); | |
| 518 | + ATH_DUMP_BTCOEX("Number of BDR", mci->num_bdr); | |
| 519 | + ATH_DUMP_BTCOEX("Aggr. Limit", mci->aggr_limit); | |
| 520 | + ATH_DUMP_BTCOEX("Stomp Type", btcoex->bt_stomp_type); | |
| 521 | + ATH_DUMP_BTCOEX("BTCoex Period (msec)", btcoex->btcoex_period); | |
| 522 | + ATH_DUMP_BTCOEX("Duty Cycle", btcoex->duty_cycle); | |
| 523 | + ATH_DUMP_BTCOEX("BT Wait time", btcoex->bt_wait_time); | |
| 524 | + ATH_DUMP_BTCOEX("Concurrent Tx", btcoex_hw->mci.concur_tx); | |
| 525 | + ATH_DUMP_BTCOEX("Concur RSSI count", btcoex->rssi_count); | |
| 526 | + len += snprintf(buf + len, size - len, "BT Weights: "); | |
| 527 | + for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++) | |
| 528 | + len += snprintf(buf + len, size - len, "%08x ", | |
| 529 | + btcoex_hw->bt_weight[i]); | |
| 530 | + len += snprintf(buf + len, size - len, "\n"); | |
| 531 | + len += snprintf(buf + len, size - len, "WLAN Weights: "); | |
| 532 | + for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++) | |
| 533 | + len += snprintf(buf + len, size - len, "%08x ", | |
| 534 | + btcoex_hw->wlan_weight[i]); | |
| 535 | + len += snprintf(buf + len, size - len, "\n"); | |
| 536 | + len += snprintf(buf + len, size - len, "Tx Priorities: "); | |
| 537 | + for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++) | |
| 538 | + len += snprintf(buf + len, size - len, "%08x ", | |
| 539 | + btcoex_hw->tx_prio[i]); | |
| 540 | + len += snprintf(buf + len, size - len, "\n"); | |
| 541 | +#undef ATH_DUMP_BTCOEX | |
| 542 | + | |
| 543 | + return len; | |
| 544 | +} | |
| 477 | 545 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ |
| @@ -694,6 +694,20 @@ err_hw: · 693 unmodified lines | ||
| 694 | 694 | return ret; |
| 695 | 695 | } |
| 696 | 696 | |
| 697 | +static const struct ieee80211_iface_limit if_limits[] = { | |
| 698 | + { .max = 2, .types = BIT(NL80211_IFTYPE_STATION) | | |
| 699 | + BIT(NL80211_IFTYPE_P2P_CLIENT) }, | |
| 700 | + { .max = 2, .types = BIT(NL80211_IFTYPE_AP) | | |
| 701 | + BIT(NL80211_IFTYPE_P2P_GO) }, | |
| 702 | +}; | |
| 703 | + | |
| 704 | +static const struct ieee80211_iface_combination if_comb = { | |
| 705 | + .limits = if_limits, | |
| 706 | + .n_limits = ARRAY_SIZE(if_limits), | |
| 707 | + .max_interfaces = 2, | |
| 708 | + .num_different_channels = 1, | |
| 709 | +}; | |
| 710 | + | |
| 697 | 711 | static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, |
| 698 | 712 | struct ieee80211_hw *hw) |
| 699 | 713 | { |
| @@ -716,6 +730,9 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, · 16 unmodified lines | ||
| 716 | 730 | BIT(NL80211_IFTYPE_P2P_GO) | |
| 717 | 731 | BIT(NL80211_IFTYPE_P2P_CLIENT); |
| 718 | 732 | |
| 733 | + hw->wiphy->iface_combinations = &if_comb; | |
| 734 | + hw->wiphy->n_iface_combinations = 1; | |
| 735 | + | |
| 719 | 736 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
| 720 | 737 | |
| 721 | 738 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN | |
| @@ -1036,26 +1036,6 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, · 1035 unmodified lines | ||
| 1036 | 1036 | |
| 1037 | 1037 | mutex_lock(&priv->mutex); |
| 1038 | 1038 | |
| 1039 | − if (priv->nvifs >= ATH9K_HTC_MAX_VIF) { | |
| 1040 | − mutex_unlock(&priv->mutex); | |
| 1041 | − return -ENOBUFS; | |
| 1042 | − } | |
| 1043 | − | |
| 1044 | − if (priv->num_ibss_vif || | |
| 1045 | − (priv->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) { | |
| 1046 | − ath_err(common, "IBSS coexistence with other modes is not allowed\n"); | |
| 1047 | − mutex_unlock(&priv->mutex); | |
| 1048 | − return -ENOBUFS; | |
| 1049 | − } | |
| 1050 | − | |
| 1051 | − if (((vif->type == NL80211_IFTYPE_AP) || | |
| 1052 | − (vif->type == NL80211_IFTYPE_ADHOC)) && | |
| 1053 | − ((priv->num_ap_vif + priv->num_ibss_vif) >= ATH9K_HTC_MAX_BCN_VIF)) { | |
| 1054 | − ath_err(common, "Max. number of beaconing interfaces reached\n"); | |
| 1055 | − mutex_unlock(&priv->mutex); | |
| 1056 | − return -ENOBUFS; | |
| 1057 | − } | |
| 1058 | − | |
| 1059 | 1039 | ath9k_htc_ps_wakeup(priv); |
| 1060 | 1040 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); |
| 1061 | 1041 | memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); |
| @@ -2153,9 +2153,6 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah) · 2152 unmodified lines | ||
| 2153 | 2153 | AR_RTC_FORCE_WAKE_EN); |
| 2154 | 2154 | udelay(50); |
| 2155 | 2155 | |
| 2156 | − if (ath9k_hw_mci_is_enabled(ah)) | |
| 2157 | − ar9003_mci_set_power_awake(ah); | |
| 2158 | − | |
| 2159 | 2156 | for (i = POWER_UP_TIME / 50; i > 0; i--) { |
| 2160 | 2157 | val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; |
| 2161 | 2158 | if (val == AR_RTC_STATUS_ON) |
| @@ -2171,6 +2168,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah) · 9 unmodified lines | ||
| 2171 | 2168 | return false; |
| 2172 | 2169 | } |
| 2173 | 2170 | |
| 2171 | + if (ath9k_hw_mci_is_enabled(ah)) | |
| 2172 | + ar9003_mci_set_power_awake(ah); | |
| 2173 | + | |
| 2174 | 2174 | REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); |
| 2175 | 2175 | |
| 2176 | 2176 | return true; |
| @@ -401,6 +401,7 @@ enum ath9k_int { · 400 unmodified lines | ||
| 401 | 401 | struct ath9k_hw_cal_data { |
| 402 | 402 | u16 channel; |
| 403 | 403 | u32 channelFlags; |
| 404 | + u32 chanmode; | |
| 404 | 405 | int32_t CalValid; |
| 405 | 406 | int8_t iCoff; |
| 406 | 407 | int8_t qCoff; |
| @@ -834,6 +835,7 @@ struct ath_hw { · 427 unmodified lines | ||
| 834 | 835 | int coarse_low[5]; |
| 835 | 836 | int firpwr[5]; |
| 836 | 837 | enum ath9k_ani_cmd ani_function; |
| 838 | + u32 ani_skip_count; | |
| 837 | 839 | |
| 838 | 840 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
| 839 | 841 | struct ath_btcoex_hw btcoex_hw; |
| @@ -687,6 +687,7 @@ static const struct ieee80211_iface_combination if_comb = { · 686 unmodified lines | ||
| 687 | 687 | .n_limits = ARRAY_SIZE(if_limits), |
| 688 | 688 | .max_interfaces = 2048, |
| 689 | 689 | .num_different_channels = 1, |
| 690 | + .beacon_int_infra_match = true, | |
| 690 | 691 | }; |
| 691 | 692 | |
| 692 | 693 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) |
| @@ -350,8 +350,18 @@ void ath_ani_calibrate(unsigned long data) · 349 unmodified lines | ||
| 350 | 350 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; |
| 351 | 351 | |
| 352 | 352 | /* Only calibrate if awake */ |
| 353 | − if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) | |
| 353 | + if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) { | |
| 354 | + if (++ah->ani_skip_count >= ATH_ANI_MAX_SKIP_COUNT) { | |
| 355 | + spin_lock_irqsave(&sc->sc_pm_lock, flags); | |
| 356 | + sc->ps_flags |= PS_WAIT_FOR_ANI; | |
| 357 | + spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | |
| 358 | + } | |
| 354 | 359 | goto set_timer; |
| 360 | + } | |
| 361 | + ah->ani_skip_count = 0; | |
| 362 | + spin_lock_irqsave(&sc->sc_pm_lock, flags); | |
| 363 | + sc->ps_flags &= ~PS_WAIT_FOR_ANI; | |
| 364 | + spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | |
| 355 | 365 | |
| 356 | 366 | ath9k_ps_wakeup(sc); |
| 357 | 367 | |
| @@ -131,7 +131,8 @@ void ath9k_ps_restore(struct ath_softc *sc) · 130 unmodified lines | ||
| 131 | 131 | !(sc->ps_flags & (PS_WAIT_FOR_BEACON | |
| 132 | 132 | PS_WAIT_FOR_CAB | |
| 133 | 133 | PS_WAIT_FOR_PSPOLL_DATA | |
| 134 | − PS_WAIT_FOR_TX_ACK))) { | |
| 134 | + PS_WAIT_FOR_TX_ACK | | |
| 135 | + PS_WAIT_FOR_ANI))) { | |
| 135 | 136 | mode = ATH9K_PM_NETWORK_SLEEP; |
| 136 | 137 | if (ath9k_hw_btcoex_is_enabled(sc->sc_ah)) |
| 137 | 138 | ath9k_btcoex_stop_gen_timer(sc); |
| @@ -292,6 +293,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, · 154 unmodified lines | ||
| 292 | 293 | goto out; |
| 293 | 294 | } |
| 294 | 295 | |
| 296 | + if (ath9k_hw_mci_is_enabled(sc->sc_ah) && | |
| 297 | + (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) | |
| 298 | + ath9k_mci_set_txpower(sc, true, false); | |
| 299 | + | |
| 295 | 300 | if (!ath_complete_reset(sc, true)) |
| 296 | 301 | r = -EIO; |
| 297 | 302 | |
| @@ -1449,6 +1454,9 @@ static void ath9k_set_assoc_state(struct ath_softc *sc, · 1151 unmodified lines | ||
| 1449 | 1454 | sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; |
| 1450 | 1455 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
| 1451 | 1456 | |
| 1457 | + if (ath9k_hw_mci_is_enabled(sc->sc_ah)) | |
| 1458 | + ath9k_mci_update_wlan_channels(sc, false); | |
| 1459 | + | |
| 1452 | 1460 | ath_dbg(common, CONFIG, |
| 1453 | 1461 | "Primary Station interface: %pM, BSSID: %pM\n", |
| 1454 | 1462 | vif->addr, common->curbssid); |
| @@ -1505,6 +1513,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, · 50 unmodified lines | ||
| 1505 | 1513 | memset(common->curbssid, 0, ETH_ALEN); |
| 1506 | 1514 | common->curaid = 0; |
| 1507 | 1515 | ath9k_hw_write_associd(sc->sc_ah); |
| 1516 | + if (ath9k_hw_mci_is_enabled(sc->sc_ah)) | |
| 1517 | + ath9k_mci_update_wlan_channels(sc, true); | |
| 1508 | 1518 | } |
| 1509 | 1519 | } |
| 1510 | 1520 | |
| @@ -43,6 +43,7 @@ static bool ath_mci_add_profile(struct ath_common *common, · 42 unmodified lines | ||
| 43 | 43 | struct ath_mci_profile_info *info) |
| 44 | 44 | { |
| 45 | 45 | struct ath_mci_profile_info *entry; |
| 46 | + u8 voice_priority[] = { 110, 110, 110, 112, 110, 110, 114, 116, 118 }; | |
| 46 | 47 | |
| 47 | 48 | if ((mci->num_sco == ATH_MCI_MAX_SCO_PROFILE) && |
| 48 | 49 | (info->type == MCI_GPM_COEX_PROFILE_VOICE)) |
| @@ -59,6 +60,12 @@ static bool ath_mci_add_profile(struct ath_common *common, · 10 unmodified lines | ||
| 59 | 60 | memcpy(entry, info, 10); |
| 60 | 61 | INC_PROF(mci, info); |
| 61 | 62 | list_add_tail(&entry->list, &mci->info); |
| 63 | + if (info->type == MCI_GPM_COEX_PROFILE_VOICE) { | |
| 64 | + if (info->voice_type < sizeof(voice_priority)) | |
| 65 | + mci->voice_priority = voice_priority[info->voice_type]; | |
| 66 | + else | |
| 67 | + mci->voice_priority = 110; | |
| 68 | + } | |
| 62 | 69 | |
| 63 | 70 | return true; |
| 64 | 71 | } |
| @@ -150,7 +157,7 @@ static void ath_mci_update_scheme(struct ath_softc *sc) · 85 unmodified lines | ||
| 150 | 157 | * For single PAN/FTP profile, allocate 35% for BT |
| 151 | 158 | * to improve WLAN throughput. |
| 152 | 159 | */ |
| 153 | − btcoex->duty_cycle = 35; | |
| 160 | + btcoex->duty_cycle = AR_SREV_9565(sc->sc_ah) ? 40 : 35; | |
| 154 | 161 | btcoex->btcoex_period = 53; |
| 155 | 162 | ath_dbg(common, MCI, |
| 156 | 163 | "Single PAN/FTP bt period %d ms dutycycle %d\n", |
| @@ -250,6 +257,57 @@ static void ath9k_mci_work(struct work_struct *work) · 93 unmodified lines | ||
| 250 | 257 | ath_mci_update_scheme(sc); |
| 251 | 258 | } |
| 252 | 259 | |
| 260 | +static void ath_mci_update_stomp_txprio(u8 cur_txprio, u8 *stomp_prio) | |
| 261 | +{ | |
| 262 | + if (cur_txprio < stomp_prio[ATH_BTCOEX_STOMP_NONE]) | |
| 263 | + stomp_prio[ATH_BTCOEX_STOMP_NONE] = cur_txprio; | |
| 264 | + | |
| 265 | + if (cur_txprio > stomp_prio[ATH_BTCOEX_STOMP_ALL]) | |
| 266 | + stomp_prio[ATH_BTCOEX_STOMP_ALL] = cur_txprio; | |
| 267 | + | |
| 268 | + if ((cur_txprio > ATH_MCI_HI_PRIO) && | |
| 269 | + (cur_txprio < stomp_prio[ATH_BTCOEX_STOMP_LOW])) | |
| 270 | + stomp_prio[ATH_BTCOEX_STOMP_LOW] = cur_txprio; | |
| 271 | +} | |
| 272 | + | |
| 273 | +static void ath_mci_set_concur_txprio(struct ath_softc *sc) | |
| 274 | +{ | |
| 275 | + struct ath_btcoex *btcoex = &sc->btcoex; | |
| 276 | + struct ath_mci_profile *mci = &btcoex->mci; | |
| 277 | + u8 stomp_txprio[] = { 0, 0, 0, 0 }; /* all, low, none, low_ftp */ | |
| 278 | + | |
| 279 | + if (mci->num_mgmt) { | |
| 280 | + stomp_txprio[ATH_BTCOEX_STOMP_ALL] = ATH_MCI_INQUIRY_PRIO; | |
| 281 | + if (!mci->num_pan && !mci->num_other_acl) | |
| 282 | + stomp_txprio[ATH_BTCOEX_STOMP_NONE] = | |
| 283 | + ATH_MCI_INQUIRY_PRIO; | |
| 284 | + } else { | |
| 285 | + u8 prof_prio[] = { 50, 90, 94, 52 };/* RFCOMM, A2DP, HID, PAN */ | |
| 286 | + | |
| 287 | + stomp_txprio[ATH_BTCOEX_STOMP_LOW] = | |
| 288 | + stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0xff; | |
| 289 | + | |
| 290 | + if (mci->num_sco) | |
| 291 | + ath_mci_update_stomp_txprio(mci->voice_priority, | |
| 292 | + stomp_txprio); | |
| 293 | + if (mci->num_other_acl) | |
| 294 | + ath_mci_update_stomp_txprio(prof_prio[0], stomp_txprio); | |
| 295 | + if (mci->num_a2dp) | |
| 296 | + ath_mci_update_stomp_txprio(prof_prio[1], stomp_txprio); | |
| 297 | + if (mci->num_hid) | |
| 298 | + ath_mci_update_stomp_txprio(prof_prio[2], stomp_txprio); | |
| 299 | + if (mci->num_pan) | |
| 300 | + ath_mci_update_stomp_txprio(prof_prio[3], stomp_txprio); | |
| 301 | + | |
| 302 | + if (stomp_txprio[ATH_BTCOEX_STOMP_NONE] == 0xff) | |
| 303 | + stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0; | |
| 304 | + | |
| 305 | + if (stomp_txprio[ATH_BTCOEX_STOMP_LOW] == 0xff) | |
| 306 | + stomp_txprio[ATH_BTCOEX_STOMP_LOW] = 0; | |
| 307 | + } | |
| 308 | + ath9k_hw_btcoex_set_concur_txprio(sc->sc_ah, stomp_txprio); | |
| 309 | +} | |
| 310 | + | |
| 253 | 311 | static u8 ath_mci_process_profile(struct ath_softc *sc, |
| 254 | 312 | struct ath_mci_profile_info *info) |
| 255 | 313 | { |
| @@ -281,6 +339,7 @@ static u8 ath_mci_process_profile(struct ath_softc *sc, · 25 unmodified lines | ||
| 281 | 339 | } else |
| 282 | 340 | ath_mci_del_profile(common, mci, entry); |
| 283 | 341 | |
| 342 | + ath_mci_set_concur_txprio(sc); | |
| 284 | 343 | return 1; |
| 285 | 344 | } |
| 286 | 345 | |
| @@ -314,6 +373,7 @@ static u8 ath_mci_process_status(struct ath_softc *sc, · 27 unmodified lines | ||
| 314 | 373 | mci->num_mgmt++; |
| 315 | 374 | } while (++i < ATH_MCI_MAX_PROFILE); |
| 316 | 375 | |
| 376 | + ath_mci_set_concur_txprio(sc); | |
| 317 | 377 | if (old_num_mgmt != mci->num_mgmt) |
| 318 | 378 | return 1; |
| 319 | 379 | |
| @@ -600,3 +660,112 @@ void ath_mci_enable(struct ath_softc *sc) · 280 unmodified lines | ||
| 600 | 660 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) |
| 601 | 661 | sc->sc_ah->imask |= ATH9K_INT_MCI; |
| 602 | 662 | } |
| 663 | + | |
| 664 | +void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all) | |
| 665 | +{ | |
| 666 | + struct ath_hw *ah = sc->sc_ah; | |
| 667 | + struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | |
| 668 | + struct ath9k_channel *chan = ah->curchan; | |
| 669 | + u32 channelmap[] = {0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff}; | |
| 670 | + int i; | |
| 671 | + s16 chan_start, chan_end; | |
| 672 | + u16 wlan_chan; | |
| 673 | + | |
| 674 | + if (!chan || !IS_CHAN_2GHZ(chan)) | |
| 675 | + return; | |
| 676 | + | |
| 677 | + if (allow_all) | |
| 678 | + goto send_wlan_chan; | |
| 679 | + | |
| 680 | + wlan_chan = chan->channel - 2402; | |
| 681 | + | |
| 682 | + chan_start = wlan_chan - 10; | |
| 683 | + chan_end = wlan_chan + 10; | |
| 684 | + | |
| 685 | + if (chan->chanmode == CHANNEL_G_HT40PLUS) | |
| 686 | + chan_end += 20; | |
| 687 | + else if (chan->chanmode == CHANNEL_G_HT40MINUS) | |
| 688 | + chan_start -= 20; | |
| 689 | + | |
| 690 | + /* adjust side band */ | |
| 691 | + chan_start -= 7; | |
| 692 | + chan_end += 7; | |
| 693 | + | |
| 694 | + if (chan_start <= 0) | |
| 695 | + chan_start = 0; | |
| 696 | + if (chan_end >= ATH_MCI_NUM_BT_CHANNELS) | |
| 697 | + chan_end = ATH_MCI_NUM_BT_CHANNELS - 1; | |
| 698 | + | |
| 699 | + ath_dbg(ath9k_hw_common(ah), MCI, | |
| 700 | + "WLAN current channel %d mask BT channel %d - %d\n", | |
| 701 | + wlan_chan, chan_start, chan_end); | |
| 702 | + | |
| 703 | + for (i = chan_start; i < chan_end; i++) | |
| 704 | + MCI_GPM_CLR_CHANNEL_BIT(&channelmap, i); | |
| 705 | + | |
| 706 | +send_wlan_chan: | |
| 707 | + /* update and send wlan channels info to BT */ | |
| 708 | + for (i = 0; i < 4; i++) | |
| 709 | + mci->wlan_channels[i] = channelmap[i]; | |
| 710 | + ar9003_mci_send_wlan_channels(ah); | |
| 711 | + ar9003_mci_state(ah, MCI_STATE_SEND_VERSION_QUERY); | |
| 712 | +} | |
| 713 | + | |
| 714 | +void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel, | |
| 715 | + bool concur_tx) | |
| 716 | +{ | |
| 717 | + struct ath_hw *ah = sc->sc_ah; | |
| 718 | + struct ath9k_hw_mci *mci_hw = &sc->sc_ah->btcoex_hw.mci; | |
| 719 | + bool old_concur_tx = mci_hw->concur_tx; | |
| 720 | + | |
| 721 | + if (!(mci_hw->config & ATH_MCI_CONFIG_CONCUR_TX)) { | |
| 722 | + mci_hw->concur_tx = false; | |
| 723 | + return; | |
| 724 | + } | |
| 725 | + | |
| 726 | + if (!IS_CHAN_2GHZ(ah->curchan)) | |
| 727 | + return; | |
| 728 | + | |
| 729 | + if (setchannel) { | |
| 730 | + struct ath9k_hw_cal_data *caldata = &sc->caldata; | |
| 731 | + if ((caldata->chanmode == CHANNEL_G_HT40PLUS) && | |
| 732 | + (ah->curchan->channel > caldata->channel) && | |
| 733 | + (ah->curchan->channel <= caldata->channel + 20)) | |
| 734 | + return; | |
| 735 | + if ((caldata->chanmode == CHANNEL_G_HT40MINUS) && | |
| 736 | + (ah->curchan->channel < caldata->channel) && | |
| 737 | + (ah->curchan->channel >= caldata->channel - 20)) | |
| 738 | + return; | |
| 739 | + mci_hw->concur_tx = false; | |
| 740 | + } else | |
| 741 | + mci_hw->concur_tx = concur_tx; | |
| 742 | + | |
| 743 | + if (old_concur_tx != mci_hw->concur_tx) | |
| 744 | + ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false); | |
| 745 | +} | |
| 746 | + | |
| 747 | +void ath9k_mci_update_rssi(struct ath_softc *sc) | |
| 748 | +{ | |
| 749 | + struct ath_hw *ah = sc->sc_ah; | |
| 750 | + struct ath_btcoex *btcoex = &sc->btcoex; | |
| 751 | + struct ath9k_hw_mci *mci_hw = &sc->sc_ah->btcoex_hw.mci; | |
| 752 | + | |
| 753 | + if (!(mci_hw->config & ATH_MCI_CONFIG_CONCUR_TX)) | |
| 754 | + return; | |
| 755 | + | |
| 756 | + if (ah->stats.avgbrssi >= 40) { | |
| 757 | + if (btcoex->rssi_count < 0) | |
| 758 | + btcoex->rssi_count = 0; | |
| 759 | + if (++btcoex->rssi_count >= ATH_MCI_CONCUR_TX_SWITCH) { | |
| 760 | + btcoex->rssi_count = 0; | |
| 761 | + ath9k_mci_set_txpower(sc, false, true); | |
| 762 | + } | |
| 763 | + } else { | |
| 764 | + if (btcoex->rssi_count > 0) | |
| 765 | + btcoex->rssi_count = 0; | |
| 766 | + if (--btcoex->rssi_count <= -ATH_MCI_CONCUR_TX_SWITCH) { | |
| 767 | + btcoex->rssi_count = 0; | |
| 768 | + ath9k_mci_set_txpower(sc, false, false); | |
| 769 | + } | |
| 770 | + } | |
| 771 | +} | |
| @@ -32,6 +32,27 @@ · 31 unmodified lines | ||
| 32 | 32 | #define ATH_MCI_MAX_PROFILE (ATH_MCI_MAX_ACL_PROFILE +\ |
| 33 | 33 | ATH_MCI_MAX_SCO_PROFILE) |
| 34 | 34 | |
| 35 | +#define ATH_MCI_INQUIRY_PRIO 62 | |
| 36 | +#define ATH_MCI_HI_PRIO 60 | |
| 37 | +#define ATH_MCI_NUM_BT_CHANNELS 79 | |
| 38 | +#define ATH_MCI_CONCUR_TX_SWITCH 5 | |
| 39 | + | |
| 40 | +#define MCI_GPM_SET_CHANNEL_BIT(_p_gpm, _bt_chan) \ | |
| 41 | + do { \ | |
| 42 | + if (_bt_chan < ATH_MCI_NUM_BT_CHANNELS) { \ | |
| 43 | + *(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_CHANNEL_MAP + \ | |
| 44 | + (_bt_chan / 8)) |= (1 << (_bt_chan & 7)); \ | |
| 45 | + } \ | |
| 46 | + } while (0) | |
| 47 | + | |
| 48 | +#define MCI_GPM_CLR_CHANNEL_BIT(_p_gpm, _bt_chan) \ | |
| 49 | + do { \ | |
| 50 | + if (_bt_chan < ATH_MCI_NUM_BT_CHANNELS) { \ | |
| 51 | + *(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_CHANNEL_MAP + \ | |
| 52 | + (_bt_chan / 8)) &= ~(1 << (_bt_chan & 7));\ | |
| 53 | + } \ | |
| 54 | + } while (0) | |
| 55 | + | |
| 35 | 56 | #define INC_PROF(_mci, _info) do { \ |
| 36 | 57 | switch (_info->type) { \ |
| 37 | 58 | case MCI_GPM_COEX_PROFILE_RFCOMM:\ |
| @@ -49,6 +70,7 @@ · 11 unmodified lines | ||
| 49 | 70 | _mci->num_pan++; \ |
| 50 | 71 | break; \ |
| 51 | 72 | case MCI_GPM_COEX_PROFILE_VOICE: \ |
| 73 | + case MCI_GPM_COEX_PROFILE_A2DPVO:\ | |
| 52 | 74 | _mci->num_sco++; \ |
| 53 | 75 | break; \ |
| 54 | 76 | default: \ |
| @@ -73,6 +95,7 @@ · 18 unmodified lines | ||
| 73 | 95 | _mci->num_pan--; \ |
| 74 | 96 | break; \ |
| 75 | 97 | case MCI_GPM_COEX_PROFILE_VOICE: \ |
| 98 | + case MCI_GPM_COEX_PROFILE_A2DPVO:\ | |
| 76 | 99 | _mci->num_sco--; \ |
| 77 | 100 | break; \ |
| 78 | 101 | default: \ |
| @@ -113,6 +136,7 @@ struct ath_mci_profile { · 34 unmodified lines | ||
| 113 | 136 | u8 num_pan; |
| 114 | 137 | u8 num_other_acl; |
| 115 | 138 | u8 num_bdr; |
| 139 | + u8 voice_priority; | |
| 116 | 140 | }; |
| 117 | 141 | |
| 118 | 142 | struct ath_mci_buf { |
| @@ -130,13 +154,25 @@ void ath_mci_flush_profile(struct ath_mci_profile *mci); · 11 unmodified lines | ||
| 130 | 154 | int ath_mci_setup(struct ath_softc *sc); |
| 131 | 155 | void ath_mci_cleanup(struct ath_softc *sc); |
| 132 | 156 | void ath_mci_intr(struct ath_softc *sc); |
| 157 | +void ath9k_mci_update_rssi(struct ath_softc *sc); | |
| 133 | 158 | |
| 134 | 159 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
| 135 | 160 | void ath_mci_enable(struct ath_softc *sc); |
| 161 | +void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all); | |
| 162 | +void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel, | |
| 163 | + bool concur_tx); | |
| 136 | 164 | #else |
| 137 | 165 | static inline void ath_mci_enable(struct ath_softc *sc) |
| 138 | 166 | { |
| 139 | 167 | } |
| 168 | +static inline void ath9k_mci_update_wlan_channels(struct ath_softc *sc, | |
| 169 | + bool allow_all) | |
| 170 | +{ | |
| 171 | +} | |
| 172 | +static inline void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel, | |
| 173 | + bool concur_tx) | |
| 174 | +{ | |
| 175 | +} | |
| 140 | 176 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ |
| 141 | 177 | |
| 142 | 178 | #endif /* MCI_H*/ |
| @@ -1105,7 +1105,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) · 1104 unmodified lines | ||
| 1105 | 1105 | else |
| 1106 | 1106 | rs.is_mybeacon = false; |
| 1107 | 1107 | |
| 1108 | − sc->rx.num_pkts++; | |
| 1108 | + if (ieee80211_is_data_present(hdr->frame_control) && | |
| 1109 | + !ieee80211_is_qos_nullfunc(hdr->frame_control)) | |
| 1110 | + sc->rx.num_pkts++; | |
| 1111 | + | |
| 1109 | 1112 | ath_debug_stat_rx(sc, &rs); |
| 1110 | 1113 | |
| 1111 | 1114 | /* |
| @@ -907,10 +907,6 @@ · 906 unmodified lines | ||
| 907 | 907 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ |
| 908 | 908 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20)) |
| 909 | 909 | |
| 910 | −#define AR_SREV_9462_20_OR_LATER(_ah) \ | |
| 911 | − (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ | |
| 912 | − ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20)) | |
| 913 | − | |
| 914 | 910 | #define AR_SREV_9565(_ah) \ |
| 915 | 911 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565)) |
| 916 | 912 | |
| @@ -2315,6 +2311,8 @@ enum { · 1398 unmodified lines | ||
| 2315 | 2311 | #define AR_BTCOEX_MAX_TXPWR(_x) (0x18c0 + ((_x) << 2)) |
| 2316 | 2312 | #define AR_BTCOEX_WL_LNA 0x1940 |
| 2317 | 2313 | #define AR_BTCOEX_RFGAIN_CTRL 0x1944 |
| 2314 | +#define AR_BTCOEX_WL_LNA_TIMEOUT 0x003FFFFF | |
| 2315 | +#define AR_BTCOEX_WL_LNA_TIMEOUT_S 0 | |
| 2318 | 2316 | |
| 2319 | 2317 | #define AR_BTCOEX_CTRL2 0x1948 |
| 2320 | 2318 | #define AR_BTCOEX_CTRL2_TXPWR_THRESH 0x0007F800 |
| @@ -2360,4 +2358,11 @@ enum { · 39 unmodified lines | ||
| 2360 | 2358 | #define AR_GLB_SWREG_DISCONT_MODE 0x2002c |
| 2361 | 2359 | #define AR_GLB_SWREG_DISCONT_EN_BT_WLAN 0x3 |
| 2362 | 2360 | |
| 2361 | +#define AR_MCI_MISC 0x1a74 | |
| 2362 | +#define AR_MCI_MISC_HW_FIX_EN 0x00000001 | |
| 2363 | +#define AR_MCI_MISC_HW_FIX_EN_S 0 | |
| 2364 | +#define AR_MCI_DBG_CNT_CTRL 0x1a78 | |
| 2365 | +#define AR_MCI_DBG_CNT_CTRL_ENABLE 0x00000001 | |
| 2366 | +#define AR_MCI_DBG_CNT_CTRL_ENABLE_S 0 | |
| 2367 | + | |
| 2363 | 2368 | #endif |
| @@ -118,7 +118,7 @@ static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah) · 117 unmodified lines | ||
| 118 | 118 | (ap_mac_addr[1] << 8) | (ap_mac_addr[0]); |
| 119 | 119 | data_word[5] = (ap_mac_addr[5] << 8) | (ap_mac_addr[4]); |
| 120 | 120 | |
| 121 | − if (AR_SREV_9462_20_OR_LATER(ah)) { | |
| 121 | + if (AR_SREV_9462_20(ah)) { | |
| 122 | 122 | /* AR9462 2.0 has an extra descriptor word (time based |
| 123 | 123 | * discard) compared to other chips */ |
| 124 | 124 | REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0); |
| @@ -343,7 +343,24 @@ int carl9170_set_operating_mode(struct ar9170 *ar) · 342 unmodified lines | ||
| 343 | 343 | break; |
| 344 | 344 | } |
| 345 | 345 | } else { |
| 346 | − mac_addr = NULL; | |
| 346 | + /* | |
| 347 | + * Enable monitor mode | |
| 348 | + * | |
| 349 | + * rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER; | |
| 350 | + * sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC; | |
| 351 | + * | |
| 352 | + * When the hardware is in SNIFFER_PROMISC mode, | |
| 353 | + * it generates spurious ACKs for every incoming | |
| 354 | + * frame. This confuses every peer in the | |
| 355 | + * vicinity and the network throughput will suffer | |
| 356 | + * badly. | |
| 357 | + * | |
| 358 | + * Hence, the hardware will be put into station | |
| 359 | + * mode and just the rx filters are disabled. | |
| 360 | + */ | |
| 361 | + cam_mode |= AR9170_MAC_CAM_STA; | |
| 362 | + rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST; | |
| 363 | + mac_addr = common->macaddr; | |
| 347 | 364 | bssid = NULL; |
| 348 | 365 | } |
| 349 | 366 | rcu_read_unlock(); |
| @@ -355,8 +372,6 @@ int carl9170_set_operating_mode(struct ar9170 *ar) · 5 unmodified lines | ||
| 355 | 372 | enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE; |
| 356 | 373 | |
| 357 | 374 | if (ar->sniffer_enabled) { |
| 358 | − rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER; | |
| 359 | − sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC; | |
| 360 | 375 | enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE; |
| 361 | 376 | } |
| 362 | 377 | |
| @@ -164,9 +164,6 @@ void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) · 163 unmodified lines | ||
| 164 | 164 | struct carl9170_rsp *cmd = buf; |
| 165 | 165 | struct ieee80211_vif *vif; |
| 166 | 166 | |
| 167 | − if (carl9170_check_sequence(ar, cmd->hdr.seq)) | |
| 168 | − return; | |
| 169 | − | |
| 170 | 167 | if ((cmd->hdr.cmd & CARL9170_RSP_FLAG) != CARL9170_RSP_FLAG) { |
| 171 | 168 | if (!(cmd->hdr.cmd & CARL9170_CMD_ASYNC_FLAG)) |
| 172 | 169 | carl9170_cmd_callback(ar, len, buf); |
| @@ -663,6 +660,35 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms, · 490 unmodified lines | ||
| 663 | 660 | return false; |
| 664 | 661 | } |
| 665 | 662 | |
| 663 | +static int carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len, | |
| 664 | + struct ieee80211_rx_status *status) | |
| 665 | +{ | |
| 666 | + struct sk_buff *skb; | |
| 667 | + | |
| 668 | + /* (driver) frame trap handler | |
| 669 | + * | |
| 670 | + * Because power-saving mode handing has to be implemented by | |
| 671 | + * the driver/firmware. We have to check each incoming beacon | |
| 672 | + * from the associated AP, if there's new data for us (either | |
| 673 | + * broadcast/multicast or unicast) we have to react quickly. | |
| 674 | + * | |
| 675 | + * So, if you have you want to add additional frame trap | |
| 676 | + * handlers, this would be the perfect place! | |
| 677 | + */ | |
| 678 | + | |
| 679 | + carl9170_ps_beacon(ar, buf, len); | |
| 680 | + | |
| 681 | + carl9170_ba_check(ar, buf, len); | |
| 682 | + | |
| 683 | + skb = carl9170_rx_copy_data(buf, len); | |
| 684 | + if (!skb) | |
| 685 | + return -ENOMEM; | |
| 686 | + | |
| 687 | + memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | |
| 688 | + ieee80211_rx(ar->hw, skb); | |
| 689 | + return 0; | |
| 690 | +} | |
| 691 | + | |
| 666 | 692 | /* |
| 667 | 693 | * If the frame alignment is right (or the kernel has |
| 668 | 694 | * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there |
| @@ -672,14 +698,12 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms, · 3 unmodified lines | ||
| 672 | 698 | * mode, and we need to observe the proper ordering, |
| 673 | 699 | * this is non-trivial. |
| 674 | 700 | */ |
| 675 | − | |
| 676 | −static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) | |
| 701 | +static void carl9170_rx_untie_data(struct ar9170 *ar, u8 *buf, int len) | |
| 677 | 702 | { |
| 678 | 703 | struct ar9170_rx_head *head; |
| 679 | 704 | struct ar9170_rx_macstatus *mac; |
| 680 | 705 | struct ar9170_rx_phystatus *phy = NULL; |
| 681 | 706 | struct ieee80211_rx_status status; |
| 682 | − struct sk_buff *skb; | |
| 683 | 707 | int mpdu_len; |
| 684 | 708 | u8 mac_status; |
| 685 | 709 | |
| @@ -791,18 +815,10 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) · 105 unmodified lines | ||
| 791 | 815 | if (phy) |
| 792 | 816 | carl9170_rx_phy_status(ar, phy, &status); |
| 793 | 817 | |
| 794 | − carl9170_ps_beacon(ar, buf, mpdu_len); | |
| 795 | − | |
| 796 | − carl9170_ba_check(ar, buf, mpdu_len); | |
| 797 | − | |
| 798 | − skb = carl9170_rx_copy_data(buf, mpdu_len); | |
| 799 | − if (!skb) | |
| 818 | + if (carl9170_handle_mpdu(ar, buf, mpdu_len, &status)) | |
| 800 | 819 | goto drop; |
| 801 | 820 | |
| 802 | − memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | |
| 803 | − ieee80211_rx(ar->hw, skb); | |
| 804 | 821 | return; |
| 805 | − | |
| 806 | 822 | drop: |
| 807 | 823 | ar->rx_dropped++; |
| 808 | 824 | } |
| @@ -820,6 +836,9 @@ static void carl9170_rx_untie_cmds(struct ar9170 *ar, const u8 *respbuf, · 11 unmodified lines | ||
| 820 | 836 | if (unlikely(i > resplen)) |
| 821 | 837 | break; |
| 822 | 838 | |
| 839 | + if (carl9170_check_sequence(ar, cmd->hdr.seq)) | |
| 840 | + break; | |
| 841 | + | |
| 823 | 842 | carl9170_handle_command_response(ar, cmd, cmd->hdr.len + 4); |
| 824 | 843 | } |
| 825 | 844 | |
| @@ -851,7 +870,7 @@ static void __carl9170_rx(struct ar9170 *ar, u8 *buf, unsigned int len) · 25 unmodified lines | ||
| 851 | 870 | if (i == 12) |
| 852 | 871 | carl9170_rx_untie_cmds(ar, buf, len); |
| 853 | 872 | else |
| 854 | − carl9170_handle_mpdu(ar, buf, len); | |
| 873 | + carl9170_rx_untie_data(ar, buf, len); | |
| 855 | 874 | } |
| 856 | 875 | |
| 857 | 876 | 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) · 294 unmodified lines | ||
| 295 | 295 | goto resubmit; |
| 296 | 296 | } |
| 297 | 297 | |
| 298 | + /* | |
| 299 | + * While the carl9170 firmware does not use this EP, the | |
| 300 | + * firmware loader in the EEPROM unfortunately does. | |
| 301 | + * Therefore we need to be ready to handle out-of-band | |
| 302 | + * responses and traps in case the firmware crashed and | |
| 303 | + * the loader took over again. | |
| 304 | + */ | |
| 298 | 305 | carl9170_handle_command_response(ar, urb->transfer_buffer, |
| 299 | 306 | urb->actual_length); |
| 300 | 307 | |
| @@ -20,8 +20,8 @@ · 19 unmodified lines | ||
| 20 | 20 | #include "ath.h" |
| 21 | 21 | #include "reg.h" |
| 22 | 22 | |
| 23 | −#define REG_READ (common->ops->read) | |
| 24 | −#define REG_WRITE (common->ops->write) | |
| 23 | +#define REG_READ (common->ops->read) | |
| 24 | +#define REG_WRITE(_ah, _reg, _val) (common->ops->write)(_ah, _val, _reg) | |
| 25 | 25 | |
| 26 | 26 | /** |
| 27 | 27 | * ath_hw_set_bssid_mask - filter out bssids we listen |
| @@ -119,8 +119,8 @@ void ath_hw_setbssidmask(struct ath_common *common) · 91 unmodified lines | ||
| 119 | 119 | { |
| 120 | 120 | void *ah = common->ah; |
| 121 | 121 | |
| 122 | − REG_WRITE(ah, get_unaligned_le32(common->bssidmask), AR_BSSMSKL); | |
| 123 | − REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU); | |
| 122 | + REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(common->bssidmask)); | |
| 123 | + REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(common->bssidmask + 4)); | |
| 124 | 124 | } |
| 125 | 125 | EXPORT_SYMBOL(ath_hw_setbssidmask); |
| 126 | 126 | |
| @@ -139,7 +139,7 @@ void ath_hw_cycle_counters_update(struct ath_common *common) · 12 unmodified lines | ||
| 139 | 139 | void *ah = common->ah; |
| 140 | 140 | |
| 141 | 141 | /* freeze */ |
| 142 | − REG_WRITE(ah, AR_MIBC_FMC, AR_MIBC); | |
| 142 | + REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC); | |
| 143 | 143 | |
| 144 | 144 | /* read */ |
| 145 | 145 | cycles = REG_READ(ah, AR_CCCNT); |
| @@ -148,13 +148,13 @@ void ath_hw_cycle_counters_update(struct ath_common *common) · 2 unmodified lines | ||
| 148 | 148 | tx = REG_READ(ah, AR_TFCNT); |
| 149 | 149 | |
| 150 | 150 | /* clear */ |
| 151 | − REG_WRITE(ah, 0, AR_CCCNT); | |
| 152 | − REG_WRITE(ah, 0, AR_RFCNT); | |
| 153 | − REG_WRITE(ah, 0, AR_RCCNT); | |
| 154 | − REG_WRITE(ah, 0, AR_TFCNT); | |
| 151 | + REG_WRITE(ah, AR_CCCNT, 0); | |
| 152 | + REG_WRITE(ah, AR_RFCNT, 0); | |
| 153 | + REG_WRITE(ah, AR_RCCNT, 0); | |
| 154 | + REG_WRITE(ah, AR_TFCNT, 0); | |
| 155 | 155 | |
| 156 | 156 | /* unfreeze */ |
| 157 | − REG_WRITE(ah, 0, AR_MIBC); | |
| 157 | + REG_WRITE(ah, AR_MIBC, 0); | |
| 158 | 158 | |
| 159 | 159 | /* update all cycle counters here */ |
| 160 | 160 | common->cc_ani.cycles += cycles; |
| @@ -4652,7 +4652,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) · 4651 unmodified lines | ||
| 4652 | 4652 | switch (dev->dev->bus_type) { |
| 4653 | 4653 | #ifdef CONFIG_B43_BCMA |
| 4654 | 4654 | case B43_BUS_BCMA: |
| 4655 | − bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci, | |
| 4655 | + bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci[0], | |
| 4656 | 4656 | dev->dev->bdev, true); |
| 4657 | 4657 | break; |
| 4658 | 4658 | #endif |
| @@ -24,6 +24,7 @@ ccflags-y += -D__CHECK_ENDIAN__ · 23 unmodified lines | ||
| 24 | 24 | obj-$(CONFIG_BRCMFMAC) += brcmfmac.o |
| 25 | 25 | brcmfmac-objs += \ |
| 26 | 26 | wl_cfg80211.o \ |
| 27 | + fwil.o \ | |
| 27 | 28 | dhd_cdc.o \ |
| 28 | 29 | dhd_common.o \ |
| 29 | 30 | dhd_linux.o |
| @@ -318,6 +318,12 @@ struct brcmf_event { · 317 unmodified lines | ||
| 318 | 318 | #define BRCMF_E_LINK_ASSOC_REC 3 |
| 319 | 319 | #define BRCMF_E_LINK_BSSCFG_DIS 4 |
| 320 | 320 | |
| 321 | +/* Small, medium and maximum buffer size for dcmd | |
| 322 | + */ | |
| 323 | +#define BRCMF_DCMD_SMLEN 256 | |
| 324 | +#define BRCMF_DCMD_MEDLEN 1536 | |
| 325 | +#define BRCMF_DCMD_MAXLEN 8192 | |
| 326 | + | |
| 321 | 327 | /* Pattern matching filter. Specifies an offset within received packets to |
| 322 | 328 | * start matching, the pattern to match, the size of the pattern, and a bitmask |
| 323 | 329 | * that indicates which bits within the pattern should be matched. |
| @@ -623,7 +629,6 @@ struct brcmf_pub { · 299 unmodified lines | ||
| 623 | 629 | u8 wme_dp; /* wme discard priority */ |
| 624 | 630 | |
| 625 | 631 | /* Dongle media info */ |
| 626 | − bool iswl; /* Dongle-resident driver is wl */ | |
| 627 | 632 | unsigned long drv_version; /* Version of dongle-resident driver */ |
| 628 | 633 | u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */ |
| 629 | 634 | |
| @@ -651,16 +656,10 @@ struct brcmf_pub { · 21 unmodified lines | ||
| 651 | 656 | int in_suspend; /* flag set to 1 when early suspend called */ |
| 652 | 657 | int dtim_skip; /* dtim skip , default 0 means wake each dtim */ |
| 653 | 658 | |
| 654 | − /* Pkt filter defination */ | |
| 655 | − char *pktfilter[100]; | |
| 656 | − int pktfilter_count; | |
| 657 | − | |
| 658 | − u8 country_code[BRCM_CNTRY_BUF_SZ]; | |
| 659 | − char eventmask[BRCMF_EVENTING_MASK_LEN]; | |
| 660 | − | |
| 661 | 659 | struct brcmf_if *iflist[BRCMF_MAX_IFS]; |
| 662 | 660 | |
| 663 | 661 | struct mutex proto_block; |
| 662 | + unsigned char proto_buf[BRCMF_DCMD_MAXLEN]; | |
| 664 | 663 | |
| 665 | 664 | struct work_struct setmacaddr_work; |
| 666 | 665 | struct work_struct multicast_work; |
| @@ -671,6 +670,11 @@ struct brcmf_pub { · 4 unmodified lines | ||
| 671 | 670 | #endif |
| 672 | 671 | }; |
| 673 | 672 | |
| 673 | +struct bcmevent_name { | |
| 674 | + uint event; | |
| 675 | + const char *name; | |
| 676 | +}; | |
| 677 | + | |
| 674 | 678 | struct brcmf_if_event { |
| 675 | 679 | u8 ifidx; |
| 676 | 680 | u8 action; |
| @@ -678,47 +682,60 @@ struct brcmf_if_event { · 1 unmodified line | ||
| 678 | 682 | u8 bssidx; |
| 679 | 683 | }; |
| 680 | 684 | |
| 681 | −struct bcmevent_name { | |
| 682 | − uint event; | |
| 683 | − const char *name; | |
| 685 | +/* forward declaration */ | |
| 686 | +struct brcmf_cfg80211_vif; | |
| 687 | + | |
| 688 | +/** | |
| 689 | + * struct brcmf_if - interface control information. | |
| 690 | + * | |
| 691 | + * @drvr: points to device related information. | |
| 692 | + * @vif: points to cfg80211 specific interface information. | |
| 693 | + * @ndev: associated network device. | |
| 694 | + * @stats: interface specific network statistics. | |
| 695 | + * @idx: interface index in device firmware. | |
| 696 | + * @bssidx: index of bss associated with this interface. | |
| 697 | + * @mac_addr: assigned mac address. | |
| 698 | + */ | |
| 699 | +struct brcmf_if { | |
| 700 | + struct brcmf_pub *drvr; | |
| 701 | + struct brcmf_cfg80211_vif *vif; | |
| 702 | + struct net_device *ndev; | |
| 703 | + struct net_device_stats stats; | |
| 704 | + int idx; | |
| 705 | + s32 bssidx; | |
| 706 | + u8 mac_addr[ETH_ALEN]; | |
| 684 | 707 | }; |
| 685 | 708 | |
| 709 | +static inline s32 brcmf_ndev_bssidx(struct net_device *ndev) | |
| 710 | +{ | |
| 711 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 712 | + return ifp->bssidx; | |
| 713 | +} | |
| 714 | + | |
| 686 | 715 | extern const struct bcmevent_name bcmevent_names[]; |
| 687 | 716 | |
| 688 | 717 | extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen, |
| 689 | 718 | char *buf, uint len); |
| 690 | −extern uint brcmf_c_mkiovar_bsscfg(char *name, char *data, uint datalen, | |
| 691 | − char *buf, uint buflen, s32 bssidx); | |
| 692 | 719 | |
| 693 | 720 | extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev); |
| 694 | 721 | |
| 695 | −extern s32 brcmf_exec_dcmd(struct net_device *dev, u32 cmd, void *arg, u32 len); | |
| 696 | −extern int brcmf_netlink_dcmd(struct net_device *ndev, struct brcmf_dcmd *dcmd); | |
| 697 | − | |
| 698 | 722 | /* Return pointer to interface name */ |
| 699 | 723 | extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx); |
| 700 | 724 | |
| 701 | 725 | /* Query dongle */ |
| 702 | 726 | extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, |
| 703 | 727 | uint cmd, void *buf, uint len); |
| 704 | − | |
| 705 | −#ifdef DEBUG | |
| 706 | −extern int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size); | |
| 707 | −#endif /* DEBUG */ | |
| 728 | +extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | |
| 729 | + void *buf, uint len); | |
| 708 | 730 | |
| 709 | 731 | extern int brcmf_ifname2idx(struct brcmf_pub *drvr, char *name); |
| 710 | 732 | extern int brcmf_c_host_event(struct brcmf_pub *drvr, int *idx, |
| 711 | 733 | void *pktdata, struct brcmf_event_msg *, |
| 712 | 734 | void **data_ptr); |
| 713 | 735 | |
| 736 | +extern int brcmf_net_attach(struct brcmf_if *ifp); | |
| 737 | +extern struct brcmf_if *brcmf_add_if(struct device *dev, int ifidx, s32 bssidx, | |
| 738 | + char *name, u8 *mac_addr); | |
| 714 | 739 | extern void brcmf_del_if(struct brcmf_pub *drvr, int ifidx); |
| 715 | 740 | |
| 716 | −extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg); | |
| 717 | −extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, | |
| 718 | − int enable, int master_mode); | |
| 719 | − | |
| 720 | −#define BRCMF_DCMD_SMLEN 256 /* "small" cmd buffer required */ | |
| 721 | −#define BRCMF_DCMD_MEDLEN 1536 /* "med" cmd buffer required */ | |
| 722 | −#define BRCMF_DCMD_MAXLEN 8192 /* max length cmd buffer required */ | |
| 723 | − | |
| 724 | 741 | #endif /* _BRCMF_H_ */ |
| @@ -111,9 +111,6 @@ extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, · 110 unmodified lines | ||
| 111 | 111 | |
| 112 | 112 | extern int brcmf_bus_start(struct device *dev); |
| 113 | 113 | |
| 114 | −extern int brcmf_add_if(struct device *dev, int ifidx, | |
| 115 | − char *name, u8 *mac_addr); | |
| 116 | − | |
| 117 | 114 | #ifdef CONFIG_BRCMFMAC_SDIO |
| 118 | 115 | extern void brcmf_sdio_exit(void); |
| 119 | 116 | extern void brcmf_sdio_init(void); |
| @@ -458,35 +458,6 @@ void brcmf_proto_detach(struct brcmf_pub *drvr) · 457 unmodified lines | ||
| 458 | 458 | drvr->prot = NULL; |
| 459 | 459 | } |
| 460 | 460 | |
| 461 | −int brcmf_proto_init(struct brcmf_pub *drvr) | |
| 462 | −{ | |
| 463 | − int ret = 0; | |
| 464 | − char buf[128]; | |
| 465 | − | |
| 466 | − brcmf_dbg(TRACE, "Enter\n"); | |
| 467 | − | |
| 468 | − mutex_lock(&drvr->proto_block); | |
| 469 | − | |
| 470 | − /* Get the device MAC address */ | |
| 471 | − strcpy(buf, "cur_etheraddr"); | |
| 472 | − ret = brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, | |
| 473 | − buf, sizeof(buf)); | |
| 474 | − if (ret < 0) { | |
| 475 | − mutex_unlock(&drvr->proto_block); | |
| 476 | − return ret; | |
| 477 | − } | |
| 478 | − memcpy(drvr->mac, buf, ETH_ALEN); | |
| 479 | − | |
| 480 | − mutex_unlock(&drvr->proto_block); | |
| 481 | − | |
| 482 | − ret = brcmf_c_preinit_dcmds(drvr); | |
| 483 | − | |
| 484 | − /* Always assumes wl for now */ | |
| 485 | − drvr->iswl = true; | |
| 486 | − | |
| 487 | − return ret; | |
| 488 | −} | |
| 489 | − | |
| 490 | 461 | void brcmf_proto_stop(struct brcmf_pub *drvr) |
| 491 | 462 | { |
| 492 | 463 | /* Nothing to do for CDC */ |
| @@ -28,12 +28,17 @@ · 27 unmodified lines | ||
| 28 | 28 | #include "dhd_bus.h" |
| 29 | 29 | #include "dhd_proto.h" |
| 30 | 30 | #include "dhd_dbg.h" |
| 31 | +#include "fwil.h" | |
| 31 | 32 | |
| 32 | 33 | #define BRCM_OUI "\x00\x10\x18" |
| 33 | 34 | #define DOT11_OUI_LEN 3 |
| 34 | 35 | #define BCMILCP_BCM_SUBTYPE_EVENT 1 |
| 35 | −#define PKTFILTER_BUF_SIZE 2048 | |
| 36 | +#define PKTFILTER_BUF_SIZE 128 | |
| 36 | 37 | #define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */ |
| 38 | +#define BRCMF_DEFAULT_BCN_TIMEOUT 3 | |
| 39 | +#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40 | |
| 40 | +#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40 | |
| 41 | +#define BRCMF_DEFAULT_PACKET_FILTER "100 0 0 0 0x01 0x00" | |
| 37 | 42 | |
| 38 | 43 | #define MSGTRACE_VERSION 1 |
| 39 | 44 | |
| @@ -88,52 +93,6 @@ brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen) · 48 unmodified lines | ||
| 88 | 93 | return len; |
| 89 | 94 | } |
| 90 | 95 | |
| 91 | −uint | |
| 92 | −brcmf_c_mkiovar_bsscfg(char *name, char *data, uint datalen, | |
| 93 | − char *buf, uint buflen, s32 bssidx) | |
| 94 | −{ | |
| 95 | − const s8 *prefix = "bsscfg:"; | |
| 96 | − s8 *p; | |
| 97 | − u32 prefixlen; | |
| 98 | − u32 namelen; | |
| 99 | − u32 iolen; | |
| 100 | − __le32 bssidx_le; | |
| 101 | − | |
| 102 | − if (bssidx == 0) | |
| 103 | − return brcmf_c_mkiovar(name, data, datalen, buf, buflen); | |
| 104 | − | |
| 105 | − prefixlen = (u32) strlen(prefix); /* lengh of bsscfg prefix */ | |
| 106 | − namelen = (u32) strlen(name) + 1; /* lengh of iovar name + null */ | |
| 107 | − iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen; | |
| 108 | − | |
| 109 | − if (buflen < 0 || iolen > (u32)buflen) { | |
| 110 | − brcmf_dbg(ERROR, "buffer is too short\n"); | |
| 111 | − return 0; | |
| 112 | − } | |
| 113 | − | |
| 114 | − p = buf; | |
| 115 | − | |
| 116 | − /* copy prefix, no null */ | |
| 117 | − memcpy(p, prefix, prefixlen); | |
| 118 | − p += prefixlen; | |
| 119 | − | |
| 120 | − /* copy iovar name including null */ | |
| 121 | − memcpy(p, name, namelen); | |
| 122 | − p += namelen; | |
| 123 | − | |
| 124 | − /* bss config index as first data */ | |
| 125 | − bssidx_le = cpu_to_le32(bssidx); | |
| 126 | − memcpy(p, &bssidx_le, sizeof(bssidx_le)); | |
| 127 | − p += sizeof(bssidx_le); | |
| 128 | − | |
| 129 | − /* parameter buffer follows */ | |
| 130 | − if (datalen) | |
| 131 | − memcpy(p, data, datalen); | |
| 132 | − | |
| 133 | − return iolen; | |
| 134 | − | |
| 135 | −} | |
| 136 | − | |
| 137 | 96 | bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, |
| 138 | 97 | struct sk_buff *pkt, int prec) |
| 139 | 98 | { |
| @@ -490,6 +449,7 @@ brcmf_c_host_event(struct brcmf_pub *drvr, int *ifidx, void *pktdata, · 350 unmodified lines | ||
| 490 | 449 | /* check whether packet is a BRCM event pkt */ |
| 491 | 450 | struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata; |
| 492 | 451 | struct brcmf_if_event *ifevent; |
| 452 | + struct brcmf_if *ifp; | |
| 493 | 453 | char *event_data; |
| 494 | 454 | u32 type, status; |
| 495 | 455 | u16 flags; |
| @@ -525,12 +485,17 @@ brcmf_c_host_event(struct brcmf_pub *drvr, int *ifidx, void *pktdata, · 29 unmodified lines | ||
| 525 | 485 | brcmf_dbg(TRACE, "if event\n"); |
| 526 | 486 | |
| 527 | 487 | if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) { |
| 528 | − if (ifevent->action == BRCMF_E_IF_ADD) | |
| 529 | − brcmf_add_if(drvr->dev, ifevent->ifidx, | |
| 530 | − event->ifname, | |
| 531 | − pvt_data->eth.h_dest); | |
| 532 | − else | |
| 488 | + if (ifevent->action == BRCMF_E_IF_ADD) { | |
| 489 | + ifp = brcmf_add_if(drvr->dev, ifevent->ifidx, | |
| 490 | + ifevent->bssidx, | |
| 491 | + event->ifname, | |
| 492 | + pvt_data->eth.h_dest); | |
| 493 | + if (IS_ERR(ifp)) | |
| 494 | + return PTR_ERR(ifp); | |
| 495 | + brcmf_net_attach(ifp); | |
| 496 | + } else { | |
| 533 | 497 | brcmf_del_if(drvr, ifevent->ifidx); |
| 498 | + } | |
| 534 | 499 | } else { |
| 535 | 500 | brcmf_dbg(ERROR, "Invalid ifidx %d for %s\n", |
| 536 | 501 | ifevent->ifidx, event->ifname); |
| @@ -603,90 +568,57 @@ static int brcmf_c_pattern_atoh(char *src, char *dst) · 66 unmodified lines | ||
| 603 | 568 | return i; |
| 604 | 569 | } |
| 605 | 570 | |
| 606 | −void | |
| 607 | −brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable, | |
| 608 | − int master_mode) | |
| 571 | +static void | |
| 572 | +brcmf_c_pktfilter_offload_enable(struct brcmf_if *ifp, char *arg, int enable, | |
| 573 | + int master_mode) | |
| 609 | 574 | { |
| 610 | 575 | unsigned long res; |
| 611 | − char *argv[8]; | |
| 612 | − int i = 0; | |
| 613 | − const char *str; | |
| 614 | − int buf_len; | |
| 615 | − int str_len; | |
| 576 | + char *argv; | |
| 616 | 577 | char *arg_save = NULL, *arg_org = NULL; |
| 617 | − int rc; | |
| 618 | − char buf[128]; | |
| 578 | + s32 err; | |
| 619 | 579 | struct brcmf_pkt_filter_enable_le enable_parm; |
| 620 | − struct brcmf_pkt_filter_enable_le *pkt_filterp; | |
| 621 | − __le32 mmode_le; | |
| 622 | 580 | |
| 623 | − arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC); | |
| 581 | + arg_save = kstrdup(arg, GFP_ATOMIC); | |
| 624 | 582 | if (!arg_save) |
| 625 | 583 | goto fail; |
| 626 | 584 | |
| 627 | 585 | arg_org = arg_save; |
| 628 | − memcpy(arg_save, arg, strlen(arg) + 1); | |
| 629 | 586 | |
| 630 | − argv[i] = strsep(&arg_save, " "); | |
| 587 | + argv = strsep(&arg_save, " "); | |
| 631 | 588 | |
| 632 | − i = 0; | |
| 633 | − if (NULL == argv[i]) { | |
| 589 | + if (argv == NULL) { | |
| 634 | 590 | brcmf_dbg(ERROR, "No args provided\n"); |
| 635 | 591 | goto fail; |
| 636 | 592 | } |
| 637 | 593 | |
| 638 | − str = "pkt_filter_enable"; | |
| 639 | − str_len = strlen(str); | |
| 640 | − strncpy(buf, str, str_len); | |
| 641 | − buf[str_len] = '\0'; | |
| 642 | − buf_len = str_len + 1; | |
| 643 | − | |
| 644 | − pkt_filterp = (struct brcmf_pkt_filter_enable_le *) (buf + str_len + 1); | |
| 645 | − | |
| 646 | 594 | /* Parse packet filter id. */ |
| 647 | 595 | enable_parm.id = 0; |
| 648 | − if (!kstrtoul(argv[i], 0, &res)) | |
| 596 | + if (!kstrtoul(argv, 0, &res)) | |
| 649 | 597 | enable_parm.id = cpu_to_le32((u32)res); |
| 650 | 598 | |
| 651 | − /* Parse enable/disable value. */ | |
| 599 | + /* Enable/disable the specified filter. */ | |
| 652 | 600 | enable_parm.enable = cpu_to_le32(enable); |
| 653 | 601 | |
| 654 | − buf_len += sizeof(enable_parm); | |
| 655 | − memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm)); | |
| 602 | + err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_enable", &enable_parm, | |
| 603 | + sizeof(enable_parm)); | |
| 604 | + if (err) | |
| 605 | + brcmf_dbg(ERROR, "Set pkt_filter_enable error (%d)\n", err); | |
| 656 | 606 | |
| 657 | − /* Enable/disable the specified filter. */ | |
| 658 | − rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len); | |
| 659 | − rc = rc >= 0 ? 0 : rc; | |
| 660 | − if (rc) | |
| 661 | − brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n", | |
| 662 | − arg, rc); | |
| 663 | − else | |
| 664 | − brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg); | |
| 665 | − | |
| 666 | − /* Contorl the master mode */ | |
| 667 | − mmode_le = cpu_to_le32(master_mode); | |
| 668 | − brcmf_c_mkiovar("pkt_filter_mode", (char *)&mmode_le, 4, buf, | |
| 669 | − sizeof(buf)); | |
| 670 | − rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, | |
| 671 | − sizeof(buf)); | |
| 672 | − rc = rc >= 0 ? 0 : rc; | |
| 673 | − if (rc) | |
| 674 | − brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n", | |
| 675 | − arg, rc); | |
| 607 | + /* Control the master mode */ | |
| 608 | + err = brcmf_fil_iovar_int_set(ifp, "pkt_filter_mode", master_mode); | |
| 609 | + if (err) | |
| 610 | + brcmf_dbg(ERROR, "Set pkt_filter_mode error (%d)\n", err); | |
| 676 | 611 | |
| 677 | 612 | fail: |
| 678 | 613 | kfree(arg_org); |
| 679 | 614 | } |
| 680 | 615 | |
| 681 | −void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg) | |
| 616 | +static void brcmf_c_pktfilter_offload_set(struct brcmf_if *ifp, char *arg) | |
| 682 | 617 | { |
| 683 | − const char *str; | |
| 684 | − struct brcmf_pkt_filter_le pkt_filter; | |
| 685 | − struct brcmf_pkt_filter_le *pkt_filterp; | |
| 618 | + struct brcmf_pkt_filter_le *pkt_filter; | |
| 686 | 619 | unsigned long res; |
| 687 | 620 | int buf_len; |
| 688 | − int str_len; | |
| 689 | − int rc; | |
| 621 | + s32 err; | |
| 690 | 622 | u32 mask_size; |
| 691 | 623 | u32 pattern_size; |
| 692 | 624 | char *argv[8], *buf = NULL; |
| @@ -704,104 +636,64 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg) · 11 unmodified lines | ||
| 704 | 636 | goto fail; |
| 705 | 637 | |
| 706 | 638 | argv[i] = strsep(&arg_save, " "); |
| 707 | − while (argv[i++]) | |
| 639 | + while (argv[i]) { | |
| 640 | + i++; | |
| 641 | + if (i >= 8) { | |
| 642 | + brcmf_dbg(ERROR, "Too many parameters\n"); | |
| 643 | + goto fail; | |
| 644 | + } | |
| 708 | 645 | argv[i] = strsep(&arg_save, " "); |
| 646 | + } | |
| 709 | 647 | |
| 710 | − i = 0; | |
| 711 | − if (NULL == argv[i]) { | |
| 712 | − brcmf_dbg(ERROR, "No args provided\n"); | |
| 648 | + if (i != 6) { | |
| 649 | + brcmf_dbg(ERROR, "Not enough args provided %d\n", i); | |
| 713 | 650 | goto fail; |
| 714 | 651 | } |
| 715 | 652 | |
| 716 | − str = "pkt_filter_add"; | |
| 717 | − strcpy(buf, str); | |
| 718 | − str_len = strlen(str); | |
| 719 | − buf_len = str_len + 1; | |
| 720 | − | |
| 721 | − pkt_filterp = (struct brcmf_pkt_filter_le *) (buf + str_len + 1); | |
| 653 | + pkt_filter = (struct brcmf_pkt_filter_le *)buf; | |
| 722 | 654 | |
| 723 | 655 | /* Parse packet filter id. */ |
| 724 | − pkt_filter.id = 0; | |
| 725 | − if (!kstrtoul(argv[i], 0, &res)) | |
| 726 | − pkt_filter.id = cpu_to_le32((u32)res); | |
| 727 | − | |
| 728 | − if (NULL == argv[++i]) { | |
| 729 | − brcmf_dbg(ERROR, "Polarity not provided\n"); | |
| 730 | − goto fail; | |
| 731 | − } | |
| 656 | + pkt_filter->id = 0; | |
| 657 | + if (!kstrtoul(argv[0], 0, &res)) | |
| 658 | + pkt_filter->id = cpu_to_le32((u32)res); | |
| 732 | 659 | |
| 733 | 660 | /* Parse filter polarity. */ |
| 734 | − pkt_filter.negate_match = 0; | |
| 735 | − if (!kstrtoul(argv[i], 0, &res)) | |
| 736 | − pkt_filter.negate_match = cpu_to_le32((u32)res); | |
| 737 | − | |
| 738 | − if (NULL == argv[++i]) { | |
| 739 | − brcmf_dbg(ERROR, "Filter type not provided\n"); | |
| 740 | − goto fail; | |
| 741 | − } | |
| 661 | + pkt_filter->negate_match = 0; | |
| 662 | + if (!kstrtoul(argv[1], 0, &res)) | |
| 663 | + pkt_filter->negate_match = cpu_to_le32((u32)res); | |
| 742 | 664 | |
| 743 | 665 | /* Parse filter type. */ |
| 744 | − pkt_filter.type = 0; | |
| 745 | − if (!kstrtoul(argv[i], 0, &res)) | |
| 746 | − pkt_filter.type = cpu_to_le32((u32)res); | |
| 747 | − | |
| 748 | − if (NULL == argv[++i]) { | |
| 749 | − brcmf_dbg(ERROR, "Offset not provided\n"); | |
| 750 | − goto fail; | |
| 751 | − } | |
| 666 | + pkt_filter->type = 0; | |
| 667 | + if (!kstrtoul(argv[2], 0, &res)) | |
| 668 | + pkt_filter->type = cpu_to_le32((u32)res); | |
| 752 | 669 | |
| 753 | 670 | /* Parse pattern filter offset. */ |
| 754 | − pkt_filter.u.pattern.offset = 0; | |
| 755 | − if (!kstrtoul(argv[i], 0, &res)) | |
| 756 | − pkt_filter.u.pattern.offset = cpu_to_le32((u32)res); | |
| 757 | − | |
| 758 | − if (NULL == argv[++i]) { | |
| 759 | − brcmf_dbg(ERROR, "Bitmask not provided\n"); | |
| 760 | − goto fail; | |
| 761 | − } | |
| 671 | + pkt_filter->u.pattern.offset = 0; | |
| 672 | + if (!kstrtoul(argv[3], 0, &res)) | |
| 673 | + pkt_filter->u.pattern.offset = cpu_to_le32((u32)res); | |
| 762 | 674 | |
| 763 | 675 | /* Parse pattern filter mask. */ |
| 764 | − mask_size = | |
| 765 | − brcmf_c_pattern_atoh | |
| 766 | − (argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern); | |
| 767 | − | |
| 768 | − if (NULL == argv[++i]) { | |
| 769 | − brcmf_dbg(ERROR, "Pattern not provided\n"); | |
| 770 | − goto fail; | |
| 771 | − } | |
| 676 | + mask_size = brcmf_c_pattern_atoh(argv[4], | |
| 677 | + (char *)pkt_filter->u.pattern.mask_and_pattern); | |
| 772 | 678 | |
| 773 | 679 | /* Parse pattern filter pattern. */ |
| 774 | − pattern_size = | |
| 775 | − brcmf_c_pattern_atoh(argv[i], | |
| 776 | − (char *)&pkt_filterp->u.pattern. | |
| 777 | − mask_and_pattern[mask_size]); | |
| 680 | + pattern_size = brcmf_c_pattern_atoh(argv[5], | |
| 681 | + (char *)&pkt_filter->u.pattern.mask_and_pattern[mask_size]); | |
| 778 | 682 | |
| 779 | 683 | if (mask_size != pattern_size) { |
| 780 | 684 | brcmf_dbg(ERROR, "Mask and pattern not the same size\n"); |
| 781 | 685 | goto fail; |
| 782 | 686 | } |
| 783 | 687 | |
| 784 | − pkt_filter.u.pattern.size_bytes = cpu_to_le32(mask_size); | |
| 785 | − buf_len += BRCMF_PKT_FILTER_FIXED_LEN; | |
| 786 | − buf_len += (BRCMF_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size); | |
| 787 | − | |
| 788 | − /* Keep-alive attributes are set in local | |
| 789 | − * variable (keep_alive_pkt), and | |
| 790 | − ** then memcpy'ed into buffer (keep_alive_pktp) since there is no | |
| 791 | − ** guarantee that the buffer is properly aligned. | |
| 792 | − */ | |
| 793 | − memcpy((char *)pkt_filterp, | |
| 794 | − &pkt_filter, | |
| 795 | − BRCMF_PKT_FILTER_FIXED_LEN + BRCMF_PKT_FILTER_PATTERN_FIXED_LEN); | |
| 796 | − | |
| 797 | − rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len); | |
| 798 | − rc = rc >= 0 ? 0 : rc; | |
| 688 | + pkt_filter->u.pattern.size_bytes = cpu_to_le32(mask_size); | |
| 689 | + buf_len = sizeof(*pkt_filter); | |
| 690 | + buf_len -= sizeof(pkt_filter->u.pattern.mask_and_pattern); | |
| 691 | + buf_len += mask_size + pattern_size; | |
| 799 | 692 | |
| 800 | − if (rc) | |
| 801 | − brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n", | |
| 802 | − arg, rc); | |
| 803 | − else | |
| 804 | − brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg); | |
| 693 | + err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_add", pkt_filter, | |
| 694 | + buf_len); | |
| 695 | + if (err) | |
| 696 | + brcmf_dbg(ERROR, "Set pkt_filter_add error (%d)\n", err); | |
| 805 | 697 | |
| 806 | 698 | fail: |
| 807 | 699 | kfree(arg_org); |
| @@ -809,130 +701,125 @@ fail: · 1 unmodified line | ||
| 809 | 701 | kfree(buf); |
| 810 | 702 | } |
| 811 | 703 | |
| 812 | −static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode) | |
| 704 | +int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | |
| 813 | 705 | { |
| 814 | − char iovbuf[32]; | |
| 815 | − int retcode; | |
| 816 | − __le32 arp_mode_le; | |
| 817 | − | |
| 818 | − arp_mode_le = cpu_to_le32(arp_mode); | |
| 819 | − brcmf_c_mkiovar("arp_ol", (char *)&arp_mode_le, 4, iovbuf, | |
| 820 | − sizeof(iovbuf)); | |
| 821 | − retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, | |
| 822 | − iovbuf, sizeof(iovbuf)); | |
| 823 | − retcode = retcode >= 0 ? 0 : retcode; | |
| 824 | − if (retcode) | |
| 825 | − brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, retcode = %d\n", | |
| 826 | − arp_mode, retcode); | |
| 827 | − else | |
| 828 | − brcmf_dbg(TRACE, "successfully set ARP offload mode to 0x%x\n", | |
| 829 | − arp_mode); | |
| 830 | −} | |
| 831 | − | |
| 832 | −static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable) | |
| 833 | −{ | |
| 834 | − char iovbuf[32]; | |
| 835 | − int retcode; | |
| 836 | − __le32 arp_enable_le; | |
| 837 | − | |
| 838 | − arp_enable_le = cpu_to_le32(arp_enable); | |
| 839 | − | |
| 840 | − brcmf_c_mkiovar("arpoe", (char *)&arp_enable_le, 4, | |
| 841 | − iovbuf, sizeof(iovbuf)); | |
| 842 | − retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, | |
| 843 | − iovbuf, sizeof(iovbuf)); | |
| 844 | − retcode = retcode >= 0 ? 0 : retcode; | |
| 845 | − if (retcode) | |
| 846 | − brcmf_dbg(TRACE, "failed to enable ARP offload to %d, retcode = %d\n", | |
| 847 | − arp_enable, retcode); | |
| 848 | − else | |
| 849 | − brcmf_dbg(TRACE, "successfully enabled ARP offload to %d\n", | |
| 850 | − arp_enable); | |
| 851 | −} | |
| 852 | − | |
| 853 | −int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) | |
| 854 | −{ | |
| 855 | − char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for | |
| 856 | − "event_msgs" + '\0' + bitvec */ | |
| 857 | − char buf[128], *ptr; | |
| 858 | − __le32 roaming_le = cpu_to_le32(1); | |
| 859 | − __le32 bcn_timeout_le = cpu_to_le32(3); | |
| 860 | − __le32 scan_assoc_time_le = cpu_to_le32(40); | |
| 861 | − __le32 scan_unassoc_time_le = cpu_to_le32(40); | |
| 862 | − int i; | |
| 706 | + s8 eventmask[BRCMF_EVENTING_MASK_LEN]; | |
| 707 | + u8 buf[BRCMF_DCMD_SMLEN]; | |
| 708 | + char *ptr; | |
| 709 | + s32 err; | |
| 863 | 710 | struct brcmf_bus_dcmd *cmdlst; |
| 864 | 711 | struct list_head *cur, *q; |
| 865 | 712 | |
| 866 | − mutex_lock(&drvr->proto_block); | |
| 867 | − | |
| 868 | − /* Set Country code */ | |
| 869 | − if (drvr->country_code[0] != 0) { | |
| 870 | − if (brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_COUNTRY, | |
| 871 | − drvr->country_code, | |
| 872 | − sizeof(drvr->country_code)) < 0) | |
| 873 | − brcmf_dbg(ERROR, "country code setting failed\n"); | |
| 713 | + /* retreive mac address */ | |
| 714 | + err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, | |
| 715 | + sizeof(ifp->mac_addr)); | |
| 716 | + if (err < 0) { | |
| 717 | + brcmf_dbg(ERROR, "Retreiving cur_etheraddr failed, %d\n", | |
| 718 | + err); | |
| 719 | + goto done; | |
| 874 | 720 | } |
| 721 | + memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac)); | |
| 875 | 722 | |
| 876 | 723 | /* query for 'ver' to get version info from firmware */ |
| 877 | 724 | memset(buf, 0, sizeof(buf)); |
| 878 | − ptr = buf; | |
| 879 | − brcmf_c_mkiovar("ver", NULL, 0, buf, sizeof(buf)); | |
| 880 | − brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, buf, sizeof(buf)); | |
| 725 | + strcpy(buf, "ver"); | |
| 726 | + err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf)); | |
| 727 | + if (err < 0) { | |
| 728 | + brcmf_dbg(ERROR, "Retreiving version information failed, %d\n", | |
| 729 | + err); | |
| 730 | + goto done; | |
| 731 | + } | |
| 732 | + ptr = (char *)buf; | |
| 881 | 733 | strsep(&ptr, "\n"); |
| 882 | 734 | /* Print fw version info */ |
| 883 | 735 | brcmf_dbg(ERROR, "Firmware version = %s\n", buf); |
| 884 | 736 | |
| 885 | − /* Setup timeout if Beacons are lost and roam is off to report | |
| 886 | − link down */ | |
| 887 | − brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout_le, 4, iovbuf, | |
| 888 | − sizeof(iovbuf)); | |
| 889 | − brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, | |
| 890 | − sizeof(iovbuf)); | |
| 737 | + /* | |
| 738 | + * Setup timeout if Beacons are lost and roam is off to report | |
| 739 | + * link down | |
| 740 | + */ | |
| 741 | + err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", | |
| 742 | + BRCMF_DEFAULT_BCN_TIMEOUT); | |
| 743 | + if (err) { | |
| 744 | + brcmf_dbg(ERROR, "bcn_timeout error (%d)\n", err); | |
| 745 | + goto done; | |
| 746 | + } | |
| 891 | 747 | |
| 892 | 748 | /* Enable/Disable build-in roaming to allowed ext supplicant to take |
| 893 | − of romaing */ | |
| 894 | − brcmf_c_mkiovar("roam_off", (char *)&roaming_le, 4, | |
| 895 | − iovbuf, sizeof(iovbuf)); | |
| 896 | − brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, | |
| 897 | − sizeof(iovbuf)); | |
| 898 | − | |
| 899 | − /* Setup event_msgs */ | |
| 900 | − brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN, | |
| 901 | − iovbuf, sizeof(iovbuf)); | |
| 902 | − brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, | |
| 903 | − sizeof(iovbuf)); | |
| 904 | − | |
| 905 | − brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME, | |
| 906 | − (char *)&scan_assoc_time_le, sizeof(scan_assoc_time_le)); | |
| 907 | − brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME, | |
| 908 | − (char *)&scan_unassoc_time_le, sizeof(scan_unassoc_time_le)); | |
| 909 | − | |
| 910 | − /* Set and enable ARP offload feature */ | |
| 911 | − brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE); | |
| 912 | − brcmf_c_arp_offload_enable(drvr, true); | |
| 913 | − | |
| 914 | − /* Set up pkt filter */ | |
| 915 | − for (i = 0; i < drvr->pktfilter_count; i++) { | |
| 916 | − brcmf_c_pktfilter_offload_set(drvr, drvr->pktfilter[i]); | |
| 917 | − brcmf_c_pktfilter_offload_enable(drvr, drvr->pktfilter[i], | |
| 918 | − 0, true); | |
| 749 | + * of romaing | |
| 750 | + */ | |
| 751 | + err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1); | |
| 752 | + if (err) { | |
| 753 | + brcmf_dbg(ERROR, "roam_off error (%d)\n", err); | |
| 754 | + goto done; | |
| 755 | + } | |
| 756 | + | |
| 757 | + /* Setup event_msgs, enable E_IF */ | |
| 758 | + err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask, | |
| 759 | + BRCMF_EVENTING_MASK_LEN); | |
| 760 | + if (err) { | |
| 761 | + brcmf_dbg(ERROR, "Get event_msgs error (%d)\n", err); | |
| 762 | + goto done; | |
| 763 | + } | |
| 764 | + setbit(eventmask, BRCMF_E_IF); | |
| 765 | + err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask, | |
| 766 | + BRCMF_EVENTING_MASK_LEN); | |
| 767 | + if (err) { | |
| 768 | + brcmf_dbg(ERROR, "Set event_msgs error (%d)\n", err); | |
| 769 | + goto done; | |
| 770 | + } | |
| 771 | + | |
| 772 | + /* Setup default scan channel time */ | |
| 773 | + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, | |
| 774 | + BRCMF_DEFAULT_SCAN_CHANNEL_TIME); | |
| 775 | + if (err) { | |
| 776 | + brcmf_dbg(ERROR, "BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n", | |
| 777 | + err); | |
| 778 | + goto done; | |
| 919 | 779 | } |
| 920 | 780 | |
| 781 | + /* Setup default scan unassoc time */ | |
| 782 | + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME, | |
| 783 | + BRCMF_DEFAULT_SCAN_UNASSOC_TIME); | |
| 784 | + if (err) { | |
| 785 | + brcmf_dbg(ERROR, "BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n", | |
| 786 | + err); | |
| 787 | + goto done; | |
| 788 | + } | |
| 789 | + | |
| 790 | + /* Try to set and enable ARP offload feature, this may fail */ | |
| 791 | + err = brcmf_fil_iovar_int_set(ifp, "arp_ol", BRCMF_ARPOL_MODE); | |
| 792 | + if (err) { | |
| 793 | + brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n", | |
| 794 | + BRCMF_ARPOL_MODE, err); | |
| 795 | + err = 0; | |
| 796 | + } else { | |
| 797 | + err = brcmf_fil_iovar_int_set(ifp, "arpoe", 1); | |
| 798 | + if (err) { | |
| 799 | + brcmf_dbg(TRACE, "failed to enable ARP offload err = %d\n", | |
| 800 | + err); | |
| 801 | + err = 0; | |
| 802 | + } else | |
| 803 | + brcmf_dbg(TRACE, "successfully enabled ARP offload to 0x%x\n", | |
| 804 | + BRCMF_ARPOL_MODE); | |
| 805 | + } | |
| 806 | + | |
| 807 | + /* Setup packet filter */ | |
| 808 | + brcmf_c_pktfilter_offload_set(ifp, BRCMF_DEFAULT_PACKET_FILTER); | |
| 809 | + brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER, | |
| 810 | + 0, true); | |
| 811 | + | |
| 921 | 812 | /* set bus specific command if there is any */ |
| 922 | − list_for_each_safe(cur, q, &drvr->bus_if->dcmd_list) { | |
| 813 | + list_for_each_safe(cur, q, &ifp->drvr->bus_if->dcmd_list) { | |
| 923 | 814 | cmdlst = list_entry(cur, struct brcmf_bus_dcmd, list); |
| 924 | 815 | if (cmdlst->name && cmdlst->param && cmdlst->param_len) { |
| 925 | − brcmf_c_mkiovar(cmdlst->name, cmdlst->param, | |
| 926 | − cmdlst->param_len, iovbuf, | |
| 927 | − sizeof(iovbuf)); | |
| 928 | − brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, | |
| 929 | − iovbuf, sizeof(iovbuf)); | |
| 816 | + brcmf_fil_iovar_data_set(ifp, cmdlst->name, | |
| 817 | + cmdlst->param, | |
| 818 | + cmdlst->param_len); | |
| 930 | 819 | } |
| 931 | 820 | list_del(cur); |
| 932 | 821 | kfree(cmdlst); |
| 933 | 822 | } |
| 934 | − | |
| 935 | − mutex_unlock(&drvr->proto_block); | |
| 936 | − | |
| 937 | − return 0; | |
| 823 | +done: | |
| 824 | + return err; | |
| 938 | 825 | } |
| @@ -16,8 +16,10 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <linux/debugfs.h> |
| 17 | 17 | #include <linux/if_ether.h> |
| 18 | 18 | #include <linux/if.h> |
| 19 | +#include <linux/netdevice.h> | |
| 19 | 20 | #include <linux/ieee80211.h> |
| 20 | 21 | #include <linux/module.h> |
| 22 | +#include <linux/netdevice.h> | |
| 21 | 23 | |
| 22 | 24 | #include <defs.h> |
| 23 | 25 | #include <brcmu_wifi.h> |
| @@ -31,6 +31,7 @@ · 30 unmodified lines | ||
| 31 | 31 | #define BRCMF_EVENT_VAL 0x0800 |
| 32 | 32 | #define BRCMF_BTA_VAL 0x1000 |
| 33 | 33 | #define BRCMF_ISCAN_VAL 0x2000 |
| 34 | +#define BRCMF_FIL_VAL 0x4000 | |
| 34 | 35 | |
| 35 | 36 | #if defined(DEBUG) |
| 36 | 37 | |
| @@ -56,6 +57,7 @@ do { \ · 19 unmodified lines | ||
| 56 | 57 | #define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL) |
| 57 | 58 | #define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL) |
| 58 | 59 | #define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL) |
| 60 | +#define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL) | |
| 59 | 61 | |
| 60 | 62 | #else /* (defined DEBUG) || (defined DEBUG) */ |
| 61 | 63 | |
| @@ -67,6 +69,7 @@ do { \ · 5 unmodified lines | ||
| 67 | 69 | #define BRCMF_BYTES_ON() 0 |
| 68 | 70 | #define BRCMF_GLOM_ON() 0 |
| 69 | 71 | #define BRCMF_EVENT_ON() 0 |
| 72 | +#define BRCMF_FIL_ON() 0 | |
| 70 | 73 | |
| 71 | 74 | #endif /* defined(DEBUG) */ |
| 72 | 75 | |
| @@ -52,16 +52,6 @@ MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards"); · 51 unmodified lines | ||
| 52 | 52 | MODULE_LICENSE("Dual BSD/GPL"); |
| 53 | 53 | |
| 54 | 54 | |
| 55 | −/* Interface control information */ | |
| 56 | −struct brcmf_if { | |
| 57 | − struct brcmf_pub *drvr; /* back pointer to brcmf_pub */ | |
| 58 | − /* OS/stack specifics */ | |
| 59 | − struct net_device *ndev; | |
| 60 | − struct net_device_stats stats; | |
| 61 | − int idx; /* iface idx in dongle */ | |
| 62 | − u8 mac_addr[ETH_ALEN]; /* assigned MAC address */ | |
| 63 | −}; | |
| 64 | − | |
| 65 | 55 | /* Error bits */ |
| 66 | 56 | int brcmf_msg_level = BRCMF_ERROR_VAL; |
| 67 | 57 | module_param(brcmf_msg_level, int, 0); |
| @@ -629,12 +619,9 @@ static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr) · 561 unmodified lines | ||
| 629 | 619 | brcmf_dbg(ERROR, "dongle is not up\n"); |
| 630 | 620 | return -ENODEV; |
| 631 | 621 | } |
| 632 | − | |
| 633 | 622 | /* finally, report dongle driver type */ |
| 634 | − else if (drvr->iswl) | |
| 635 | − sprintf(info.driver, "wl"); | |
| 636 | 623 | else |
| 637 | − sprintf(info.driver, "xx"); | |
| 624 | + sprintf(info.driver, "wl"); | |
| 638 | 625 | |
| 639 | 626 | sprintf(info.version, "%lu", drvr->drv_version); |
| 640 | 627 | 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, · 78 unmodified lines | ||
| 719 | 706 | return -EOPNOTSUPP; |
| 720 | 707 | } |
| 721 | 708 | |
| 722 | −/* called only from within this driver. Sends a command to the dongle. */ | |
| 723 | −s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len) | |
| 724 | −{ | |
| 725 | − struct brcmf_dcmd dcmd; | |
| 726 | − s32 err = 0; | |
| 727 | − int buflen = 0; | |
| 728 | − bool is_set_key_cmd; | |
| 729 | − struct brcmf_if *ifp = netdev_priv(ndev); | |
| 730 | − struct brcmf_pub *drvr = ifp->drvr; | |
| 731 | − | |
| 732 | − memset(&dcmd, 0, sizeof(dcmd)); | |
| 733 | − dcmd.cmd = cmd; | |
| 734 | − dcmd.buf = arg; | |
| 735 | − dcmd.len = len; | |
| 736 | − | |
| 737 | − if (dcmd.buf != NULL) | |
| 738 | − buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN); | |
| 739 | − | |
| 740 | − /* send to dongle (must be up, and wl) */ | |
| 741 | − if ((drvr->bus_if->state != BRCMF_BUS_DATA)) { | |
| 742 | − brcmf_dbg(ERROR, "DONGLE_DOWN\n"); | |
| 743 | − err = -EIO; | |
| 744 | − goto done; | |
| 745 | − } | |
| 746 | − | |
| 747 | − if (!drvr->iswl) { | |
| 748 | − err = -EIO; | |
| 749 | − goto done; | |
| 750 | − } | |
| 751 | − | |
| 752 | − /* | |
| 753 | − * Intercept BRCMF_C_SET_KEY CMD - serialize M4 send and | |
| 754 | − * set key CMD to prevent M4 encryption. | |
| 755 | − */ | |
| 756 | − is_set_key_cmd = ((dcmd.cmd == BRCMF_C_SET_KEY) || | |
| 757 | − ((dcmd.cmd == BRCMF_C_SET_VAR) && | |
| 758 | − !(strncmp("wsec_key", dcmd.buf, 9))) || | |
| 759 | − ((dcmd.cmd == BRCMF_C_SET_VAR) && | |
| 760 | − !(strncmp("bsscfg:wsec_key", dcmd.buf, 15)))); | |
| 761 | − if (is_set_key_cmd) | |
| 762 | − brcmf_netdev_wait_pend8021x(ndev); | |
| 763 | − | |
| 764 | − err = brcmf_proto_dcmd(drvr, ifp->idx, &dcmd, buflen); | |
| 765 | − | |
| 766 | −done: | |
| 767 | − if (err > 0) | |
| 768 | − err = 0; | |
| 769 | − | |
| 770 | − return err; | |
| 771 | −} | |
| 772 | − | |
| 773 | −int brcmf_netlink_dcmd(struct net_device *ndev, struct brcmf_dcmd *dcmd) | |
| 774 | −{ | |
| 775 | − brcmf_dbg(TRACE, "enter: cmd %x buf %p len %d\n", | |
| 776 | − dcmd->cmd, dcmd->buf, dcmd->len); | |
| 777 | − | |
| 778 | − return brcmf_exec_dcmd(ndev, dcmd->cmd, dcmd->buf, dcmd->len); | |
| 779 | −} | |
| 780 | − | |
| 781 | 709 | static int brcmf_netdev_stop(struct net_device *ndev) |
| 782 | 710 | { |
| 783 | 711 | struct brcmf_if *ifp = netdev_priv(ndev); |
| @@ -851,7 +779,7 @@ static const struct net_device_ops brcmf_netdev_ops_pri = { · 67 unmodified lines | ||
| 851 | 779 | .ndo_set_rx_mode = brcmf_netdev_set_multicast_list |
| 852 | 780 | }; |
| 853 | 781 | |
| 854 | −static int brcmf_net_attach(struct brcmf_if *ifp) | |
| 782 | +int brcmf_net_attach(struct brcmf_if *ifp) | |
| 855 | 783 | { |
| 856 | 784 | struct brcmf_pub *drvr = ifp->drvr; |
| 857 | 785 | struct net_device *ndev; |
| @@ -885,15 +813,6 @@ static int brcmf_net_attach(struct brcmf_if *ifp) · 27 unmodified lines | ||
| 885 | 813 | |
| 886 | 814 | memcpy(ndev->dev_addr, temp_addr, ETH_ALEN); |
| 887 | 815 | |
| 888 | − /* attach to cfg80211 for primary interface */ | |
| 889 | − if (!ifp->idx) { | |
| 890 | − drvr->config = brcmf_cfg80211_attach(ndev, drvr->dev, drvr); | |
| 891 | − if (drvr->config == NULL) { | |
| 892 | − brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n"); | |
| 893 | − goto fail; | |
| 894 | − } | |
| 895 | − } | |
| 896 | − | |
| 897 | 816 | if (register_netdev(ndev) != 0) { |
| 898 | 817 | brcmf_dbg(ERROR, "couldn't register the net device\n"); |
| 899 | 818 | goto fail; |
| @@ -905,11 +824,12 @@ static int brcmf_net_attach(struct brcmf_if *ifp) · 5 unmodified lines | ||
| 905 | 824 | |
| 906 | 825 | fail: |
| 907 | 826 | ndev->netdev_ops = NULL; |
| 827 | + free_netdev(ndev); | |
| 908 | 828 | return -EBADE; |
| 909 | 829 | } |
| 910 | 830 | |
| 911 | −int | |
| 912 | −brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr) | |
| 831 | +struct brcmf_if *brcmf_add_if(struct device *dev, int ifidx, s32 bssidx, | |
| 832 | + char *name, u8 *mac_addr) | |
| 913 | 833 | { |
| 914 | 834 | struct brcmf_if *ifp; |
| 915 | 835 | struct net_device *ndev; |
| @@ -936,7 +856,7 @@ brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr) · 20 unmodified lines | ||
| 936 | 856 | ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup); |
| 937 | 857 | if (!ndev) { |
| 938 | 858 | brcmf_dbg(ERROR, "OOM - alloc_netdev\n"); |
| 939 | − return -ENOMEM; | |
| 859 | + return ERR_PTR(-ENOMEM); | |
| 940 | 860 | } |
| 941 | 861 | |
| 942 | 862 | ifp = netdev_priv(ndev); |
| @@ -944,20 +864,14 @@ brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr) · 1 unmodified line | ||
| 944 | 864 | ifp->drvr = drvr; |
| 945 | 865 | drvr->iflist[ifidx] = ifp; |
| 946 | 866 | ifp->idx = ifidx; |
| 867 | + ifp->bssidx = bssidx; | |
| 947 | 868 | if (mac_addr != NULL) |
| 948 | 869 | memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN); |
| 949 | 870 | |
| 950 | − if (brcmf_net_attach(ifp)) { | |
| 951 | − brcmf_dbg(ERROR, "brcmf_net_attach failed"); | |
| 952 | − free_netdev(ifp->ndev); | |
| 953 | − drvr->iflist[ifidx] = NULL; | |
| 954 | − return -EOPNOTSUPP; | |
| 955 | − } | |
| 956 | − | |
| 957 | 871 | brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n", |
| 958 | 872 | current->pid, ifp->ndev->name); |
| 959 | 873 | |
| 960 | − return 0; | |
| 874 | + return ifp; | |
| 961 | 875 | } |
| 962 | 876 | |
| 963 | 877 | void brcmf_del_if(struct brcmf_pub *drvr, int ifidx) |
| @@ -1036,10 +950,9 @@ fail: · 72 unmodified lines | ||
| 1036 | 950 | int brcmf_bus_start(struct device *dev) |
| 1037 | 951 | { |
| 1038 | 952 | int ret = -1; |
| 1039 | − /* Room for "event_msgs" + '\0' + bitvec */ | |
| 1040 | − char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; | |
| 1041 | 953 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
| 1042 | 954 | struct brcmf_pub *drvr = bus_if->drvr; |
| 955 | + struct brcmf_if *ifp; | |
| 1043 | 956 | |
| 1044 | 957 | brcmf_dbg(TRACE, "\n"); |
| 1045 | 958 | |
| @@ -1050,49 +963,30 @@ int brcmf_bus_start(struct device *dev) · 4 unmodified lines | ||
| 1050 | 963 | return ret; |
| 1051 | 964 | } |
| 1052 | 965 | |
| 1053 | − brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN, | |
| 1054 | − iovbuf, sizeof(iovbuf)); | |
| 1055 | − brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, iovbuf, | |
| 1056 | − sizeof(iovbuf)); | |
| 1057 | − memcpy(drvr->eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN); | |
| 1058 | − | |
| 1059 | − setbit(drvr->eventmask, BRCMF_E_SET_SSID); | |
| 1060 | − setbit(drvr->eventmask, BRCMF_E_PRUNE); | |
| 1061 | − setbit(drvr->eventmask, BRCMF_E_AUTH); | |
| 1062 | − setbit(drvr->eventmask, BRCMF_E_REASSOC); | |
| 1063 | − setbit(drvr->eventmask, BRCMF_E_REASSOC_IND); | |
| 1064 | − setbit(drvr->eventmask, BRCMF_E_DEAUTH_IND); | |
| 1065 | − setbit(drvr->eventmask, BRCMF_E_DISASSOC_IND); | |
| 1066 | − setbit(drvr->eventmask, BRCMF_E_DISASSOC); | |
| 1067 | − setbit(drvr->eventmask, BRCMF_E_JOIN); | |
| 1068 | − setbit(drvr->eventmask, BRCMF_E_ASSOC_IND); | |
| 1069 | − setbit(drvr->eventmask, BRCMF_E_PSK_SUP); | |
| 1070 | − setbit(drvr->eventmask, BRCMF_E_LINK); | |
| 1071 | − setbit(drvr->eventmask, BRCMF_E_NDIS_LINK); | |
| 1072 | − setbit(drvr->eventmask, BRCMF_E_MIC_ERROR); | |
| 1073 | − setbit(drvr->eventmask, BRCMF_E_PMKID_CACHE); | |
| 1074 | − setbit(drvr->eventmask, BRCMF_E_TXFAIL); | |
| 1075 | − setbit(drvr->eventmask, BRCMF_E_JOIN_START); | |
| 1076 | − setbit(drvr->eventmask, BRCMF_E_SCAN_COMPLETE); | |
| 1077 | − | |
| 1078 | −/* enable dongle roaming event */ | |
| 1079 | − | |
| 1080 | − drvr->pktfilter_count = 1; | |
| 1081 | − /* Setup filter to allow only unicast */ | |
| 1082 | − drvr->pktfilter[0] = "100 0 0 0 0x01 0x00"; | |
| 1083 | − | |
| 1084 | − /* Bus is ready, do any protocol initialization */ | |
| 1085 | − ret = brcmf_proto_init(drvr); | |
| 966 | + /* add primary networking interface */ | |
| 967 | + ifp = brcmf_add_if(dev, 0, 0, "wlan%d", NULL); | |
| 968 | + if (IS_ERR(ifp)) | |
| 969 | + return PTR_ERR(ifp); | |
| 970 | + | |
| 971 | + /* signal bus ready */ | |
| 972 | + bus_if->state = BRCMF_BUS_DATA; | |
| 973 | + | |
| 974 | + /* Bus is ready, do any initialization */ | |
| 975 | + ret = brcmf_c_preinit_dcmds(ifp); | |
| 1086 | 976 | if (ret < 0) |
| 1087 | 977 | return ret; |
| 1088 | 978 | |
| 1089 | − /* add primary networking interface */ | |
| 1090 | − ret = brcmf_add_if(dev, 0, "wlan%d", drvr->mac); | |
| 1091 | − if (ret < 0) | |
| 979 | + drvr->config = brcmf_cfg80211_attach(drvr); | |
| 980 | + if (drvr->config == NULL) | |
| 981 | + return -ENOMEM; | |
| 982 | + | |
| 983 | + ret = brcmf_net_attach(ifp); | |
| 984 | + if (ret < 0) { | |
| 985 | + brcmf_dbg(ERROR, "brcmf_net_attach failed"); | |
| 986 | + drvr->iflist[0] = NULL; | |
| 1092 | 987 | return ret; |
| 988 | + } | |
| 1093 | 989 | |
| 1094 | − /* signal bus ready */ | |
| 1095 | − bus_if->state = BRCMF_BUS_DATA; | |
| 1096 | 990 | return 0; |
| 1097 | 991 | } |
| 1098 | 992 | |
| @@ -1163,42 +1057,6 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev) · 64 unmodified lines | ||
| 1163 | 1057 | return pend; |
| 1164 | 1058 | } |
| 1165 | 1059 | |
| 1166 | −#ifdef DEBUG | |
| 1167 | −int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size) | |
| 1168 | −{ | |
| 1169 | − int ret = 0; | |
| 1170 | − struct file *fp; | |
| 1171 | − mm_segment_t old_fs; | |
| 1172 | − loff_t pos = 0; | |
| 1173 | − | |
| 1174 | − /* change to KERNEL_DS address limit */ | |
| 1175 | − old_fs = get_fs(); | |
| 1176 | − set_fs(KERNEL_DS); | |
| 1177 | − | |
| 1178 | − /* open file to write */ | |
| 1179 | − fp = filp_open("/tmp/mem_dump", O_WRONLY | O_CREAT, 0640); | |
| 1180 | − if (!fp) { | |
| 1181 | − brcmf_dbg(ERROR, "open file error\n"); | |
| 1182 | − ret = -1; | |
| 1183 | − goto exit; | |
| 1184 | − } | |
| 1185 | − | |
| 1186 | − /* Write buf to file */ | |
| 1187 | − fp->f_op->write(fp, (char __user *)buf, size, &pos); | |
| 1188 | − | |
| 1189 | −exit: | |
| 1190 | − /* free buf before return */ | |
| 1191 | − kfree(buf); | |
| 1192 | − /* close file before return */ | |
| 1193 | − if (fp) | |
| 1194 | − filp_close(fp, NULL); | |
| 1195 | − /* restore previous address limit */ | |
| 1196 | − set_fs(old_fs); | |
| 1197 | − | |
| 1198 | − return ret; | |
| 1199 | −} | |
| 1200 | −#endif /* DEBUG */ | |
| 1201 | − | |
| 1202 | 1060 | static void brcmf_driver_init(struct work_struct *work) |
| 1203 | 1061 | { |
| 1204 | 1062 | brcmf_debugfs_init(); |
| @@ -27,11 +27,6 @@ extern int brcmf_proto_attach(struct brcmf_pub *drvr); · 26 unmodified lines | ||
| 27 | 27 | /* Unlink, frees allocated protocol memory (including brcmf_proto) */ |
| 28 | 28 | extern void brcmf_proto_detach(struct brcmf_pub *drvr); |
| 29 | 29 | |
| 30 | −/* Initialize protocol: sync w/dongle state. | |
| 31 | − * Sets dongle media info (iswl, drv_version, mac address). | |
| 32 | − */ | |
| 33 | −extern int brcmf_proto_init(struct brcmf_pub *drvr); | |
| 34 | − | |
| 35 | 30 | /* Stop protocol: sync w/dongle state. */ |
| 36 | 31 | extern void brcmf_proto_stop(struct brcmf_pub *drvr); |
| 37 | 32 | |
| @@ -45,7 +40,8 @@ extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, · 7 unmodified lines | ||
| 45 | 40 | extern int brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx, |
| 46 | 41 | struct brcmf_dcmd *dcmd, int len); |
| 47 | 42 | |
| 48 | −extern int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr); | |
| 43 | +/* Sets dongle media info (drv_version, mac address). */ | |
| 44 | +extern int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); | |
| 49 | 45 | |
| 50 | 46 | extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, |
| 51 | 47 | uint cmd, void *buf, uint len); |
| @@ -614,6 +614,12 @@ static const uint max_roundup = 512; · 613 unmodified lines | ||
| 614 | 614 | |
| 615 | 615 | #define ALIGNMENT 4 |
| 616 | 616 | |
| 617 | +enum brcmf_sdio_frmtype { | |
| 618 | + BRCMF_SDIO_FT_NORMAL, | |
| 619 | + BRCMF_SDIO_FT_SUPER, | |
| 620 | + BRCMF_SDIO_FT_SUB, | |
| 621 | +}; | |
| 622 | + | |
| 617 | 623 | static void pkt_align(struct sk_buff *p, int len, int align) |
| 618 | 624 | { |
| 619 | 625 | uint datalign; |
| @@ -1032,7 +1038,8 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus) · 412 unmodified lines | ||
| 1032 | 1038 | } |
| 1033 | 1039 | |
| 1034 | 1040 | static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, |
| 1035 | − struct brcmf_sdio_read *rd) | |
| 1041 | + struct brcmf_sdio_read *rd, | |
| 1042 | + enum brcmf_sdio_frmtype type) | |
| 1036 | 1043 | { |
| 1037 | 1044 | u16 len, checksum; |
| 1038 | 1045 | u8 rx_seq, fc, tx_seq_max; |
| @@ -1059,6 +1066,15 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, · 20 unmodified lines | ||
| 1059 | 1066 | brcmf_dbg(ERROR, "HW header length error\n"); |
| 1060 | 1067 | return false; |
| 1061 | 1068 | } |
| 1069 | + if (type == BRCMF_SDIO_FT_SUPER && | |
| 1070 | + (roundup(len, bus->blocksize) != rd->len)) { | |
| 1071 | + brcmf_dbg(ERROR, "HW superframe header length error\n"); | |
| 1072 | + return false; | |
| 1073 | + } | |
| 1074 | + if (type == BRCMF_SDIO_FT_SUB && len > rd->len) { | |
| 1075 | + brcmf_dbg(ERROR, "HW subframe header length error\n"); | |
| 1076 | + return false; | |
| 1077 | + } | |
| 1062 | 1078 | rd->len = len; |
| 1063 | 1079 | |
| 1064 | 1080 | /* |
| @@ -1071,9 +1087,16 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, · 6 unmodified lines | ||
| 1071 | 1087 | * Byte 5: Maximum Sequence number allow for Tx |
| 1072 | 1088 | * Byte 6~7: Reserved |
| 1073 | 1089 | */ |
| 1090 | + if (type == BRCMF_SDIO_FT_SUPER && | |
| 1091 | + SDPCM_GLOMDESC(&header[SDPCM_FRAMETAG_LEN])) { | |
| 1092 | + brcmf_dbg(ERROR, "Glom descriptor found in superframe head\n"); | |
| 1093 | + rd->len = 0; | |
| 1094 | + return false; | |
| 1095 | + } | |
| 1074 | 1096 | rx_seq = SDPCM_PACKET_SEQUENCE(&header[SDPCM_FRAMETAG_LEN]); |
| 1075 | 1097 | rd->channel = SDPCM_PACKET_CHANNEL(&header[SDPCM_FRAMETAG_LEN]); |
| 1076 | − if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL) { | |
| 1098 | + if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL && | |
| 1099 | + type != BRCMF_SDIO_FT_SUPER) { | |
| 1077 | 1100 | brcmf_dbg(ERROR, "HW header length too long\n"); |
| 1078 | 1101 | bus->sdiodev->bus_if->dstats.rx_errors++; |
| 1079 | 1102 | bus->sdcnt.rx_toolong++; |
| @@ -1081,6 +1104,17 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, · 1 unmodified line | ||
| 1081 | 1104 | rd->len = 0; |
| 1082 | 1105 | return false; |
| 1083 | 1106 | } |
| 1107 | + if (type == BRCMF_SDIO_FT_SUPER && rd->channel != SDPCM_GLOM_CHANNEL) { | |
| 1108 | + brcmf_dbg(ERROR, "Wrong channel for superframe\n"); | |
| 1109 | + rd->len = 0; | |
| 1110 | + return false; | |
| 1111 | + } | |
| 1112 | + if (type == BRCMF_SDIO_FT_SUB && rd->channel != SDPCM_DATA_CHANNEL && | |
| 1113 | + rd->channel != SDPCM_EVENT_CHANNEL) { | |
| 1114 | + brcmf_dbg(ERROR, "Wrong channel for subframe\n"); | |
| 1115 | + rd->len = 0; | |
| 1116 | + return false; | |
| 1117 | + } | |
| 1084 | 1118 | rd->dat_offset = SDPCM_DOFFSET_VALUE(&header[SDPCM_FRAMETAG_LEN]); |
| 1085 | 1119 | if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) { |
| 1086 | 1120 | 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, · 8 unmodified lines | ||
| 1095 | 1129 | bus->sdcnt.rx_badseq++; |
| 1096 | 1130 | rd->seq_num = rx_seq; |
| 1097 | 1131 | } |
| 1132 | + /* no need to check the reset for subframe */ | |
| 1133 | + if (type == BRCMF_SDIO_FT_SUB) | |
| 1134 | + return true; | |
| 1098 | 1135 | rd->len_nxtfrm = header[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; |
| 1099 | 1136 | if (rd->len_nxtfrm << 4 > MAX_RX_DATASZ) { |
| 1100 | 1137 | /* only warm for NON glom packet */ |
| @@ -1126,16 +1163,16 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) · 25 unmodified lines | ||
| 1126 | 1163 | u16 dlen, totlen; |
| 1127 | 1164 | u8 *dptr, num = 0; |
| 1128 | 1165 | |
| 1129 | − u16 sublen, check; | |
| 1166 | + u16 sublen; | |
| 1130 | 1167 | struct sk_buff *pfirst, *pnext; |
| 1131 | 1168 | |
| 1132 | 1169 | int errcode; |
| 1133 | − u8 chan, seq, doff, sfdoff; | |
| 1134 | − u8 txmax; | |
| 1170 | + u8 doff, sfdoff; | |
| 1135 | 1171 | |
| 1136 | 1172 | int ifidx = 0; |
| 1137 | 1173 | bool usechain = bus->use_rxchain; |
| 1138 | − u16 next_len; | |
| 1174 | + | |
| 1175 | + struct brcmf_sdio_read rd_new; | |
| 1139 | 1176 | |
| 1140 | 1177 | /* If packets, issue read(s) and send up packet chain */ |
| 1141 | 1178 | /* Return sequence numbers consumed? */ |
| @@ -1279,68 +1316,15 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) · 137 unmodified lines | ||
| 1279 | 1316 | pfirst->data, min_t(int, pfirst->len, 48), |
| 1280 | 1317 | "SUPERFRAME:\n"); |
| 1281 | 1318 | |
| 1282 | − /* Validate the superframe header */ | |
| 1283 | − dptr = (u8 *) (pfirst->data); | |
| 1284 | − sublen = get_unaligned_le16(dptr); | |
| 1285 | − check = get_unaligned_le16(dptr + sizeof(u16)); | |
| 1286 | − | |
| 1287 | − chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); | |
| 1288 | − seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); | |
| 1289 | − next_len = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; | |
| 1290 | − if ((next_len << 4) > MAX_RX_DATASZ) { | |
| 1291 | − brcmf_dbg(INFO, "nextlen too large (%d) seq %d\n", | |
| 1292 | − next_len, seq); | |
| 1293 | − next_len = 0; | |
| 1294 | − } | |
| 1295 | − bus->cur_read.len = next_len << 4; | |
| 1296 | − doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); | |
| 1297 | − txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); | |
| 1298 | − | |
| 1299 | − errcode = 0; | |
| 1300 | − if ((u16)~(sublen ^ check)) { | |
| 1301 | − brcmf_dbg(ERROR, "(superframe): HW hdr error: len/check 0x%04x/0x%04x\n", | |
| 1302 | − sublen, check); | |
| 1303 | − errcode = -1; | |
| 1304 | − } else if (roundup(sublen, bus->blocksize) != dlen) { | |
| 1305 | − brcmf_dbg(ERROR, "(superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n", | |
| 1306 | − sublen, roundup(sublen, bus->blocksize), | |
| 1307 | − dlen); | |
| 1308 | − errcode = -1; | |
| 1309 | − } else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) != | |
| 1310 | − SDPCM_GLOM_CHANNEL) { | |
| 1311 | − brcmf_dbg(ERROR, "(superframe): bad channel %d\n", | |
| 1312 | − SDPCM_PACKET_CHANNEL( | |
| 1313 | − &dptr[SDPCM_FRAMETAG_LEN])); | |
| 1314 | − errcode = -1; | |
| 1315 | − } else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) { | |
| 1316 | − brcmf_dbg(ERROR, "(superframe): got 2nd descriptor?\n"); | |
| 1317 | − errcode = -1; | |
| 1318 | − } else if ((doff < SDPCM_HDRLEN) || | |
| 1319 | − (doff > (pfirst->len - SDPCM_HDRLEN))) { | |
| 1320 | − brcmf_dbg(ERROR, "(superframe): Bad data offset %d: HW %d pkt %d min %d\n", | |
| 1321 | − doff, sublen, pfirst->len, SDPCM_HDRLEN); | |
| 1322 | − errcode = -1; | |
| 1323 | − } | |
| 1324 | − | |
| 1325 | − /* Check sequence number of superframe SW header */ | |
| 1326 | − if (rxseq != seq) { | |
| 1327 | − brcmf_dbg(INFO, "(superframe) rx_seq %d, expected %d\n", | |
| 1328 | − seq, rxseq); | |
| 1329 | − bus->sdcnt.rx_badseq++; | |
| 1330 | − rxseq = seq; | |
| 1331 | − } | |
| 1332 | − | |
| 1333 | − /* Check window for sanity */ | |
| 1334 | − if ((u8) (txmax - bus->tx_seq) > 0x40) { | |
| 1335 | − brcmf_dbg(ERROR, "unlikely tx max %d with tx_seq %d\n", | |
| 1336 | − txmax, bus->tx_seq); | |
| 1337 | − txmax = bus->tx_seq + 2; | |
| 1338 | − } | |
| 1339 | − bus->tx_max = txmax; | |
| 1319 | + rd_new.seq_num = rxseq; | |
| 1320 | + rd_new.len = dlen; | |
| 1321 | + errcode = -!brcmf_sdio_hdparser(bus, pfirst->data, &rd_new, | |
| 1322 | + BRCMF_SDIO_FT_SUPER); | |
| 1323 | + bus->cur_read.len = rd_new.len_nxtfrm << 4; | |
| 1340 | 1324 | |
| 1341 | 1325 | /* Remove superframe header, remember offset */ |
| 1342 | − skb_pull(pfirst, doff); | |
| 1343 | − sfdoff = doff; | |
| 1326 | + skb_pull(pfirst, rd_new.dat_offset); | |
| 1327 | + sfdoff = rd_new.dat_offset; | |
| 1344 | 1328 | num = 0; |
| 1345 | 1329 | |
| 1346 | 1330 | /* Validate all the subframe headers */ |
| @@ -1349,34 +1333,14 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) · 2 unmodified lines | ||
| 1349 | 1333 | if (errcode) |
| 1350 | 1334 | break; |
| 1351 | 1335 | |
| 1352 | − dptr = (u8 *) (pnext->data); | |
| 1353 | − dlen = (u16) (pnext->len); | |
| 1354 | − sublen = get_unaligned_le16(dptr); | |
| 1355 | − check = get_unaligned_le16(dptr + sizeof(u16)); | |
| 1356 | − chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); | |
| 1357 | − doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); | |
| 1336 | + rd_new.len = pnext->len; | |
| 1337 | + rd_new.seq_num = rxseq++; | |
| 1338 | + errcode = -!brcmf_sdio_hdparser(bus, pnext->data, | |
| 1339 | + &rd_new, | |
| 1340 | + BRCMF_SDIO_FT_SUB); | |
| 1358 | 1341 | brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), |
| 1359 | − dptr, 32, "subframe:\n"); | |
| 1342 | + pnext->data, 32, "subframe:\n"); | |
| 1360 | 1343 | |
| 1361 | − if ((u16)~(sublen ^ check)) { | |
| 1362 | − brcmf_dbg(ERROR, "(subframe %d): HW hdr error: len/check 0x%04x/0x%04x\n", | |
| 1363 | − num, sublen, check); | |
| 1364 | − errcode = -1; | |
| 1365 | − } else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) { | |
| 1366 | − brcmf_dbg(ERROR, "(subframe %d): length mismatch: len 0x%04x, expect 0x%04x\n", | |
| 1367 | − num, sublen, dlen); | |
| 1368 | − errcode = -1; | |
| 1369 | − } else if ((chan != SDPCM_DATA_CHANNEL) && | |
| 1370 | − (chan != SDPCM_EVENT_CHANNEL)) { | |
| 1371 | − brcmf_dbg(ERROR, "(subframe %d): bad channel %d\n", | |
| 1372 | − num, chan); | |
| 1373 | − errcode = -1; | |
| 1374 | − } else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) { | |
| 1375 | − brcmf_dbg(ERROR, "(subframe %d): Bad data offset %d: HW %d min %d\n", | |
| 1376 | − num, doff, sublen, SDPCM_HDRLEN); | |
| 1377 | − errcode = -1; | |
| 1378 | − } | |
| 1379 | − /* increase the subframe count */ | |
| 1380 | 1344 | num++; |
| 1381 | 1345 | } |
| 1382 | 1346 | |
| @@ -1402,27 +1366,11 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) · 19 unmodified lines | ||
| 1402 | 1366 | skb_queue_walk_safe(&bus->glom, pfirst, pnext) { |
| 1403 | 1367 | dptr = (u8 *) (pfirst->data); |
| 1404 | 1368 | sublen = get_unaligned_le16(dptr); |
| 1405 | − chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); | |
| 1406 | − seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); | |
| 1407 | 1369 | doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); |
| 1408 | 1370 | |
| 1409 | − brcmf_dbg(GLOM, "Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n", | |
| 1410 | − num, pfirst, pfirst->data, | |
| 1411 | − pfirst->len, sublen, chan, seq); | |
| 1412 | − | |
| 1413 | − /* precondition: chan == SDPCM_DATA_CHANNEL || | |
| 1414 | − chan == SDPCM_EVENT_CHANNEL */ | |
| 1415 | − | |
| 1416 | − if (rxseq != seq) { | |
| 1417 | − brcmf_dbg(GLOM, "rx_seq %d, expected %d\n", | |
| 1418 | − seq, rxseq); | |
| 1419 | − bus->sdcnt.rx_badseq++; | |
| 1420 | − rxseq = seq; | |
| 1421 | − } | |
| 1422 | − rxseq++; | |
| 1423 | − | |
| 1424 | 1371 | brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(), |
| 1425 | − dptr, dlen, "Rx Subframe Data:\n"); | |
| 1372 | + dptr, pfirst->len, | |
| 1373 | + "Rx Subframe Data:\n"); | |
| 1426 | 1374 | |
| 1427 | 1375 | __skb_trim(pfirst, sublen); |
| 1428 | 1376 | skb_pull(pfirst, doff); |
| @@ -1642,7 +1590,8 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) · 213 unmodified lines | ||
| 1642 | 1590 | bus->rxhdr, SDPCM_HDRLEN, |
| 1643 | 1591 | "RxHdr:\n"); |
| 1644 | 1592 | |
| 1645 | − if (!brcmf_sdio_hdparser(bus, bus->rxhdr, rd)) { | |
| 1593 | + if (!brcmf_sdio_hdparser(bus, bus->rxhdr, rd, | |
| 1594 | + BRCMF_SDIO_FT_NORMAL)) { | |
| 1646 | 1595 | if (!bus->rxpending) |
| 1647 | 1596 | break; |
| 1648 | 1597 | else |
| @@ -1701,7 +1650,8 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) · 52 unmodified lines | ||
| 1701 | 1650 | } else { |
| 1702 | 1651 | memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN); |
| 1703 | 1652 | rd_new.seq_num = rd->seq_num; |
| 1704 | − if (!brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new)) { | |
| 1653 | + if (!brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new, | |
| 1654 | + BRCMF_SDIO_FT_NORMAL)) { | |
| 1705 | 1655 | rd->len = 0; |
| 1706 | 1656 | brcmu_pkt_buf_free_skb(pkt); |
| 1707 | 1657 | } |
| @@ -0,0 +1,336 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2012 Broadcom Corporation | |
| 3 | + * | |
| 4 | + * Permission to use, copy, modify, and/or distribute this software for any | |
| 5 | + * purpose with or without fee is hereby granted, provided that the above | |
| 6 | + * copyright notice and this permission notice appear in all copies. | |
| 7 | + * | |
| 8 | + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
| 9 | + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
| 10 | + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | |
| 11 | + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
| 12 | + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | |
| 13 | + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |
| 14 | + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
| 15 | + */ | |
| 16 | + | |
| 17 | +/* FWIL is the Firmware Interface Layer. In this module the support functions | |
| 18 | + * are located to set and get variables to and from the firmware. | |
| 19 | + */ | |
| 20 | + | |
| 21 | +#include <linux/kernel.h> | |
| 22 | +#include <linux/netdevice.h> | |
| 23 | +#include <defs.h> | |
| 24 | +#include <brcmu_utils.h> | |
| 25 | +#include <brcmu_wifi.h> | |
| 26 | +#include "dhd.h" | |
| 27 | +#include "dhd_bus.h" | |
| 28 | +#include "dhd_dbg.h" | |
| 29 | +#include "fwil.h" | |
| 30 | + | |
| 31 | + | |
| 32 | +static s32 | |
| 33 | +brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) | |
| 34 | +{ | |
| 35 | + struct brcmf_pub *drvr = ifp->drvr; | |
| 36 | + s32 err; | |
| 37 | + | |
| 38 | + if (drvr->bus_if->state == BRCMF_BUS_DOWN) { | |
| 39 | + brcmf_dbg(ERROR, "bus is down. we have nothing to do.\n"); | |
| 40 | + return -EIO; | |
| 41 | + } | |
| 42 | + | |
| 43 | + if (data != NULL) | |
| 44 | + len = min_t(uint, len, BRCMF_DCMD_MAXLEN); | |
| 45 | + if (set) | |
| 46 | + err = brcmf_proto_cdc_set_dcmd(drvr, ifp->idx, cmd, data, len); | |
| 47 | + else | |
| 48 | + err = brcmf_proto_cdc_query_dcmd(drvr, ifp->idx, cmd, data, | |
| 49 | + len); | |
| 50 | + | |
| 51 | + if (err >= 0) | |
| 52 | + err = 0; | |
| 53 | + else | |
| 54 | + brcmf_dbg(ERROR, "Failed err=%d\n", err); | |
| 55 | + | |
| 56 | + return err; | |
| 57 | +} | |
| 58 | + | |
| 59 | +s32 | |
| 60 | +brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len) | |
| 61 | +{ | |
| 62 | + s32 err; | |
| 63 | + | |
| 64 | + mutex_lock(&ifp->drvr->proto_block); | |
| 65 | + | |
| 66 | + brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len); | |
| 67 | + brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data"); | |
| 68 | + | |
| 69 | + err = brcmf_fil_cmd_data(ifp, cmd, data, len, true); | |
| 70 | + mutex_unlock(&ifp->drvr->proto_block); | |
| 71 | + | |
| 72 | + return err; | |
| 73 | +} | |
| 74 | + | |
| 75 | +s32 | |
| 76 | +brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len) | |
| 77 | +{ | |
| 78 | + s32 err; | |
| 79 | + | |
| 80 | + mutex_lock(&ifp->drvr->proto_block); | |
| 81 | + err = brcmf_fil_cmd_data(ifp, cmd, data, len, false); | |
| 82 | + | |
| 83 | + brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len); | |
| 84 | + brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data"); | |
| 85 | + | |
| 86 | + mutex_unlock(&ifp->drvr->proto_block); | |
| 87 | + | |
| 88 | + return err; | |
| 89 | +} | |
| 90 | + | |
| 91 | + | |
| 92 | +s32 | |
| 93 | +brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data) | |
| 94 | +{ | |
| 95 | + s32 err; | |
| 96 | + __le32 data_le = cpu_to_le32(data); | |
| 97 | + | |
| 98 | + mutex_lock(&ifp->drvr->proto_block); | |
| 99 | + err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), true); | |
| 100 | + mutex_unlock(&ifp->drvr->proto_block); | |
| 101 | + | |
| 102 | + return err; | |
| 103 | +} | |
| 104 | + | |
| 105 | +s32 | |
| 106 | +brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data) | |
| 107 | +{ | |
| 108 | + s32 err; | |
| 109 | + __le32 data_le = cpu_to_le32(*data); | |
| 110 | + | |
| 111 | + mutex_lock(&ifp->drvr->proto_block); | |
| 112 | + err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), false); | |
| 113 | + mutex_unlock(&ifp->drvr->proto_block); | |
| 114 | + *data = le32_to_cpu(data_le); | |
| 115 | + | |
| 116 | + return err; | |
| 117 | +} | |
| 118 | + | |
| 119 | +static u32 | |
| 120 | +brcmf_create_iovar(char *name, char *data, u32 datalen, char *buf, u32 buflen) | |
| 121 | +{ | |
| 122 | + u32 len; | |
| 123 | + | |
| 124 | + len = strlen(name) + 1; | |
| 125 | + | |
| 126 | + if ((len + datalen) > buflen) | |
| 127 | + return 0; | |
| 128 | + | |
| 129 | + memcpy(buf, name, len); | |
| 130 | + | |
| 131 | + /* append data onto the end of the name string */ | |
| 132 | + if (data && datalen) | |
| 133 | + memcpy(&buf[len], data, datalen); | |
| 134 | + | |
| 135 | + return len + datalen; | |
| 136 | +} | |
| 137 | + | |
| 138 | + | |
| 139 | +s32 | |
| 140 | +brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data, | |
| 141 | + u32 len) | |
| 142 | +{ | |
| 143 | + struct brcmf_pub *drvr = ifp->drvr; | |
| 144 | + s32 err; | |
| 145 | + u32 buflen; | |
| 146 | + | |
| 147 | + mutex_lock(&drvr->proto_block); | |
| 148 | + | |
| 149 | + brcmf_dbg(FIL, "name=%s, len=%d\n", name, len); | |
| 150 | + brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data"); | |
| 151 | + | |
| 152 | + buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf, | |
| 153 | + sizeof(drvr->proto_buf)); | |
| 154 | + if (buflen) { | |
| 155 | + err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf, | |
| 156 | + buflen, true); | |
| 157 | + } else { | |
| 158 | + err = -EPERM; | |
| 159 | + brcmf_dbg(ERROR, "Creating iovar failed\n"); | |
| 160 | + } | |
| 161 | + | |
| 162 | + mutex_unlock(&drvr->proto_block); | |
| 163 | + return err; | |
| 164 | +} | |
| 165 | + | |
| 166 | +s32 | |
| 167 | +brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data, | |
| 168 | + u32 len) | |
| 169 | +{ | |
| 170 | + struct brcmf_pub *drvr = ifp->drvr; | |
| 171 | + s32 err; | |
| 172 | + u32 buflen; | |
| 173 | + | |
| 174 | + mutex_lock(&drvr->proto_block); | |
| 175 | + | |
| 176 | + buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf, | |
| 177 | + sizeof(drvr->proto_buf)); | |
| 178 | + if (buflen) { | |
| 179 | + err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf, | |
| 180 | + buflen, false); | |
| 181 | + if (err == 0) | |
| 182 | + memcpy(data, drvr->proto_buf, len); | |
| 183 | + } else { | |
| 184 | + err = -EPERM; | |
| 185 | + brcmf_dbg(ERROR, "Creating iovar failed\n"); | |
| 186 | + } | |
| 187 | + | |
| 188 | + brcmf_dbg(FIL, "name=%s, len=%d\n", name, len); | |
| 189 | + brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data"); | |
| 190 | + | |
| 191 | + mutex_unlock(&drvr->proto_block); | |
| 192 | + return err; | |
| 193 | +} | |
| 194 | + | |
| 195 | +s32 | |
| 196 | +brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data) | |
| 197 | +{ | |
| 198 | + __le32 data_le = cpu_to_le32(data); | |
| 199 | + | |
| 200 | + return brcmf_fil_iovar_data_set(ifp, name, &data_le, sizeof(data_le)); | |
| 201 | +} | |
| 202 | + | |
| 203 | +s32 | |
| 204 | +brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data) | |
| 205 | +{ | |
| 206 | + __le32 data_le = cpu_to_le32(*data); | |
| 207 | + s32 err; | |
| 208 | + | |
| 209 | + err = brcmf_fil_iovar_data_get(ifp, name, &data_le, sizeof(data_le)); | |
| 210 | + if (err == 0) | |
| 211 | + *data = le32_to_cpu(data_le); | |
| 212 | + return err; | |
| 213 | +} | |
| 214 | + | |
| 215 | +static u32 | |
| 216 | +brcmf_create_bsscfg(s32 bssidx, char *name, char *data, u32 datalen, char *buf, | |
| 217 | + u32 buflen) | |
| 218 | +{ | |
| 219 | + const s8 *prefix = "bsscfg:"; | |
| 220 | + s8 *p; | |
| 221 | + u32 prefixlen; | |
| 222 | + u32 namelen; | |
| 223 | + u32 iolen; | |
| 224 | + __le32 bssidx_le; | |
| 225 | + | |
| 226 | + if (bssidx == 0) | |
| 227 | + return brcmf_create_iovar(name, data, datalen, buf, buflen); | |
| 228 | + | |
| 229 | + prefixlen = strlen(prefix); | |
| 230 | + namelen = strlen(name) + 1; /* lengh of iovar name + null */ | |
| 231 | + iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen; | |
| 232 | + | |
| 233 | + if (buflen < iolen) { | |
| 234 | + brcmf_dbg(ERROR, "buffer is too short\n"); | |
| 235 | + return 0; | |
| 236 | + } | |
| 237 | + | |
| 238 | + p = buf; | |
| 239 | + | |
| 240 | + /* copy prefix, no null */ | |
| 241 | + memcpy(p, prefix, prefixlen); | |
| 242 | + p += prefixlen; | |
| 243 | + | |
| 244 | + /* copy iovar name including null */ | |
| 245 | + memcpy(p, name, namelen); | |
| 246 | + p += namelen; | |
| 247 | + | |
| 248 | + /* bss config index as first data */ | |
| 249 | + bssidx_le = cpu_to_le32(bssidx); | |
| 250 | + memcpy(p, &bssidx_le, sizeof(bssidx_le)); | |
| 251 | + p += sizeof(bssidx_le); | |
| 252 | + | |
| 253 | + /* parameter buffer follows */ | |
| 254 | + if (datalen) | |
| 255 | + memcpy(p, data, datalen); | |
| 256 | + | |
| 257 | + return iolen; | |
| 258 | +} | |
| 259 | + | |
| 260 | +s32 | |
| 261 | +brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name, | |
| 262 | + void *data, u32 len) | |
| 263 | +{ | |
| 264 | + struct brcmf_pub *drvr = ifp->drvr; | |
| 265 | + s32 err; | |
| 266 | + u32 buflen; | |
| 267 | + | |
| 268 | + mutex_lock(&drvr->proto_block); | |
| 269 | + | |
| 270 | + brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len); | |
| 271 | + brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data"); | |
| 272 | + | |
| 273 | + buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len, | |
| 274 | + drvr->proto_buf, sizeof(drvr->proto_buf)); | |
| 275 | + if (buflen) { | |
| 276 | + err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf, | |
| 277 | + buflen, true); | |
| 278 | + } else { | |
| 279 | + err = -EPERM; | |
| 280 | + brcmf_dbg(ERROR, "Creating bsscfg failed\n"); | |
| 281 | + } | |
| 282 | + | |
| 283 | + mutex_unlock(&drvr->proto_block); | |
| 284 | + return err; | |
| 285 | +} | |
| 286 | + | |
| 287 | +s32 | |
| 288 | +brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, | |
| 289 | + void *data, u32 len) | |
| 290 | +{ | |
| 291 | + struct brcmf_pub *drvr = ifp->drvr; | |
| 292 | + s32 err; | |
| 293 | + u32 buflen; | |
| 294 | + | |
| 295 | + mutex_lock(&drvr->proto_block); | |
| 296 | + | |
| 297 | + buflen = brcmf_create_bsscfg(ifp->bssidx, name, NULL, len, | |
| 298 | + drvr->proto_buf, sizeof(drvr->proto_buf)); | |
| 299 | + if (buflen) { | |
| 300 | + err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf, | |
| 301 | + buflen, false); | |
| 302 | + if (err == 0) | |
| 303 | + memcpy(data, drvr->proto_buf, len); | |
| 304 | + } else { | |
| 305 | + err = -EPERM; | |
| 306 | + brcmf_dbg(ERROR, "Creating bsscfg failed\n"); | |
| 307 | + } | |
| 308 | + brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len); | |
| 309 | + brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data"); | |
| 310 | + | |
| 311 | + mutex_unlock(&drvr->proto_block); | |
| 312 | + return err; | |
| 313 | + | |
| 314 | +} | |
| 315 | + | |
| 316 | +s32 | |
| 317 | +brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data) | |
| 318 | +{ | |
| 319 | + __le32 data_le = cpu_to_le32(data); | |
| 320 | + | |
| 321 | + return brcmf_fil_bsscfg_data_set(ifp, name, &data_le, | |
| 322 | + sizeof(data_le)); | |
| 323 | +} | |
| 324 | + | |
| 325 | +s32 | |
| 326 | +brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data) | |
| 327 | +{ | |
| 328 | + __le32 data_le = cpu_to_le32(*data); | |
| 329 | + s32 err; | |
| 330 | + | |
| 331 | + err = brcmf_fil_bsscfg_data_get(ifp, name, &data_le, | |
| 332 | + sizeof(data_le)); | |
| 333 | + if (err == 0) | |
| 334 | + *data = le32_to_cpu(data_le); | |
| 335 | + return err; | |
| 336 | +} | |
| @@ -0,0 +1,39 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2012 Broadcom Corporation | |
| 3 | + * | |
| 4 | + * Permission to use, copy, modify, and/or distribute this software for any | |
| 5 | + * purpose with or without fee is hereby granted, provided that the above | |
| 6 | + * copyright notice and this permission notice appear in all copies. | |
| 7 | + * | |
| 8 | + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | |
| 9 | + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
| 10 | + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | |
| 11 | + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
| 12 | + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | |
| 13 | + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |
| 14 | + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
| 15 | + */ | |
| 16 | + | |
| 17 | +#ifndef _fwil_h_ | |
| 18 | +#define _fwil_h_ | |
| 19 | + | |
| 20 | +s32 brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len); | |
| 21 | +s32 brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len); | |
| 22 | +s32 brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data); | |
| 23 | +s32 brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data); | |
| 24 | + | |
| 25 | +s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data, | |
| 26 | + u32 len); | |
| 27 | +s32 brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data, | |
| 28 | + u32 len); | |
| 29 | +s32 brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data); | |
| 30 | +s32 brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data); | |
| 31 | + | |
| 32 | +s32 brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name, void *data, | |
| 33 | + u32 len); | |
| 34 | +s32 brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, void *data, | |
| 35 | + u32 len); | |
| 36 | +s32 brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data); | |
| 37 | +s32 brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data); | |
| 38 | + | |
| 39 | +#endif /* _fwil_h_ */ | |
| @@ -42,7 +42,6 @@ · 41 unmodified lines | ||
| 42 | 42 | |
| 43 | 43 | #define IOCTL_RESP_TIMEOUT 2000 |
| 44 | 44 | |
| 45 | −#define BRCMF_USB_SYNC_TIMEOUT 300 /* ms */ | |
| 46 | 45 | #define BRCMF_USB_DLIMAGE_SPINWAIT 100 /* in unit of ms */ |
| 47 | 46 | #define BRCMF_USB_DLIMAGE_LIMIT 500 /* spinwait limit (ms) */ |
| 48 | 47 | |
| @@ -116,10 +115,6 @@ struct brcmf_usbdev_info { · 67 unmodified lines | ||
| 116 | 115 | u8 *image; /* buffer for combine fw and nvram */ |
| 117 | 116 | int image_len; |
| 118 | 117 | |
| 119 | − wait_queue_head_t wait; | |
| 120 | − bool waitdone; | |
| 121 | − int sync_urb_status; | |
| 122 | − | |
| 123 | 118 | struct usb_device *usbdev; |
| 124 | 119 | struct device *dev; |
| 125 | 120 | |
| @@ -131,7 +126,6 @@ struct brcmf_usbdev_info { · 5 unmodified lines | ||
| 131 | 126 | int ctl_urb_status; |
| 132 | 127 | int ctl_completed; |
| 133 | 128 | wait_queue_head_t ioctl_resp_wait; |
| 134 | − wait_queue_head_t ctrl_wait; | |
| 135 | 129 | ulong ctl_op; |
| 136 | 130 | |
| 137 | 131 | struct urb *bulk_urb; /* used for FW download */ |
| @@ -754,34 +748,14 @@ static void brcmf_usb_down(struct device *dev) · 616 unmodified lines | ||
| 754 | 748 | brcmf_usb_free_q(&devinfo->rx_postq, true); |
| 755 | 749 | } |
| 756 | 750 | |
| 757 | −static int | |
| 758 | −brcmf_usb_sync_wait(struct brcmf_usbdev_info *devinfo, u16 time) | |
| 759 | −{ | |
| 760 | − int ret; | |
| 761 | − int err = 0; | |
| 762 | − int ms = time; | |
| 763 | − | |
| 764 | − ret = wait_event_interruptible_timeout(devinfo->wait, | |
| 765 | − devinfo->waitdone == true, (ms * HZ / 1000)); | |
| 766 | − | |
| 767 | − if ((devinfo->waitdone == false) || (devinfo->sync_urb_status)) { | |
| 768 | − brcmf_dbg(ERROR, "timeout(%d) or urb err=%d\n", | |
| 769 | − ret, devinfo->sync_urb_status); | |
| 770 | − err = -EINVAL; | |
| 771 | − } | |
| 772 | − devinfo->waitdone = false; | |
| 773 | − return err; | |
| 774 | −} | |
| 775 | − | |
| 776 | 751 | static void |
| 777 | 752 | brcmf_usb_sync_complete(struct urb *urb) |
| 778 | 753 | { |
| 779 | 754 | struct brcmf_usbdev_info *devinfo = |
| 780 | 755 | (struct brcmf_usbdev_info *)urb->context; |
| 781 | 756 | |
| 782 | − devinfo->waitdone = true; | |
| 783 | − wake_up_interruptible(&devinfo->wait); | |
| 784 | − devinfo->sync_urb_status = urb->status; | |
| 757 | + devinfo->ctl_completed = true; | |
| 758 | + brcmf_usb_ioctl_resp_wake(devinfo); | |
| 785 | 759 | } |
| 786 | 760 | |
| 787 | 761 | 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, · 25 unmodified lines | ||
| 813 | 787 | (void *) tmpbuf, size, |
| 814 | 788 | (usb_complete_t)brcmf_usb_sync_complete, devinfo); |
| 815 | 789 | |
| 790 | + devinfo->ctl_completed = false; | |
| 816 | 791 | ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC); |
| 817 | 792 | if (ret < 0) { |
| 818 | 793 | 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, · 1 unmodified line | ||
| 820 | 795 | return false; |
| 821 | 796 | } |
| 822 | 797 | |
| 823 | − ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT); | |
| 798 | + ret = brcmf_usb_ioctl_resp_wait(devinfo); | |
| 824 | 799 | memcpy(buffer, tmpbuf, buflen); |
| 825 | 800 | kfree(tmpbuf); |
| 826 | 801 | |
| 827 | − return (ret == 0); | |
| 802 | + return ret; | |
| 828 | 803 | } |
| 829 | 804 | |
| 830 | 805 | static bool |
| @@ -918,13 +893,14 @@ brcmf_usb_dl_send_bulk(struct brcmf_usbdev_info *devinfo, void *buffer, int len) · 87 unmodified lines | ||
| 918 | 893 | |
| 919 | 894 | devinfo->bulk_urb->transfer_flags |= URB_ZERO_PACKET; |
| 920 | 895 | |
| 896 | + devinfo->ctl_completed = false; | |
| 921 | 897 | ret = usb_submit_urb(devinfo->bulk_urb, GFP_ATOMIC); |
| 922 | 898 | if (ret) { |
| 923 | 899 | brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret); |
| 924 | 900 | return ret; |
| 925 | 901 | } |
| 926 | − ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT); | |
| 927 | − return ret; | |
| 902 | + ret = brcmf_usb_ioctl_resp_wait(devinfo); | |
| 903 | + return (ret == 0); | |
| 928 | 904 | } |
| 929 | 905 | |
| 930 | 906 | static int |
| @@ -1284,7 +1260,6 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo, · 353 unmodified lines | ||
| 1284 | 1260 | goto error; |
| 1285 | 1261 | } |
| 1286 | 1262 | |
| 1287 | − init_waitqueue_head(&devinfo->wait); | |
| 1288 | 1263 | if (!brcmf_usb_dlneeded(devinfo)) |
| 1289 | 1264 | return &devinfo->bus_pub; |
| 1290 | 1265 | |
| @@ -35,6 +35,7 @@ · 34 unmodified lines | ||
| 35 | 35 | #include <brcmu_wifi.h> |
| 36 | 36 | #include "dhd.h" |
| 37 | 37 | #include "wl_cfg80211.h" |
| 38 | +#include "fwil.h" | |
| 38 | 39 | |
| 39 | 40 | #define BRCMF_SCAN_IE_LEN_MAX 2048 |
| 40 | 41 | #define BRCMF_PNO_VERSION 2 |
| @@ -48,6 +49,8 @@ · 7 unmodified lines | ||
| 48 | 49 | #define BRCMF_PNO_SCAN_COMPLETE 1 |
| 49 | 50 | #define BRCMF_PNO_SCAN_INCOMPLETE 0 |
| 50 | 51 | |
| 52 | +#define BRCMF_IFACE_MAX_CNT 2 | |
| 53 | + | |
| 51 | 54 | #define TLV_LEN_OFF 1 /* length offset */ |
| 52 | 55 | #define TLV_HDR_LEN 2 /* header length */ |
| 53 | 56 | #define TLV_BODY_OFF 2 /* body offset */ |
| @@ -91,16 +94,13 @@ · 37 unmodified lines | ||
| 91 | 94 | #define BRCMF_ASSOC_PARAMS_FIXED_SIZE \ |
| 92 | 95 | (sizeof(struct brcmf_assoc_params_le) - sizeof(u16)) |
| 93 | 96 | |
| 94 | −static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255}; | |
| 95 | − | |
| 96 | 97 | static u32 brcmf_dbg_level = WL_DBG_ERR; |
| 97 | 98 | |
| 98 | −static bool check_sys_up(struct wiphy *wiphy) | |
| 99 | +static bool check_vif_up(struct brcmf_cfg80211_vif *vif) | |
| 99 | 100 | { |
| 100 | − struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | |
| 101 | − if (!test_bit(WL_STATUS_READY, &cfg->status)) { | |
| 102 | − WL_INFO("device is not ready : status (%d)\n", | |
| 103 | − (int)cfg->status); | |
| 101 | + if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state)) { | |
| 102 | + WL_INFO("device is not ready : status (%lu)\n", | |
| 103 | + vif->sme_state); | |
| 104 | 104 | return false; |
| 105 | 105 | } |
| 106 | 106 | return true; |
| @@ -391,55 +391,29 @@ static u8 brcmf_mw_to_qdbm(u16 mw) · 284 unmodified lines | ||
| 391 | 391 | return qdbm; |
| 392 | 392 | } |
| 393 | 393 | |
| 394 | −/* function for reading/writing a single u32 from/to the dongle */ | |
| 395 | −static int | |
| 396 | −brcmf_exec_dcmd_u32(struct net_device *ndev, u32 cmd, u32 *par) | |
| 394 | +static u16 channel_to_chanspec(struct ieee80211_channel *ch) | |
| 397 | 395 | { |
| 398 | − int err; | |
| 399 | − __le32 par_le = cpu_to_le32(*par); | |
| 400 | − | |
| 401 | − err = brcmf_exec_dcmd(ndev, cmd, &par_le, sizeof(__le32)); | |
| 402 | − *par = le32_to_cpu(par_le); | |
| 403 | − | |
| 404 | − return err; | |
| 405 | −} | |
| 406 | − | |
| 407 | −static s32 | |
| 408 | −brcmf_dev_iovar_setbuf_bsscfg(struct net_device *ndev, s8 *name, | |
| 409 | − void *param, s32 paramlen, | |
| 410 | − void *buf, s32 buflen, s32 bssidx) | |
| 411 | −{ | |
| 412 | − s32 err = -ENOMEM; | |
| 413 | − u32 len; | |
| 414 | − | |
| 415 | − len = brcmf_c_mkiovar_bsscfg(name, param, paramlen, | |
| 416 | − buf, buflen, bssidx); | |
| 417 | − BUG_ON(!len); | |
| 418 | − if (len > 0) | |
| 419 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len); | |
| 420 | − if (err) | |
| 421 | − WL_ERR("error (%d)\n", err); | |
| 396 | + u16 chanspec; | |
| 422 | 397 | |
| 423 | − return err; | |
| 424 | −} | |
| 398 | + chanspec = ieee80211_frequency_to_channel(ch->center_freq); | |
| 399 | + chanspec &= WL_CHANSPEC_CHAN_MASK; | |
| 425 | 400 | |
| 426 | −static s32 | |
| 427 | −brcmf_dev_iovar_getbuf_bsscfg(struct net_device *ndev, s8 *name, | |
| 428 | − void *param, s32 paramlen, | |
| 429 | − void *buf, s32 buflen, s32 bssidx) | |
| 430 | −{ | |
| 431 | − s32 err = -ENOMEM; | |
| 432 | − u32 len; | |
| 433 | − | |
| 434 | − len = brcmf_c_mkiovar_bsscfg(name, param, paramlen, | |
| 435 | − buf, buflen, bssidx); | |
| 436 | − BUG_ON(!len); | |
| 437 | − if (len > 0) | |
| 438 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, buf, len); | |
| 439 | − if (err) | |
| 440 | − WL_ERR("error (%d)\n", err); | |
| 401 | + if (ch->band == IEEE80211_BAND_2GHZ) | |
| 402 | + chanspec |= WL_CHANSPEC_BAND_2G; | |
| 403 | + else | |
| 404 | + chanspec |= WL_CHANSPEC_BAND_5G; | |
| 441 | 405 | |
| 442 | − return err; | |
| 406 | + if (ch->flags & IEEE80211_CHAN_NO_HT40) { | |
| 407 | + chanspec |= WL_CHANSPEC_BW_20; | |
| 408 | + chanspec |= WL_CHANSPEC_CTL_SB_NONE; | |
| 409 | + } else { | |
| 410 | + chanspec |= WL_CHANSPEC_BW_40; | |
| 411 | + if (ch->flags & IEEE80211_CHAN_NO_HT40PLUS) | |
| 412 | + chanspec |= WL_CHANSPEC_CTL_SB_LOWER; | |
| 413 | + else | |
| 414 | + chanspec |= WL_CHANSPEC_CTL_SB_UPPER; | |
| 415 | + } | |
| 416 | + return chanspec; | |
| 443 | 417 | } |
| 444 | 418 | |
| 445 | 419 | static void convert_key_from_CPU(struct brcmf_wsec_key *key, |
| @@ -457,18 +431,17 @@ static void convert_key_from_CPU(struct brcmf_wsec_key *key, · 11 unmodified lines | ||
| 457 | 431 | } |
| 458 | 432 | |
| 459 | 433 | static int |
| 460 | −send_key_to_dongle(struct brcmf_cfg80211_info *cfg, s32 bssidx, | |
| 461 | − struct net_device *ndev, struct brcmf_wsec_key *key) | |
| 434 | +send_key_to_dongle(struct net_device *ndev, struct brcmf_wsec_key *key) | |
| 462 | 435 | { |
| 463 | 436 | int err; |
| 464 | 437 | struct brcmf_wsec_key_le key_le; |
| 465 | 438 | |
| 466 | 439 | convert_key_from_CPU(key, &key_le); |
| 467 | 440 | |
| 468 | − err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le, | |
| 469 | − sizeof(key_le), | |
| 470 | − cfg->extra_buf, | |
| 471 | − WL_EXTRA_BUF_MAX, bssidx); | |
| 441 | + brcmf_netdev_wait_pend8021x(ndev); | |
| 442 | + | |
| 443 | + err = brcmf_fil_bsscfg_data_set(netdev_priv(ndev), "wsec_key", &key_le, | |
| 444 | + sizeof(key_le)); | |
| 472 | 445 | |
| 473 | 446 | if (err) |
| 474 | 447 | WL_ERR("wsec_key error (%d)\n", err); |
| @@ -480,6 +453,7 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, · 5 unmodified lines | ||
| 480 | 453 | enum nl80211_iftype type, u32 *flags, |
| 481 | 454 | struct vif_params *params) |
| 482 | 455 | { |
| 456 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 483 | 457 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 484 | 458 | s32 infra = 0; |
| 485 | 459 | s32 ap = 0; |
| @@ -511,7 +485,7 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, · 25 unmodified lines | ||
| 511 | 485 | } |
| 512 | 486 | |
| 513 | 487 | if (ap) { |
| 514 | − set_bit(WL_STATUS_AP_CREATING, &cfg->status); | |
| 488 | + set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); | |
| 515 | 489 | if (!cfg->ap_info) |
| 516 | 490 | cfg->ap_info = kzalloc(sizeof(*cfg->ap_info), |
| 517 | 491 | GFP_KERNEL); |
| @@ -521,7 +495,8 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, · 3 unmodified lines | ||
| 521 | 495 | } |
| 522 | 496 | WL_INFO("IF Type = AP\n"); |
| 523 | 497 | } else { |
| 524 | − err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra); | |
| 498 | + err = brcmf_fil_cmd_int_set(netdev_priv(ndev), | |
| 499 | + BRCMF_C_SET_INFRA, infra); | |
| 525 | 500 | if (err) { |
| 526 | 501 | WL_ERR("WLC_SET_INFRA error (%d)\n", err); |
| 527 | 502 | err = -EAGAIN; |
| @@ -539,99 +514,13 @@ done: · 11 unmodified lines | ||
| 539 | 514 | return err; |
| 540 | 515 | } |
| 541 | 516 | |
| 542 | −static s32 brcmf_dev_intvar_set(struct net_device *ndev, s8 *name, s32 val) | |
| 543 | −{ | |
| 544 | − s8 buf[BRCMF_DCMD_SMLEN]; | |
| 545 | − u32 len; | |
| 546 | − s32 err = 0; | |
| 547 | − __le32 val_le; | |
| 548 | − | |
| 549 | − val_le = cpu_to_le32(val); | |
| 550 | − len = brcmf_c_mkiovar(name, (char *)(&val_le), sizeof(val_le), buf, | |
| 551 | − sizeof(buf)); | |
| 552 | − BUG_ON(!len); | |
| 553 | − | |
| 554 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len); | |
| 555 | − if (err) | |
| 556 | − WL_ERR("error (%d)\n", err); | |
| 557 | − | |
| 558 | − return err; | |
| 559 | −} | |
| 560 | − | |
| 561 | −static s32 | |
| 562 | −brcmf_dev_intvar_get(struct net_device *ndev, s8 *name, s32 *retval) | |
| 563 | −{ | |
| 564 | − union { | |
| 565 | − s8 buf[BRCMF_DCMD_SMLEN]; | |
| 566 | − __le32 val; | |
| 567 | − } var; | |
| 568 | − u32 len; | |
| 569 | − u32 data_null; | |
| 570 | − s32 err = 0; | |
| 571 | − | |
| 572 | − len = | |
| 573 | − brcmf_c_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), | |
| 574 | − sizeof(var.buf)); | |
| 575 | − BUG_ON(!len); | |
| 576 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, &var, len); | |
| 577 | − if (err) | |
| 578 | − WL_ERR("error (%d)\n", err); | |
| 579 | − | |
| 580 | − *retval = le32_to_cpu(var.val); | |
| 581 | − | |
| 582 | − return err; | |
| 583 | −} | |
| 584 | − | |
| 585 | −static s32 | |
| 586 | −brcmf_dev_intvar_set_bsscfg(struct net_device *ndev, s8 *name, u32 val, | |
| 587 | − s32 bssidx) | |
| 588 | −{ | |
| 589 | − s8 buf[BRCMF_DCMD_SMLEN]; | |
| 590 | − __le32 val_le; | |
| 591 | − | |
| 592 | − val_le = cpu_to_le32(val); | |
| 593 | − | |
| 594 | − return brcmf_dev_iovar_setbuf_bsscfg(ndev, name, &val_le, | |
| 595 | − sizeof(val_le), buf, sizeof(buf), | |
| 596 | − bssidx); | |
| 597 | −} | |
| 598 | − | |
| 599 | −static s32 | |
| 600 | −brcmf_dev_intvar_get_bsscfg(struct net_device *ndev, s8 *name, s32 *val, | |
| 601 | − s32 bssidx) | |
| 602 | −{ | |
| 603 | − s8 buf[BRCMF_DCMD_SMLEN]; | |
| 604 | − s32 err; | |
| 605 | − __le32 val_le; | |
| 606 | − | |
| 607 | − memset(buf, 0, sizeof(buf)); | |
| 608 | − err = brcmf_dev_iovar_getbuf_bsscfg(ndev, name, val, sizeof(*val), buf, | |
| 609 | − sizeof(buf), bssidx); | |
| 610 | − if (err == 0) { | |
| 611 | − memcpy(&val_le, buf, sizeof(val_le)); | |
| 612 | − *val = le32_to_cpu(val_le); | |
| 613 | − } | |
| 614 | − return err; | |
| 615 | −} | |
| 616 | − | |
| 617 | − | |
| 618 | −/* | |
| 619 | − * For now brcmf_find_bssidx will return 0. Once p2p gets implemented this | |
| 620 | − * should return the ndev matching bssidx. | |
| 621 | − */ | |
| 622 | −static s32 | |
| 623 | −brcmf_find_bssidx(struct brcmf_cfg80211_info *cfg, struct net_device *ndev) | |
| 624 | −{ | |
| 625 | − return 0; | |
| 626 | −} | |
| 627 | − | |
| 628 | 517 | static void brcmf_set_mpc(struct net_device *ndev, int mpc) |
| 629 | 518 | { |
| 519 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 630 | 520 | s32 err = 0; |
| 631 | − struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | |
| 632 | 521 | |
| 633 | − if (test_bit(WL_STATUS_READY, &cfg->status)) { | |
| 634 | − err = brcmf_dev_intvar_set(ndev, "mpc", mpc); | |
| 522 | + if (check_vif_up(ifp->vif)) { | |
| 523 | + err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc); | |
| 635 | 524 | if (err) { |
| 636 | 525 | WL_ERR("fail to set mpc\n"); |
| 637 | 526 | return; |
| @@ -643,7 +532,7 @@ static void brcmf_set_mpc(struct net_device *ndev, int mpc) · 5 unmodified lines | ||
| 643 | 532 | static void brcmf_iscan_prep(struct brcmf_scan_params_le *params_le, |
| 644 | 533 | struct brcmf_ssid *ssid) |
| 645 | 534 | { |
| 646 | − memcpy(params_le->bssid, ether_bcast, ETH_ALEN); | |
| 535 | + memset(params_le->bssid, 0xFF, ETH_ALEN); | |
| 647 | 536 | params_le->bss_type = DOT11_BSSTYPE_ANY; |
| 648 | 537 | params_le->scan_type = 0; |
| 649 | 538 | params_le->channel_num = 0; |
| @@ -657,30 +546,6 @@ static void brcmf_iscan_prep(struct brcmf_scan_params_le *params_le, · 7 unmodified lines | ||
| 657 | 546 | } |
| 658 | 547 | } |
| 659 | 548 | |
| 660 | −static s32 | |
| 661 | −brcmf_dev_iovar_setbuf(struct net_device *ndev, s8 * iovar, void *param, | |
| 662 | − s32 paramlen, void *bufptr, s32 buflen) | |
| 663 | −{ | |
| 664 | − s32 iolen; | |
| 665 | − | |
| 666 | − iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen); | |
| 667 | − BUG_ON(!iolen); | |
| 668 | − | |
| 669 | − return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, bufptr, iolen); | |
| 670 | −} | |
| 671 | − | |
| 672 | −static s32 | |
| 673 | −brcmf_dev_iovar_getbuf(struct net_device *ndev, s8 * iovar, void *param, | |
| 674 | − s32 paramlen, void *bufptr, s32 buflen) | |
| 675 | −{ | |
| 676 | − s32 iolen; | |
| 677 | − | |
| 678 | − iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen); | |
| 679 | − BUG_ON(!iolen); | |
| 680 | − | |
| 681 | − return brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, bufptr, buflen); | |
| 682 | −} | |
| 683 | − | |
| 684 | 549 | static s32 |
| 685 | 550 | brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan, |
| 686 | 551 | struct brcmf_ssid *ssid, u16 action) |
| @@ -703,8 +568,8 @@ brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan, · 16 unmodified lines | ||
| 703 | 568 | params->action = cpu_to_le16(action); |
| 704 | 569 | params->scan_duration = cpu_to_le16(0); |
| 705 | 570 | |
| 706 | − err = brcmf_dev_iovar_setbuf(iscan->ndev, "iscan", params, params_size, | |
| 707 | − iscan->dcmd_buf, BRCMF_DCMD_SMLEN); | |
| 571 | + err = brcmf_fil_iovar_data_set(netdev_priv(iscan->ndev), "iscan", | |
| 572 | + params, params_size); | |
| 708 | 573 | if (err) { |
| 709 | 574 | if (err == -EBUSY) |
| 710 | 575 | WL_INFO("system busy : iscan canceled\n"); |
| @@ -721,7 +586,7 @@ static s32 brcmf_do_iscan(struct brcmf_cfg80211_info *cfg) · 10 unmodified lines | ||
| 721 | 586 | struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg); |
| 722 | 587 | struct net_device *ndev = cfg_to_ndev(cfg); |
| 723 | 588 | struct brcmf_ssid ssid; |
| 724 | − __le32 passive_scan; | |
| 589 | + u32 passive_scan; | |
| 725 | 590 | s32 err = 0; |
| 726 | 591 | |
| 727 | 592 | /* Broadcast scan by default */ |
| @@ -729,9 +594,9 @@ static s32 brcmf_do_iscan(struct brcmf_cfg80211_info *cfg) · 1 unmodified line | ||
| 729 | 594 | |
| 730 | 595 | iscan->state = WL_ISCAN_STATE_SCANING; |
| 731 | 596 | |
| 732 | − passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1); | |
| 733 | − err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCMF_C_SET_PASSIVE_SCAN, | |
| 734 | − &passive_scan, sizeof(passive_scan)); | |
| 597 | + passive_scan = cfg->active_scan ? 0 : 1; | |
| 598 | + err = brcmf_fil_cmd_int_set(netdev_priv(ndev), | |
| 599 | + BRCMF_C_SET_PASSIVE_SCAN, passive_scan); | |
| 735 | 600 | if (err) { |
| 736 | 601 | WL_ERR("error (%d)\n", err); |
| 737 | 602 | return err; |
| @@ -754,27 +619,27 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, · 16 unmodified lines | ||
| 754 | 619 | struct cfg80211_scan_request *request, |
| 755 | 620 | struct cfg80211_ssid *this_ssid) |
| 756 | 621 | { |
| 622 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 757 | 623 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); |
| 758 | 624 | struct cfg80211_ssid *ssids; |
| 759 | 625 | struct brcmf_cfg80211_scan_req *sr = cfg->scan_req_int; |
| 760 | − __le32 passive_scan; | |
| 626 | + u32 passive_scan; | |
| 761 | 627 | bool iscan_req; |
| 762 | 628 | bool spec_scan; |
| 763 | 629 | s32 err = 0; |
| 764 | 630 | u32 SSID_len; |
| 765 | 631 | |
| 766 | − if (test_bit(WL_STATUS_SCANNING, &cfg->status)) { | |
| 767 | − WL_ERR("Scanning already : status (%lu)\n", cfg->status); | |
| 632 | + if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { | |
| 633 | + WL_ERR("Scanning already: status (%lu)\n", cfg->scan_status); | |
| 768 | 634 | return -EAGAIN; |
| 769 | 635 | } |
| 770 | − if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg->status)) { | |
| 771 | − WL_ERR("Scanning being aborted : status (%lu)\n", | |
| 772 | − cfg->status); | |
| 636 | + if (test_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status)) { | |
| 637 | + WL_ERR("Scanning being aborted: status (%lu)\n", | |
| 638 | + cfg->scan_status); | |
| 773 | 639 | return -EAGAIN; |
| 774 | 640 | } |
| 775 | − if (test_bit(WL_STATUS_CONNECTING, &cfg->status)) { | |
| 776 | − WL_ERR("Connecting : status (%lu)\n", | |
| 777 | − cfg->status); | |
| 641 | + if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) { | |
| 642 | + WL_ERR("Connecting: status (%lu)\n", ifp->vif->sme_state); | |
| 778 | 643 | return -EAGAIN; |
| 779 | 644 | } |
| 780 | 645 | |
| @@ -792,7 +657,7 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, · 11 unmodified lines | ||
| 792 | 657 | } |
| 793 | 658 | |
| 794 | 659 | cfg->scan_request = request; |
| 795 | − set_bit(WL_STATUS_SCANNING, &cfg->status); | |
| 660 | + set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | |
| 796 | 661 | if (iscan_req) { |
| 797 | 662 | err = brcmf_do_iscan(cfg); |
| 798 | 663 | if (!err) |
| @@ -813,16 +678,16 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, · 14 unmodified lines | ||
| 813 | 678 | WL_SCAN("Broadcast scan\n"); |
| 814 | 679 | } |
| 815 | 680 | |
| 816 | − passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1); | |
| 817 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN, | |
| 818 | − &passive_scan, sizeof(passive_scan)); | |
| 681 | + passive_scan = cfg->active_scan ? 0 : 1; | |
| 682 | + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN, | |
| 683 | + passive_scan); | |
| 819 | 684 | if (err) { |
| 820 | 685 | WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err); |
| 821 | 686 | goto scan_out; |
| 822 | 687 | } |
| 823 | 688 | brcmf_set_mpc(ndev, 0); |
| 824 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le, | |
| 825 | − sizeof(sr->ssid_le)); | |
| 689 | + err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, | |
| 690 | + &sr->ssid_le, sizeof(sr->ssid_le)); | |
| 826 | 691 | if (err) { |
| 827 | 692 | if (err == -EBUSY) |
| 828 | 693 | WL_INFO("system busy : scan for \"%s\" " |
| @@ -838,7 +703,7 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, · 9 unmodified lines | ||
| 838 | 703 | return 0; |
| 839 | 704 | |
| 840 | 705 | scan_out: |
| 841 | − clear_bit(WL_STATUS_SCANNING, &cfg->status); | |
| 706 | + clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | |
| 842 | 707 | cfg->scan_request = NULL; |
| 843 | 708 | return err; |
| 844 | 709 | } |
| @@ -851,12 +716,10 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, · 6 unmodified lines | ||
| 851 | 716 | s32 i; |
| 852 | 717 | s32 offset; |
| 853 | 718 | u16 chanspec; |
| 854 | − u16 channel; | |
| 855 | − struct ieee80211_channel *req_channel; | |
| 856 | 719 | char *ptr; |
| 857 | 720 | struct brcmf_ssid_le ssid_le; |
| 858 | 721 | |
| 859 | − memcpy(params_le->bssid, ether_bcast, ETH_ALEN); | |
| 722 | + memset(params_le->bssid, 0xFF, ETH_ALEN); | |
| 860 | 723 | params_le->bss_type = DOT11_BSSTYPE_ANY; |
| 861 | 724 | params_le->scan_type = 0; |
| 862 | 725 | params_le->channel_num = 0; |
| @@ -876,30 +739,9 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, · 13 unmodified lines | ||
| 876 | 739 | WL_SCAN("### List of channelspecs to scan ### %d\n", n_channels); |
| 877 | 740 | if (n_channels > 0) { |
| 878 | 741 | for (i = 0; i < n_channels; i++) { |
| 879 | − chanspec = 0; | |
| 880 | − req_channel = request->channels[i]; | |
| 881 | − channel = ieee80211_frequency_to_channel( | |
| 882 | − req_channel->center_freq); | |
| 883 | − if (req_channel->band == IEEE80211_BAND_2GHZ) | |
| 884 | − chanspec |= WL_CHANSPEC_BAND_2G; | |
| 885 | − else | |
| 886 | − chanspec |= WL_CHANSPEC_BAND_5G; | |
| 887 | − | |
| 888 | − if (req_channel->flags & IEEE80211_CHAN_NO_HT40) { | |
| 889 | − chanspec |= WL_CHANSPEC_BW_20; | |
| 890 | − chanspec |= WL_CHANSPEC_CTL_SB_NONE; | |
| 891 | − } else { | |
| 892 | − chanspec |= WL_CHANSPEC_BW_40; | |
| 893 | − if (req_channel->flags & | |
| 894 | − IEEE80211_CHAN_NO_HT40PLUS) | |
| 895 | − chanspec |= WL_CHANSPEC_CTL_SB_LOWER; | |
| 896 | − else | |
| 897 | − chanspec |= WL_CHANSPEC_CTL_SB_UPPER; | |
| 898 | − } | |
| 899 | − | |
| 900 | − chanspec |= (channel & WL_CHANSPEC_CHAN_MASK); | |
| 742 | + chanspec = channel_to_chanspec(request->channels[i]); | |
| 901 | 743 | WL_SCAN("Chan : %d, Channel spec: %x\n", |
| 902 | − channel, chanspec); | |
| 744 | + request->channels[i]->hw_value, chanspec); | |
| 903 | 745 | params_le->channel_list[i] = cpu_to_le16(chanspec); |
| 904 | 746 | } |
| 905 | 747 | } else { |
| @@ -966,7 +808,7 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, · 60 unmodified lines | ||
| 966 | 808 | /* Do a scan abort to stop the driver's scan engine */ |
| 967 | 809 | WL_SCAN("ABORT scan in firmware\n"); |
| 968 | 810 | memset(¶ms_le, 0, sizeof(params_le)); |
| 969 | − memcpy(params_le.bssid, ether_bcast, ETH_ALEN); | |
| 811 | + memset(params_le.bssid, 0xFF, ETH_ALEN); | |
| 970 | 812 | params_le.bss_type = DOT11_BSSTYPE_ANY; |
| 971 | 813 | params_le.scan_type = 0; |
| 972 | 814 | params_le.channel_num = cpu_to_le32(1); |
| @@ -977,8 +819,8 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, · 4 unmodified lines | ||
| 977 | 819 | /* Scan is aborted by setting channel_list[0] to -1 */ |
| 978 | 820 | params_le.channel_list[0] = cpu_to_le16(-1); |
| 979 | 821 | /* E-Scan (or anyother type) can be aborted by SCAN */ |
| 980 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, ¶ms_le, | |
| 981 | − sizeof(params_le)); | |
| 822 | + err = brcmf_fil_cmd_data_set(netdev_priv(ndev), BRCMF_C_SCAN, | |
| 823 | + ¶ms_le, sizeof(params_le)); | |
| 982 | 824 | if (err) |
| 983 | 825 | WL_ERR("Scan abort failed\n"); |
| 984 | 826 | } |
| @@ -998,7 +840,7 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, · 13 unmodified lines | ||
| 998 | 840 | cfg80211_scan_done(scan_request, aborted); |
| 999 | 841 | brcmf_set_mpc(ndev, 1); |
| 1000 | 842 | } |
| 1001 | − if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) { | |
| 843 | + if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { | |
| 1002 | 844 | WL_ERR("Scan complete while device not scanning\n"); |
| 1003 | 845 | return -EPERM; |
| 1004 | 846 | } |
| @@ -1036,8 +878,8 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, · 31 unmodified lines | ||
| 1036 | 878 | params->action = cpu_to_le16(action); |
| 1037 | 879 | params->sync_id = cpu_to_le16(0x1234); |
| 1038 | 880 | |
| 1039 | − err = brcmf_dev_iovar_setbuf(ndev, "escan", params, params_size, | |
| 1040 | − cfg->escan_ioctl_buf, BRCMF_DCMD_MEDLEN); | |
| 881 | + err = brcmf_fil_iovar_data_set(netdev_priv(ndev), "escan", | |
| 882 | + params, params_size); | |
| 1041 | 883 | if (err) { |
| 1042 | 884 | if (err == -EBUSY) |
| 1043 | 885 | WL_INFO("system busy : escan canceled\n"); |
| @@ -1055,16 +897,16 @@ brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, · 11 unmodified lines | ||
| 1055 | 897 | struct net_device *ndev, struct cfg80211_scan_request *request) |
| 1056 | 898 | { |
| 1057 | 899 | s32 err; |
| 1058 | − __le32 passive_scan; | |
| 900 | + u32 passive_scan; | |
| 1059 | 901 | struct brcmf_scan_results *results; |
| 1060 | 902 | |
| 1061 | 903 | WL_SCAN("Enter\n"); |
| 1062 | 904 | cfg->escan_info.ndev = ndev; |
| 1063 | 905 | cfg->escan_info.wiphy = wiphy; |
| 1064 | 906 | cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANNING; |
| 1065 | − passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1); | |
| 1066 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN, | |
| 1067 | − &passive_scan, sizeof(passive_scan)); | |
| 907 | + passive_scan = cfg->active_scan ? 0 : 1; | |
| 908 | + err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PASSIVE_SCAN, | |
| 909 | + passive_scan); | |
| 1068 | 910 | if (err) { |
| 1069 | 911 | WL_ERR("error (%d)\n", err); |
| 1070 | 912 | return err; |
| @@ -1086,10 +928,11 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, · 15 unmodified lines | ||
| 1086 | 928 | struct cfg80211_scan_request *request, |
| 1087 | 929 | struct cfg80211_ssid *this_ssid) |
| 1088 | 930 | { |
| 931 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 1089 | 932 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); |
| 1090 | 933 | struct cfg80211_ssid *ssids; |
| 1091 | 934 | struct brcmf_cfg80211_scan_req *sr = cfg->scan_req_int; |
| 1092 | − __le32 passive_scan; | |
| 935 | + u32 passive_scan; | |
| 1093 | 936 | bool escan_req; |
| 1094 | 937 | bool spec_scan; |
| 1095 | 938 | s32 err; |
| @@ -1097,18 +940,17 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, · 1 unmodified line | ||
| 1097 | 940 | |
| 1098 | 941 | WL_SCAN("START ESCAN\n"); |
| 1099 | 942 | |
| 1100 | − if (test_bit(WL_STATUS_SCANNING, &cfg->status)) { | |
| 1101 | − WL_ERR("Scanning already : status (%lu)\n", cfg->status); | |
| 943 | + if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { | |
| 944 | + WL_ERR("Scanning already: status (%lu)\n", cfg->scan_status); | |
| 1102 | 945 | return -EAGAIN; |
| 1103 | 946 | } |
| 1104 | − if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg->status)) { | |
| 1105 | − WL_ERR("Scanning being aborted : status (%lu)\n", | |
| 1106 | − cfg->status); | |
| 947 | + if (test_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status)) { | |
| 948 | + WL_ERR("Scanning being aborted: status (%lu)\n", | |
| 949 | + cfg->scan_status); | |
| 1107 | 950 | return -EAGAIN; |
| 1108 | 951 | } |
| 1109 | − if (test_bit(WL_STATUS_CONNECTING, &cfg->status)) { | |
| 1110 | − WL_ERR("Connecting : status (%lu)\n", | |
| 1111 | − cfg->status); | |
| 952 | + if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) { | |
| 953 | + WL_ERR("Connecting: status (%lu)\n", ifp->vif->sme_state); | |
| 1112 | 954 | return -EAGAIN; |
| 1113 | 955 | } |
| 1114 | 956 | |
| @@ -1128,7 +970,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, · 13 unmodified lines | ||
| 1128 | 970 | } |
| 1129 | 971 | |
| 1130 | 972 | cfg->scan_request = request; |
| 1131 | − set_bit(WL_STATUS_SCANNING, &cfg->status); | |
| 973 | + set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | |
| 1132 | 974 | if (escan_req) { |
| 1133 | 975 | err = brcmf_do_escan(cfg, wiphy, ndev, request); |
| 1134 | 976 | if (!err) |
| @@ -1149,16 +991,16 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, · 14 unmodified lines | ||
| 1149 | 991 | } else |
| 1150 | 992 | WL_SCAN("Broadcast scan\n"); |
| 1151 | 993 | |
| 1152 | − passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1); | |
| 1153 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN, | |
| 1154 | − &passive_scan, sizeof(passive_scan)); | |
| 994 | + passive_scan = cfg->active_scan ? 0 : 1; | |
| 995 | + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN, | |
| 996 | + passive_scan); | |
| 1155 | 997 | if (err) { |
| 1156 | 998 | WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err); |
| 1157 | 999 | goto scan_out; |
| 1158 | 1000 | } |
| 1159 | 1001 | brcmf_set_mpc(ndev, 0); |
| 1160 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le, | |
| 1161 | − sizeof(sr->ssid_le)); | |
| 1002 | + err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, | |
| 1003 | + &sr->ssid_le, sizeof(sr->ssid_le)); | |
| 1162 | 1004 | if (err) { |
| 1163 | 1005 | if (err == -EBUSY) |
| 1164 | 1006 | WL_INFO("BUSY: scan for \"%s\" canceled\n", |
| @@ -1174,7 +1016,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, · 9 unmodified lines | ||
| 1174 | 1016 | return 0; |
| 1175 | 1017 | |
| 1176 | 1018 | scan_out: |
| 1177 | − clear_bit(WL_STATUS_SCANNING, &cfg->status); | |
| 1019 | + clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | |
| 1178 | 1020 | if (timer_pending(&cfg->escan_timeout)) |
| 1179 | 1021 | del_timer_sync(&cfg->escan_timeout); |
| 1180 | 1022 | cfg->scan_request = NULL; |
| @@ -1182,8 +1024,7 @@ scan_out: · 1 unmodified line | ||
| 1182 | 1024 | } |
| 1183 | 1025 | |
| 1184 | 1026 | static s32 |
| 1185 | −brcmf_cfg80211_scan(struct wiphy *wiphy, | |
| 1186 | − struct cfg80211_scan_request *request) | |
| 1027 | +brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) | |
| 1187 | 1028 | { |
| 1188 | 1029 | struct net_device *ndev = request->wdev->netdev; |
| 1189 | 1030 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); |
| @@ -1191,7 +1032,8 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, · 1 unmodified line | ||
| 1191 | 1032 | |
| 1192 | 1033 | WL_TRACE("Enter\n"); |
| 1193 | 1034 | |
| 1194 | − if (!check_sys_up(wiphy)) | |
| 1035 | + if (!check_vif_up(container_of(request->wdev, | |
| 1036 | + struct brcmf_cfg80211_vif, wdev))) | |
| 1195 | 1037 | return -EIO; |
| 1196 | 1038 | |
| 1197 | 1039 | if (cfg->iscan_on) |
| @@ -1210,7 +1052,8 @@ static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold) · 12 unmodified lines | ||
| 1210 | 1052 | { |
| 1211 | 1053 | s32 err = 0; |
| 1212 | 1054 | |
| 1213 | − err = brcmf_dev_intvar_set(ndev, "rtsthresh", rts_threshold); | |
| 1055 | + err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "rtsthresh", | |
| 1056 | + rts_threshold); | |
| 1214 | 1057 | if (err) |
| 1215 | 1058 | WL_ERR("Error (%d)\n", err); |
| 1216 | 1059 | |
| @@ -1221,7 +1064,8 @@ static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold) · 4 unmodified lines | ||
| 1221 | 1064 | { |
| 1222 | 1065 | s32 err = 0; |
| 1223 | 1066 | |
| 1224 | − err = brcmf_dev_intvar_set(ndev, "fragthresh", frag_threshold); | |
| 1067 | + err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "fragthresh", | |
| 1068 | + frag_threshold); | |
| 1225 | 1069 | if (err) |
| 1226 | 1070 | WL_ERR("Error (%d)\n", err); |
| 1227 | 1071 | |
| @@ -1233,7 +1077,7 @@ static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l) · 5 unmodified lines | ||
| 1233 | 1077 | s32 err = 0; |
| 1234 | 1078 | u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL); |
| 1235 | 1079 | |
| 1236 | − err = brcmf_exec_dcmd_u32(ndev, cmd, &retry); | |
| 1080 | + err = brcmf_fil_cmd_int_set(netdev_priv(ndev), cmd, retry); | |
| 1237 | 1081 | if (err) { |
| 1238 | 1082 | WL_ERR("cmd (%d) , error (%d)\n", cmd, err); |
| 1239 | 1083 | return err; |
| @@ -1245,10 +1089,11 @@ static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) · 5 unmodified lines | ||
| 1245 | 1089 | { |
| 1246 | 1090 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 1247 | 1091 | struct net_device *ndev = cfg_to_ndev(cfg); |
| 1092 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 1248 | 1093 | s32 err = 0; |
| 1249 | 1094 | |
| 1250 | 1095 | WL_TRACE("Enter\n"); |
| 1251 | − if (!check_sys_up(wiphy)) | |
| 1096 | + if (!check_vif_up(ifp->vif)) | |
| 1252 | 1097 | return -EIO; |
| 1253 | 1098 | |
| 1254 | 1099 | if (changed & WIPHY_PARAM_RTS_THRESHOLD && |
| @@ -1327,7 +1172,8 @@ static void brcmf_link_down(struct brcmf_cfg80211_info *cfg) · 72 unmodified lines | ||
| 1327 | 1172 | if (cfg->link_up) { |
| 1328 | 1173 | ndev = cfg_to_ndev(cfg); |
| 1329 | 1174 | WL_INFO("Call WLC_DISASSOC to stop excess roaming\n "); |
| 1330 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, NULL, 0); | |
| 1175 | + err = brcmf_fil_cmd_data_set(netdev_priv(ndev), | |
| 1176 | + BRCMF_C_DISASSOC, NULL, 0); | |
| 1331 | 1177 | if (err) |
| 1332 | 1178 | WL_ERR("WLC_DISASSOC failed (%d)\n", err); |
| 1333 | 1179 | cfg->link_up = false; |
| @@ -1340,7 +1186,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, · 6 unmodified lines | ||
| 1340 | 1186 | struct cfg80211_ibss_params *params) |
| 1341 | 1187 | { |
| 1342 | 1188 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 1343 | − struct brcmf_cfg80211_profile *profile = cfg->profile; | |
| 1189 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 1190 | + struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | |
| 1344 | 1191 | struct brcmf_join_params join_params; |
| 1345 | 1192 | size_t join_params_size = 0; |
| 1346 | 1193 | s32 err = 0; |
| @@ -1348,7 +1195,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, · 1 unmodified line | ||
| 1348 | 1195 | s32 bcnprd; |
| 1349 | 1196 | |
| 1350 | 1197 | WL_TRACE("Enter\n"); |
| 1351 | − if (!check_sys_up(wiphy)) | |
| 1198 | + if (!check_vif_up(ifp->vif)) | |
| 1352 | 1199 | return -EIO; |
| 1353 | 1200 | |
| 1354 | 1201 | if (params->ssid) |
| @@ -1358,7 +1205,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, · 3 unmodified lines | ||
| 1358 | 1205 | return -EOPNOTSUPP; |
| 1359 | 1206 | } |
| 1360 | 1207 | |
| 1361 | − set_bit(WL_STATUS_CONNECTING, &cfg->status); | |
| 1208 | + set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state); | |
| 1362 | 1209 | |
| 1363 | 1210 | if (params->bssid) |
| 1364 | 1211 | WL_CONN("BSSID: %pM\n", params->bssid); |
| @@ -1399,7 +1246,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, · 34 unmodified lines | ||
| 1399 | 1246 | if (params->privacy) |
| 1400 | 1247 | wsec |= WEP_ENABLED; |
| 1401 | 1248 | |
| 1402 | − err = brcmf_dev_intvar_set(ndev, "wsec", wsec); | |
| 1249 | + err = brcmf_fil_iovar_int_set(ifp, "wsec", wsec); | |
| 1403 | 1250 | if (err) { |
| 1404 | 1251 | WL_ERR("wsec failed (%d)\n", err); |
| 1405 | 1252 | goto done; |
| @@ -1411,7 +1258,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, · 5 unmodified lines | ||
| 1411 | 1258 | else |
| 1412 | 1259 | bcnprd = 100; |
| 1413 | 1260 | |
| 1414 | − err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_BCNPRD, &bcnprd); | |
| 1261 | + err = brcmf_fil_cmd_int_set(ifp, BRCM_SET_BCNPRD, bcnprd); | |
| 1415 | 1262 | if (err) { |
| 1416 | 1263 | WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err); |
| 1417 | 1264 | goto done; |
| @@ -1434,7 +1281,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, · 16 unmodified lines | ||
| 1434 | 1281 | BRCMF_ASSOC_PARAMS_FIXED_SIZE; |
| 1435 | 1282 | memcpy(profile->bssid, params->bssid, ETH_ALEN); |
| 1436 | 1283 | } else { |
| 1437 | − memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN); | |
| 1284 | + memset(join_params.params_le.bssid, 0xFF, ETH_ALEN); | |
| 1438 | 1285 | memset(profile->bssid, 0, ETH_ALEN); |
| 1439 | 1286 | } |
| 1440 | 1287 | |
| @@ -1453,8 +1300,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, · 12 unmodified lines | ||
| 1453 | 1300 | |
| 1454 | 1301 | /* set channel for starter */ |
| 1455 | 1302 | target_channel = cfg->channel; |
| 1456 | − err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_CHANNEL, | |
| 1457 | − &target_channel); | |
| 1303 | + err = brcmf_fil_cmd_int_set(ifp, BRCM_SET_CHANNEL, | |
| 1304 | + target_channel); | |
| 1458 | 1305 | if (err) { |
| 1459 | 1306 | WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err); |
| 1460 | 1307 | goto done; |
| @@ -1465,8 +1312,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, · 4 unmodified lines | ||
| 1465 | 1312 | cfg->ibss_starter = false; |
| 1466 | 1313 | |
| 1467 | 1314 | |
| 1468 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, | |
| 1469 | − &join_params, join_params_size); | |
| 1315 | + err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, | |
| 1316 | + &join_params, join_params_size); | |
| 1470 | 1317 | if (err) { |
| 1471 | 1318 | WL_ERR("WLC_SET_SSID failed (%d)\n", err); |
| 1472 | 1319 | goto done; |
| @@ -1474,7 +1321,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, · 1 unmodified line | ||
| 1474 | 1321 | |
| 1475 | 1322 | done: |
| 1476 | 1323 | if (err) |
| 1477 | − clear_bit(WL_STATUS_CONNECTING, &cfg->status); | |
| 1324 | + clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state); | |
| 1478 | 1325 | WL_TRACE("Exit\n"); |
| 1479 | 1326 | return err; |
| 1480 | 1327 | } |
| @@ -1483,10 +1330,11 @@ static s32 · 2 unmodified lines | ||
| 1483 | 1330 | brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) |
| 1484 | 1331 | { |
| 1485 | 1332 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 1333 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 1486 | 1334 | s32 err = 0; |
| 1487 | 1335 | |
| 1488 | 1336 | WL_TRACE("Enter\n"); |
| 1489 | − if (!check_sys_up(wiphy)) | |
| 1337 | + if (!check_vif_up(ifp->vif)) | |
| 1490 | 1338 | return -EIO; |
| 1491 | 1339 | |
| 1492 | 1340 | brcmf_link_down(cfg); |
| @@ -1499,8 +1347,7 @@ brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) · 6 unmodified lines | ||
| 1499 | 1347 | static s32 brcmf_set_wpa_version(struct net_device *ndev, |
| 1500 | 1348 | struct cfg80211_connect_params *sme) |
| 1501 | 1349 | { |
| 1502 | − struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | |
| 1503 | − struct brcmf_cfg80211_profile *profile = cfg->profile; | |
| 1350 | + struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); | |
| 1504 | 1351 | struct brcmf_cfg80211_security *sec; |
| 1505 | 1352 | s32 val = 0; |
| 1506 | 1353 | s32 err = 0; |
| @@ -1512,7 +1359,7 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev, · 5 unmodified lines | ||
| 1512 | 1359 | else |
| 1513 | 1360 | val = WPA_AUTH_DISABLED; |
| 1514 | 1361 | WL_CONN("setting wpa_auth to 0x%0x\n", val); |
| 1515 | − err = brcmf_dev_intvar_set(ndev, "wpa_auth", val); | |
| 1362 | + err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "wpa_auth", val); | |
| 1516 | 1363 | if (err) { |
| 1517 | 1364 | WL_ERR("set wpa_auth failed (%d)\n", err); |
| 1518 | 1365 | return err; |
| @@ -1525,8 +1372,7 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev, · 6 unmodified lines | ||
| 1525 | 1372 | static s32 brcmf_set_auth_type(struct net_device *ndev, |
| 1526 | 1373 | struct cfg80211_connect_params *sme) |
| 1527 | 1374 | { |
| 1528 | − struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | |
| 1529 | − struct brcmf_cfg80211_profile *profile = cfg->profile; | |
| 1375 | + struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); | |
| 1530 | 1376 | struct brcmf_cfg80211_security *sec; |
| 1531 | 1377 | s32 val = 0; |
| 1532 | 1378 | s32 err = 0; |
| @@ -1552,7 +1398,7 @@ static s32 brcmf_set_auth_type(struct net_device *ndev, · 19 unmodified lines | ||
| 1552 | 1398 | break; |
| 1553 | 1399 | } |
| 1554 | 1400 | |
| 1555 | − err = brcmf_dev_intvar_set(ndev, "auth", val); | |
| 1401 | + err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "auth", val); | |
| 1556 | 1402 | if (err) { |
| 1557 | 1403 | WL_ERR("set auth failed (%d)\n", err); |
| 1558 | 1404 | return err; |
| @@ -1566,8 +1412,7 @@ static s32 · 7 unmodified lines | ||
| 1566 | 1412 | brcmf_set_set_cipher(struct net_device *ndev, |
| 1567 | 1413 | struct cfg80211_connect_params *sme) |
| 1568 | 1414 | { |
| 1569 | − struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | |
| 1570 | − struct brcmf_cfg80211_profile *profile = cfg->profile; | |
| 1415 | + struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); | |
| 1571 | 1416 | struct brcmf_cfg80211_security *sec; |
| 1572 | 1417 | s32 pval = 0; |
| 1573 | 1418 | s32 gval = 0; |
| @@ -1617,7 +1462,7 @@ brcmf_set_set_cipher(struct net_device *ndev, · 43 unmodified lines | ||
| 1617 | 1462 | } |
| 1618 | 1463 | |
| 1619 | 1464 | WL_CONN("pval (%d) gval (%d)\n", pval, gval); |
| 1620 | − err = brcmf_dev_intvar_set(ndev, "wsec", pval | gval); | |
| 1465 | + err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "wsec", pval | gval); | |
| 1621 | 1466 | if (err) { |
| 1622 | 1467 | WL_ERR("error (%d)\n", err); |
| 1623 | 1468 | return err; |
| @@ -1633,14 +1478,14 @@ brcmf_set_set_cipher(struct net_device *ndev, · 9 unmodified lines | ||
| 1633 | 1478 | static s32 |
| 1634 | 1479 | brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) |
| 1635 | 1480 | { |
| 1636 | − struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | |
| 1637 | − struct brcmf_cfg80211_profile *profile = cfg->profile; | |
| 1481 | + struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); | |
| 1638 | 1482 | struct brcmf_cfg80211_security *sec; |
| 1639 | 1483 | s32 val = 0; |
| 1640 | 1484 | s32 err = 0; |
| 1641 | 1485 | |
| 1642 | 1486 | if (sme->crypto.n_akm_suites) { |
| 1643 | − err = brcmf_dev_intvar_get(ndev, "wpa_auth", &val); | |
| 1487 | + err = brcmf_fil_iovar_int_get(netdev_priv(ndev), | |
| 1488 | + "wpa_auth", &val); | |
| 1644 | 1489 | if (err) { |
| 1645 | 1490 | WL_ERR("could not get wpa_auth (%d)\n", err); |
| 1646 | 1491 | return err; |
| @@ -1674,7 +1519,8 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) · 27 unmodified lines | ||
| 1674 | 1519 | } |
| 1675 | 1520 | |
| 1676 | 1521 | WL_CONN("setting wpa_auth to %d\n", val); |
| 1677 | − err = brcmf_dev_intvar_set(ndev, "wpa_auth", val); | |
| 1522 | + err = brcmf_fil_iovar_int_set(netdev_priv(ndev), | |
| 1523 | + "wpa_auth", val); | |
| 1678 | 1524 | if (err) { |
| 1679 | 1525 | WL_ERR("could not set wpa_auth (%d)\n", err); |
| 1680 | 1526 | return err; |
| @@ -1690,13 +1536,11 @@ static s32 · 9 unmodified lines | ||
| 1690 | 1536 | brcmf_set_sharedkey(struct net_device *ndev, |
| 1691 | 1537 | struct cfg80211_connect_params *sme) |
| 1692 | 1538 | { |
| 1693 | − struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | |
| 1694 | − struct brcmf_cfg80211_profile *profile = cfg->profile; | |
| 1539 | + struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); | |
| 1695 | 1540 | struct brcmf_cfg80211_security *sec; |
| 1696 | 1541 | struct brcmf_wsec_key key; |
| 1697 | 1542 | s32 val; |
| 1698 | 1543 | s32 err = 0; |
| 1699 | − s32 bssidx; | |
| 1700 | 1544 | |
| 1701 | 1545 | WL_CONN("key len (%d)\n", sme->key_len); |
| 1702 | 1546 | |
| @@ -1739,15 +1583,14 @@ brcmf_set_sharedkey(struct net_device *ndev, · 36 unmodified lines | ||
| 1739 | 1583 | WL_CONN("key length (%d) key index (%d) algo (%d)\n", |
| 1740 | 1584 | key.len, key.index, key.algo); |
| 1741 | 1585 | WL_CONN("key \"%s\"\n", key.data); |
| 1742 | − bssidx = brcmf_find_bssidx(cfg, ndev); | |
| 1743 | − err = send_key_to_dongle(cfg, bssidx, ndev, &key); | |
| 1586 | + err = send_key_to_dongle(ndev, &key); | |
| 1744 | 1587 | if (err) |
| 1745 | 1588 | return err; |
| 1746 | 1589 | |
| 1747 | 1590 | if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) { |
| 1748 | 1591 | WL_CONN("set auth_type to shared key\n"); |
| 1749 | 1592 | val = WL_AUTH_SHARED_KEY; /* shared key */ |
| 1750 | − err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", val, bssidx); | |
| 1593 | + err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "auth", val); | |
| 1751 | 1594 | if (err) |
| 1752 | 1595 | WL_ERR("set auth failed (%d)\n", err); |
| 1753 | 1596 | } |
| @@ -1759,7 +1602,8 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, · 5 unmodified lines | ||
| 1759 | 1602 | struct cfg80211_connect_params *sme) |
| 1760 | 1603 | { |
| 1761 | 1604 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 1762 | − struct brcmf_cfg80211_profile *profile = cfg->profile; | |
| 1605 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 1606 | + struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | |
| 1763 | 1607 | struct ieee80211_channel *chan = sme->channel; |
| 1764 | 1608 | struct brcmf_join_params join_params; |
| 1765 | 1609 | size_t join_params_size; |
| @@ -1768,7 +1612,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, · 2 unmodified lines | ||
| 1768 | 1612 | s32 err = 0; |
| 1769 | 1613 | |
| 1770 | 1614 | WL_TRACE("Enter\n"); |
| 1771 | − if (!check_sys_up(wiphy)) | |
| 1615 | + if (!check_vif_up(ifp->vif)) | |
| 1772 | 1616 | return -EIO; |
| 1773 | 1617 | |
| 1774 | 1618 | if (!sme->ssid) { |
| @@ -1776,7 +1620,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, · 1 unmodified line | ||
| 1776 | 1620 | return -EOPNOTSUPP; |
| 1777 | 1621 | } |
| 1778 | 1622 | |
| 1779 | − set_bit(WL_STATUS_CONNECTING, &cfg->status); | |
| 1623 | + set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state); | |
| 1780 | 1624 | |
| 1781 | 1625 | if (chan) { |
| 1782 | 1626 | cfg->channel = |
| @@ -1827,7 +1671,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, · 44 unmodified lines | ||
| 1827 | 1671 | memcpy(&profile->ssid.SSID, sme->ssid, profile->ssid.SSID_len); |
| 1828 | 1672 | join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len); |
| 1829 | 1673 | |
| 1830 | − memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN); | |
| 1674 | + memset(join_params.params_le.bssid, 0xFF, ETH_ALEN); | |
| 1831 | 1675 | |
| 1832 | 1676 | if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN) |
| 1833 | 1677 | WL_CONN("ssid \"%s\", len (%d)\n", |
| @@ -1835,14 +1679,14 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, · 1 unmodified line | ||
| 1835 | 1679 | |
| 1836 | 1680 | brcmf_ch_to_chanspec(cfg->channel, |
| 1837 | 1681 | &join_params, &join_params_size); |
| 1838 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, | |
| 1839 | − &join_params, join_params_size); | |
| 1682 | + err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, | |
| 1683 | + &join_params, join_params_size); | |
| 1840 | 1684 | if (err) |
| 1841 | 1685 | WL_ERR("WLC_SET_SSID failed (%d)\n", err); |
| 1842 | 1686 | |
| 1843 | 1687 | done: |
| 1844 | 1688 | if (err) |
| 1845 | − clear_bit(WL_STATUS_CONNECTING, &cfg->status); | |
| 1689 | + clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state); | |
| 1846 | 1690 | WL_TRACE("Exit\n"); |
| 1847 | 1691 | return err; |
| 1848 | 1692 | } |
| @@ -1852,20 +1696,21 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, · 3 unmodified lines | ||
| 1852 | 1696 | u16 reason_code) |
| 1853 | 1697 | { |
| 1854 | 1698 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 1855 | − struct brcmf_cfg80211_profile *profile = cfg->profile; | |
| 1699 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 1700 | + struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | |
| 1856 | 1701 | struct brcmf_scb_val_le scbval; |
| 1857 | 1702 | s32 err = 0; |
| 1858 | 1703 | |
| 1859 | 1704 | WL_TRACE("Enter. Reason code = %d\n", reason_code); |
| 1860 | − if (!check_sys_up(wiphy)) | |
| 1705 | + if (!check_vif_up(ifp->vif)) | |
| 1861 | 1706 | return -EIO; |
| 1862 | 1707 | |
| 1863 | − clear_bit(WL_STATUS_CONNECTED, &cfg->status); | |
| 1708 | + clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state); | |
| 1864 | 1709 | |
| 1865 | 1710 | memcpy(&scbval.ea, &profile->bssid, ETH_ALEN); |
| 1866 | 1711 | scbval.val = cpu_to_le32(reason_code); |
| 1867 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, &scbval, | |
| 1868 | − sizeof(struct brcmf_scb_val_le)); | |
| 1712 | + err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_DISASSOC, | |
| 1713 | + &scbval, sizeof(scbval)); | |
| 1869 | 1714 | if (err) |
| 1870 | 1715 | WL_ERR("error (%d)\n", err); |
| 1871 | 1716 | |
| @@ -1882,13 +1727,14 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, · 10 unmodified lines | ||
| 1882 | 1727 | |
| 1883 | 1728 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 1884 | 1729 | struct net_device *ndev = cfg_to_ndev(cfg); |
| 1730 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 1885 | 1731 | u16 txpwrmw; |
| 1886 | 1732 | s32 err = 0; |
| 1887 | 1733 | s32 disable = 0; |
| 1888 | 1734 | s32 dbm = MBM_TO_DBM(mbm); |
| 1889 | 1735 | |
| 1890 | 1736 | WL_TRACE("Enter\n"); |
| 1891 | − if (!check_sys_up(wiphy)) | |
| 1737 | + if (!check_vif_up(ifp->vif)) | |
| 1892 | 1738 | return -EIO; |
| 1893 | 1739 | |
| 1894 | 1740 | switch (type) { |
| @@ -1905,7 +1751,7 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, · 10 unmodified lines | ||
| 1905 | 1751 | } |
| 1906 | 1752 | /* Make sure radio is off or on as far as software is concerned */ |
| 1907 | 1753 | disable = WL_RADIO_SW_DISABLE << 16; |
| 1908 | − err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_RADIO, &disable); | |
| 1754 | + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_RADIO, disable); | |
| 1909 | 1755 | if (err) |
| 1910 | 1756 | WL_ERR("WLC_SET_RADIO error (%d)\n", err); |
| 1911 | 1757 | |
| @@ -1913,8 +1759,8 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, · 1 unmodified line | ||
| 1913 | 1759 | txpwrmw = 0xffff; |
| 1914 | 1760 | else |
| 1915 | 1761 | txpwrmw = (u16) dbm; |
| 1916 | − err = brcmf_dev_intvar_set(ndev, "qtxpower", | |
| 1917 | − (s32) (brcmf_mw_to_qdbm(txpwrmw))); | |
| 1762 | + err = brcmf_fil_iovar_int_set(ifp, "qtxpower", | |
| 1763 | + (s32)brcmf_mw_to_qdbm(txpwrmw)); | |
| 1918 | 1764 | if (err) |
| 1919 | 1765 | WL_ERR("qtxpower error (%d)\n", err); |
| 1920 | 1766 | cfg->conf->tx_power = dbm; |
| @@ -1927,16 +1773,16 @@ done: · 6 unmodified lines | ||
| 1927 | 1773 | static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm) |
| 1928 | 1774 | { |
| 1929 | 1775 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 1930 | − struct net_device *ndev = cfg_to_ndev(cfg); | |
| 1776 | + struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | |
| 1931 | 1777 | s32 txpwrdbm; |
| 1932 | 1778 | u8 result; |
| 1933 | 1779 | s32 err = 0; |
| 1934 | 1780 | |
| 1935 | 1781 | WL_TRACE("Enter\n"); |
| 1936 | − if (!check_sys_up(wiphy)) | |
| 1782 | + if (!check_vif_up(ifp->vif)) | |
| 1937 | 1783 | return -EIO; |
| 1938 | 1784 | |
| 1939 | − err = brcmf_dev_intvar_get(ndev, "qtxpower", &txpwrdbm); | |
| 1785 | + err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &txpwrdbm); | |
| 1940 | 1786 | if (err) { |
| 1941 | 1787 | WL_ERR("error (%d)\n", err); |
| 1942 | 1788 | goto done; |
| @@ -1954,19 +1800,17 @@ static s32 · 11 unmodified lines | ||
| 1954 | 1800 | brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, |
| 1955 | 1801 | u8 key_idx, bool unicast, bool multicast) |
| 1956 | 1802 | { |
| 1957 | − struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | |
| 1803 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 1958 | 1804 | u32 index; |
| 1959 | 1805 | u32 wsec; |
| 1960 | 1806 | s32 err = 0; |
| 1961 | − s32 bssidx; | |
| 1962 | 1807 | |
| 1963 | 1808 | WL_TRACE("Enter\n"); |
| 1964 | 1809 | WL_CONN("key index (%d)\n", key_idx); |
| 1965 | − if (!check_sys_up(wiphy)) | |
| 1810 | + if (!check_vif_up(ifp->vif)) | |
| 1966 | 1811 | return -EIO; |
| 1967 | 1812 | |
| 1968 | − bssidx = brcmf_find_bssidx(cfg, ndev); | |
| 1969 | − err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx); | |
| 1813 | + err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec); | |
| 1970 | 1814 | if (err) { |
| 1971 | 1815 | WL_ERR("WLC_GET_WSEC error (%d)\n", err); |
| 1972 | 1816 | goto done; |
| @@ -1975,8 +1819,8 @@ brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, · 2 unmodified lines | ||
| 1975 | 1819 | if (wsec & WEP_ENABLED) { |
| 1976 | 1820 | /* Just select a new current key */ |
| 1977 | 1821 | index = key_idx; |
| 1978 | − err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_KEY_PRIMARY, | |
| 1979 | − &index); | |
| 1822 | + err = brcmf_fil_cmd_int_set(ifp, | |
| 1823 | + BRCMF_C_SET_KEY_PRIMARY, index); | |
| 1980 | 1824 | if (err) |
| 1981 | 1825 | WL_ERR("error (%d)\n", err); |
| 1982 | 1826 | } |
| @@ -1989,11 +1833,8 @@ static s32 · 6 unmodified lines | ||
| 1989 | 1833 | brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, |
| 1990 | 1834 | u8 key_idx, const u8 *mac_addr, struct key_params *params) |
| 1991 | 1835 | { |
| 1992 | − struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | |
| 1993 | 1836 | struct brcmf_wsec_key key; |
| 1994 | − struct brcmf_wsec_key_le key_le; | |
| 1995 | 1837 | s32 err = 0; |
| 1996 | − s32 bssidx; | |
| 1997 | 1838 | |
| 1998 | 1839 | memset(&key, 0, sizeof(key)); |
| 1999 | 1840 | key.index = (u32) key_idx; |
| @@ -2002,11 +1843,10 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, · 2 unmodified lines | ||
| 2002 | 1843 | if (!is_multicast_ether_addr(mac_addr)) |
| 2003 | 1844 | memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN); |
| 2004 | 1845 | key.len = (u32) params->key_len; |
| 2005 | − bssidx = brcmf_find_bssidx(cfg, ndev); | |
| 2006 | 1846 | /* check for key index change */ |
| 2007 | 1847 | if (key.len == 0) { |
| 2008 | 1848 | /* key delete */ |
| 2009 | − err = send_key_to_dongle(cfg, bssidx, ndev, &key); | |
| 1849 | + err = send_key_to_dongle(ndev, &key); | |
| 2010 | 1850 | if (err) |
| 2011 | 1851 | WL_ERR("key delete error (%d)\n", err); |
| 2012 | 1852 | } else { |
| @@ -2061,13 +1901,7 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, · 48 unmodified lines | ||
| 2061 | 1901 | WL_ERR("Invalid cipher (0x%x)\n", params->cipher); |
| 2062 | 1902 | return -EINVAL; |
| 2063 | 1903 | } |
| 2064 | − convert_key_from_CPU(&key, &key_le); | |
| 2065 | − | |
| 2066 | − brcmf_netdev_wait_pend8021x(ndev); | |
| 2067 | − err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le, | |
| 2068 | − sizeof(key_le), | |
| 2069 | − cfg->extra_buf, | |
| 2070 | − WL_EXTRA_BUF_MAX, bssidx); | |
| 1904 | + err = send_key_to_dongle(ndev, &key); | |
| 2071 | 1905 | if (err) |
| 2072 | 1906 | WL_ERR("wsec_key error (%d)\n", err); |
| 2073 | 1907 | } |
| @@ -2080,16 +1914,16 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, · 6 unmodified lines | ||
| 2080 | 1914 | struct key_params *params) |
| 2081 | 1915 | { |
| 2082 | 1916 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 1917 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 2083 | 1918 | struct brcmf_wsec_key key; |
| 2084 | 1919 | s32 val; |
| 2085 | 1920 | s32 wsec; |
| 2086 | 1921 | s32 err = 0; |
| 2087 | 1922 | u8 keybuf[8]; |
| 2088 | − s32 bssidx; | |
| 2089 | 1923 | |
| 2090 | 1924 | WL_TRACE("Enter\n"); |
| 2091 | 1925 | WL_CONN("key index (%d)\n", key_idx); |
| 2092 | − if (!check_sys_up(wiphy)) | |
| 1926 | + if (!check_vif_up(ifp->vif)) | |
| 2093 | 1927 | return -EIO; |
| 2094 | 1928 | |
| 2095 | 1929 | if (mac_addr) { |
| @@ -2147,18 +1981,17 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, · 51 unmodified lines | ||
| 2147 | 1981 | goto done; |
| 2148 | 1982 | } |
| 2149 | 1983 | |
| 2150 | − bssidx = brcmf_find_bssidx(cfg, ndev); | |
| 2151 | − err = send_key_to_dongle(cfg, bssidx, ndev, &key); | |
| 1984 | + err = send_key_to_dongle(ndev, &key); | |
| 2152 | 1985 | if (err) |
| 2153 | 1986 | goto done; |
| 2154 | 1987 | |
| 2155 | − err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx); | |
| 1988 | + err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec); | |
| 2156 | 1989 | if (err) { |
| 2157 | 1990 | WL_ERR("get wsec error (%d)\n", err); |
| 2158 | 1991 | goto done; |
| 2159 | 1992 | } |
| 2160 | 1993 | wsec |= val; |
| 2161 | − err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", wsec, bssidx); | |
| 1994 | + err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec); | |
| 2162 | 1995 | if (err) { |
| 2163 | 1996 | WL_ERR("set wsec error (%d)\n", err); |
| 2164 | 1997 | goto done; |
| @@ -2173,13 +2006,12 @@ static s32 · 8 unmodified lines | ||
| 2173 | 2006 | brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, |
| 2174 | 2007 | u8 key_idx, bool pairwise, const u8 *mac_addr) |
| 2175 | 2008 | { |
| 2176 | − struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | |
| 2009 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 2177 | 2010 | struct brcmf_wsec_key key; |
| 2178 | 2011 | s32 err = 0; |
| 2179 | − s32 bssidx; | |
| 2180 | 2012 | |
| 2181 | 2013 | WL_TRACE("Enter\n"); |
| 2182 | − if (!check_sys_up(wiphy)) | |
| 2014 | + if (!check_vif_up(ifp->vif)) | |
| 2183 | 2015 | return -EIO; |
| 2184 | 2016 | |
| 2185 | 2017 | memset(&key, 0, sizeof(key)); |
| @@ -2191,8 +2023,7 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, · 5 unmodified lines | ||
| 2191 | 2023 | WL_CONN("key index (%d)\n", key_idx); |
| 2192 | 2024 | |
| 2193 | 2025 | /* Set the new key/index */ |
| 2194 | − bssidx = brcmf_find_bssidx(cfg, ndev); | |
| 2195 | − err = send_key_to_dongle(cfg, bssidx, ndev, &key); | |
| 2026 | + err = send_key_to_dongle(ndev, &key); | |
| 2196 | 2027 | if (err) { |
| 2197 | 2028 | if (err == -EINVAL) { |
| 2198 | 2029 | if (key.index >= DOT11_MAX_DEFAULT_KEYS) |
| @@ -2213,22 +2044,20 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, · 14 unmodified lines | ||
| 2213 | 2044 | void (*callback) (void *cookie, struct key_params * params)) |
| 2214 | 2045 | { |
| 2215 | 2046 | struct key_params params; |
| 2216 | − struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | |
| 2217 | − struct brcmf_cfg80211_profile *profile = cfg->profile; | |
| 2047 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 2048 | + struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | |
| 2218 | 2049 | struct brcmf_cfg80211_security *sec; |
| 2219 | 2050 | s32 wsec; |
| 2220 | 2051 | s32 err = 0; |
| 2221 | − s32 bssidx; | |
| 2222 | 2052 | |
| 2223 | 2053 | WL_TRACE("Enter\n"); |
| 2224 | 2054 | WL_CONN("key index (%d)\n", key_idx); |
| 2225 | − if (!check_sys_up(wiphy)) | |
| 2055 | + if (!check_vif_up(ifp->vif)) | |
| 2226 | 2056 | return -EIO; |
| 2227 | 2057 | |
| 2228 | 2058 | memset(¶ms, 0, sizeof(params)); |
| 2229 | 2059 | |
| 2230 | − bssidx = brcmf_find_bssidx(cfg, ndev); | |
| 2231 | − err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx); | |
| 2060 | + err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec); | |
| 2232 | 2061 | if (err) { |
| 2233 | 2062 | WL_ERR("WLC_GET_WSEC error (%d)\n", err); |
| 2234 | 2063 | /* Ignore this error, may happen during DISASSOC */ |
| @@ -2280,33 +2109,33 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, · 45 unmodified lines | ||
| 2280 | 2109 | u8 *mac, struct station_info *sinfo) |
| 2281 | 2110 | { |
| 2282 | 2111 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 2283 | − struct brcmf_cfg80211_profile *profile = cfg->profile; | |
| 2112 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 2113 | + struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | |
| 2284 | 2114 | struct brcmf_scb_val_le scb_val; |
| 2285 | 2115 | int rssi; |
| 2286 | 2116 | s32 rate; |
| 2287 | 2117 | s32 err = 0; |
| 2288 | 2118 | u8 *bssid = profile->bssid; |
| 2289 | − struct brcmf_sta_info_le *sta_info_le; | |
| 2119 | + struct brcmf_sta_info_le sta_info_le; | |
| 2290 | 2120 | |
| 2291 | 2121 | WL_TRACE("Enter, MAC %pM\n", mac); |
| 2292 | − if (!check_sys_up(wiphy)) | |
| 2122 | + if (!check_vif_up(ifp->vif)) | |
| 2293 | 2123 | return -EIO; |
| 2294 | 2124 | |
| 2295 | 2125 | if (cfg->conf->mode == WL_MODE_AP) { |
| 2296 | − err = brcmf_dev_iovar_getbuf(ndev, "sta_info", mac, ETH_ALEN, | |
| 2297 | − cfg->dcmd_buf, | |
| 2298 | − WL_DCMD_LEN_MAX); | |
| 2126 | + memcpy(&sta_info_le, mac, ETH_ALEN); | |
| 2127 | + err = brcmf_fil_iovar_data_get(ifp, "sta_info", | |
| 2128 | + &sta_info_le, | |
| 2129 | + sizeof(sta_info_le)); | |
| 2299 | 2130 | if (err < 0) { |
| 2300 | 2131 | WL_ERR("GET STA INFO failed, %d\n", err); |
| 2301 | 2132 | goto done; |
| 2302 | 2133 | } |
| 2303 | − sta_info_le = (struct brcmf_sta_info_le *)cfg->dcmd_buf; | |
| 2304 | − | |
| 2305 | 2134 | sinfo->filled = STATION_INFO_INACTIVE_TIME; |
| 2306 | − sinfo->inactive_time = le32_to_cpu(sta_info_le->idle) * 1000; | |
| 2307 | − if (le32_to_cpu(sta_info_le->flags) & BRCMF_STA_ASSOC) { | |
| 2135 | + sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000; | |
| 2136 | + if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) { | |
| 2308 | 2137 | sinfo->filled |= STATION_INFO_CONNECTED_TIME; |
| 2309 | − sinfo->connected_time = le32_to_cpu(sta_info_le->in); | |
| 2138 | + sinfo->connected_time = le32_to_cpu(sta_info_le.in); | |
| 2310 | 2139 | } |
| 2311 | 2140 | WL_TRACE("STA idle time : %d ms, connected time :%d sec\n", |
| 2312 | 2141 | sinfo->inactive_time, sinfo->connected_time); |
| @@ -2318,7 +2147,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, · 5 unmodified lines | ||
| 2318 | 2147 | goto done; |
| 2319 | 2148 | } |
| 2320 | 2149 | /* Report the current tx rate */ |
| 2321 | − err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_RATE, &rate); | |
| 2150 | + err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate); | |
| 2322 | 2151 | if (err) { |
| 2323 | 2152 | WL_ERR("Could not get rate (%d)\n", err); |
| 2324 | 2153 | goto done; |
| @@ -2328,10 +2157,11 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, · 3 unmodified lines | ||
| 2328 | 2157 | WL_CONN("Rate %d Mbps\n", rate / 2); |
| 2329 | 2158 | } |
| 2330 | 2159 | |
| 2331 | − if (test_bit(WL_STATUS_CONNECTED, &cfg->status)) { | |
| 2160 | + if (test_bit(BRCMF_VIF_STATUS_CONNECTED, | |
| 2161 | + &ifp->vif->sme_state)) { | |
| 2332 | 2162 | memset(&scb_val, 0, sizeof(scb_val)); |
| 2333 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val, | |
| 2334 | − sizeof(scb_val)); | |
| 2163 | + err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI, | |
| 2164 | + &scb_val, sizeof(scb_val)); | |
| 2335 | 2165 | if (err) { |
| 2336 | 2166 | WL_ERR("Could not get rssi (%d)\n", err); |
| 2337 | 2167 | goto done; |
| @@ -2356,6 +2186,7 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, · 18 unmodified lines | ||
| 2356 | 2186 | s32 pm; |
| 2357 | 2187 | s32 err = 0; |
| 2358 | 2188 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 2189 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 2359 | 2190 | |
| 2360 | 2191 | WL_TRACE("Enter\n"); |
| 2361 | 2192 | |
| @@ -2367,7 +2198,7 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, · 5 unmodified lines | ||
| 2367 | 2198 | * FW later while initializing the dongle |
| 2368 | 2199 | */ |
| 2369 | 2200 | cfg->pwr_save = enabled; |
| 2370 | − if (!test_bit(WL_STATUS_READY, &cfg->status)) { | |
| 2201 | + if (!check_vif_up(ifp->vif)) { | |
| 2371 | 2202 | |
| 2372 | 2203 | WL_INFO("Device is not ready, storing the value in cfg_info struct\n"); |
| 2373 | 2204 | goto done; |
| @@ -2376,7 +2207,7 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, · 2 unmodified lines | ||
| 2376 | 2207 | pm = enabled ? PM_FAST : PM_OFF; |
| 2377 | 2208 | WL_INFO("power save %s\n", (pm ? "enabled" : "disabled")); |
| 2378 | 2209 | |
| 2379 | − err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &pm); | |
| 2210 | + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, pm); | |
| 2380 | 2211 | if (err) { |
| 2381 | 2212 | if (err == -ENODEV) |
| 2382 | 2213 | WL_ERR("net_device is not ready yet\n"); |
| @@ -2393,6 +2224,7 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev, · 10 unmodified lines | ||
| 2393 | 2224 | const u8 *addr, |
| 2394 | 2225 | const struct cfg80211_bitrate_mask *mask) |
| 2395 | 2226 | { |
| 2227 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 2396 | 2228 | struct brcm_rateset_le rateset_le; |
| 2397 | 2229 | s32 rate; |
| 2398 | 2230 | s32 val; |
| @@ -2402,13 +2234,13 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev, · 3 unmodified lines | ||
| 2402 | 2234 | s32 err = 0; |
| 2403 | 2235 | |
| 2404 | 2236 | WL_TRACE("Enter\n"); |
| 2405 | − if (!check_sys_up(wiphy)) | |
| 2237 | + if (!check_vif_up(ifp->vif)) | |
| 2406 | 2238 | return -EIO; |
| 2407 | 2239 | |
| 2408 | 2240 | /* addr param is always NULL. ignore it */ |
| 2409 | 2241 | /* Get current rateset */ |
| 2410 | − err = brcmf_exec_dcmd(ndev, BRCM_GET_CURR_RATESET, &rateset_le, | |
| 2411 | − sizeof(rateset_le)); | |
| 2242 | + err = brcmf_fil_cmd_data_get(ifp, BRCM_GET_CURR_RATESET, | |
| 2243 | + &rateset_le, sizeof(rateset_le)); | |
| 2412 | 2244 | if (err) { |
| 2413 | 2245 | WL_ERR("could not get current rateset (%d)\n", err); |
| 2414 | 2246 | goto done; |
| @@ -2435,8 +2267,8 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev, · 20 unmodified lines | ||
| 2435 | 2267 | * Set rate override, |
| 2436 | 2268 | * Since the is a/b/g-blind, both a/bg_rate are enforced. |
| 2437 | 2269 | */ |
| 2438 | − err_bg = brcmf_dev_intvar_set(ndev, "bg_rate", rate); | |
| 2439 | − err_a = brcmf_dev_intvar_set(ndev, "a_rate", rate); | |
| 2270 | + err_bg = brcmf_fil_iovar_int_set(ifp, "bg_rate", rate); | |
| 2271 | + err_a = brcmf_fil_iovar_int_set(ifp, "a_rate", rate); | |
| 2440 | 2272 | if (err_bg && err_a) { |
| 2441 | 2273 | WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a); |
| 2442 | 2274 | err = err_bg | err_a; |
| @@ -2565,7 +2397,8 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg, · 122 unmodified lines | ||
| 2565 | 2397 | |
| 2566 | 2398 | *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX); |
| 2567 | 2399 | |
| 2568 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX); | |
| 2400 | + err = brcmf_fil_cmd_data_get(netdev_priv(ndev), BRCMF_C_GET_BSS_INFO, | |
| 2401 | + buf, WL_BSS_INFO_MAX); | |
| 2569 | 2402 | if (err) { |
| 2570 | 2403 | WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err); |
| 2571 | 2404 | goto CleanUp; |
| @@ -2674,12 +2507,12 @@ brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, · 102 unmodified lines | ||
| 2674 | 2507 | return false; |
| 2675 | 2508 | } |
| 2676 | 2509 | |
| 2677 | −struct brcmf_vs_tlv * | |
| 2510 | +static struct brcmf_vs_tlv * | |
| 2678 | 2511 | brcmf_find_wpaie(u8 *parse, u32 len) |
| 2679 | 2512 | { |
| 2680 | 2513 | struct brcmf_tlv *ie; |
| 2681 | 2514 | |
| 2682 | − while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_WPA))) { | |
| 2515 | + while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_VENDOR_SPECIFIC))) { | |
| 2683 | 2516 | if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len, |
| 2684 | 2517 | WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE)) |
| 2685 | 2518 | return (struct brcmf_vs_tlv *)ie; |
| @@ -2689,7 +2522,9 @@ brcmf_find_wpaie(u8 *parse, u32 len) · 3 unmodified lines | ||
| 2689 | 2522 | |
| 2690 | 2523 | static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) |
| 2691 | 2524 | { |
| 2692 | − struct brcmf_cfg80211_profile *profile = cfg->profile; | |
| 2525 | + struct net_device *ndev = cfg_to_ndev(cfg); | |
| 2526 | + struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); | |
| 2527 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 2693 | 2528 | struct brcmf_bss_info_le *bi; |
| 2694 | 2529 | struct brcmf_ssid *ssid; |
| 2695 | 2530 | struct brcmf_tlv *tim; |
| @@ -2706,8 +2541,8 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) · 10 unmodified lines | ||
| 2706 | 2541 | ssid = &profile->ssid; |
| 2707 | 2542 | |
| 2708 | 2543 | *(__le32 *)cfg->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX); |
| 2709 | − err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCMF_C_GET_BSS_INFO, | |
| 2710 | − cfg->extra_buf, WL_EXTRA_BUF_MAX); | |
| 2544 | + err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, | |
| 2545 | + cfg->extra_buf, WL_EXTRA_BUF_MAX); | |
| 2711 | 2546 | if (err) { |
| 2712 | 2547 | WL_ERR("Could not get bss info %d\n", err); |
| 2713 | 2548 | goto update_bss_info_out; |
| @@ -2732,8 +2567,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) · 18 unmodified lines | ||
| 2732 | 2567 | * so we speficially query dtim information to dongle. |
| 2733 | 2568 | */ |
| 2734 | 2569 | u32 var; |
| 2735 | − err = brcmf_dev_intvar_get(cfg_to_ndev(cfg), | |
| 2736 | − "dtim_assoc", &var); | |
| 2570 | + err = brcmf_fil_iovar_int_get(ifp, "dtim_assoc", &var); | |
| 2737 | 2571 | if (err) { |
| 2738 | 2572 | WL_ERR("wl dtim_assoc failed (%d)\n", err); |
| 2739 | 2573 | goto update_bss_info_out; |
| @@ -2741,9 +2575,6 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) · 1 unmodified line | ||
| 2741 | 2575 | dtim_period = (u8)var; |
| 2742 | 2576 | } |
| 2743 | 2577 | |
| 2744 | − profile->beacon_interval = beacon_interval; | |
| 2745 | − profile->dtim_period = dtim_period; | |
| 2746 | − | |
| 2747 | 2578 | update_bss_info_out: |
| 2748 | 2579 | WL_TRACE("Exit"); |
| 2749 | 2580 | return err; |
| @@ -2755,7 +2586,7 @@ static void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg) · 5 unmodified lines | ||
| 2755 | 2586 | struct escan_info *escan = &cfg->escan_info; |
| 2756 | 2587 | struct brcmf_ssid ssid; |
| 2757 | 2588 | |
| 2758 | − set_bit(WL_STATUS_SCAN_ABORTING, &cfg->status); | |
| 2589 | + set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status); | |
| 2759 | 2590 | if (cfg->iscan_on) { |
| 2760 | 2591 | iscan->state = WL_ISCAN_STATE_IDLE; |
| 2761 | 2592 | |
| @@ -2781,8 +2612,8 @@ static void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg) · 19 unmodified lines | ||
| 2781 | 2612 | escan->escan_state = WL_ESCAN_STATE_IDLE; |
| 2782 | 2613 | brcmf_notify_escan_complete(cfg, escan->ndev, true, true); |
| 2783 | 2614 | } |
| 2784 | − clear_bit(WL_STATUS_SCANNING, &cfg->status); | |
| 2785 | − clear_bit(WL_STATUS_SCAN_ABORTING, &cfg->status); | |
| 2615 | + clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | |
| 2616 | + clear_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status); | |
| 2786 | 2617 | } |
| 2787 | 2618 | |
| 2788 | 2619 | static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan, |
| @@ -2791,7 +2622,7 @@ static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan, · 2 unmodified lines | ||
| 2791 | 2622 | struct brcmf_cfg80211_info *cfg = iscan_to_cfg(iscan); |
| 2792 | 2623 | struct net_device *ndev = cfg_to_ndev(cfg); |
| 2793 | 2624 | |
| 2794 | − if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) { | |
| 2625 | + if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { | |
| 2795 | 2626 | WL_ERR("Scan complete while device not scanning\n"); |
| 2796 | 2627 | return; |
| 2797 | 2628 | } |
| @@ -2820,7 +2651,6 @@ static s32 · 22 unmodified lines | ||
| 2820 | 2651 | brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status, |
| 2821 | 2652 | struct brcmf_scan_results **bss_list) |
| 2822 | 2653 | { |
| 2823 | − struct brcmf_iscan_results list; | |
| 2824 | 2654 | struct brcmf_scan_results *results; |
| 2825 | 2655 | struct brcmf_scan_results_le *results_le; |
| 2826 | 2656 | struct brcmf_iscan_results *list_buf; |
| @@ -2830,15 +2660,13 @@ brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status, · 3 unmodified lines | ||
| 2830 | 2660 | list_buf = (struct brcmf_iscan_results *)iscan->scan_buf; |
| 2831 | 2661 | results = &list_buf->results; |
| 2832 | 2662 | results_le = &list_buf->results_le; |
| 2833 | − results->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE; | |
| 2834 | − results->version = 0; | |
| 2835 | − results->count = 0; | |
| 2663 | + results_le->buflen = cpu_to_le32(sizeof(iscan->scan_buf)); | |
| 2664 | + results_le->version = 0; | |
| 2665 | + results_le->count = 0; | |
| 2836 | 2666 | |
| 2837 | − memset(&list, 0, sizeof(list)); | |
| 2838 | − list.results_le.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX); | |
| 2839 | − err = brcmf_dev_iovar_getbuf(iscan->ndev, "iscanresults", &list, | |
| 2840 | − BRCMF_ISCAN_RESULTS_FIXED_SIZE, | |
| 2841 | − iscan->scan_buf, WL_ISCAN_BUF_MAX); | |
| 2667 | + err = brcmf_fil_iovar_data_get(netdev_priv(iscan->ndev), "iscanresults", | |
| 2668 | + iscan->scan_buf, | |
| 2669 | + sizeof(iscan->scan_buf)); | |
| 2842 | 2670 | if (err) { |
| 2843 | 2671 | WL_ERR("error (%d)\n", err); |
| 2844 | 2672 | return err; |
| @@ -3052,10 +2880,10 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg, · 207 unmodified lines | ||
| 3052 | 2880 | status = be32_to_cpu(e->status); |
| 3053 | 2881 | |
| 3054 | 2882 | if (!ndev || !cfg->escan_on || |
| 3055 | − !test_bit(WL_STATUS_SCANNING, &cfg->status)) { | |
| 2883 | + !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { | |
| 3056 | 2884 | WL_ERR("scan not ready ndev %p wl->escan_on %d drv_status %x\n", |
| 3057 | 2885 | ndev, cfg->escan_on, |
| 3058 | − !test_bit(WL_STATUS_SCANNING, &cfg->status)); | |
| 2886 | + !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)); | |
| 3059 | 2887 | return -EPERM; |
| 3060 | 2888 | } |
| 3061 | 2889 | |
| @@ -3159,16 +2987,17 @@ static __always_inline void brcmf_delay(u32 ms) · 97 unmodified lines | ||
| 3159 | 2987 | static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) |
| 3160 | 2988 | { |
| 3161 | 2989 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 2990 | + struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | |
| 3162 | 2991 | |
| 3163 | 2992 | /* |
| 3164 | − * Check for WL_STATUS_READY before any function call which | |
| 2993 | + * Check for BRCMF_VIF_STATUS_READY before any function call which | |
| 3165 | 2994 | * could result is bus access. Don't block the resume for |
| 3166 | 2995 | * any driver error conditions |
| 3167 | 2996 | */ |
| 3168 | 2997 | WL_TRACE("Enter\n"); |
| 3169 | 2998 | |
| 3170 | − if (test_bit(WL_STATUS_READY, &cfg->status)) | |
| 3171 | − brcmf_invoke_iscan(wiphy_to_cfg(wiphy)); | |
| 2999 | + if (check_vif_up(ifp->vif)) | |
| 3000 | + brcmf_invoke_iscan(cfg); | |
| 3172 | 3001 | |
| 3173 | 3002 | WL_TRACE("Exit\n"); |
| 3174 | 3003 | return 0; |
| @@ -3179,84 +3008,52 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, · 4 unmodified lines | ||
| 3179 | 3008 | { |
| 3180 | 3009 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 3181 | 3010 | struct net_device *ndev = cfg_to_ndev(cfg); |
| 3011 | + struct brcmf_cfg80211_vif *vif; | |
| 3182 | 3012 | |
| 3183 | 3013 | WL_TRACE("Enter\n"); |
| 3184 | 3014 | |
| 3185 | 3015 | /* |
| 3186 | − * Check for WL_STATUS_READY before any function call which | |
| 3187 | − * could result is bus access. Don't block the suspend for | |
| 3188 | − * any driver error conditions | |
| 3189 | − */ | |
| 3190 | − | |
| 3191 | − /* | |
| 3192 | − * While going to suspend if associated with AP disassociate | |
| 3193 | − * from AP to save power while system is in suspended state | |
| 3016 | + * if the primary net_device is not READY there is nothing | |
| 3017 | + * we can do but pray resume goes smoothly. | |
| 3194 | 3018 | */ |
| 3195 | − if ((test_bit(WL_STATUS_CONNECTED, &cfg->status) || | |
| 3196 | − test_bit(WL_STATUS_CONNECTING, &cfg->status)) && | |
| 3197 | − test_bit(WL_STATUS_READY, &cfg->status)) { | |
| 3198 | − WL_INFO("Disassociating from AP" | |
| 3199 | − " while entering suspend state\n"); | |
| 3200 | − brcmf_link_down(cfg); | |
| 3019 | + vif = ((struct brcmf_if *)netdev_priv(ndev))->vif; | |
| 3020 | + if (!check_vif_up(vif)) | |
| 3021 | + goto exit; | |
| 3201 | 3022 | |
| 3023 | + list_for_each_entry(vif, &cfg->vif_list, list) { | |
| 3024 | + if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state)) | |
| 3025 | + continue; | |
| 3202 | 3026 | /* |
| 3203 | − * Make sure WPA_Supplicant receives all the event | |
| 3204 | − * generated due to DISASSOC call to the fw to keep | |
| 3205 | − * the state fw and WPA_Supplicant state consistent | |
| 3027 | + * While going to suspend if associated with AP disassociate | |
| 3028 | + * from AP to save power while system is in suspended state | |
| 3206 | 3029 | */ |
| 3207 | − brcmf_delay(500); | |
| 3030 | + if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state) || | |
| 3031 | + test_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state)) { | |
| 3032 | + WL_INFO("Disassociating from AP before suspend\n"); | |
| 3033 | + brcmf_link_down(cfg); | |
| 3034 | + | |
| 3035 | + /* Make sure WPA_Supplicant receives all the event | |
| 3036 | + * generated due to DISASSOC call to the fw to keep | |
| 3037 | + * the state fw and WPA_Supplicant state consistent | |
| 3038 | + */ | |
| 3039 | + brcmf_delay(500); | |
| 3040 | + } | |
| 3208 | 3041 | } |
| 3209 | 3042 | |
| 3210 | − if (test_bit(WL_STATUS_READY, &cfg->status)) | |
| 3043 | + /* end any scanning */ | |
| 3044 | + if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) | |
| 3211 | 3045 | brcmf_abort_scanning(cfg); |
| 3212 | − else | |
| 3213 | − clear_bit(WL_STATUS_SCANNING, &cfg->status); | |
| 3214 | 3046 | |
| 3215 | 3047 | /* Turn off watchdog timer */ |
| 3216 | − if (test_bit(WL_STATUS_READY, &cfg->status)) | |
| 3217 | − brcmf_set_mpc(ndev, 1); | |
| 3048 | + brcmf_set_mpc(ndev, 1); | |
| 3218 | 3049 | |
| 3050 | +exit: | |
| 3219 | 3051 | WL_TRACE("Exit\n"); |
| 3220 | − | |
| 3052 | + /* clear any scanning activity */ | |
| 3053 | + cfg->scan_status = 0; | |
| 3221 | 3054 | return 0; |
| 3222 | 3055 | } |
| 3223 | 3056 | |
| 3224 | −static __used s32 | |
| 3225 | −brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len) | |
| 3226 | −{ | |
| 3227 | − struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | |
| 3228 | − u32 buflen; | |
| 3229 | − | |
| 3230 | − buflen = brcmf_c_mkiovar(name, buf, len, cfg->dcmd_buf, | |
| 3231 | − WL_DCMD_LEN_MAX); | |
| 3232 | − BUG_ON(!buflen); | |
| 3233 | − | |
| 3234 | − return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg->dcmd_buf, | |
| 3235 | − buflen); | |
| 3236 | −} | |
| 3237 | − | |
| 3238 | −static s32 | |
| 3239 | −brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf, | |
| 3240 | − s32 buf_len) | |
| 3241 | −{ | |
| 3242 | − struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | |
| 3243 | − u32 len; | |
| 3244 | − s32 err = 0; | |
| 3245 | − | |
| 3246 | − len = brcmf_c_mkiovar(name, NULL, 0, cfg->dcmd_buf, | |
| 3247 | − WL_DCMD_LEN_MAX); | |
| 3248 | − BUG_ON(!len); | |
| 3249 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg->dcmd_buf, | |
| 3250 | − WL_DCMD_LEN_MAX); | |
| 3251 | − if (err) { | |
| 3252 | − WL_ERR("error (%d)\n", err); | |
| 3253 | − return err; | |
| 3254 | − } | |
| 3255 | − memcpy(buf, cfg->dcmd_buf, buf_len); | |
| 3256 | − | |
| 3257 | − return err; | |
| 3258 | −} | |
| 3259 | − | |
| 3260 | 3057 | static __used s32 |
| 3261 | 3058 | brcmf_update_pmklist(struct net_device *ndev, |
| 3262 | 3059 | struct brcmf_cfg80211_pmk_list *pmk_list, s32 err) |
| @@ -3275,8 +3072,8 @@ brcmf_update_pmklist(struct net_device *ndev, · 12 unmodified lines | ||
| 3275 | 3072 | } |
| 3276 | 3073 | |
| 3277 | 3074 | if (!err) |
| 3278 | − brcmf_dev_bufvar_set(ndev, "pmkid_info", (char *)pmk_list, | |
| 3279 | − sizeof(*pmk_list)); | |
| 3075 | + brcmf_fil_iovar_data_set(netdev_priv(ndev), "pmkid_info", | |
| 3076 | + (char *)pmk_list, sizeof(*pmk_list)); | |
| 3280 | 3077 | |
| 3281 | 3078 | return err; |
| 3282 | 3079 | } |
| @@ -3286,13 +3083,14 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, · 3 unmodified lines | ||
| 3286 | 3083 | struct cfg80211_pmksa *pmksa) |
| 3287 | 3084 | { |
| 3288 | 3085 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 3086 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 3289 | 3087 | struct pmkid_list *pmkids = &cfg->pmk_list->pmkids; |
| 3290 | 3088 | s32 err = 0; |
| 3291 | 3089 | int i; |
| 3292 | 3090 | int pmkid_len; |
| 3293 | 3091 | |
| 3294 | 3092 | WL_TRACE("Enter\n"); |
| 3295 | − if (!check_sys_up(wiphy)) | |
| 3093 | + if (!check_vif_up(ifp->vif)) | |
| 3296 | 3094 | return -EIO; |
| 3297 | 3095 | |
| 3298 | 3096 | pmkid_len = le32_to_cpu(pmkids->npmkid); |
| @@ -3325,12 +3123,13 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, · 26 unmodified lines | ||
| 3325 | 3123 | struct cfg80211_pmksa *pmksa) |
| 3326 | 3124 | { |
| 3327 | 3125 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 3126 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 3328 | 3127 | struct pmkid_list pmkid; |
| 3329 | 3128 | s32 err = 0; |
| 3330 | 3129 | int i, pmkid_len; |
| 3331 | 3130 | |
| 3332 | 3131 | WL_TRACE("Enter\n"); |
| 3333 | − if (!check_sys_up(wiphy)) | |
| 3132 | + if (!check_vif_up(ifp->vif)) | |
| 3334 | 3133 | return -EIO; |
| 3335 | 3134 | |
| 3336 | 3135 | memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN); |
| @@ -3375,10 +3174,11 @@ static s32 · 38 unmodified lines | ||
| 3375 | 3174 | brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) |
| 3376 | 3175 | { |
| 3377 | 3176 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 3177 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 3378 | 3178 | s32 err = 0; |
| 3379 | 3179 | |
| 3380 | 3180 | WL_TRACE("Enter\n"); |
| 3381 | − if (!check_sys_up(wiphy)) | |
| 3181 | + if (!check_vif_up(ifp->vif)) | |
| 3382 | 3182 | return -EIO; |
| 3383 | 3183 | |
| 3384 | 3184 | memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list)); |
| @@ -3478,15 +3278,15 @@ brcmf_notify_sched_scan_results(struct brcmf_cfg80211_info *cfg, · 93 unmodified lines | ||
| 3478 | 3278 | if (request->n_ssids) |
| 3479 | 3279 | request->ssids = &ssid[0]; |
| 3480 | 3280 | |
| 3481 | − if (test_bit(WL_STATUS_SCANNING, &cfg->status)) { | |
| 3281 | + if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { | |
| 3482 | 3282 | /* Abort any on-going scan */ |
| 3483 | 3283 | brcmf_abort_scanning(cfg); |
| 3484 | 3284 | } |
| 3485 | 3285 | |
| 3486 | − set_bit(WL_STATUS_SCANNING, &cfg->status); | |
| 3286 | + set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | |
| 3487 | 3287 | err = brcmf_do_escan(cfg, wiphy, ndev, request); |
| 3488 | 3288 | if (err) { |
| 3489 | − clear_bit(WL_STATUS_SCANNING, &cfg->status); | |
| 3289 | + clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); | |
| 3490 | 3290 | goto out_err; |
| 3491 | 3291 | } |
| 3492 | 3292 | cfg->sched_escan = true; |
| @@ -3512,15 +3312,14 @@ out_err: · 19 unmodified lines | ||
| 3512 | 3312 | #ifndef CONFIG_BRCMISCAN |
| 3513 | 3313 | static int brcmf_dev_pno_clean(struct net_device *ndev) |
| 3514 | 3314 | { |
| 3515 | − char iovbuf[128]; | |
| 3516 | 3315 | int ret; |
| 3517 | 3316 | |
| 3518 | 3317 | /* Disable pfn */ |
| 3519 | − ret = brcmf_dev_intvar_set(ndev, "pfn", 0); | |
| 3318 | + ret = brcmf_fil_iovar_int_set(netdev_priv(ndev), "pfn", 0); | |
| 3520 | 3319 | if (ret == 0) { |
| 3521 | 3320 | /* clear pfn */ |
| 3522 | − ret = brcmf_dev_iovar_setbuf(ndev, "pfnclear", NULL, 0, | |
| 3523 | − iovbuf, sizeof(iovbuf)); | |
| 3321 | + ret = brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfnclear", | |
| 3322 | + NULL, 0); | |
| 3524 | 3323 | } |
| 3525 | 3324 | if (ret < 0) |
| 3526 | 3325 | WL_ERR("failed code %d\n", ret); |
| @@ -3531,7 +3330,6 @@ static int brcmf_dev_pno_clean(struct net_device *ndev) · 4 unmodified lines | ||
| 3531 | 3330 | static int brcmf_dev_pno_config(struct net_device *ndev) |
| 3532 | 3331 | { |
| 3533 | 3332 | struct brcmf_pno_param_le pfn_param; |
| 3534 | − char iovbuf[128]; | |
| 3535 | 3333 | |
| 3536 | 3334 | memset(&pfn_param, 0, sizeof(pfn_param)); |
| 3537 | 3335 | pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION); |
| @@ -3544,9 +3342,8 @@ static int brcmf_dev_pno_config(struct net_device *ndev) · 6 unmodified lines | ||
| 3544 | 3342 | /* set up pno scan fr */ |
| 3545 | 3343 | pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME); |
| 3546 | 3344 | |
| 3547 | − return brcmf_dev_iovar_setbuf(ndev, "pfn_set", | |
| 3548 | − &pfn_param, sizeof(pfn_param), | |
| 3549 | − iovbuf, sizeof(iovbuf)); | |
| 3345 | + return brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfn_set", | |
| 3346 | + &pfn_param, sizeof(pfn_param)); | |
| 3550 | 3347 | } |
| 3551 | 3348 | |
| 3552 | 3349 | static int |
| @@ -3554,7 +3351,7 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, · 1 unmodified line | ||
| 3554 | 3351 | struct net_device *ndev, |
| 3555 | 3352 | struct cfg80211_sched_scan_request *request) |
| 3556 | 3353 | { |
| 3557 | − char iovbuf[128]; | |
| 3354 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 3558 | 3355 | struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); |
| 3559 | 3356 | struct brcmf_pno_net_param_le pfn; |
| 3560 | 3357 | int i; |
| @@ -3562,8 +3359,8 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, · 1 unmodified line | ||
| 3562 | 3359 | |
| 3563 | 3360 | WL_SCAN("Enter n_match_sets:%d n_ssids:%d\n", |
| 3564 | 3361 | request->n_match_sets, request->n_ssids); |
| 3565 | − if (test_bit(WL_STATUS_SCANNING, &cfg->status)) { | |
| 3566 | − WL_ERR("Scanning already : status (%lu)\n", cfg->status); | |
| 3362 | + if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { | |
| 3363 | + WL_ERR("Scanning already: status (%lu)\n", cfg->scan_status); | |
| 3567 | 3364 | return -EAGAIN; |
| 3568 | 3365 | } |
| 3569 | 3366 | |
| @@ -3620,15 +3417,14 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, · 50 unmodified lines | ||
| 3620 | 3417 | pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT); |
| 3621 | 3418 | pfn.ssid.SSID_len = cpu_to_le32(ssid_len); |
| 3622 | 3419 | memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len); |
| 3623 | − ret = brcmf_dev_iovar_setbuf(ndev, "pfn_add", | |
| 3624 | − &pfn, sizeof(pfn), | |
| 3625 | − iovbuf, sizeof(iovbuf)); | |
| 3420 | + ret = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, | |
| 3421 | + sizeof(pfn)); | |
| 3626 | 3422 | WL_SCAN(">>> PNO filter %s for ssid (%s)\n", |
| 3627 | 3423 | ret == 0 ? "set" : "failed", |
| 3628 | 3424 | ssid->ssid); |
| 3629 | 3425 | } |
| 3630 | 3426 | /* Enable the PNO */ |
| 3631 | − if (brcmf_dev_intvar_set(ndev, "pfn", 1) < 0) { | |
| 3427 | + if (brcmf_fil_iovar_int_set(ifp, "pfn", 1) < 0) { | |
| 3632 | 3428 | WL_ERR("PNO enable failed!! ret=%d\n", ret); |
| 3633 | 3429 | return -EINVAL; |
| 3634 | 3430 | } |
| @@ -3656,12 +3452,20 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy, · 21 unmodified lines | ||
| 3656 | 3452 | static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len) |
| 3657 | 3453 | { |
| 3658 | 3454 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 3659 | − struct net_device *ndev = cfg->wdev->netdev; | |
| 3455 | + struct net_device *ndev = cfg_to_ndev(cfg); | |
| 3660 | 3456 | struct brcmf_dcmd *dcmd = data; |
| 3661 | 3457 | struct sk_buff *reply; |
| 3662 | 3458 | int ret; |
| 3663 | 3459 | |
| 3664 | − ret = brcmf_netlink_dcmd(ndev, dcmd); | |
| 3460 | + WL_TRACE("cmd %x set %d buf %p len %d\n", dcmd->cmd, dcmd->set, | |
| 3461 | + dcmd->buf, dcmd->len); | |
| 3462 | + | |
| 3463 | + if (dcmd->set) | |
| 3464 | + ret = brcmf_fil_cmd_data_set(netdev_priv(ndev), dcmd->cmd, | |
| 3465 | + dcmd->buf, dcmd->len); | |
| 3466 | + else | |
| 3467 | + ret = brcmf_fil_cmd_data_get(netdev_priv(ndev), dcmd->cmd, | |
| 3468 | + dcmd->buf, dcmd->len); | |
| 3665 | 3469 | if (ret == 0) { |
| 3666 | 3470 | reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*dcmd)); |
| 3667 | 3471 | nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*dcmd), dcmd); |
| @@ -3673,23 +3477,23 @@ static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len) · 5 unmodified lines | ||
| 3673 | 3477 | |
| 3674 | 3478 | static s32 brcmf_configure_opensecurity(struct net_device *ndev, s32 bssidx) |
| 3675 | 3479 | { |
| 3480 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 3676 | 3481 | s32 err; |
| 3677 | 3482 | |
| 3678 | 3483 | /* set auth */ |
| 3679 | − err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", 0, bssidx); | |
| 3484 | + err = brcmf_fil_bsscfg_int_set(ifp, "auth", 0); | |
| 3680 | 3485 | if (err < 0) { |
| 3681 | 3486 | WL_ERR("auth error %d\n", err); |
| 3682 | 3487 | return err; |
| 3683 | 3488 | } |
| 3684 | 3489 | /* set wsec */ |
| 3685 | − err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", 0, bssidx); | |
| 3490 | + err = brcmf_fil_bsscfg_int_set(ifp, "wsec", 0); | |
| 3686 | 3491 | if (err < 0) { |
| 3687 | 3492 | WL_ERR("wsec error %d\n", err); |
| 3688 | 3493 | return err; |
| 3689 | 3494 | } |
| 3690 | 3495 | /* set upper-layer auth */ |
| 3691 | − err = brcmf_dev_intvar_set_bsscfg(ndev, "wpa_auth", | |
| 3692 | − WPA_AUTH_NONE, bssidx); | |
| 3496 | + err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", WPA_AUTH_NONE); | |
| 3693 | 3497 | if (err < 0) { |
| 3694 | 3498 | WL_ERR("wpa_auth error %d\n", err); |
| 3695 | 3499 | return err; |
| @@ -3710,6 +3514,7 @@ static s32 · 14 unmodified lines | ||
| 3710 | 3514 | brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie, |
| 3711 | 3515 | bool is_rsn_ie, s32 bssidx) |
| 3712 | 3516 | { |
| 3517 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 3713 | 3518 | u32 auth = 0; /* d11 open authentication */ |
| 3714 | 3519 | u16 count; |
| 3715 | 3520 | s32 err = 0; |
| @@ -3850,8 +3655,8 @@ brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie, · 134 unmodified lines | ||
| 3850 | 3655 | wme_bss_disable = 0; |
| 3851 | 3656 | } |
| 3852 | 3657 | /* set wme_bss_disable to sync RSN Capabilities */ |
| 3853 | − err = brcmf_dev_intvar_set_bsscfg(ndev, "wme_bss_disable", | |
| 3854 | − wme_bss_disable, bssidx); | |
| 3658 | + err = brcmf_fil_bsscfg_int_set(ifp, "wme_bss_disable", | |
| 3659 | + wme_bss_disable); | |
| 3855 | 3660 | if (err < 0) { |
| 3856 | 3661 | WL_ERR("wme_bss_disable error %d\n", err); |
| 3857 | 3662 | goto exit; |
| @@ -3861,19 +3666,19 @@ brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie, · 3 unmodified lines | ||
| 3861 | 3666 | wsec = (pval | gval | SES_OW_ENABLED); |
| 3862 | 3667 | |
| 3863 | 3668 | /* set auth */ |
| 3864 | − err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", auth, bssidx); | |
| 3669 | + err = brcmf_fil_bsscfg_int_set(ifp, "auth", auth); | |
| 3865 | 3670 | if (err < 0) { |
| 3866 | 3671 | WL_ERR("auth error %d\n", err); |
| 3867 | 3672 | goto exit; |
| 3868 | 3673 | } |
| 3869 | 3674 | /* set wsec */ |
| 3870 | − err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", wsec, bssidx); | |
| 3675 | + err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec); | |
| 3871 | 3676 | if (err < 0) { |
| 3872 | 3677 | WL_ERR("wsec error %d\n", err); |
| 3873 | 3678 | goto exit; |
| 3874 | 3679 | } |
| 3875 | 3680 | /* set upper-layer auth */ |
| 3876 | − err = brcmf_dev_intvar_set_bsscfg(ndev, "wpa_auth", wpa_auth, bssidx); | |
| 3681 | + err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_auth); | |
| 3877 | 3682 | if (err < 0) { |
| 3878 | 3683 | WL_ERR("wpa_auth error %d\n", err); |
| 3879 | 3684 | goto exit; |
| @@ -3963,17 +3768,19 @@ brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd) · 83 unmodified lines | ||
| 3963 | 3768 | return ie_len + VNDR_IE_HDR_SIZE; |
| 3964 | 3769 | } |
| 3965 | 3770 | |
| 3966 | −s32 | |
| 3771 | +static s32 | |
| 3967 | 3772 | brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg, |
| 3968 | − struct net_device *ndev, s32 bssidx, s32 pktflag, | |
| 3773 | + struct net_device *ndev, s32 pktflag, | |
| 3969 | 3774 | u8 *vndr_ie_buf, u32 vndr_ie_len) |
| 3970 | 3775 | { |
| 3776 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 3777 | + struct vif_saved_ie *saved_ie = &ifp->vif->saved_ie; | |
| 3971 | 3778 | s32 err = 0; |
| 3972 | 3779 | u8 *iovar_ie_buf; |
| 3973 | 3780 | u8 *curr_ie_buf; |
| 3974 | 3781 | u8 *mgmt_ie_buf = NULL; |
| 3975 | 3782 | int mgmt_ie_buf_len; |
| 3976 | − u32 *mgmt_ie_len = 0; | |
| 3783 | + u32 *mgmt_ie_len; | |
| 3977 | 3784 | u32 del_add_ie_buf_len = 0; |
| 3978 | 3785 | u32 total_ie_buf_len = 0; |
| 3979 | 3786 | u32 parsed_ie_buf_len = 0; |
| @@ -3984,31 +3791,29 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg, · 4 unmodified lines | ||
| 3984 | 3791 | u8 *ptr; |
| 3985 | 3792 | int remained_buf_len; |
| 3986 | 3793 | |
| 3987 | − WL_TRACE("bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag); | |
| 3794 | + WL_TRACE("bssidx %d, pktflag : 0x%02X\n", | |
| 3795 | + brcmf_ndev_bssidx(ndev), pktflag); | |
| 3988 | 3796 | iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); |
| 3989 | 3797 | if (!iovar_ie_buf) |
| 3990 | 3798 | return -ENOMEM; |
| 3991 | 3799 | curr_ie_buf = iovar_ie_buf; |
| 3992 | − if (test_bit(WL_STATUS_AP_CREATING, &cfg->status) || | |
| 3993 | − test_bit(WL_STATUS_AP_CREATED, &cfg->status)) { | |
| 3800 | + if (ifp->vif->mode == WL_MODE_AP) { | |
| 3994 | 3801 | switch (pktflag) { |
| 3995 | 3802 | case VNDR_IE_PRBRSP_FLAG: |
| 3996 | − mgmt_ie_buf = cfg->ap_info->probe_res_ie; | |
| 3997 | − mgmt_ie_len = &cfg->ap_info->probe_res_ie_len; | |
| 3998 | − mgmt_ie_buf_len = | |
| 3999 | − sizeof(cfg->ap_info->probe_res_ie); | |
| 3803 | + mgmt_ie_buf = saved_ie->probe_res_ie; | |
| 3804 | + mgmt_ie_len = &saved_ie->probe_res_ie_len; | |
| 3805 | + mgmt_ie_buf_len = sizeof(saved_ie->probe_res_ie); | |
| 4000 | 3806 | break; |
| 4001 | 3807 | case VNDR_IE_BEACON_FLAG: |
| 4002 | − mgmt_ie_buf = cfg->ap_info->beacon_ie; | |
| 4003 | − mgmt_ie_len = &cfg->ap_info->beacon_ie_len; | |
| 4004 | − mgmt_ie_buf_len = sizeof(cfg->ap_info->beacon_ie); | |
| 3808 | + mgmt_ie_buf = saved_ie->beacon_ie; | |
| 3809 | + mgmt_ie_len = &saved_ie->beacon_ie_len; | |
| 3810 | + mgmt_ie_buf_len = sizeof(saved_ie->beacon_ie); | |
| 4005 | 3811 | break; |
| 4006 | 3812 | default: |
| 4007 | 3813 | err = -EPERM; |
| 4008 | 3814 | WL_ERR("not suitable type\n"); |
| 4009 | 3815 | goto exit; |
| 4010 | 3816 | } |
| 4011 | − bssidx = 0; | |
| 4012 | 3817 | } else { |
| 4013 | 3818 | err = -EPERM; |
| 4014 | 3819 | WL_ERR("not suitable type\n"); |
| @@ -4104,11 +3909,8 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg, · 89 unmodified lines | ||
| 4104 | 3909 | } |
| 4105 | 3910 | } |
| 4106 | 3911 | if (total_ie_buf_len) { |
| 4107 | − err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "vndr_ie", | |
| 4108 | − iovar_ie_buf, | |
| 4109 | − total_ie_buf_len, | |
| 4110 | − cfg->extra_buf, | |
| 4111 | − WL_EXTRA_BUF_MAX, bssidx); | |
| 3912 | + err = brcmf_fil_bsscfg_data_set(ifp, "vndr_ie", iovar_ie_buf, | |
| 3913 | + total_ie_buf_len); | |
| 4112 | 3914 | if (err) |
| 4113 | 3915 | WL_ERR("vndr ie set error : %d\n", err); |
| 4114 | 3916 | } |
| @@ -4123,9 +3925,9 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, · 8 unmodified lines | ||
| 4123 | 3925 | struct cfg80211_ap_settings *settings) |
| 4124 | 3926 | { |
| 4125 | 3927 | s32 ie_offset; |
| 3928 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 4126 | 3929 | struct brcmf_tlv *ssid_ie; |
| 4127 | 3930 | struct brcmf_ssid_le ssid_le; |
| 4128 | − s32 ioctl_value; | |
| 4129 | 3931 | s32 err = -EPERM; |
| 4130 | 3932 | struct brcmf_tlv *rsn_ie; |
| 4131 | 3933 | struct brcmf_vs_tlv *wpa_ie; |
| @@ -4140,7 +3942,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, · 8 unmodified lines | ||
| 4140 | 3942 | settings->ssid, settings->ssid_len, settings->auth_type, |
| 4141 | 3943 | settings->inactivity_timeout); |
| 4142 | 3944 | |
| 4143 | − if (!test_bit(WL_STATUS_AP_CREATING, &cfg->status)) { | |
| 3945 | + if (!test_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state)) { | |
| 4144 | 3946 | WL_ERR("Not in AP creation mode\n"); |
| 4145 | 3947 | return -EPERM; |
| 4146 | 3948 | } |
| @@ -4164,20 +3966,17 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, · 17 unmodified lines | ||
| 4164 | 3966 | } |
| 4165 | 3967 | |
| 4166 | 3968 | brcmf_set_mpc(ndev, 0); |
| 4167 | − ioctl_value = 1; | |
| 4168 | − err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_DOWN, &ioctl_value); | |
| 3969 | + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); | |
| 4169 | 3970 | if (err < 0) { |
| 4170 | 3971 | WL_ERR("BRCMF_C_DOWN error %d\n", err); |
| 4171 | 3972 | goto exit; |
| 4172 | 3973 | } |
| 4173 | − ioctl_value = 1; | |
| 4174 | − err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &ioctl_value); | |
| 3974 | + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1); | |
| 4175 | 3975 | if (err < 0) { |
| 4176 | 3976 | WL_ERR("SET INFRA error %d\n", err); |
| 4177 | 3977 | goto exit; |
| 4178 | 3978 | } |
| 4179 | − ioctl_value = 1; | |
| 4180 | − err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AP, &ioctl_value); | |
| 3979 | + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1); | |
| 4181 | 3980 | if (err < 0) { |
| 4182 | 3981 | WL_ERR("setting AP mode failed %d\n", err); |
| 4183 | 3982 | goto exit; |
| @@ -4226,7 +4025,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, · 42 unmodified lines | ||
| 4226 | 4025 | cfg->ap_info->security_mode = false; |
| 4227 | 4026 | } |
| 4228 | 4027 | /* Set Beacon IEs to FW */ |
| 4229 | − err = brcmf_set_management_ie(cfg, ndev, bssidx, | |
| 4028 | + err = brcmf_set_management_ie(cfg, ndev, | |
| 4230 | 4029 | VNDR_IE_BEACON_FLAG, |
| 4231 | 4030 | (u8 *)settings->beacon.tail, |
| 4232 | 4031 | settings->beacon.tail_len); |
| @@ -4236,7 +4035,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, · 3 unmodified lines | ||
| 4236 | 4035 | WL_TRACE("Applied Vndr IEs for Beacon\n"); |
| 4237 | 4036 | |
| 4238 | 4037 | /* Set Probe Response IEs to FW */ |
| 4239 | − err = brcmf_set_management_ie(cfg, ndev, bssidx, | |
| 4038 | + err = brcmf_set_management_ie(cfg, ndev, | |
| 4240 | 4039 | VNDR_IE_PRBRSP_FLAG, |
| 4241 | 4040 | (u8 *)settings->beacon.proberesp_ies, |
| 4242 | 4041 | settings->beacon.proberesp_ies_len); |
| @@ -4246,25 +4045,22 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, · 3 unmodified lines | ||
| 4246 | 4045 | WL_TRACE("Applied Vndr IEs for Probe Resp\n"); |
| 4247 | 4046 | |
| 4248 | 4047 | if (settings->beacon_interval) { |
| 4249 | − ioctl_value = settings->beacon_interval; | |
| 4250 | − err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_BCNPRD, | |
| 4251 | − &ioctl_value); | |
| 4048 | + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD, | |
| 4049 | + settings->beacon_interval); | |
| 4252 | 4050 | if (err < 0) { |
| 4253 | 4051 | WL_ERR("Beacon Interval Set Error, %d\n", err); |
| 4254 | 4052 | goto exit; |
| 4255 | 4053 | } |
| 4256 | 4054 | } |
| 4257 | 4055 | if (settings->dtim_period) { |
| 4258 | − ioctl_value = settings->dtim_period; | |
| 4259 | − err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_DTIMPRD, | |
| 4260 | − &ioctl_value); | |
| 4056 | + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_DTIMPRD, | |
| 4057 | + settings->dtim_period); | |
| 4261 | 4058 | if (err < 0) { |
| 4262 | 4059 | WL_ERR("DTIM Interval Set Error, %d\n", err); |
| 4263 | 4060 | goto exit; |
| 4264 | 4061 | } |
| 4265 | 4062 | } |
| 4266 | − ioctl_value = 1; | |
| 4267 | − err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_UP, &ioctl_value); | |
| 4063 | + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1); | |
| 4268 | 4064 | if (err < 0) { |
| 4269 | 4065 | WL_ERR("BRCMF_C_UP error (%d)\n", err); |
| 4270 | 4066 | goto exit; |
| @@ -4274,14 +4070,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, · 3 unmodified lines | ||
| 4274 | 4070 | /* join parameters starts with ssid */ |
| 4275 | 4071 | memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le)); |
| 4276 | 4072 | /* create softap */ |
| 4277 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, &join_params, | |
| 4278 | − sizeof(join_params)); | |
| 4073 | + err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, | |
| 4074 | + &join_params, sizeof(join_params)); | |
| 4279 | 4075 | if (err < 0) { |
| 4280 | 4076 | WL_ERR("SET SSID error (%d)\n", err); |
| 4281 | 4077 | goto exit; |
| 4282 | 4078 | } |
| 4283 | − clear_bit(WL_STATUS_AP_CREATING, &cfg->status); | |
| 4284 | − set_bit(WL_STATUS_AP_CREATED, &cfg->status); | |
| 4079 | + clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); | |
| 4080 | + set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); | |
| 4285 | 4081 | |
| 4286 | 4082 | exit: |
| 4287 | 4083 | if (err) |
| @@ -4291,8 +4087,8 @@ exit: · 3 unmodified lines | ||
| 4291 | 4087 | |
| 4292 | 4088 | static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) |
| 4293 | 4089 | { |
| 4090 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 4294 | 4091 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
| 4295 | − s32 ioctl_value; | |
| 4296 | 4092 | s32 err = -EPERM; |
| 4297 | 4093 | |
| 4298 | 4094 | WL_TRACE("Enter\n"); |
| @@ -4301,21 +4097,20 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) · 2 unmodified lines | ||
| 4301 | 4097 | /* Due to most likely deauths outstanding we sleep */ |
| 4302 | 4098 | /* first to make sure they get processed by fw. */ |
| 4303 | 4099 | msleep(400); |
| 4304 | − ioctl_value = 0; | |
| 4305 | − err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AP, &ioctl_value); | |
| 4100 | + err = brcmf_fil_cmd_int_set(netdev_priv(ndev), | |
| 4101 | + BRCMF_C_SET_AP, 0); | |
| 4306 | 4102 | if (err < 0) { |
| 4307 | 4103 | WL_ERR("setting AP mode failed %d\n", err); |
| 4308 | 4104 | goto exit; |
| 4309 | 4105 | } |
| 4310 | − ioctl_value = 0; | |
| 4311 | − err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_UP, &ioctl_value); | |
| 4106 | + err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_UP, 0); | |
| 4312 | 4107 | if (err < 0) { |
| 4313 | 4108 | WL_ERR("BRCMF_C_UP error %d\n", err); |
| 4314 | 4109 | goto exit; |
| 4315 | 4110 | } |
| 4316 | 4111 | brcmf_set_mpc(ndev, 1); |
| 4317 | − clear_bit(WL_STATUS_AP_CREATING, &cfg->status); | |
| 4318 | − clear_bit(WL_STATUS_AP_CREATED, &cfg->status); | |
| 4112 | + clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); | |
| 4113 | + clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); | |
| 4319 | 4114 | } |
| 4320 | 4115 | exit: |
| 4321 | 4116 | return err; |
| @@ -4326,6 +4121,7 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, · 4 unmodified lines | ||
| 4326 | 4121 | u8 *mac) |
| 4327 | 4122 | { |
| 4328 | 4123 | struct brcmf_scb_val_le scbval; |
| 4124 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 4329 | 4125 | s32 err; |
| 4330 | 4126 | |
| 4331 | 4127 | if (!mac) |
| @@ -4333,13 +4129,13 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, · 1 unmodified line | ||
| 4333 | 4129 | |
| 4334 | 4130 | WL_TRACE("Enter %pM\n", mac); |
| 4335 | 4131 | |
| 4336 | − if (!check_sys_up(wiphy)) | |
| 4132 | + if (!check_vif_up(ifp->vif)) | |
| 4337 | 4133 | return -EIO; |
| 4338 | 4134 | |
| 4339 | 4135 | memcpy(&scbval.ea, mac, ETH_ALEN); |
| 4340 | 4136 | scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING); |
| 4341 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON, | |
| 4342 | − &scbval, sizeof(scbval)); | |
| 4137 | + err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON, | |
| 4138 | + &scbval, sizeof(scbval)); | |
| 4343 | 4139 | if (err) |
| 4344 | 4140 | WL_ERR("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err); |
| 4345 | 4141 | |
| @@ -4410,72 +4206,97 @@ static void brcmf_wiphy_pno_params(struct wiphy *wiphy) · 64 unmodified lines | ||
| 4410 | 4206 | #endif |
| 4411 | 4207 | } |
| 4412 | 4208 | |
| 4413 | −static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev) | |
| 4209 | +static struct wiphy *brcmf_setup_wiphy(struct device *phydev) | |
| 4414 | 4210 | { |
| 4415 | − struct wireless_dev *wdev; | |
| 4211 | + struct wiphy *wiphy; | |
| 4416 | 4212 | s32 err = 0; |
| 4417 | 4213 | |
| 4418 | − wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); | |
| 4419 | − if (!wdev) | |
| 4420 | − return ERR_PTR(-ENOMEM); | |
| 4421 | − | |
| 4422 | − wdev->wiphy = wiphy_new(&wl_cfg80211_ops, | |
| 4423 | − sizeof(struct brcmf_cfg80211_info)); | |
| 4424 | − if (!wdev->wiphy) { | |
| 4214 | + wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info)); | |
| 4215 | + if (!wiphy) { | |
| 4425 | 4216 | WL_ERR("Could not allocate wiphy device\n"); |
| 4426 | − err = -ENOMEM; | |
| 4427 | − goto wiphy_new_out; | |
| 4428 | − } | |
| 4429 | − set_wiphy_dev(wdev->wiphy, ndev); | |
| 4430 | − wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; | |
| 4431 | − wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; | |
| 4432 | − wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | |
| 4433 | − BIT(NL80211_IFTYPE_ADHOC) | | |
| 4434 | − BIT(NL80211_IFTYPE_AP); | |
| 4435 | − wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; | |
| 4436 | − wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set | |
| 4217 | + return ERR_PTR(-ENOMEM); | |
| 4218 | + } | |
| 4219 | + set_wiphy_dev(wiphy, phydev); | |
| 4220 | + wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; | |
| 4221 | + wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; | |
| 4222 | + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | |
| 4223 | + BIT(NL80211_IFTYPE_ADHOC) | | |
| 4224 | + BIT(NL80211_IFTYPE_AP); | |
| 4225 | + wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; | |
| 4226 | + wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set | |
| 4437 | 4227 | * it as 11a by default. |
| 4438 | 4228 | * This will be updated with |
| 4439 | 4229 | * 11n phy tables in |
| 4440 | 4230 | * "ifconfig up" |
| 4441 | 4231 | * if phy has 11n capability |
| 4442 | 4232 | */ |
| 4443 | − wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | |
| 4444 | − wdev->wiphy->cipher_suites = __wl_cipher_suites; | |
| 4445 | − wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); | |
| 4446 | − wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power | |
| 4233 | + wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | |
| 4234 | + wiphy->cipher_suites = __wl_cipher_suites; | |
| 4235 | + wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); | |
| 4236 | + wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power | |
| 4447 | 4237 | * save mode |
| 4448 | 4238 | * by default |
| 4449 | 4239 | */ |
| 4450 | − brcmf_wiphy_pno_params(wdev->wiphy); | |
| 4451 | − err = wiphy_register(wdev->wiphy); | |
| 4240 | + brcmf_wiphy_pno_params(wiphy); | |
| 4241 | + err = wiphy_register(wiphy); | |
| 4452 | 4242 | if (err < 0) { |
| 4453 | 4243 | WL_ERR("Could not register wiphy device (%d)\n", err); |
| 4454 | − goto wiphy_register_out; | |
| 4244 | + wiphy_free(wiphy); | |
| 4245 | + return ERR_PTR(err); | |
| 4246 | + } | |
| 4247 | + return wiphy; | |
| 4248 | +} | |
| 4249 | + | |
| 4250 | +static | |
| 4251 | +struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, | |
| 4252 | + struct net_device *netdev, | |
| 4253 | + s32 mode, bool pm_block) | |
| 4254 | +{ | |
| 4255 | + struct brcmf_cfg80211_vif *vif; | |
| 4256 | + | |
| 4257 | + if (cfg->vif_cnt == BRCMF_IFACE_MAX_CNT) | |
| 4258 | + return ERR_PTR(-ENOSPC); | |
| 4259 | + | |
| 4260 | + vif = kzalloc(sizeof(*vif), GFP_KERNEL); | |
| 4261 | + if (!vif) | |
| 4262 | + return ERR_PTR(-ENOMEM); | |
| 4263 | + | |
| 4264 | + vif->wdev.wiphy = cfg->wiphy; | |
| 4265 | + vif->wdev.netdev = netdev; | |
| 4266 | + vif->wdev.iftype = brcmf_mode_to_nl80211_iftype(mode); | |
| 4267 | + | |
| 4268 | + if (netdev) { | |
| 4269 | + vif->ifp = netdev_priv(netdev); | |
| 4270 | + netdev->ieee80211_ptr = &vif->wdev; | |
| 4271 | + SET_NETDEV_DEV(netdev, wiphy_dev(cfg->wiphy)); | |
| 4455 | 4272 | } |
| 4456 | − return wdev; | |
| 4457 | 4273 | |
| 4458 | −wiphy_register_out: | |
| 4459 | − wiphy_free(wdev->wiphy); | |
| 4274 | + vif->mode = mode; | |
| 4275 | + vif->pm_block = pm_block; | |
| 4276 | + vif->roam_off = -1; | |
| 4460 | 4277 | |
| 4461 | −wiphy_new_out: | |
| 4462 | − kfree(wdev); | |
| 4278 | + brcmf_init_prof(&vif->profile); | |
| 4463 | 4279 | |
| 4464 | − return ERR_PTR(err); | |
| 4280 | + list_add_tail(&vif->list, &cfg->vif_list); | |
| 4281 | + cfg->vif_cnt++; | |
| 4282 | + return vif; | |
| 4465 | 4283 | } |
| 4466 | 4284 | |
| 4467 | −static void brcmf_free_wdev(struct brcmf_cfg80211_info *cfg) | |
| 4285 | +static void brcmf_free_vif(struct brcmf_cfg80211_vif *vif) | |
| 4468 | 4286 | { |
| 4469 | − struct wireless_dev *wdev = cfg->wdev; | |
| 4287 | + struct brcmf_cfg80211_info *cfg; | |
| 4288 | + struct wiphy *wiphy; | |
| 4470 | 4289 | |
| 4471 | − if (!wdev) { | |
| 4472 | − WL_ERR("wdev is invalid\n"); | |
| 4473 | − return; | |
| 4290 | + wiphy = vif->wdev.wiphy; | |
| 4291 | + cfg = wiphy_priv(wiphy); | |
| 4292 | + list_del(&vif->list); | |
| 4293 | + cfg->vif_cnt--; | |
| 4294 | + | |
| 4295 | + kfree(vif); | |
| 4296 | + if (!cfg->vif_cnt) { | |
| 4297 | + wiphy_unregister(wiphy); | |
| 4298 | + wiphy_free(wiphy); | |
| 4474 | 4299 | } |
| 4475 | − wiphy_unregister(wdev->wiphy); | |
| 4476 | − wiphy_free(wdev->wiphy); | |
| 4477 | − kfree(wdev); | |
| 4478 | − cfg->wdev = NULL; | |
| 4479 | 4300 | } |
| 4480 | 4301 | |
| 4481 | 4302 | static bool brcmf_is_linkup(struct brcmf_cfg80211_info *cfg, |
| @@ -4541,7 +4362,7 @@ static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg) · 59 unmodified lines | ||
| 4541 | 4362 | |
| 4542 | 4363 | static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg) |
| 4543 | 4364 | { |
| 4544 | − struct net_device *ndev = cfg_to_ndev(cfg); | |
| 4365 | + struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | |
| 4545 | 4366 | struct brcmf_cfg80211_assoc_ielen_le *assoc_info; |
| 4546 | 4367 | struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); |
| 4547 | 4368 | u32 req_len; |
| @@ -4550,8 +4371,8 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg) · 2 unmodified lines | ||
| 4550 | 4371 | |
| 4551 | 4372 | brcmf_clear_assoc_ies(cfg); |
| 4552 | 4373 | |
| 4553 | − err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg->extra_buf, | |
| 4554 | − WL_ASSOC_INFO_MAX); | |
| 4374 | + err = brcmf_fil_iovar_data_get(ifp, "assoc_info", | |
| 4375 | + cfg->extra_buf, WL_ASSOC_INFO_MAX); | |
| 4555 | 4376 | if (err) { |
| 4556 | 4377 | WL_ERR("could not get assoc info (%d)\n", err); |
| 4557 | 4378 | return err; |
| @@ -4561,9 +4382,9 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg) · 3 unmodified lines | ||
| 4561 | 4382 | req_len = le32_to_cpu(assoc_info->req_len); |
| 4562 | 4383 | resp_len = le32_to_cpu(assoc_info->resp_len); |
| 4563 | 4384 | if (req_len) { |
| 4564 | − err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies", | |
| 4565 | − cfg->extra_buf, | |
| 4566 | − WL_ASSOC_INFO_MAX); | |
| 4385 | + err = brcmf_fil_iovar_data_get(ifp, "assoc_req_ies", | |
| 4386 | + cfg->extra_buf, | |
| 4387 | + WL_ASSOC_INFO_MAX); | |
| 4567 | 4388 | if (err) { |
| 4568 | 4389 | WL_ERR("could not get assoc req (%d)\n", err); |
| 4569 | 4390 | return err; |
| @@ -4577,9 +4398,9 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg) · 7 unmodified lines | ||
| 4577 | 4398 | conn_info->req_ie = NULL; |
| 4578 | 4399 | } |
| 4579 | 4400 | if (resp_len) { |
| 4580 | − err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies", | |
| 4581 | − cfg->extra_buf, | |
| 4582 | − WL_ASSOC_INFO_MAX); | |
| 4401 | + err = brcmf_fil_iovar_data_get(ifp, "assoc_resp_ies", | |
| 4402 | + cfg->extra_buf, | |
| 4403 | + WL_ASSOC_INFO_MAX); | |
| 4583 | 4404 | if (err) { |
| 4584 | 4405 | WL_ERR("could not get assoc resp (%d)\n", err); |
| 4585 | 4406 | return err; |
| @@ -4603,7 +4424,8 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, · 17 unmodified lines | ||
| 4603 | 4424 | struct net_device *ndev, |
| 4604 | 4425 | const struct brcmf_event_msg *e) |
| 4605 | 4426 | { |
| 4606 | − struct brcmf_cfg80211_profile *profile = cfg->profile; | |
| 4427 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 4428 | + struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | |
| 4607 | 4429 | struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); |
| 4608 | 4430 | struct wiphy *wiphy = cfg_to_wiphy(cfg); |
| 4609 | 4431 | struct ieee80211_channel *notify_channel = NULL; |
| @@ -4628,7 +4450,8 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, · 18 unmodified lines | ||
| 4628 | 4450 | |
| 4629 | 4451 | /* data sent to dongle has to be little endian */ |
| 4630 | 4452 | *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX); |
| 4631 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX); | |
| 4453 | + err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, | |
| 4454 | + buf, WL_BSS_INFO_MAX); | |
| 4632 | 4455 | |
| 4633 | 4456 | if (err) |
| 4634 | 4457 | goto done; |
| @@ -4652,7 +4475,7 @@ done: · 17 unmodified lines | ||
| 4652 | 4475 | conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); |
| 4653 | 4476 | WL_CONN("Report roaming result\n"); |
| 4654 | 4477 | |
| 4655 | − set_bit(WL_STATUS_CONNECTED, &cfg->status); | |
| 4478 | + set_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state); | |
| 4656 | 4479 | WL_TRACE("Exit\n"); |
| 4657 | 4480 | return err; |
| 4658 | 4481 | } |
| @@ -4662,13 +4485,15 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg, · 3 unmodified lines | ||
| 4662 | 4485 | struct net_device *ndev, const struct brcmf_event_msg *e, |
| 4663 | 4486 | bool completed) |
| 4664 | 4487 | { |
| 4665 | − struct brcmf_cfg80211_profile *profile = cfg->profile; | |
| 4488 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 4489 | + struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | |
| 4666 | 4490 | struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); |
| 4667 | 4491 | s32 err = 0; |
| 4668 | 4492 | |
| 4669 | 4493 | WL_TRACE("Enter\n"); |
| 4670 | 4494 | |
| 4671 | − if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg->status)) { | |
| 4495 | + if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTING, | |
| 4496 | + &ifp->vif->sme_state)) { | |
| 4672 | 4497 | if (completed) { |
| 4673 | 4498 | brcmf_get_assoc_ies(cfg); |
| 4674 | 4499 | memcpy(profile->bssid, e->addr, ETH_ALEN); |
| @@ -4684,7 +4509,8 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg, · 9 unmodified lines | ||
| 4684 | 4509 | WLAN_STATUS_AUTH_TIMEOUT, |
| 4685 | 4510 | GFP_KERNEL); |
| 4686 | 4511 | if (completed) |
| 4687 | − set_bit(WL_STATUS_CONNECTED, &cfg->status); | |
| 4512 | + set_bit(BRCMF_VIF_STATUS_CONNECTED, | |
| 4513 | + &ifp->vif->sme_state); | |
| 4688 | 4514 | WL_CONN("Report connect result - connection %s\n", |
| 4689 | 4515 | completed ? "succeeded" : "failed"); |
| 4690 | 4516 | } |
| @@ -4736,7 +4562,8 @@ brcmf_notify_connect_status(struct brcmf_cfg80211_info *cfg, · 45 unmodified lines | ||
| 4736 | 4562 | struct net_device *ndev, |
| 4737 | 4563 | const struct brcmf_event_msg *e, void *data) |
| 4738 | 4564 | { |
| 4739 | − struct brcmf_cfg80211_profile *profile = cfg->profile; | |
| 4565 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 4566 | + struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | |
| 4740 | 4567 | s32 err = 0; |
| 4741 | 4568 | |
| 4742 | 4569 | if (cfg->conf->mode == WL_MODE_AP) { |
| @@ -4747,30 +4574,34 @@ brcmf_notify_connect_status(struct brcmf_cfg80211_info *cfg, · 4 unmodified lines | ||
| 4747 | 4574 | memcpy(profile->bssid, e->addr, ETH_ALEN); |
| 4748 | 4575 | wl_inform_ibss(cfg, ndev, e->addr); |
| 4749 | 4576 | cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL); |
| 4750 | − clear_bit(WL_STATUS_CONNECTING, &cfg->status); | |
| 4751 | − set_bit(WL_STATUS_CONNECTED, &cfg->status); | |
| 4577 | + clear_bit(BRCMF_VIF_STATUS_CONNECTING, | |
| 4578 | + &ifp->vif->sme_state); | |
| 4579 | + set_bit(BRCMF_VIF_STATUS_CONNECTED, | |
| 4580 | + &ifp->vif->sme_state); | |
| 4752 | 4581 | } else |
| 4753 | 4582 | brcmf_bss_connect_done(cfg, ndev, e, true); |
| 4754 | 4583 | } else if (brcmf_is_linkdown(cfg, e)) { |
| 4755 | 4584 | WL_CONN("Linkdown\n"); |
| 4756 | 4585 | if (brcmf_is_ibssmode(cfg)) { |
| 4757 | − clear_bit(WL_STATUS_CONNECTING, &cfg->status); | |
| 4758 | − if (test_and_clear_bit(WL_STATUS_CONNECTED, | |
| 4759 | − &cfg->status)) | |
| 4586 | + clear_bit(BRCMF_VIF_STATUS_CONNECTING, | |
| 4587 | + &ifp->vif->sme_state); | |
| 4588 | + if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED, | |
| 4589 | + &ifp->vif->sme_state)) | |
| 4760 | 4590 | brcmf_link_down(cfg); |
| 4761 | 4591 | } else { |
| 4762 | 4592 | brcmf_bss_connect_done(cfg, ndev, e, false); |
| 4763 | − if (test_and_clear_bit(WL_STATUS_CONNECTED, | |
| 4764 | − &cfg->status)) { | |
| 4593 | + if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED, | |
| 4594 | + &ifp->vif->sme_state)) { | |
| 4765 | 4595 | cfg80211_disconnected(ndev, 0, NULL, 0, |
| 4766 | − GFP_KERNEL); | |
| 4596 | + GFP_KERNEL); | |
| 4767 | 4597 | brcmf_link_down(cfg); |
| 4768 | 4598 | } |
| 4769 | 4599 | } |
| 4770 | − brcmf_init_prof(cfg->profile); | |
| 4600 | + brcmf_init_prof(ndev_to_prof(ndev)); | |
| 4771 | 4601 | } else if (brcmf_is_nonetwork(cfg, e)) { |
| 4772 | 4602 | if (brcmf_is_ibssmode(cfg)) |
| 4773 | − clear_bit(WL_STATUS_CONNECTING, &cfg->status); | |
| 4603 | + clear_bit(BRCMF_VIF_STATUS_CONNECTING, | |
| 4604 | + &ifp->vif->sme_state); | |
| 4774 | 4605 | else |
| 4775 | 4606 | brcmf_bss_connect_done(cfg, ndev, e, false); |
| 4776 | 4607 | } |
| @@ -4783,12 +4614,13 @@ brcmf_notify_roaming_status(struct brcmf_cfg80211_info *cfg, · 6 unmodified lines | ||
| 4783 | 4614 | struct net_device *ndev, |
| 4784 | 4615 | const struct brcmf_event_msg *e, void *data) |
| 4785 | 4616 | { |
| 4617 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 4786 | 4618 | s32 err = 0; |
| 4787 | 4619 | u32 event = be32_to_cpu(e->event_type); |
| 4788 | 4620 | u32 status = be32_to_cpu(e->status); |
| 4789 | 4621 | |
| 4790 | 4622 | if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) { |
| 4791 | − if (test_bit(WL_STATUS_CONNECTED, &cfg->status)) | |
| 4623 | + if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state)) | |
| 4792 | 4624 | brcmf_bss_roaming_done(cfg, ndev, e); |
| 4793 | 4625 | else |
| 4794 | 4626 | brcmf_bss_connect_done(cfg, ndev, e, true); |
| @@ -4821,6 +4653,7 @@ brcmf_notify_scan_status(struct brcmf_cfg80211_info *cfg, · 26 unmodified lines | ||
| 4821 | 4653 | struct net_device *ndev, |
| 4822 | 4654 | const struct brcmf_event_msg *e, void *data) |
| 4823 | 4655 | { |
| 4656 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 4824 | 4657 | struct brcmf_channel_info_le channel_inform_le; |
| 4825 | 4658 | struct brcmf_scan_results_le *bss_list_le; |
| 4826 | 4659 | u32 len = WL_SCAN_BUF_MAX; |
| @@ -4835,15 +4668,16 @@ brcmf_notify_scan_status(struct brcmf_cfg80211_info *cfg, · 8 unmodified lines | ||
| 4835 | 4668 | return brcmf_wakeup_iscan(cfg_to_iscan(cfg)); |
| 4836 | 4669 | } |
| 4837 | 4670 | |
| 4838 | − if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) { | |
| 4671 | + if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { | |
| 4839 | 4672 | WL_ERR("Scan complete while device not scanning\n"); |
| 4840 | 4673 | scan_abort = true; |
| 4841 | 4674 | err = -EINVAL; |
| 4842 | 4675 | goto scan_done_out; |
| 4843 | 4676 | } |
| 4844 | 4677 | |
| 4845 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_inform_le, | |
| 4846 | − sizeof(channel_inform_le)); | |
| 4678 | + err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CHANNEL, | |
| 4679 | + &channel_inform_le, | |
| 4680 | + sizeof(channel_inform_le)); | |
| 4847 | 4681 | if (err) { |
| 4848 | 4682 | WL_ERR("scan busy (%d)\n", err); |
| 4849 | 4683 | scan_abort = true; |
| @@ -4857,8 +4691,8 @@ brcmf_notify_scan_status(struct brcmf_cfg80211_info *cfg, · 7 unmodified lines | ||
| 4857 | 4691 | |
| 4858 | 4692 | memset(cfg->scan_results, 0, len); |
| 4859 | 4693 | bss_list_le->buflen = cpu_to_le32(len); |
| 4860 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS, | |
| 4861 | − cfg->scan_results, len); | |
| 4694 | + err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_SCAN_RESULTS, | |
| 4695 | + cfg->scan_results, len); | |
| 4862 | 4696 | if (err) { |
| 4863 | 4697 | WL_ERR("%s Scan_results error (%d)\n", ndev->name, err); |
| 4864 | 4698 | err = -EINVAL; |
| @@ -4920,8 +4754,6 @@ static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg) · 55 unmodified lines | ||
| 4920 | 4754 | cfg->bss_info = NULL; |
| 4921 | 4755 | kfree(cfg->conf); |
| 4922 | 4756 | cfg->conf = NULL; |
| 4923 | − kfree(cfg->profile); | |
| 4924 | − cfg->profile = NULL; | |
| 4925 | 4757 | kfree(cfg->scan_req_int); |
| 4926 | 4758 | cfg->scan_req_int = NULL; |
| 4927 | 4759 | kfree(cfg->escan_ioctl_buf); |
| @@ -4950,9 +4782,6 @@ static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg) · 22 unmodified lines | ||
| 4950 | 4782 | cfg->conf = kzalloc(sizeof(*cfg->conf), GFP_KERNEL); |
| 4951 | 4783 | if (!cfg->conf) |
| 4952 | 4784 | goto init_priv_mem_out; |
| 4953 | − cfg->profile = kzalloc(sizeof(*cfg->profile), GFP_KERNEL); | |
| 4954 | − if (!cfg->profile) | |
| 4955 | − goto init_priv_mem_out; | |
| 4956 | 4785 | cfg->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); |
| 4957 | 4786 | if (!cfg->bss_info) |
| 4958 | 4787 | goto init_priv_mem_out; |
| @@ -5129,7 +4958,6 @@ static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg) · 170 unmodified lines | ||
| 5129 | 4958 | return err; |
| 5130 | 4959 | brcmf_init_escan(cfg); |
| 5131 | 4960 | brcmf_init_conf(cfg->conf); |
| 5132 | − brcmf_init_prof(cfg->profile); | |
| 5133 | 4961 | brcmf_link_down(cfg); |
| 5134 | 4962 | |
| 5135 | 4963 | return err; |
| @@ -5145,12 +4973,14 @@ static void wl_deinit_priv(struct brcmf_cfg80211_info *cfg) · 9 unmodified lines | ||
| 5145 | 4973 | brcmf_deinit_priv_mem(cfg); |
| 5146 | 4974 | } |
| 5147 | 4975 | |
| 5148 | −struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct net_device *ndev, | |
| 5149 | − struct device *busdev, | |
| 5150 | − struct brcmf_pub *drvr) | |
| 4976 | +struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr) | |
| 5151 | 4977 | { |
| 5152 | − struct wireless_dev *wdev; | |
| 4978 | + struct net_device *ndev = drvr->iflist[0]->ndev; | |
| 4979 | + struct device *busdev = drvr->dev; | |
| 5153 | 4980 | struct brcmf_cfg80211_info *cfg; |
| 4981 | + struct wiphy *wiphy; | |
| 4982 | + struct brcmf_cfg80211_vif *vif; | |
| 4983 | + struct brcmf_if *ifp; | |
| 5154 | 4984 | s32 err = 0; |
| 5155 | 4985 | |
| 5156 | 4986 | if (!ndev) { |
| @@ -5158,35 +4988,45 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct net_device *ndev, · 1 unmodified line | ||
| 5158 | 4988 | return NULL; |
| 5159 | 4989 | } |
| 5160 | 4990 | |
| 5161 | − wdev = brcmf_alloc_wdev(busdev); | |
| 5162 | − if (IS_ERR(wdev)) { | |
| 4991 | + ifp = netdev_priv(ndev); | |
| 4992 | + wiphy = brcmf_setup_wiphy(busdev); | |
| 4993 | + if (IS_ERR(wiphy)) | |
| 5163 | 4994 | return NULL; |
| 5164 | − } | |
| 5165 | 4995 | |
| 5166 | − wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS); | |
| 5167 | − cfg = wdev_to_cfg(wdev); | |
| 5168 | − cfg->wdev = wdev; | |
| 4996 | + cfg = wiphy_priv(wiphy); | |
| 4997 | + cfg->wiphy = wiphy; | |
| 5169 | 4998 | cfg->pub = drvr; |
| 5170 | − ndev->ieee80211_ptr = wdev; | |
| 5171 | − SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); | |
| 5172 | − wdev->netdev = ndev; | |
| 4999 | + INIT_LIST_HEAD(&cfg->vif_list); | |
| 5000 | + | |
| 5001 | + vif = brcmf_alloc_vif(cfg, ndev, WL_MODE_BSS, false); | |
| 5002 | + if (IS_ERR(vif)) { | |
| 5003 | + wiphy_free(wiphy); | |
| 5004 | + return NULL; | |
| 5005 | + } | |
| 5006 | + | |
| 5173 | 5007 | err = wl_init_priv(cfg); |
| 5174 | 5008 | if (err) { |
| 5175 | 5009 | WL_ERR("Failed to init iwm_priv (%d)\n", err); |
| 5176 | 5010 | goto cfg80211_attach_out; |
| 5177 | 5011 | } |
| 5178 | 5012 | |
| 5013 | + ifp->vif = vif; | |
| 5179 | 5014 | return cfg; |
| 5180 | 5015 | |
| 5181 | 5016 | cfg80211_attach_out: |
| 5182 | − brcmf_free_wdev(cfg); | |
| 5017 | + brcmf_free_vif(vif); | |
| 5183 | 5018 | return NULL; |
| 5184 | 5019 | } |
| 5185 | 5020 | |
| 5186 | 5021 | void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) |
| 5187 | 5022 | { |
| 5023 | + struct brcmf_cfg80211_vif *vif; | |
| 5024 | + struct brcmf_cfg80211_vif *tmp; | |
| 5025 | + | |
| 5188 | 5026 | wl_deinit_priv(cfg); |
| 5189 | − brcmf_free_wdev(cfg); | |
| 5027 | + list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) { | |
| 5028 | + brcmf_free_vif(vif); | |
| 5029 | + } | |
| 5190 | 5030 | } |
| 5191 | 5031 | |
| 5192 | 5032 | void |
| @@ -5202,22 +5042,18 @@ brcmf_cfg80211_event(struct net_device *ndev, · 9 unmodified lines | ||
| 5202 | 5042 | |
| 5203 | 5043 | static s32 brcmf_dongle_eventmsg(struct net_device *ndev) |
| 5204 | 5044 | { |
| 5205 | − /* Room for "event_msgs" + '\0' + bitvec */ | |
| 5206 | − s8 iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; | |
| 5207 | 5045 | s8 eventmask[BRCMF_EVENTING_MASK_LEN]; |
| 5208 | 5046 | s32 err = 0; |
| 5209 | 5047 | |
| 5210 | 5048 | WL_TRACE("Enter\n"); |
| 5211 | 5049 | |
| 5212 | 5050 | /* Setup event_msgs */ |
| 5213 | − brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, | |
| 5214 | − iovbuf, sizeof(iovbuf)); | |
| 5215 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf)); | |
| 5051 | + err = brcmf_fil_iovar_data_get(netdev_priv(ndev), "event_msgs", | |
| 5052 | + eventmask, BRCMF_EVENTING_MASK_LEN); | |
| 5216 | 5053 | if (err) { |
| 5217 | 5054 | WL_ERR("Get event_msgs error (%d)\n", err); |
| 5218 | 5055 | goto dongle_eventmsg_out; |
| 5219 | 5056 | } |
| 5220 | − memcpy(eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN); | |
| 5221 | 5057 | |
| 5222 | 5058 | setbit(eventmask, BRCMF_E_SET_SSID); |
| 5223 | 5059 | setbit(eventmask, BRCMF_E_ROAM); |
| @@ -5241,9 +5077,8 @@ static s32 brcmf_dongle_eventmsg(struct net_device *ndev) · 17 unmodified lines | ||
| 5241 | 5077 | setbit(eventmask, BRCMF_E_ESCAN_RESULT); |
| 5242 | 5078 | setbit(eventmask, BRCMF_E_PFN_NET_FOUND); |
| 5243 | 5079 | |
| 5244 | − brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, | |
| 5245 | − iovbuf, sizeof(iovbuf)); | |
| 5246 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); | |
| 5080 | + err = brcmf_fil_iovar_data_set(netdev_priv(ndev), "event_msgs", | |
| 5081 | + eventmask, BRCMF_EVENTING_MASK_LEN); | |
| 5247 | 5082 | if (err) { |
| 5248 | 5083 | WL_ERR("Set event_msgs error (%d)\n", err); |
| 5249 | 5084 | goto dongle_eventmsg_out; |
| @@ -5257,23 +5092,17 @@ dongle_eventmsg_out: · 7 unmodified lines | ||
| 5257 | 5092 | static s32 |
| 5258 | 5093 | brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) |
| 5259 | 5094 | { |
| 5260 | − s8 iovbuf[32]; | |
| 5095 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 5261 | 5096 | s32 err = 0; |
| 5262 | 5097 | __le32 roamtrigger[2]; |
| 5263 | 5098 | __le32 roam_delta[2]; |
| 5264 | − __le32 bcn_to_le; | |
| 5265 | − __le32 roamvar_le; | |
| 5266 | 5099 | |
| 5267 | 5100 | /* |
| 5268 | 5101 | * Setup timeout if Beacons are lost and roam is |
| 5269 | 5102 | * off to report link down |
| 5270 | 5103 | */ |
| 5271 | 5104 | if (roamvar) { |
| 5272 | − bcn_to_le = cpu_to_le32(bcn_timeout); | |
| 5273 | − brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_to_le, | |
| 5274 | − sizeof(bcn_to_le), iovbuf, sizeof(iovbuf)); | |
| 5275 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, | |
| 5276 | − iovbuf, sizeof(iovbuf)); | |
| 5105 | + err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout); | |
| 5277 | 5106 | if (err) { |
| 5278 | 5107 | WL_ERR("bcn_timeout error (%d)\n", err); |
| 5279 | 5108 | goto dongle_rom_out; |
| @@ -5285,10 +5114,7 @@ brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) · 5 unmodified lines | ||
| 5285 | 5114 | * to take care of roaming |
| 5286 | 5115 | */ |
| 5287 | 5116 | WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On"); |
| 5288 | − roamvar_le = cpu_to_le32(roamvar); | |
| 5289 | − brcmf_c_mkiovar("roam_off", (char *)&roamvar_le, | |
| 5290 | − sizeof(roamvar_le), iovbuf, sizeof(iovbuf)); | |
| 5291 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); | |
| 5117 | + err = brcmf_fil_iovar_int_set(ifp, "roam_off", roamvar); | |
| 5292 | 5118 | if (err) { |
| 5293 | 5119 | WL_ERR("roam_off error (%d)\n", err); |
| 5294 | 5120 | goto dongle_rom_out; |
| @@ -5296,8 +5122,8 @@ brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) · 1 unmodified line | ||
| 5296 | 5122 | |
| 5297 | 5123 | roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL); |
| 5298 | 5124 | roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL); |
| 5299 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_TRIGGER, | |
| 5300 | − (void *)roamtrigger, sizeof(roamtrigger)); | |
| 5125 | + err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_TRIGGER, | |
| 5126 | + (void *)roamtrigger, sizeof(roamtrigger)); | |
| 5301 | 5127 | if (err) { |
| 5302 | 5128 | WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err); |
| 5303 | 5129 | goto dongle_rom_out; |
| @@ -5305,8 +5131,8 @@ brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) · 1 unmodified line | ||
| 5305 | 5131 | |
| 5306 | 5132 | roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA); |
| 5307 | 5133 | roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL); |
| 5308 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_DELTA, | |
| 5309 | − (void *)roam_delta, sizeof(roam_delta)); | |
| 5134 | + err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_DELTA, | |
| 5135 | + (void *)roam_delta, sizeof(roam_delta)); | |
| 5310 | 5136 | if (err) { |
| 5311 | 5137 | WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err); |
| 5312 | 5138 | goto dongle_rom_out; |
| @@ -5320,13 +5146,11 @@ static s32 · 7 unmodified lines | ||
| 5320 | 5146 | brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, |
| 5321 | 5147 | s32 scan_unassoc_time, s32 scan_passive_time) |
| 5322 | 5148 | { |
| 5149 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 5323 | 5150 | s32 err = 0; |
| 5324 | − __le32 scan_assoc_tm_le = cpu_to_le32(scan_assoc_time); | |
| 5325 | − __le32 scan_unassoc_tm_le = cpu_to_le32(scan_unassoc_time); | |
| 5326 | − __le32 scan_passive_tm_le = cpu_to_le32(scan_passive_time); | |
| 5327 | 5151 | |
| 5328 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME, | |
| 5329 | − &scan_assoc_tm_le, sizeof(scan_assoc_tm_le)); | |
| 5152 | + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, | |
| 5153 | + scan_assoc_time); | |
| 5330 | 5154 | if (err) { |
| 5331 | 5155 | if (err == -EOPNOTSUPP) |
| 5332 | 5156 | WL_INFO("Scan assoc time is not supported\n"); |
| @@ -5334,8 +5158,8 @@ brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, · 1 unmodified line | ||
| 5334 | 5158 | WL_ERR("Scan assoc time error (%d)\n", err); |
| 5335 | 5159 | goto dongle_scantime_out; |
| 5336 | 5160 | } |
| 5337 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME, | |
| 5338 | − &scan_unassoc_tm_le, sizeof(scan_unassoc_tm_le)); | |
| 5161 | + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME, | |
| 5162 | + scan_unassoc_time); | |
| 5339 | 5163 | if (err) { |
| 5340 | 5164 | if (err == -EOPNOTSUPP) |
| 5341 | 5165 | WL_INFO("Scan unassoc time is not supported\n"); |
| @@ -5344,8 +5168,8 @@ brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, · 2 unmodified lines | ||
| 5344 | 5168 | goto dongle_scantime_out; |
| 5345 | 5169 | } |
| 5346 | 5170 | |
| 5347 | − err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME, | |
| 5348 | − &scan_passive_tm_le, sizeof(scan_passive_tm_le)); | |
| 5171 | + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_PASSIVE_TIME, | |
| 5172 | + scan_passive_time); | |
| 5349 | 5173 | if (err) { |
| 5350 | 5174 | if (err == -EOPNOTSUPP) |
| 5351 | 5175 | WL_INFO("Scan passive time is not supported\n"); |
| @@ -5360,13 +5184,14 @@ dongle_scantime_out: · 8 unmodified lines | ||
| 5360 | 5184 | |
| 5361 | 5185 | static s32 wl_update_wiphybands(struct brcmf_cfg80211_info *cfg) |
| 5362 | 5186 | { |
| 5187 | + struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | |
| 5363 | 5188 | struct wiphy *wiphy; |
| 5364 | 5189 | s32 phy_list; |
| 5365 | 5190 | s8 phy; |
| 5366 | 5191 | s32 err = 0; |
| 5367 | 5192 | |
| 5368 | − err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCM_GET_PHYLIST, | |
| 5369 | − &phy_list, sizeof(phy_list)); | |
| 5193 | + err = brcmf_fil_cmd_data_get(ifp, BRCM_GET_PHYLIST, | |
| 5194 | + &phy_list, sizeof(phy_list)); | |
| 5370 | 5195 | if (err) { |
| 5371 | 5196 | WL_ERR("error (%d)\n", err); |
| 5372 | 5197 | return err; |
| @@ -5408,7 +5233,8 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) · 35 unmodified lines | ||
| 5408 | 5233 | goto default_conf_out; |
| 5409 | 5234 | |
| 5410 | 5235 | power_mode = cfg->pwr_save ? PM_FAST : PM_OFF; |
| 5411 | − err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode); | |
| 5236 | + err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PM, | |
| 5237 | + power_mode); | |
| 5412 | 5238 | if (err) |
| 5413 | 5239 | goto default_conf_out; |
| 5414 | 5240 | WL_INFO("power save set to %s\n", |
| @@ -5436,47 +5262,12 @@ default_conf_out: · 21 unmodified lines | ||
| 5436 | 5262 | |
| 5437 | 5263 | } |
| 5438 | 5264 | |
| 5439 | −static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_info *cfg) | |
| 5440 | −{ | |
| 5441 | − char buf[10+IFNAMSIZ]; | |
| 5442 | − struct dentry *fd; | |
| 5443 | − s32 err = 0; | |
| 5444 | − | |
| 5445 | − sprintf(buf, "netdev:%s", cfg_to_ndev(cfg)->name); | |
| 5446 | − cfg->debugfsdir = debugfs_create_dir(buf, | |
| 5447 | − cfg_to_wiphy(cfg)->debugfsdir); | |
| 5448 | − | |
| 5449 | − fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg->debugfsdir, | |
| 5450 | − (u16 *)&cfg->profile->beacon_interval); | |
| 5451 | − if (!fd) { | |
| 5452 | − err = -ENOMEM; | |
| 5453 | − goto err_out; | |
| 5454 | − } | |
| 5455 | − | |
| 5456 | − fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg->debugfsdir, | |
| 5457 | − (u8 *)&cfg->profile->dtim_period); | |
| 5458 | − if (!fd) { | |
| 5459 | − err = -ENOMEM; | |
| 5460 | − goto err_out; | |
| 5461 | − } | |
| 5462 | − | |
| 5463 | −err_out: | |
| 5464 | − return err; | |
| 5465 | −} | |
| 5466 | − | |
| 5467 | −static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_info *cfg) | |
| 5468 | −{ | |
| 5469 | − debugfs_remove_recursive(cfg->debugfsdir); | |
| 5470 | − cfg->debugfsdir = NULL; | |
| 5471 | −} | |
| 5472 | − | |
| 5473 | 5265 | static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg) |
| 5474 | 5266 | { |
| 5267 | + struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | |
| 5475 | 5268 | s32 err = 0; |
| 5476 | 5269 | |
| 5477 | − set_bit(WL_STATUS_READY, &cfg->status); | |
| 5478 | − | |
| 5479 | − brcmf_debugfs_add_netdev_params(cfg); | |
| 5270 | + set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state); | |
| 5480 | 5271 | |
| 5481 | 5272 | err = brcmf_config_dongle(cfg); |
| 5482 | 5273 | if (err) |
| @@ -5489,13 +5280,16 @@ static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg) · 6 unmodified lines | ||
| 5489 | 5280 | |
| 5490 | 5281 | static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg) |
| 5491 | 5282 | { |
| 5283 | + struct net_device *ndev = cfg_to_ndev(cfg); | |
| 5284 | + struct brcmf_if *ifp = netdev_priv(ndev); | |
| 5285 | + | |
| 5492 | 5286 | /* |
| 5493 | 5287 | * While going down, if associated with AP disassociate |
| 5494 | 5288 | * from AP to save power |
| 5495 | 5289 | */ |
| 5496 | − if ((test_bit(WL_STATUS_CONNECTED, &cfg->status) || | |
| 5497 | − test_bit(WL_STATUS_CONNECTING, &cfg->status)) && | |
| 5498 | − test_bit(WL_STATUS_READY, &cfg->status)) { | |
| 5290 | + if ((test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state) || | |
| 5291 | + test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) && | |
| 5292 | + check_vif_up(ifp->vif)) { | |
| 5499 | 5293 | WL_INFO("Disassociating from AP"); |
| 5500 | 5294 | brcmf_link_down(cfg); |
| 5501 | 5295 | |
| @@ -5507,9 +5301,7 @@ static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg) · 5 unmodified lines | ||
| 5507 | 5301 | } |
| 5508 | 5302 | |
| 5509 | 5303 | brcmf_abort_scanning(cfg); |
| 5510 | − clear_bit(WL_STATUS_READY, &cfg->status); | |
| 5511 | − | |
| 5512 | − brcmf_debugfs_remove_netdev(cfg); | |
| 5304 | + clear_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state); | |
| 5513 | 5305 | |
| 5514 | 5306 | return 0; |
| 5515 | 5307 | } |
| @@ -127,15 +127,15 @@ do { \ · 126 unmodified lines | ||
| 127 | 127 | #define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ |
| 128 | 128 | #define IE_MAX_LEN 512 |
| 129 | 129 | |
| 130 | −/* dongle status */ | |
| 131 | −enum wl_status { | |
| 132 | − WL_STATUS_READY, | |
| 133 | − WL_STATUS_SCANNING, | |
| 134 | − WL_STATUS_SCAN_ABORTING, | |
| 135 | − WL_STATUS_CONNECTING, | |
| 136 | − WL_STATUS_CONNECTED, | |
| 137 | − WL_STATUS_AP_CREATING, | |
| 138 | − WL_STATUS_AP_CREATED | |
| 130 | +/** | |
| 131 | + * enum brcmf_scan_status - dongle scan status | |
| 132 | + * | |
| 133 | + * @BRCMF_SCAN_STATUS_BUSY: scanning in progress on dongle. | |
| 134 | + * @BRCMF_SCAN_STATUS_ABORT: scan being aborted on dongle. | |
| 135 | + */ | |
| 136 | +enum brcmf_scan_status { | |
| 137 | + BRCMF_SCAN_STATUS_BUSY, | |
| 138 | + BRCMF_SCAN_STATUS_ABORT, | |
| 139 | 139 | }; |
| 140 | 140 | |
| 141 | 141 | /* wi-fi mode */ |
| @@ -145,19 +145,6 @@ enum wl_mode { · 3 unmodified lines | ||
| 145 | 145 | WL_MODE_AP |
| 146 | 146 | }; |
| 147 | 147 | |
| 148 | −/* dongle profile list */ | |
| 149 | −enum wl_prof_list { | |
| 150 | − WL_PROF_MODE, | |
| 151 | − WL_PROF_SSID, | |
| 152 | − WL_PROF_SEC, | |
| 153 | − WL_PROF_IBSS, | |
| 154 | − WL_PROF_BAND, | |
| 155 | − WL_PROF_BSSID, | |
| 156 | − WL_PROF_ACT, | |
| 157 | − WL_PROF_BEACONINT, | |
| 158 | − WL_PROF_DTIMPERIOD | |
| 159 | −}; | |
| 160 | − | |
| 161 | 148 | /* dongle iscan state */ |
| 162 | 149 | enum wl_iscan_state { |
| 163 | 150 | WL_ISCAN_STATE_IDLE, |
| @@ -214,25 +201,73 @@ struct brcmf_cfg80211_security { · 50 unmodified lines | ||
| 214 | 201 | u32 wpa_auth; |
| 215 | 202 | }; |
| 216 | 203 | |
| 217 | −/* ibss information for currently joined ibss network */ | |
| 218 | −struct brcmf_cfg80211_ibss { | |
| 219 | − u8 beacon_interval; /* in millisecond */ | |
| 220 | − u8 atim; /* in millisecond */ | |
| 221 | − s8 join_only; | |
| 222 | − u8 band; | |
| 223 | − u8 channel; | |
| 224 | −}; | |
| 225 | − | |
| 226 | −/* dongle profile */ | |
| 204 | +/** | |
| 205 | + * struct brcmf_cfg80211_profile - profile information. | |
| 206 | + * | |
| 207 | + * @ssid: ssid of associated/associating ap. | |
| 208 | + * @bssid: bssid of joined/joining ibss. | |
| 209 | + * @sec: security information. | |
| 210 | + */ | |
| 227 | 211 | struct brcmf_cfg80211_profile { |
| 228 | − u32 mode; | |
| 229 | 212 | struct brcmf_ssid ssid; |
| 230 | 213 | u8 bssid[ETH_ALEN]; |
| 231 | − u16 beacon_interval; | |
| 232 | − u8 dtim_period; | |
| 233 | 214 | struct brcmf_cfg80211_security sec; |
| 234 | − struct brcmf_cfg80211_ibss ibss; | |
| 235 | − s32 band; | |
| 215 | +}; | |
| 216 | + | |
| 217 | +/** | |
| 218 | + * enum brcmf_vif_status - bit indices for vif status. | |
| 219 | + * | |
| 220 | + * @BRCMF_VIF_STATUS_READY: ready for operation. | |
| 221 | + * @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress. | |
| 222 | + * @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully. | |
| 223 | + * @BRCMF_VIF_STATUS_AP_CREATING: interface configured for AP operation. | |
| 224 | + * @BRCMF_VIF_STATUS_AP_CREATED: AP operation started. | |
| 225 | + */ | |
| 226 | +enum brcmf_vif_status { | |
| 227 | + BRCMF_VIF_STATUS_READY, | |
| 228 | + BRCMF_VIF_STATUS_CONNECTING, | |
| 229 | + BRCMF_VIF_STATUS_CONNECTED, | |
| 230 | + BRCMF_VIF_STATUS_AP_CREATING, | |
| 231 | + BRCMF_VIF_STATUS_AP_CREATED | |
| 232 | +}; | |
| 233 | + | |
| 234 | +/** | |
| 235 | + * struct vif_saved_ie - holds saved IEs for a virtual interface. | |
| 236 | + * | |
| 237 | + * @probe_res_ie: IE info for probe response. | |
| 238 | + * @beacon_ie: IE info for beacon frame. | |
| 239 | + * @probe_res_ie_len: IE info length for probe response. | |
| 240 | + * @beacon_ie_len: IE info length for beacon frame. | |
| 241 | + */ | |
| 242 | +struct vif_saved_ie { | |
| 243 | + u8 probe_res_ie[IE_MAX_LEN]; | |
| 244 | + u8 beacon_ie[IE_MAX_LEN]; | |
| 245 | + u32 probe_res_ie_len; | |
| 246 | + u32 beacon_ie_len; | |
| 247 | +}; | |
| 248 | + | |
| 249 | +/** | |
| 250 | + * struct brcmf_cfg80211_vif - virtual interface specific information. | |
| 251 | + * | |
| 252 | + * @ifp: lower layer interface pointer | |
| 253 | + * @wdev: wireless device. | |
| 254 | + * @profile: profile information. | |
| 255 | + * @mode: operating mode. | |
| 256 | + * @roam_off: roaming state. | |
| 257 | + * @sme_state: SME state using enum brcmf_vif_status bits. | |
| 258 | + * @pm_block: power-management blocked. | |
| 259 | + * @list: linked list. | |
| 260 | + */ | |
| 261 | +struct brcmf_cfg80211_vif { | |
| 262 | + struct brcmf_if *ifp; | |
| 263 | + struct wireless_dev wdev; | |
| 264 | + struct brcmf_cfg80211_profile profile; | |
| 265 | + s32 mode; | |
| 266 | + s32 roam_off; | |
| 267 | + unsigned long sme_state; | |
| 268 | + bool pm_block; | |
| 269 | + struct vif_saved_ie saved_ie; | |
| 270 | + struct list_head list; | |
| 236 | 271 | }; |
| 237 | 272 | |
| 238 | 273 | /* dongle iscan event loop */ |
| @@ -383,7 +418,7 @@ struct brcmf_pno_scanresults_le { · 144 unmodified lines | ||
| 383 | 418 | /** |
| 384 | 419 | * struct brcmf_cfg80211_info - dongle private data of cfg80211 interface |
| 385 | 420 | * |
| 386 | − * @wdev: representing wl cfg80211 device. | |
| 421 | + * @wiphy: wiphy object for cfg80211 interface. | |
| 387 | 422 | * @conf: dongle configuration. |
| 388 | 423 | * @scan_request: cfg80211 scan request object. |
| 389 | 424 | * @el: main event loop. |
| @@ -395,12 +430,11 @@ struct brcmf_pno_scanresults_le { · 5 unmodified lines | ||
| 395 | 430 | * @scan_req_int: internal scan request object. |
| 396 | 431 | * @bss_info: bss information for cfg80211 layer. |
| 397 | 432 | * @ie: information element object for internal purpose. |
| 398 | − * @profile: holding dongle profile. | |
| 399 | 433 | * @iscan: iscan controller information. |
| 400 | 434 | * @conn_info: association info. |
| 401 | 435 | * @pmk_list: wpa2 pmk list. |
| 402 | 436 | * @event_work: event handler work struct. |
| 403 | − * @status: current dongle status. | |
| 437 | + * @scan_status: scan activity on the dongle. | |
| 404 | 438 | * @pub: common driver information. |
| 405 | 439 | * @channel: current channel. |
| 406 | 440 | * @iscan_on: iscan on/off switch. |
| @@ -422,10 +456,11 @@ struct brcmf_pno_scanresults_le { · 15 unmodified lines | ||
| 422 | 456 | * @escan_timeout_work: scan timeout worker. |
| 423 | 457 | * @escan_ioctl_buf: dongle command buffer for escan commands. |
| 424 | 458 | * @ap_info: host ap information. |
| 425 | − * @ci: used to link this structure to netdev private data. | |
| 459 | + * @vif_list: linked list of vif instances. | |
| 460 | + * @vif_cnt: number of vif instances. | |
| 426 | 461 | */ |
| 427 | 462 | struct brcmf_cfg80211_info { |
| 428 | − struct wireless_dev *wdev; | |
| 463 | + struct wiphy *wiphy; | |
| 429 | 464 | struct brcmf_cfg80211_conf *conf; |
| 430 | 465 | struct cfg80211_scan_request *scan_request; |
| 431 | 466 | struct brcmf_cfg80211_event_loop el; |
| @@ -437,12 +472,11 @@ struct brcmf_cfg80211_info { · 5 unmodified lines | ||
| 437 | 472 | struct brcmf_cfg80211_scan_req *scan_req_int; |
| 438 | 473 | struct wl_cfg80211_bss_info *bss_info; |
| 439 | 474 | struct brcmf_cfg80211_ie ie; |
| 440 | − struct brcmf_cfg80211_profile *profile; | |
| 441 | 475 | struct brcmf_cfg80211_iscan_ctrl *iscan; |
| 442 | 476 | struct brcmf_cfg80211_connect_info conn_info; |
| 443 | 477 | struct brcmf_cfg80211_pmk_list *pmk_list; |
| 444 | 478 | struct work_struct event_work; |
| 445 | − unsigned long status; | |
| 479 | + unsigned long scan_status; | |
| 446 | 480 | struct brcmf_pub *pub; |
| 447 | 481 | u32 channel; |
| 448 | 482 | bool iscan_on; |
| @@ -464,11 +498,13 @@ struct brcmf_cfg80211_info { · 15 unmodified lines | ||
| 464 | 498 | struct work_struct escan_timeout_work; |
| 465 | 499 | u8 *escan_ioctl_buf; |
| 466 | 500 | struct ap_info *ap_info; |
| 501 | + struct list_head vif_list; | |
| 502 | + u8 vif_cnt; | |
| 467 | 503 | }; |
| 468 | 504 | |
| 469 | −static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *w) | |
| 505 | +static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *cfg) | |
| 470 | 506 | { |
| 471 | − return w->wdev->wiphy; | |
| 507 | + return cfg->wiphy; | |
| 472 | 508 | } |
| 473 | 509 | |
| 474 | 510 | 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) · 6 unmodified lines | ||
| 481 | 517 | return (struct brcmf_cfg80211_info *)(wdev_priv(wd)); |
| 482 | 518 | } |
| 483 | 519 | |
| 484 | −static inline struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg) | |
| 520 | +static inline | |
| 521 | +struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg) | |
| 485 | 522 | { |
| 486 | − return cfg->wdev->netdev; | |
| 523 | + struct brcmf_cfg80211_vif *vif; | |
| 524 | + vif = list_first_entry(&cfg->vif_list, struct brcmf_cfg80211_vif, list); | |
| 525 | + return vif->wdev.netdev; | |
| 487 | 526 | } |
| 488 | 527 | |
| 489 | 528 | 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) · 1 unmodified line | ||
| 491 | 530 | return wdev_to_cfg(ndev->ieee80211_ptr); |
| 492 | 531 | } |
| 493 | 532 | |
| 533 | +static inline struct brcmf_cfg80211_profile *ndev_to_prof(struct net_device *nd) | |
| 534 | +{ | |
| 535 | + struct brcmf_if *ifp = netdev_priv(nd); | |
| 536 | + return &ifp->vif->profile; | |
| 537 | +} | |
| 538 | + | |
| 494 | 539 | #define iscan_to_cfg(i) ((struct brcmf_cfg80211_info *)(i->data)) |
| 495 | 540 | #define cfg_to_iscan(w) (w->iscan) |
| 496 | 541 | |
| @@ -500,9 +545,7 @@ brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg) · 3 unmodified lines | ||
| 500 | 545 | return &cfg->conn_info; |
| 501 | 546 | } |
| 502 | 547 | |
| 503 | −struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct net_device *ndev, | |
| 504 | − struct device *busdev, | |
| 505 | − struct brcmf_pub *drvr); | |
| 548 | +struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr); | |
| 506 | 549 | void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg); |
| 507 | 550 | |
| 508 | 551 | /* event handler from dongle */ |
| @@ -692,7 +692,7 @@ void ai_pci_up(struct si_pub *sih) · 691 unmodified lines | ||
| 692 | 692 | sii = container_of(sih, struct si_info, pub); |
| 693 | 693 | |
| 694 | 694 | if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) |
| 695 | − bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, true); | |
| 695 | + bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci[0], true); | |
| 696 | 696 | } |
| 697 | 697 | |
| 698 | 698 | /* Unconfigure and/or apply various WARs when going down */ |
| @@ -703,7 +703,7 @@ void ai_pci_down(struct si_pub *sih) · 4 unmodified lines | ||
| 703 | 703 | sii = container_of(sih, struct si_info, pub); |
| 704 | 704 | |
| 705 | 705 | if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) |
| 706 | − bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, false); | |
| 706 | + bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci[0], false); | |
| 707 | 707 | } |
| 708 | 708 | |
| 709 | 709 | /* Enable BT-COEX & Ex-PA for 4313 */ |
| @@ -5077,7 +5077,7 @@ static int brcms_b_up_prep(struct brcms_hardware *wlc_hw) · 5076 unmodified lines | ||
| 5077 | 5077 | * Configure pci/pcmcia here instead of in brcms_c_attach() |
| 5078 | 5078 | * to allow mfg hotswap: down, hotswap (chip power cycle), up. |
| 5079 | 5079 | */ |
| 5080 | − bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci, wlc_hw->d11core, | |
| 5080 | + bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci[0], wlc_hw->d11core, | |
| 5081 | 5081 | true); |
| 5082 | 5082 | |
| 5083 | 5083 | /* |
| @@ -415,7 +415,7 @@ static void hostap_rx_sta_beacon(local_info_t *local, struct sk_buff *skb, · 414 unmodified lines | ||
| 415 | 415 | ssid = pos + 2; |
| 416 | 416 | ssid_len = pos[1]; |
| 417 | 417 | break; |
| 418 | − case WLAN_EID_GENERIC: | |
| 418 | + case WLAN_EID_VENDOR_SPECIFIC: | |
| 419 | 419 | if (pos[1] >= 4 && |
| 420 | 420 | pos[2] == 0x00 && pos[3] == 0x50 && |
| 421 | 421 | pos[4] == 0xf2 && pos[5] == 1) { |
| @@ -1108,7 +1108,7 @@ static const char *get_info_element_string(u16 id) · 1107 unmodified lines | ||
| 1108 | 1108 | MFIE_STRING(ERP_INFO); |
| 1109 | 1109 | MFIE_STRING(RSN); |
| 1110 | 1110 | MFIE_STRING(EXT_SUPP_RATES); |
| 1111 | − MFIE_STRING(GENERIC); | |
| 1111 | + MFIE_STRING(VENDOR_SPECIFIC); | |
| 1112 | 1112 | MFIE_STRING(QOS_PARAMETER); |
| 1113 | 1113 | default: |
| 1114 | 1114 | return "UNKNOWN"; |
| @@ -1248,8 +1248,8 @@ static int libipw_parse_info_param(struct libipw_info_element · 133 unmodified lines | ||
| 1248 | 1248 | LIBIPW_DEBUG_MGMT("WLAN_EID_CHALLENGE: ignored\n"); |
| 1249 | 1249 | break; |
| 1250 | 1250 | |
| 1251 | − case WLAN_EID_GENERIC: | |
| 1252 | − LIBIPW_DEBUG_MGMT("WLAN_EID_GENERIC: %d bytes\n", | |
| 1251 | + case WLAN_EID_VENDOR_SPECIFIC: | |
| 1252 | + LIBIPW_DEBUG_MGMT("WLAN_EID_VENDOR_SPECIFIC: %d bytes\n", | |
| 1253 | 1253 | info_element->len); |
| 1254 | 1254 | if (!libipw_parse_qos_info_param_IE(info_element, |
| 1255 | 1255 | network)) |
| @@ -1191,8 +1191,6 @@ static void iwl_option_config(struct iwl_priv *priv) · 1190 unmodified lines | ||
| 1191 | 1191 | |
| 1192 | 1192 | static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) |
| 1193 | 1193 | { |
| 1194 | − u16 radio_cfg; | |
| 1195 | − | |
| 1196 | 1194 | priv->eeprom_data->sku = priv->eeprom_data->sku; |
| 1197 | 1195 | |
| 1198 | 1196 | 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) · 9 unmodified lines | ||
| 1208 | 1206 | |
| 1209 | 1207 | IWL_INFO(priv, "Device SKU: 0x%X\n", priv->eeprom_data->sku); |
| 1210 | 1208 | |
| 1211 | − radio_cfg = priv->eeprom_data->radio_cfg; | |
| 1212 | − | |
| 1213 | 1209 | priv->hw_params.tx_chains_num = |
| 1214 | 1210 | num_of_ant(priv->eeprom_data->valid_tx_ant); |
| 1215 | 1211 | 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, · 118 unmodified lines | ||
| 1334 | 1330 | /* Configure transport layer */ |
| 1335 | 1331 | iwl_trans_configure(priv->trans, &trans_cfg); |
| 1336 | 1332 | |
| 1333 | + trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD; | |
| 1334 | + trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start); | |
| 1335 | + | |
| 1337 | 1336 | /* At this point both hw and priv are allocated. */ |
| 1338 | 1337 | |
| 1339 | 1338 | SET_IEEE80211_DEV(priv->hw, priv->trans->dev); |
| @@ -2152,8 +2151,6 @@ static int __init iwl_init(void) · 812 unmodified lines | ||
| 2152 | 2151 | { |
| 2153 | 2152 | |
| 2154 | 2153 | int ret; |
| 2155 | − pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); | |
| 2156 | − pr_info(DRV_COPYRIGHT "\n"); | |
| 2157 | 2154 | |
| 2158 | 2155 | ret = iwlagn_rate_control_register(); |
| 2159 | 2156 | if (ret) { |
| @@ -25,6 +25,39 @@ · 24 unmodified lines | ||
| 25 | 25 | *****************************************************************************/ |
| 26 | 26 | |
| 27 | 27 | #if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ) |
| 28 | +#include <linux/skbuff.h> | |
| 29 | +#include <linux/ieee80211.h> | |
| 30 | +#include <net/cfg80211.h> | |
| 31 | +#include "iwl-trans.h" | |
| 32 | +#if !defined(__IWLWIFI_DEVICE_TRACE) | |
| 33 | +static inline bool iwl_trace_data(struct sk_buff *skb) | |
| 34 | +{ | |
| 35 | + struct ieee80211_hdr *hdr = (void *)skb->data; | |
| 36 | + | |
| 37 | + if (ieee80211_is_data(hdr->frame_control)) | |
| 38 | + return skb->protocol != cpu_to_be16(ETH_P_PAE); | |
| 39 | + return false; | |
| 40 | +} | |
| 41 | + | |
| 42 | +static inline size_t iwl_rx_trace_len(const struct iwl_trans *trans, | |
| 43 | + void *rxbuf, size_t len) | |
| 44 | +{ | |
| 45 | + struct iwl_cmd_header *cmd = (void *)((u8 *)rxbuf + sizeof(__le32)); | |
| 46 | + struct ieee80211_hdr *hdr; | |
| 47 | + | |
| 48 | + if (cmd->cmd != trans->rx_mpdu_cmd) | |
| 49 | + return len; | |
| 50 | + | |
| 51 | + hdr = (void *)((u8 *)cmd + sizeof(struct iwl_cmd_header) + | |
| 52 | + trans->rx_mpdu_cmd_hdr_size); | |
| 53 | + if (!ieee80211_is_data(hdr->frame_control)) | |
| 54 | + return len; | |
| 55 | + /* maybe try to identify EAPOL frames? */ | |
| 56 | + return sizeof(__le32) + sizeof(*cmd) + trans->rx_mpdu_cmd_hdr_size + | |
| 57 | + ieee80211_hdrlen(hdr->frame_control); | |
| 58 | +} | |
| 59 | +#endif | |
| 60 | + | |
| 28 | 61 | #define __IWLWIFI_DEVICE_TRACE |
| 29 | 62 | |
| 30 | 63 | #include <linux/tracepoint.h> |
| @@ -234,6 +267,48 @@ TRACE_EVENT(iwlwifi_dbg, · 203 unmodified lines | ||
| 234 | 267 | TP_printk("%s", (char *)__get_dynamic_array(msg)) |
| 235 | 268 | ); |
| 236 | 269 | |
| 270 | +#undef TRACE_SYSTEM | |
| 271 | +#define TRACE_SYSTEM iwlwifi_data | |
| 272 | + | |
| 273 | +TRACE_EVENT(iwlwifi_dev_tx_data, | |
| 274 | + TP_PROTO(const struct device *dev, | |
| 275 | + struct sk_buff *skb, | |
| 276 | + void *data, size_t data_len), | |
| 277 | + TP_ARGS(dev, skb, data, data_len), | |
| 278 | + TP_STRUCT__entry( | |
| 279 | + DEV_ENTRY | |
| 280 | + | |
| 281 | + __dynamic_array(u8, data, iwl_trace_data(skb) ? data_len : 0) | |
| 282 | + ), | |
| 283 | + TP_fast_assign( | |
| 284 | + DEV_ASSIGN; | |
| 285 | + if (iwl_trace_data(skb)) | |
| 286 | + memcpy(__get_dynamic_array(data), data, data_len); | |
| 287 | + ), | |
| 288 | + TP_printk("[%s] TX frame data", __get_str(dev)) | |
| 289 | +); | |
| 290 | + | |
| 291 | +TRACE_EVENT(iwlwifi_dev_rx_data, | |
| 292 | + TP_PROTO(const struct device *dev, | |
| 293 | + const struct iwl_trans *trans, | |
| 294 | + void *rxbuf, size_t len), | |
| 295 | + TP_ARGS(dev, trans, rxbuf, len), | |
| 296 | + TP_STRUCT__entry( | |
| 297 | + DEV_ENTRY | |
| 298 | + | |
| 299 | + __dynamic_array(u8, data, | |
| 300 | + len - iwl_rx_trace_len(trans, rxbuf, len)) | |
| 301 | + ), | |
| 302 | + TP_fast_assign( | |
| 303 | + size_t offs = iwl_rx_trace_len(trans, rxbuf, len); | |
| 304 | + DEV_ASSIGN; | |
| 305 | + if (offs < len) | |
| 306 | + memcpy(__get_dynamic_array(data), | |
| 307 | + ((u8 *)rxbuf) + offs, len - offs); | |
| 308 | + ), | |
| 309 | + TP_printk("[%s] TX frame data", __get_str(dev)) | |
| 310 | +); | |
| 311 | + | |
| 237 | 312 | #undef TRACE_SYSTEM |
| 238 | 313 | #define TRACE_SYSTEM iwlwifi |
| 239 | 314 | |
| @@ -270,25 +345,28 @@ TRACE_EVENT(iwlwifi_dev_hcmd, · 30 unmodified lines | ||
| 270 | 345 | ); |
| 271 | 346 | |
| 272 | 347 | TRACE_EVENT(iwlwifi_dev_rx, |
| 273 | − TP_PROTO(const struct device *dev, void *rxbuf, size_t len), | |
| 274 | − TP_ARGS(dev, rxbuf, len), | |
| 348 | + TP_PROTO(const struct device *dev, const struct iwl_trans *trans, | |
| 349 | + void *rxbuf, size_t len), | |
| 350 | + TP_ARGS(dev, trans, rxbuf, len), | |
| 275 | 351 | TP_STRUCT__entry( |
| 276 | 352 | DEV_ENTRY |
| 277 | − __dynamic_array(u8, rxbuf, len) | |
| 353 | + __dynamic_array(u8, rxbuf, iwl_rx_trace_len(trans, rxbuf, len)) | |
| 278 | 354 | ), |
| 279 | 355 | TP_fast_assign( |
| 280 | 356 | DEV_ASSIGN; |
| 281 | − memcpy(__get_dynamic_array(rxbuf), rxbuf, len); | |
| 357 | + memcpy(__get_dynamic_array(rxbuf), rxbuf, | |
| 358 | + iwl_rx_trace_len(trans, rxbuf, len)); | |
| 282 | 359 | ), |
| 283 | 360 | TP_printk("[%s] RX cmd %#.2x", |
| 284 | 361 | __get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4]) |
| 285 | 362 | ); |
| 286 | 363 | |
| 287 | 364 | TRACE_EVENT(iwlwifi_dev_tx, |
| 288 | − TP_PROTO(const struct device *dev, void *tfd, size_t tfdlen, | |
| 365 | + TP_PROTO(const struct device *dev, struct sk_buff *skb, | |
| 366 | + void *tfd, size_t tfdlen, | |
| 289 | 367 | void *buf0, size_t buf0_len, |
| 290 | 368 | void *buf1, size_t buf1_len), |
| 291 | − TP_ARGS(dev, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len), | |
| 369 | + TP_ARGS(dev, skb, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len), | |
| 292 | 370 | TP_STRUCT__entry( |
| 293 | 371 | DEV_ENTRY |
| 294 | 372 | |
| @@ -301,14 +379,15 @@ TRACE_EVENT(iwlwifi_dev_tx, · 6 unmodified lines | ||
| 301 | 379 | * for the possible padding). |
| 302 | 380 | */ |
| 303 | 381 | __dynamic_array(u8, buf0, buf0_len) |
| 304 | − __dynamic_array(u8, buf1, buf1_len) | |
| 382 | + __dynamic_array(u8, buf1, iwl_trace_data(skb) ? 0 : buf1_len) | |
| 305 | 383 | ), |
| 306 | 384 | TP_fast_assign( |
| 307 | 385 | DEV_ASSIGN; |
| 308 | 386 | __entry->framelen = buf0_len + buf1_len; |
| 309 | 387 | memcpy(__get_dynamic_array(tfd), tfd, tfdlen); |
| 310 | 388 | memcpy(__get_dynamic_array(buf0), buf0, buf0_len); |
| 311 | − memcpy(__get_dynamic_array(buf1), buf1, buf1_len); | |
| 389 | + if (!iwl_trace_data(skb)) | |
| 390 | + memcpy(__get_dynamic_array(buf1), buf1, buf1_len); | |
| 312 | 391 | ), |
| 313 | 392 | TP_printk("[%s] TX %.2x (%zu bytes)", |
| 314 | 393 | __get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0], |
| @@ -327,11 +327,11 @@ u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr) · 326 unmodified lines | ||
| 327 | 327 | EXPORT_SYMBOL_GPL(iwl_read_targ_mem); |
| 328 | 328 | |
| 329 | 329 | int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr, |
| 330 | − void *buf, int dwords) | |
| 330 | + const void *buf, int dwords) | |
| 331 | 331 | { |
| 332 | 332 | unsigned long flags; |
| 333 | 333 | int offs, result = 0; |
| 334 | − u32 *vals = buf; | |
| 334 | + const u32 *vals = buf; | |
| 335 | 335 | |
| 336 | 336 | spin_lock_irqsave(&trans->reg_lock, flags); |
| 337 | 337 | if (likely(iwl_grab_nic_access(trans))) { |
| @@ -87,7 +87,7 @@ void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr, · 86 unmodified lines | ||
| 87 | 87 | } while (0) |
| 88 | 88 | |
| 89 | 89 | int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr, |
| 90 | − void *buf, int dwords); | |
| 90 | + const void *buf, int dwords); | |
| 91 | 91 | |
| 92 | 92 | u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr); |
| 93 | 93 | int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val); |
| @@ -213,6 +213,9 @@ · 212 unmodified lines | ||
| 213 | 213 | #define SCD_CONTEXT_QUEUE_OFFSET(x)\ |
| 214 | 214 | (SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8)) |
| 215 | 215 | |
| 216 | +#define SCD_TX_STTS_QUEUE_OFFSET(x)\ | |
| 217 | + (SCD_TX_STTS_MEM_LOWER_BOUND + ((x) * 16)) | |
| 218 | + | |
| 216 | 219 | #define SCD_TRANS_TBL_OFFSET_QUEUE(x) \ |
| 217 | 220 | ((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc) |
| 218 | 221 | |
| @@ -444,6 +444,10 @@ enum iwl_trans_state { · 443 unmodified lines | ||
| 444 | 444 | * @dev_cmd_headroom: room needed for the transport's private use before the |
| 445 | 445 | * device_cmd for Tx - for internal use only |
| 446 | 446 | * The user should use iwl_trans_{alloc,free}_tx_cmd. |
| 447 | + * @rx_mpdu_cmd: MPDU RX command ID, must be assigned by opmode before | |
| 448 | + * starting the firmware, used for tracing | |
| 449 | + * @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the | |
| 450 | + * start of the 802.11 header in the @rx_mpdu_cmd | |
| 447 | 451 | */ |
| 448 | 452 | struct iwl_trans { |
| 449 | 453 | const struct iwl_trans_ops *ops; |
| @@ -457,6 +461,8 @@ struct iwl_trans { · 7 unmodified lines | ||
| 457 | 461 | u32 hw_id; |
| 458 | 462 | char hw_id_str[52]; |
| 459 | 463 | |
| 464 | + u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size; | |
| 465 | + | |
| 460 | 466 | bool pm_support; |
| 461 | 467 | |
| 462 | 468 | wait_queue_head_t wait_command_queue; |
| @@ -516,6 +522,8 @@ static inline int iwl_trans_start_fw(struct iwl_trans *trans, · 53 unmodified lines | ||
| 516 | 522 | { |
| 517 | 523 | might_sleep(); |
| 518 | 524 | |
| 525 | + WARN_ON_ONCE(!trans->rx_mpdu_cmd); | |
| 526 | + | |
| 519 | 527 | return trans->ops->start_fw(trans, fw); |
| 520 | 528 | } |
| 521 | 529 | |
| @@ -411,7 +411,8 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, · 410 unmodified lines | ||
| 411 | 411 | |
| 412 | 412 | len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; |
| 413 | 413 | len += sizeof(u32); /* account for status word */ |
| 414 | − trace_iwlwifi_dev_rx(trans->dev, pkt, len); | |
| 414 | + trace_iwlwifi_dev_rx(trans->dev, trans, pkt, len); | |
| 415 | + trace_iwlwifi_dev_rx_data(trans->dev, trans, pkt, len); | |
| 415 | 416 | |
| 416 | 417 | /* Reclaim a command buffer only if this packet is a response |
| 417 | 418 | * to a (driver-originated) command. |
| @@ -300,7 +300,7 @@ static void iwl_trans_pcie_queue_stuck_timer(unsigned long data) · 299 unmodified lines | ||
| 300 | 300 | struct iwl_trans_pcie *trans_pcie = txq->trans_pcie; |
| 301 | 301 | struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie); |
| 302 | 302 | u32 scd_sram_addr = trans_pcie->scd_base_addr + |
| 303 | − SCD_TX_STTS_MEM_LOWER_BOUND + (16 * txq->q.id); | |
| 303 | + SCD_TX_STTS_QUEUE_OFFSET(txq->q.id); | |
| 304 | 304 | u8 buf[16]; |
| 305 | 305 | int i; |
| 306 | 306 | |
| @@ -1385,11 +1385,13 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, · 1078 unmodified lines | ||
| 1385 | 1385 | dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen, |
| 1386 | 1386 | DMA_BIDIRECTIONAL); |
| 1387 | 1387 | |
| 1388 | − trace_iwlwifi_dev_tx(trans->dev, | |
| 1388 | + trace_iwlwifi_dev_tx(trans->dev, skb, | |
| 1389 | 1389 | &txq->tfds[txq->q.write_ptr], |
| 1390 | 1390 | sizeof(struct iwl_tfd), |
| 1391 | 1391 | &dev_cmd->hdr, firstlen, |
| 1392 | 1392 | skb->data + hdr_len, secondlen); |
| 1393 | + trace_iwlwifi_dev_tx_data(trans->dev, skb, | |
| 1394 | + skb->data + hdr_len, secondlen); | |
| 1393 | 1395 | |
| 1394 | 1396 | /* start timer if queue currently empty */ |
| 1395 | 1397 | 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, · 118 unmodified lines | ||
| 1514 | 1516 | struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; |
| 1515 | 1517 | /* n_bd is usually 256 => n_bd - 1 = 0xff */ |
| 1516 | 1518 | int tfd_num = ssn & (txq->q.n_bd - 1); |
| 1517 | − int freed = 0; | |
| 1518 | 1519 | |
| 1519 | 1520 | spin_lock(&txq->lock); |
| 1520 | 1521 | |
| 1521 | 1522 | if (txq->q.read_ptr != tfd_num) { |
| 1522 | 1523 | IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n", |
| 1523 | 1524 | txq_id, txq->q.read_ptr, tfd_num, ssn); |
| 1524 | − freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); | |
| 1525 | + iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); | |
| 1525 | 1526 | if (iwl_queue_space(&txq->q) > txq->q.low_mark) |
| 1526 | 1527 | iwl_wake_queue(trans, txq); |
| 1527 | 1528 | } |
| @@ -480,21 +480,20 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, · 479 unmodified lines | ||
| 480 | 480 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) |
| 481 | 481 | { |
| 482 | 482 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
| 483 | − u16 rd_ptr, wr_ptr; | |
| 484 | − int n_bd = trans_pcie->txq[txq_id].q.n_bd; | |
| 483 | + u32 stts_addr = trans_pcie->scd_base_addr + | |
| 484 | + SCD_TX_STTS_QUEUE_OFFSET(txq_id); | |
| 485 | + static const u32 zero_val[4] = {}; | |
| 485 | 486 | |
| 486 | 487 | if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) { |
| 487 | 488 | WARN_ONCE(1, "queue %d not used", txq_id); |
| 488 | 489 | return; |
| 489 | 490 | } |
| 490 | 491 | |
| 491 | − rd_ptr = iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & (n_bd - 1); | |
| 492 | − wr_ptr = iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)); | |
| 492 | + iwl_txq_set_inactive(trans, txq_id); | |
| 493 | 493 | |
| 494 | − WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]", | |
| 495 | − txq_id, rd_ptr, wr_ptr); | |
| 494 | + _iwl_write_targ_mem_dwords(trans, stts_addr, | |
| 495 | + zero_val, ARRAY_SIZE(zero_val)); | |
| 496 | 496 | |
| 497 | − iwl_txq_set_inactive(trans, txq_id); | |
| 498 | 497 | IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); |
| 499 | 498 | } |
| 500 | 499 | |
| @@ -549,7 +548,10 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) · 48 unmodified lines | ||
| 549 | 548 | * allocated into separate TFDs, then we will need to |
| 550 | 549 | * increase the size of the buffers. |
| 551 | 550 | */ |
| 552 | − if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE)) | |
| 551 | + if (WARN(copy_size > TFD_MAX_PAYLOAD_SIZE, | |
| 552 | + "Command %s (%#x) is too large (%d bytes)\n", | |
| 553 | + trans_pcie_get_cmd_string(trans_pcie, cmd->id), | |
| 554 | + cmd->id, copy_size)) | |
| 553 | 555 | return -EINVAL; |
| 554 | 556 | |
| 555 | 557 | spin_lock_bh(&txq->lock); |
| @@ -101,7 +101,7 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action, · 100 unmodified lines | ||
| 101 | 101 | |
| 102 | 102 | switch (action) { |
| 103 | 103 | case CMD_ACT_MESH_CONFIG_START: |
| 104 | − ie->id = WLAN_EID_GENERIC; | |
| 104 | + ie->id = WLAN_EID_VENDOR_SPECIFIC; | |
| 105 | 105 | ie->val.oui[0] = 0x00; |
| 106 | 106 | ie->val.oui[1] = 0x50; |
| 107 | 107 | ie->val.oui[2] = 0x43; |
| @@ -58,8 +58,7 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, · 57 unmodified lines | ||
| 58 | 58 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) |
| 59 | 59 | mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr); |
| 60 | 60 | else |
| 61 | − mwifiex_process_rx_packet(priv->adapter, | |
| 62 | − rx_tmp_ptr); | |
| 61 | + mwifiex_process_rx_packet(priv, rx_tmp_ptr); | |
| 63 | 62 | } |
| 64 | 63 | } |
| 65 | 64 | |
| @@ -106,7 +105,7 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv, · 40 unmodified lines | ||
| 106 | 105 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) |
| 107 | 106 | mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr); |
| 108 | 107 | else |
| 109 | − mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr); | |
| 108 | + mwifiex_process_rx_packet(priv, rx_tmp_ptr); | |
| 110 | 109 | } |
| 111 | 110 | |
| 112 | 111 | spin_lock_irqsave(&priv->rx_pkt_lock, flags); |
| @@ -442,8 +441,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, · 329 unmodified lines | ||
| 442 | 441 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) |
| 443 | 442 | mwifiex_handle_uap_rx_forward(priv, payload); |
| 444 | 443 | else |
| 445 | − mwifiex_process_rx_packet(priv->adapter, | |
| 446 | − payload); | |
| 444 | + mwifiex_process_rx_packet(priv, payload); | |
| 447 | 445 | } |
| 448 | 446 | return 0; |
| 449 | 447 | } |
| @@ -471,13 +471,13 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) · 470 unmodified lines | ||
| 471 | 471 | flag = 1; |
| 472 | 472 | first_chan = (u32) ch->hw_value; |
| 473 | 473 | next_chan = first_chan; |
| 474 | − max_pwr = ch->max_reg_power; | |
| 474 | + max_pwr = ch->max_power; | |
| 475 | 475 | no_of_parsed_chan = 1; |
| 476 | 476 | continue; |
| 477 | 477 | } |
| 478 | 478 | |
| 479 | 479 | if (ch->hw_value == next_chan + 1 && |
| 480 | − ch->max_reg_power == max_pwr) { | |
| 480 | + ch->max_power == max_pwr) { | |
| 481 | 481 | next_chan++; |
| 482 | 482 | no_of_parsed_chan++; |
| 483 | 483 | } else { |
| @@ -488,7 +488,7 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) · 4 unmodified lines | ||
| 488 | 488 | no_of_triplet++; |
| 489 | 489 | first_chan = (u32) ch->hw_value; |
| 490 | 490 | next_chan = first_chan; |
| 491 | − max_pwr = ch->max_reg_power; | |
| 491 | + max_pwr = ch->max_power; | |
| 492 | 492 | no_of_parsed_chan = 1; |
| 493 | 493 | } |
| 494 | 494 | } |
| @@ -1819,12 +1819,18 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, · 1324 unmodified lines | ||
| 1819 | 1819 | |
| 1820 | 1820 | wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name); |
| 1821 | 1821 | |
| 1822 | − if (atomic_read(&priv->wmm.tx_pkts_queued) >= | |
| 1822 | + if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) && | |
| 1823 | + atomic_read(&priv->wmm.tx_pkts_queued) >= | |
| 1823 | 1824 | MWIFIEX_MIN_TX_PENDING_TO_CANCEL_SCAN) { |
| 1824 | 1825 | dev_dbg(priv->adapter->dev, "scan rejected due to traffic\n"); |
| 1825 | 1826 | return -EBUSY; |
| 1826 | 1827 | } |
| 1827 | 1828 | |
| 1829 | + if (priv->user_scan_cfg) { | |
| 1830 | + dev_err(priv->adapter->dev, "cmd: Scan already in process..\n"); | |
| 1831 | + return -EBUSY; | |
| 1832 | + } | |
| 1833 | + | |
| 1828 | 1834 | priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), |
| 1829 | 1835 | GFP_KERNEL); |
| 1830 | 1836 | if (!priv->user_scan_cfg) { |
| @@ -2116,7 +2122,6 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, · 285 unmodified lines | ||
| 2116 | 2122 | } |
| 2117 | 2123 | |
| 2118 | 2124 | sema_init(&priv->async_sem, 1); |
| 2119 | − priv->scan_pending_on_block = false; | |
| 2120 | 2125 | |
| 2121 | 2126 | dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); |
| 2122 | 2127 | |
| @@ -2253,8 +2258,9 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) · 130 unmodified lines | ||
| 2253 | 2258 | wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1; |
| 2254 | 2259 | wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1; |
| 2255 | 2260 | |
| 2256 | − wiphy->features = NL80211_FEATURE_HT_IBSS | | |
| 2257 | − NL80211_FEATURE_INACTIVITY_TIMER; | |
| 2261 | + wiphy->features |= NL80211_FEATURE_HT_IBSS | | |
| 2262 | + NL80211_FEATURE_INACTIVITY_TIMER | | |
| 2263 | + NL80211_FEATURE_LOW_PRIORITY_SCAN; | |
| 2258 | 2264 | |
| 2259 | 2265 | /* Reserve space for mwifiex specific private data for BSS */ |
| 2260 | 2266 | wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); |
| @@ -917,21 +917,24 @@ mwifiex_cmd_timeout_func(unsigned long function_context) · 916 unmodified lines | ||
| 917 | 917 | |
| 918 | 918 | dev_err(adapter->dev, "last_cmd_index = %d\n", |
| 919 | 919 | adapter->dbg.last_cmd_index); |
| 920 | − print_hex_dump_bytes("last_cmd_id: ", DUMP_PREFIX_OFFSET, | |
| 921 | − adapter->dbg.last_cmd_id, DBG_CMD_NUM); | |
| 922 | − print_hex_dump_bytes("last_cmd_act: ", DUMP_PREFIX_OFFSET, | |
| 923 | − adapter->dbg.last_cmd_act, DBG_CMD_NUM); | |
| 920 | + dev_err(adapter->dev, "last_cmd_id: %*ph\n", | |
| 921 | + (int)sizeof(adapter->dbg.last_cmd_id), | |
| 922 | + adapter->dbg.last_cmd_id); | |
| 923 | + dev_err(adapter->dev, "last_cmd_act: %*ph\n", | |
| 924 | + (int)sizeof(adapter->dbg.last_cmd_act), | |
| 925 | + adapter->dbg.last_cmd_act); | |
| 924 | 926 | |
| 925 | 927 | dev_err(adapter->dev, "last_cmd_resp_index = %d\n", |
| 926 | 928 | adapter->dbg.last_cmd_resp_index); |
| 927 | − print_hex_dump_bytes("last_cmd_resp_id: ", DUMP_PREFIX_OFFSET, | |
| 928 | − adapter->dbg.last_cmd_resp_id, | |
| 929 | − DBG_CMD_NUM); | |
| 929 | + dev_err(adapter->dev, "last_cmd_resp_id: %*ph\n", | |
| 930 | + (int)sizeof(adapter->dbg.last_cmd_resp_id), | |
| 931 | + adapter->dbg.last_cmd_resp_id); | |
| 930 | 932 | |
| 931 | 933 | dev_err(adapter->dev, "last_event_index = %d\n", |
| 932 | 934 | adapter->dbg.last_event_index); |
| 933 | − print_hex_dump_bytes("last_event: ", DUMP_PREFIX_OFFSET, | |
| 934 | − adapter->dbg.last_event, DBG_CMD_NUM); | |
| 935 | + dev_err(adapter->dev, "last_event: %*ph\n", | |
| 936 | + (int)sizeof(adapter->dbg.last_event), | |
| 937 | + adapter->dbg.last_event); | |
| 935 | 938 | |
| 936 | 939 | dev_err(adapter->dev, "data_sent=%d cmd_sent=%d\n", |
| 937 | 940 | adapter->data_sent, adapter->cmd_sent); |
| @@ -84,18 +84,19 @@ static void scan_delay_timer_fn(unsigned long data) · 83 unmodified lines | ||
| 84 | 84 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); |
| 85 | 85 | |
| 86 | 86 | if (priv->user_scan_cfg) { |
| 87 | − dev_dbg(priv->adapter->dev, | |
| 88 | − "info: %s: scan aborted\n", __func__); | |
| 89 | − cfg80211_scan_done(priv->scan_request, 1); | |
| 90 | − priv->scan_request = NULL; | |
| 87 | + if (priv->scan_request) { | |
| 88 | + dev_dbg(priv->adapter->dev, | |
| 89 | + "info: aborting scan\n"); | |
| 90 | + cfg80211_scan_done(priv->scan_request, 1); | |
| 91 | + priv->scan_request = NULL; | |
| 92 | + } else { | |
| 93 | + dev_dbg(priv->adapter->dev, | |
| 94 | + "info: scan already aborted\n"); | |
| 95 | + } | |
| 96 | + | |
| 91 | 97 | kfree(priv->user_scan_cfg); |
| 92 | 98 | priv->user_scan_cfg = NULL; |
| 93 | 99 | } |
| 94 | − | |
| 95 | − if (priv->scan_pending_on_block) { | |
| 96 | − priv->scan_pending_on_block = false; | |
| 97 | − up(&priv->async_sem); | |
| 98 | − } | |
| 99 | 100 | goto done; |
| 100 | 101 | } |
| 101 | 102 | |
| @@ -472,6 +472,14 @@ mwifiex_open(struct net_device *dev) · 471 unmodified lines | ||
| 472 | 472 | static int |
| 473 | 473 | mwifiex_close(struct net_device *dev) |
| 474 | 474 | { |
| 475 | + struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | |
| 476 | + | |
| 477 | + if (priv->scan_request) { | |
| 478 | + dev_dbg(priv->adapter->dev, "aborting scan on ndo_stop\n"); | |
| 479 | + cfg80211_scan_done(priv->scan_request, 1); | |
| 480 | + priv->scan_request = NULL; | |
| 481 | + } | |
| 482 | + | |
| 475 | 483 | return 0; |
| 476 | 484 | } |
| 477 | 485 | |
| @@ -115,8 +115,6 @@ enum { · 114 unmodified lines | ||
| 115 | 115 | #define MWIFIEX_TYPE_DATA 0 |
| 116 | 116 | #define MWIFIEX_TYPE_EVENT 3 |
| 117 | 117 | |
| 118 | −#define DBG_CMD_NUM 5 | |
| 119 | − | |
| 120 | 118 | #define MAX_BITMAP_RATES_SIZE 10 |
| 121 | 119 | |
| 122 | 120 | #define MAX_CHANNEL_BAND_BG 14 |
| @@ -484,7 +482,6 @@ struct mwifiex_private { · 361 unmodified lines | ||
| 484 | 482 | u8 nick_name[16]; |
| 485 | 483 | u16 current_key_index; |
| 486 | 484 | struct semaphore async_sem; |
| 487 | − u8 scan_pending_on_block; | |
| 488 | 485 | u8 report_scan_result; |
| 489 | 486 | struct cfg80211_scan_request *scan_request; |
| 490 | 487 | struct mwifiex_user_scan_cfg *user_scan_cfg; |
| @@ -750,9 +747,9 @@ int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter); · 259 unmodified lines | ||
| 750 | 747 | |
| 751 | 748 | int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *); |
| 752 | 749 | |
| 753 | −int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb); | |
| 750 | +int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb); | |
| 754 | 751 | |
| 755 | −int mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter, | |
| 752 | +int mwifiex_process_mgmt_packet(struct mwifiex_private *priv, | |
| 756 | 753 | struct sk_buff *skb); |
| 757 | 754 | |
| 758 | 755 | int mwifiex_process_event(struct mwifiex_adapter *adapter); |
| @@ -809,7 +806,7 @@ void mwifiex_hs_activated_event(struct mwifiex_private *priv, · 50 unmodified lines | ||
| 809 | 806 | u8 activated); |
| 810 | 807 | int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, |
| 811 | 808 | struct host_cmd_ds_command *resp); |
| 812 | −int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, | |
| 809 | +int mwifiex_process_rx_packet(struct mwifiex_private *priv, | |
| 813 | 810 | struct sk_buff *skb); |
| 814 | 811 | int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no, |
| 815 | 812 | u16 cmd_action, u32 cmd_oid, |
| @@ -819,9 +816,9 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, · 3 unmodified lines | ||
| 819 | 816 | void *data_buf, void *cmd_buf); |
| 820 | 817 | int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no, |
| 821 | 818 | struct host_cmd_ds_command *resp); |
| 822 | −int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *, | |
| 819 | +int mwifiex_process_sta_rx_packet(struct mwifiex_private *, | |
| 823 | 820 | struct sk_buff *skb); |
| 824 | −int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter, | |
| 821 | +int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv, | |
| 825 | 822 | struct sk_buff *skb); |
| 826 | 823 | int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv, |
| 827 | 824 | struct sk_buff *skb); |
| @@ -153,7 +153,7 @@ mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) · 152 unmodified lines | ||
| 153 | 153 | |
| 154 | 154 | if (((bss_desc->bcn_wpa_ie) && |
| 155 | 155 | ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id == |
| 156 | − WLAN_EID_WPA))) { | |
| 156 | + WLAN_EID_VENDOR_SPECIFIC))) { | |
| 157 | 157 | iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data; |
| 158 | 158 | oui = &mwifiex_wpa_oui[cipher][0]; |
| 159 | 159 | ret = mwifiex_search_oui_in_ie(iebody, oui); |
| @@ -202,7 +202,7 @@ mwifiex_is_bss_no_sec(struct mwifiex_private *priv, · 42 unmodified lines | ||
| 202 | 202 | if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && |
| 203 | 203 | !priv->sec_info.wpa2_enabled && ((!bss_desc->bcn_wpa_ie) || |
| 204 | 204 | ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != |
| 205 | − WLAN_EID_WPA)) && | |
| 205 | + WLAN_EID_VENDOR_SPECIFIC)) && | |
| 206 | 206 | ((!bss_desc->bcn_rsn_ie) || |
| 207 | 207 | ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != |
| 208 | 208 | WLAN_EID_RSN)) && |
| @@ -237,7 +237,8 @@ mwifiex_is_bss_wpa(struct mwifiex_private *priv, · 28 unmodified lines | ||
| 237 | 237 | { |
| 238 | 238 | if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled && |
| 239 | 239 | !priv->sec_info.wpa2_enabled && ((bss_desc->bcn_wpa_ie) && |
| 240 | − ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id == WLAN_EID_WPA)) | |
| 240 | + ((*(bss_desc->bcn_wpa_ie)). | |
| 241 | + vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC)) | |
| 241 | 242 | /* |
| 242 | 243 | * Privacy bit may NOT be set in some APs like |
| 243 | 244 | * LinkSys WRT54G && bss_desc->privacy |
| @@ -309,7 +310,8 @@ mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv, · 65 unmodified lines | ||
| 309 | 310 | if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && |
| 310 | 311 | !priv->sec_info.wpa2_enabled && |
| 311 | 312 | ((!bss_desc->bcn_wpa_ie) || |
| 312 | − ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != WLAN_EID_WPA)) && | |
| 313 | + ((*(bss_desc->bcn_wpa_ie)). | |
| 314 | + vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) && | |
| 313 | 315 | ((!bss_desc->bcn_rsn_ie) || |
| 314 | 316 | ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) && |
| 315 | 317 | !priv->sec_info.encryption_mode && bss_desc->privacy) { |
| @@ -329,7 +331,8 @@ mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv, · 13 unmodified lines | ||
| 329 | 331 | if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && |
| 330 | 332 | !priv->sec_info.wpa2_enabled && |
| 331 | 333 | ((!bss_desc->bcn_wpa_ie) || |
| 332 | − ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != WLAN_EID_WPA)) && | |
| 334 | + ((*(bss_desc->bcn_wpa_ie)). | |
| 335 | + vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) && | |
| 333 | 336 | ((!bss_desc->bcn_rsn_ie) || |
| 334 | 337 | ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) && |
| 335 | 338 | priv->sec_info.encryption_mode && bss_desc->privacy) { |
| @@ -938,6 +941,11 @@ mwifiex_config_scan(struct mwifiex_private *priv, · 602 unmodified lines | ||
| 938 | 941 | chan_idx)->chan_scan_mode_bitmap |
| 939 | 942 | &= ~MWIFIEX_PASSIVE_SCAN; |
| 940 | 943 | |
| 944 | + if (*filtered_scan) | |
| 945 | + (scan_chan_list + | |
| 946 | + chan_idx)->chan_scan_mode_bitmap | |
| 947 | + |= MWIFIEX_DISABLE_CHAN_FILT; | |
| 948 | + | |
| 941 | 949 | if (user_scan_in->chan_list[chan_idx].scan_time) { |
| 942 | 950 | scan_dur = (u16) user_scan_in-> |
| 943 | 951 | chan_list[chan_idx].scan_time; |
| @@ -1759,26 +1767,39 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, · 815 unmodified lines | ||
| 1759 | 1767 | } |
| 1760 | 1768 | if (priv->report_scan_result) |
| 1761 | 1769 | priv->report_scan_result = false; |
| 1762 | − if (priv->scan_pending_on_block) { | |
| 1763 | − priv->scan_pending_on_block = false; | |
| 1764 | − up(&priv->async_sem); | |
| 1765 | − } | |
| 1766 | 1770 | |
| 1767 | 1771 | if (priv->user_scan_cfg) { |
| 1768 | − dev_dbg(priv->adapter->dev, | |
| 1769 | − "info: %s: sending scan results\n", __func__); | |
| 1770 | − cfg80211_scan_done(priv->scan_request, 0); | |
| 1771 | − priv->scan_request = NULL; | |
| 1772 | + if (priv->scan_request) { | |
| 1773 | + dev_dbg(priv->adapter->dev, | |
| 1774 | + "info: notifying scan done\n"); | |
| 1775 | + cfg80211_scan_done(priv->scan_request, 0); | |
| 1776 | + priv->scan_request = NULL; | |
| 1777 | + } else { | |
| 1778 | + dev_dbg(priv->adapter->dev, | |
| 1779 | + "info: scan already aborted\n"); | |
| 1780 | + } | |
| 1781 | + | |
| 1772 | 1782 | kfree(priv->user_scan_cfg); |
| 1773 | 1783 | priv->user_scan_cfg = NULL; |
| 1774 | 1784 | } |
| 1775 | 1785 | } else { |
| 1776 | − if (!mwifiex_wmm_lists_empty(adapter)) { | |
| 1786 | + if (priv->user_scan_cfg && !priv->scan_request) { | |
| 1787 | + spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | |
| 1788 | + flags); | |
| 1789 | + adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT; | |
| 1790 | + mod_timer(&priv->scan_delay_timer, jiffies); | |
| 1791 | + dev_dbg(priv->adapter->dev, | |
| 1792 | + "info: %s: triggerring scan abort\n", __func__); | |
| 1793 | + } else if (!mwifiex_wmm_lists_empty(adapter) && | |
| 1794 | + (priv->scan_request && (priv->scan_request->flags & | |
| 1795 | + NL80211_SCAN_FLAG_LOW_PRIORITY))) { | |
| 1777 | 1796 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, |
| 1778 | 1797 | flags); |
| 1779 | 1798 | adapter->scan_delay_cnt = 1; |
| 1780 | 1799 | mod_timer(&priv->scan_delay_timer, jiffies + |
| 1781 | 1800 | msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC)); |
| 1801 | + dev_dbg(priv->adapter->dev, | |
| 1802 | + "info: %s: deferring scan\n", __func__); | |
| 1782 | 1803 | } else { |
| 1783 | 1804 | /* Get scan command from scan_pending_q and put to |
| 1784 | 1805 | cmd_pending_q */ |
| @@ -1891,7 +1912,6 @@ int mwifiex_request_scan(struct mwifiex_private *priv, · 106 unmodified lines | ||
| 1891 | 1912 | __func__); |
| 1892 | 1913 | return -1; |
| 1893 | 1914 | } |
| 1894 | − priv->scan_pending_on_block = true; | |
| 1895 | 1915 | |
| 1896 | 1916 | priv->adapter->scan_wait_q_woken = false; |
| 1897 | 1917 | |
| @@ -1905,10 +1925,7 @@ int mwifiex_request_scan(struct mwifiex_private *priv, · 7 unmodified lines | ||
| 1905 | 1925 | if (!ret) |
| 1906 | 1926 | ret = mwifiex_wait_queue_complete(priv->adapter); |
| 1907 | 1927 | |
| 1908 | − if (ret == -1) { | |
| 1909 | − priv->scan_pending_on_block = false; | |
| 1910 | − up(&priv->async_sem); | |
| 1911 | − } | |
| 1928 | + up(&priv->async_sem); | |
| 1912 | 1929 | |
| 1913 | 1930 | return ret; |
| 1914 | 1931 | } |
| @@ -85,10 +85,6 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv, · 84 unmodified lines | ||
| 85 | 85 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); |
| 86 | 86 | if (priv->report_scan_result) |
| 87 | 87 | priv->report_scan_result = false; |
| 88 | − if (priv->scan_pending_on_block) { | |
| 89 | − priv->scan_pending_on_block = false; | |
| 90 | − up(&priv->async_sem); | |
| 91 | − } | |
| 92 | 88 | break; |
| 93 | 89 | |
| 94 | 90 | case HostCmd_CMD_MAC_CONTROL: |
| @@ -713,7 +713,7 @@ static int mwifiex_set_wpa_ie_helper(struct mwifiex_private *priv, · 712 unmodified lines | ||
| 713 | 713 | dev_dbg(priv->adapter->dev, "cmd: Set Wpa_ie_len=%d IE=%#x\n", |
| 714 | 714 | priv->wpa_ie_len, priv->wpa_ie[0]); |
| 715 | 715 | |
| 716 | − if (priv->wpa_ie[0] == WLAN_EID_WPA) { | |
| 716 | + if (priv->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) { | |
| 717 | 717 | priv->sec_info.wpa_enabled = true; |
| 718 | 718 | } else if (priv->wpa_ie[0] == WLAN_EID_RSN) { |
| 719 | 719 | priv->sec_info.wpa2_enabled = true; |
| @@ -1253,7 +1253,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr, · 533 unmodified lines | ||
| 1253 | 1253 | } |
| 1254 | 1254 | pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr; |
| 1255 | 1255 | /* Test to see if it is a WPA IE, if not, then it is a gen IE */ |
| 1256 | − if (((pvendor_ie->element_id == WLAN_EID_WPA) && | |
| 1256 | + if (((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) && | |
| 1257 | 1257 | (!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) || |
| 1258 | 1258 | (pvendor_ie->element_id == WLAN_EID_RSN)) { |
| 1259 | 1259 | |
| @@ -38,14 +38,10 @@ · 37 unmodified lines | ||
| 38 | 38 | * |
| 39 | 39 | * The completion callback is called after processing in complete. |
| 40 | 40 | */ |
| 41 | −int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, | |
| 41 | +int mwifiex_process_rx_packet(struct mwifiex_private *priv, | |
| 42 | 42 | struct sk_buff *skb) |
| 43 | 43 | { |
| 44 | 44 | int ret; |
| 45 | − struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); | |
| 46 | − struct mwifiex_private *priv = | |
| 47 | − mwifiex_get_priv_by_id(adapter, rx_info->bss_num, | |
| 48 | − rx_info->bss_type); | |
| 49 | 45 | struct rx_packet_hdr *rx_pkt_hdr; |
| 50 | 46 | struct rxpd *local_rx_pd; |
| 51 | 47 | int hdr_chop; |
| @@ -98,9 +94,9 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, · 46 unmodified lines | ||
| 98 | 94 | |
| 99 | 95 | priv->rxpd_htinfo = local_rx_pd->ht_info; |
| 100 | 96 | |
| 101 | − ret = mwifiex_recv_packet(adapter, skb); | |
| 97 | + ret = mwifiex_recv_packet(priv, skb); | |
| 102 | 98 | if (ret == -1) |
| 103 | − dev_err(adapter->dev, "recv packet failed\n"); | |
| 99 | + dev_err(priv->adapter->dev, "recv packet failed\n"); | |
| 104 | 100 | |
| 105 | 101 | return ret; |
| 106 | 102 | } |
| @@ -117,21 +113,15 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, · 10 unmodified lines | ||
| 117 | 113 | * |
| 118 | 114 | * The completion callback is called after processing in complete. |
| 119 | 115 | */ |
| 120 | −int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, | |
| 116 | +int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv, | |
| 121 | 117 | struct sk_buff *skb) |
| 122 | 118 | { |
| 119 | + struct mwifiex_adapter *adapter = priv->adapter; | |
| 123 | 120 | int ret = 0; |
| 124 | 121 | struct rxpd *local_rx_pd; |
| 125 | − struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); | |
| 126 | 122 | struct rx_packet_hdr *rx_pkt_hdr; |
| 127 | 123 | u8 ta[ETH_ALEN]; |
| 128 | 124 | u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num; |
| 129 | − struct mwifiex_private *priv = | |
| 130 | − mwifiex_get_priv_by_id(adapter, rx_info->bss_num, | |
| 131 | − rx_info->bss_type); | |
| 132 | − | |
| 133 | − if (!priv) | |
| 134 | − return -1; | |
| 135 | 125 | |
| 136 | 126 | local_rx_pd = (struct rxpd *) (skb->data); |
| 137 | 127 | 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, · 31 unmodified lines | ||
| 169 | 159 | |
| 170 | 160 | while (!skb_queue_empty(&list)) { |
| 171 | 161 | rx_skb = __skb_dequeue(&list); |
| 172 | − ret = mwifiex_recv_packet(adapter, rx_skb); | |
| 162 | + ret = mwifiex_recv_packet(priv, rx_skb); | |
| 173 | 163 | if (ret == -1) |
| 174 | 164 | dev_err(adapter->dev, "Rx of A-MSDU failed"); |
| 175 | 165 | } |
| 176 | 166 | return 0; |
| 177 | 167 | } else if (rx_pkt_type == PKT_TYPE_MGMT) { |
| 178 | − ret = mwifiex_process_mgmt_packet(adapter, skb); | |
| 168 | + ret = mwifiex_process_mgmt_packet(priv, skb); | |
| 179 | 169 | if (ret) |
| 180 | 170 | dev_err(adapter->dev, "Rx of mgmt packet failed"); |
| 181 | 171 | dev_kfree_skb_any(skb); |
| @@ -188,7 +178,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, · 6 unmodified lines | ||
| 188 | 178 | */ |
| 189 | 179 | if (!IS_11N_ENABLED(priv) || |
| 190 | 180 | memcmp(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN)) { |
| 191 | − mwifiex_process_rx_packet(adapter, skb); | |
| 181 | + mwifiex_process_rx_packet(priv, skb); | |
| 192 | 182 | return ret; |
| 193 | 183 | } |
| 194 | 184 | |
| @@ -48,13 +48,19 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, · 47 unmodified lines | ||
| 48 | 48 | if (!priv) |
| 49 | 49 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); |
| 50 | 50 | |
| 51 | + if (!priv) { | |
| 52 | + dev_err(adapter->dev, "data: priv not found. Drop RX packet\n"); | |
| 53 | + dev_kfree_skb_any(skb); | |
| 54 | + return -1; | |
| 55 | + } | |
| 56 | + | |
| 51 | 57 | rx_info->bss_num = priv->bss_num; |
| 52 | 58 | rx_info->bss_type = priv->bss_type; |
| 53 | 59 | |
| 54 | 60 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) |
| 55 | − return mwifiex_process_uap_rx_packet(adapter, skb); | |
| 61 | + return mwifiex_process_uap_rx_packet(priv, skb); | |
| 56 | 62 | |
| 57 | − return mwifiex_process_sta_rx_packet(adapter, skb); | |
| 63 | + return mwifiex_process_sta_rx_packet(priv, skb); | |
| 58 | 64 | } |
| 59 | 65 | EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet); |
| 60 | 66 | |
| @@ -188,10 +188,19 @@ mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg, · 187 unmodified lines | ||
| 188 | 188 | int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable); |
| 189 | 189 | const u8 *var_pos = params->beacon.head + var_offset; |
| 190 | 190 | int len = params->beacon.head_len - var_offset; |
| 191 | + u8 rate_len = 0; | |
| 191 | 192 | |
| 192 | 193 | rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len); |
| 193 | − if (rate_ie) | |
| 194 | + if (rate_ie) { | |
| 194 | 195 | memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len); |
| 196 | + rate_len = rate_ie->len; | |
| 197 | + } | |
| 198 | + | |
| 199 | + rate_ie = (void *)cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, | |
| 200 | + params->beacon.tail, | |
| 201 | + params->beacon.tail_len); | |
| 202 | + if (rate_ie) | |
| 203 | + memcpy(bss_cfg->rates + rate_len, rate_ie + 1, rate_ie->len); | |
| 195 | 204 | |
| 196 | 205 | return; |
| 197 | 206 | } |
| @@ -146,7 +146,7 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv, · 145 unmodified lines | ||
| 146 | 146 | } |
| 147 | 147 | |
| 148 | 148 | /* Forward unicat/Inter-BSS packets to kernel. */ |
| 149 | − return mwifiex_process_rx_packet(adapter, skb); | |
| 149 | + return mwifiex_process_rx_packet(priv, skb); | |
| 150 | 150 | } |
| 151 | 151 | |
| 152 | 152 | /* |
| @@ -159,24 +159,17 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv, · 6 unmodified lines | ||
| 159 | 159 | * |
| 160 | 160 | * The completion callback is called after processing is complete. |
| 161 | 161 | */ |
| 162 | −int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter, | |
| 162 | +int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv, | |
| 163 | 163 | struct sk_buff *skb) |
| 164 | 164 | { |
| 165 | + struct mwifiex_adapter *adapter = priv->adapter; | |
| 165 | 166 | int ret; |
| 166 | 167 | struct uap_rxpd *uap_rx_pd; |
| 167 | − struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); | |
| 168 | 168 | struct rx_packet_hdr *rx_pkt_hdr; |
| 169 | 169 | u16 rx_pkt_type; |
| 170 | 170 | u8 ta[ETH_ALEN], pkt_type; |
| 171 | 171 | struct mwifiex_sta_node *node; |
| 172 | 172 | |
| 173 | − struct mwifiex_private *priv = | |
| 174 | − mwifiex_get_priv_by_id(adapter, rx_info->bss_num, | |
| 175 | − rx_info->bss_type); | |
| 176 | − | |
| 177 | − if (!priv) | |
| 178 | − return -1; | |
| 179 | − | |
| 180 | 173 | uap_rx_pd = (struct uap_rxpd *)(skb->data); |
| 181 | 174 | rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type); |
| 182 | 175 | 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, · 27 unmodified lines | ||
| 210 | 203 | |
| 211 | 204 | while (!skb_queue_empty(&list)) { |
| 212 | 205 | rx_skb = __skb_dequeue(&list); |
| 213 | − ret = mwifiex_recv_packet(adapter, rx_skb); | |
| 206 | + ret = mwifiex_recv_packet(priv, rx_skb); | |
| 214 | 207 | if (ret) |
| 215 | 208 | dev_err(adapter->dev, |
| 216 | 209 | "AP:Rx A-MSDU failed"); |
| @@ -218,7 +211,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter, · 1 unmodified line | ||
| 218 | 211 | |
| 219 | 212 | return 0; |
| 220 | 213 | } else if (rx_pkt_type == PKT_TYPE_MGMT) { |
| 221 | − ret = mwifiex_process_mgmt_packet(adapter, skb); | |
| 214 | + ret = mwifiex_process_mgmt_packet(priv, skb); | |
| 222 | 215 | if (ret) |
| 223 | 216 | dev_err(adapter->dev, "Rx of mgmt packet failed"); |
| 224 | 217 | dev_kfree_skb_any(skb); |
| @@ -146,20 +146,16 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv, · 145 unmodified lines | ||
| 146 | 146 | * to the kernel. |
| 147 | 147 | */ |
| 148 | 148 | int |
| 149 | −mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter, | |
| 149 | +mwifiex_process_mgmt_packet(struct mwifiex_private *priv, | |
| 150 | 150 | struct sk_buff *skb) |
| 151 | 151 | { |
| 152 | 152 | struct rxpd *rx_pd; |
| 153 | − struct mwifiex_private *priv; | |
| 154 | 153 | u16 pkt_len; |
| 155 | 154 | |
| 156 | 155 | if (!skb) |
| 157 | 156 | return -1; |
| 158 | 157 | |
| 159 | 158 | rx_pd = (struct rxpd *)skb->data; |
| 160 | − priv = mwifiex_get_priv_by_id(adapter, rx_pd->bss_num, rx_pd->bss_type); | |
| 161 | − if (!priv) | |
| 162 | − return -1; | |
| 163 | 159 | |
| 164 | 160 | skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset)); |
| 165 | 161 | skb_pull(skb, sizeof(pkt_len)); |
| @@ -190,20 +186,11 @@ mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter, · 24 unmodified lines | ||
| 190 | 186 | * the function creates a blank SKB, fills it with the data from the |
| 191 | 187 | * received buffer and then sends this new SKB to the kernel. |
| 192 | 188 | */ |
| 193 | −int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |
| 189 | +int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb) | |
| 194 | 190 | { |
| 195 | − struct mwifiex_rxinfo *rx_info; | |
| 196 | − struct mwifiex_private *priv; | |
| 197 | − | |
| 198 | 191 | if (!skb) |
| 199 | 192 | return -1; |
| 200 | 193 | |
| 201 | − rx_info = MWIFIEX_SKB_RXCB(skb); | |
| 202 | − priv = mwifiex_get_priv_by_id(adapter, rx_info->bss_num, | |
| 203 | − rx_info->bss_type); | |
| 204 | − if (!priv) | |
| 205 | − return -1; | |
| 206 | − | |
| 207 | 194 | skb->dev = priv->netdev; |
| 208 | 195 | skb->protocol = eth_type_trans(skb, priv->netdev); |
| 209 | 196 | skb->ip_summed = CHECKSUM_NONE; |
| @@ -225,7 +212,7 @@ int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb) · 15 unmodified lines | ||
| 225 | 212 | * fragments. Currently we fail the Filesndl-ht.scr script |
| 226 | 213 | * for UDP, hence this fix |
| 227 | 214 | */ |
| 228 | − if ((adapter->iface_type == MWIFIEX_USB) && | |
| 215 | + if ((priv->adapter->iface_type == MWIFIEX_USB) && | |
| 229 | 216 | (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE)) |
| 230 | 217 | skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE); |
| 231 | 218 | |
| @@ -39,7 +39,7 @@ static inline u8 *orinoco_get_wpa_ie(u8 *data, size_t len) · 38 unmodified lines | ||
| 39 | 39 | { |
| 40 | 40 | u8 *p = data; |
| 41 | 41 | while ((p + 2 + WPA_SELECTOR_LEN) < (data + len)) { |
| 42 | − if ((p[0] == WLAN_EID_GENERIC) && | |
| 42 | + if ((p[0] == WLAN_EID_VENDOR_SPECIFIC) && | |
| 43 | 43 | (memcmp(&p[2], WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0)) |
| 44 | 44 | return p; |
| 45 | 45 | p += p[1] + 2; |
| @@ -865,7 +865,7 @@ static int ezusb_firmware_download(struct ezusb_priv *upriv, · 864 unmodified lines | ||
| 865 | 865 | static int ezusb_access_ltv(struct ezusb_priv *upriv, |
| 866 | 866 | struct request_context *ctx, |
| 867 | 867 | u16 length, const void *data, u16 frame_type, |
| 868 | − void *ans_buff, int ans_size, u16 *ans_length) | |
| 868 | + void *ans_buff, unsigned ans_size, u16 *ans_length) | |
| 869 | 869 | { |
| 870 | 870 | int req_size; |
| 871 | 871 | int retval = 0; |
| @@ -933,7 +933,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv, · 61 unmodified lines | ||
| 933 | 933 | } |
| 934 | 934 | if (ctx->in_rid) { |
| 935 | 935 | struct ezusb_packet *ans = ctx->buf; |
| 936 | − int exp_len; | |
| 936 | + unsigned exp_len; | |
| 937 | 937 | |
| 938 | 938 | if (ans->hermes_len != 0) |
| 939 | 939 | exp_len = le16_to_cpu(ans->hermes_len) * 2 + 12; |
| @@ -949,8 +949,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv, · 9 unmodified lines | ||
| 949 | 949 | } |
| 950 | 950 | |
| 951 | 951 | if (ans_buff) |
| 952 | − memcpy(ans_buff, ans->data, | |
| 953 | − min_t(int, exp_len, ans_size)); | |
| 952 | + memcpy(ans_buff, ans->data, min(exp_len, ans_size)); | |
| 954 | 953 | if (ans_length) |
| 955 | 954 | *ans_length = le16_to_cpu(ans->hermes_len); |
| 956 | 955 | } |
| @@ -995,7 +994,7 @@ static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid, · 38 unmodified lines | ||
| 995 | 994 | struct ezusb_priv *upriv = hw->priv; |
| 996 | 995 | struct request_context *ctx; |
| 997 | 996 | |
| 998 | − if ((bufsize < 0) || (bufsize % 2)) | |
| 997 | + if (bufsize % 2) | |
| 999 | 998 | return -EINVAL; |
| 1000 | 999 | |
| 1001 | 1000 | ctx = ezusb_alloc_ctx(upriv, rid, rid); |
| @@ -2520,20 +2520,37 @@ static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev, · 2519 unmodified lines | ||
| 2520 | 2520 | return comp_value; |
| 2521 | 2521 | } |
| 2522 | 2522 | |
| 2523 | +static int rt2800_get_txpower_reg_delta(struct rt2x00_dev *rt2x00dev, | |
| 2524 | + int power_level, int max_power) | |
| 2525 | +{ | |
| 2526 | + int delta; | |
| 2527 | + | |
| 2528 | + if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) | |
| 2529 | + return 0; | |
| 2530 | + | |
| 2531 | + /* | |
| 2532 | + * XXX: We don't know the maximum transmit power of our hardware since | |
| 2533 | + * the EEPROM doesn't expose it. We only know that we are calibrated | |
| 2534 | + * to 100% tx power. | |
| 2535 | + * | |
| 2536 | + * Hence, we assume the regulatory limit that cfg80211 calulated for | |
| 2537 | + * the current channel is our maximum and if we are requested to lower | |
| 2538 | + * the value we just reduce our tx power accordingly. | |
| 2539 | + */ | |
| 2540 | + delta = power_level - max_power; | |
| 2541 | + return min(delta, 0); | |
| 2542 | +} | |
| 2543 | + | |
| 2523 | 2544 | static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, |
| 2524 | 2545 | enum ieee80211_band band, int power_level, |
| 2525 | 2546 | u8 txpower, int delta) |
| 2526 | 2547 | { |
| 2527 | − u32 reg; | |
| 2528 | 2548 | u16 eeprom; |
| 2529 | 2549 | u8 criterion; |
| 2530 | 2550 | u8 eirp_txpower; |
| 2531 | 2551 | u8 eirp_txpower_criterion; |
| 2532 | 2552 | u8 reg_limit; |
| 2533 | 2553 | |
| 2534 | − if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b)) | |
| 2535 | − return txpower; | |
| 2536 | − | |
| 2537 | 2554 | if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) { |
| 2538 | 2555 | /* |
| 2539 | 2556 | * Check if eirp txpower exceed txpower_limit. |
| @@ -2542,11 +2559,13 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, · 2 unmodified lines | ||
| 2542 | 2559 | * .11b data rate need add additional 4dbm |
| 2543 | 2560 | * when calculating eirp txpower. |
| 2544 | 2561 | */ |
| 2545 | − rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, ®); | |
| 2546 | − criterion = rt2x00_get_field32(reg, TX_PWR_CFG_0_6MBS); | |
| 2562 | + rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + 1, | |
| 2563 | + &eeprom); | |
| 2564 | + criterion = rt2x00_get_field16(eeprom, | |
| 2565 | + EEPROM_TXPOWER_BYRATE_RATE0); | |
| 2547 | 2566 | |
| 2548 | − rt2x00_eeprom_read(rt2x00dev, | |
| 2549 | − EEPROM_EIRP_MAX_TX_POWER, &eeprom); | |
| 2567 | + rt2x00_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, | |
| 2568 | + &eeprom); | |
| 2550 | 2569 | |
| 2551 | 2570 | if (band == IEEE80211_BAND_2GHZ) |
| 2552 | 2571 | eirp_txpower_criterion = rt2x00_get_field16(eeprom, |
| @@ -2563,36 +2582,71 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, · 10 unmodified lines | ||
| 2563 | 2582 | } else |
| 2564 | 2583 | reg_limit = 0; |
| 2565 | 2584 | |
| 2566 | − return txpower + delta - reg_limit; | |
| 2585 | + txpower = max(0, txpower + delta - reg_limit); | |
| 2586 | + return min_t(u8, txpower, 0xc); | |
| 2567 | 2587 | } |
| 2568 | 2588 | |
| 2589 | +/* | |
| 2590 | + * We configure transmit power using MAC TX_PWR_CFG_{0,...,N} registers and | |
| 2591 | + * BBP R1 register. TX_PWR_CFG_X allow to configure per rate TX power values, | |
| 2592 | + * 4 bits for each rate (tune from 0 to 15 dBm). BBP_R1 controls transmit power | |
| 2593 | + * for all rates, but allow to set only 4 discrete values: -12, -6, 0 and 6 dBm. | |
| 2594 | + * Reference per rate transmit power values are located in the EEPROM at | |
| 2595 | + * EEPROM_TXPOWER_BYRATE offset. We adjust them and BBP R1 settings according to | |
| 2596 | + * current conditions (i.e. band, bandwidth, temperature, user settings). | |
| 2597 | + */ | |
| 2569 | 2598 | static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, |
| 2570 | − enum ieee80211_band band, | |
| 2599 | + struct ieee80211_channel *chan, | |
| 2571 | 2600 | int power_level) |
| 2572 | 2601 | { |
| 2573 | − u8 txpower; | |
| 2602 | + u8 txpower, r1; | |
| 2574 | 2603 | u16 eeprom; |
| 2575 | − int i, is_rate_b; | |
| 2576 | − u32 reg; | |
| 2577 | − u8 r1; | |
| 2578 | − u32 offset; | |
| 2579 | − int delta; | |
| 2604 | + u32 reg, offset; | |
| 2605 | + int i, is_rate_b, delta, power_ctrl; | |
| 2606 | + enum ieee80211_band band = chan->band; | |
| 2580 | 2607 | |
| 2581 | 2608 | /* |
| 2582 | − * Calculate HT40 compensation delta | |
| 2609 | + * Calculate HT40 compensation. For 40MHz we need to add or subtract | |
| 2610 | + * value read from EEPROM (different for 2GHz and for 5GHz). | |
| 2583 | 2611 | */ |
| 2584 | 2612 | delta = rt2800_get_txpower_bw_comp(rt2x00dev, band); |
| 2585 | 2613 | |
| 2586 | 2614 | /* |
| 2587 | − * calculate temperature compensation delta | |
| 2615 | + * Calculate temperature compensation. Depends on measurement of current | |
| 2616 | + * TSSI (Transmitter Signal Strength Indication) we know TX power (due | |
| 2617 | + * to temperature or maybe other factors) is smaller or bigger than | |
| 2618 | + * expected. We adjust it, based on TSSI reference and boundaries values | |
| 2619 | + * provided in EEPROM. | |
| 2588 | 2620 | */ |
| 2589 | 2621 | delta += rt2800_get_gain_calibration_delta(rt2x00dev); |
| 2590 | 2622 | |
| 2591 | 2623 | /* |
| 2592 | − * set to normal bbp tx power control mode: +/- 0dBm | |
| 2624 | + * Decrease power according to user settings, on devices with unknown | |
| 2625 | + * maximum tx power. For other devices we take user power_level into | |
| 2626 | + * consideration on rt2800_compensate_txpower(). | |
| 2627 | + */ | |
| 2628 | + delta += rt2800_get_txpower_reg_delta(rt2x00dev, power_level, | |
| 2629 | + chan->max_power); | |
| 2630 | + | |
| 2631 | + /* | |
| 2632 | + * BBP_R1 controls TX power for all rates, it allow to set the following | |
| 2633 | + * gains -12, -6, 0, +6 dBm by setting values 2, 1, 0, 3 respectively. | |
| 2634 | + * | |
| 2635 | + * TODO: we do not use +6 dBm option to do not increase power beyond | |
| 2636 | + * regulatory limit, however this could be utilized for devices with | |
| 2637 | + * CAPABILITY_POWER_LIMIT. | |
| 2593 | 2638 | */ |
| 2594 | 2639 | rt2800_bbp_read(rt2x00dev, 1, &r1); |
| 2595 | − rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, 0); | |
| 2640 | + if (delta <= -12) { | |
| 2641 | + power_ctrl = 2; | |
| 2642 | + delta += 12; | |
| 2643 | + } else if (delta <= -6) { | |
| 2644 | + power_ctrl = 1; | |
| 2645 | + delta += 6; | |
| 2646 | + } else { | |
| 2647 | + power_ctrl = 0; | |
| 2648 | + } | |
| 2649 | + rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl); | |
| 2596 | 2650 | rt2800_bbp_write(rt2x00dev, 1, r1); |
| 2597 | 2651 | offset = TX_PWR_CFG_0; |
| 2598 | 2652 | |
| @@ -2710,7 +2764,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, · 111 unmodified lines | ||
| 2710 | 2764 | |
| 2711 | 2765 | void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev) |
| 2712 | 2766 | { |
| 2713 | − rt2800_config_txpower(rt2x00dev, rt2x00dev->curr_band, | |
| 2767 | + rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.channel, | |
| 2714 | 2768 | rt2x00dev->tx_power); |
| 2715 | 2769 | } |
| 2716 | 2770 | EXPORT_SYMBOL_GPL(rt2800_gain_calibration); |
| @@ -2845,11 +2899,11 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev, · 128 unmodified lines | ||
| 2845 | 2899 | if (flags & IEEE80211_CONF_CHANGE_CHANNEL) { |
| 2846 | 2900 | rt2800_config_channel(rt2x00dev, libconf->conf, |
| 2847 | 2901 | &libconf->rf, &libconf->channel); |
| 2848 | − rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band, | |
| 2902 | + rt2800_config_txpower(rt2x00dev, libconf->conf->channel, | |
| 2849 | 2903 | libconf->conf->power_level); |
| 2850 | 2904 | } |
| 2851 | 2905 | if (flags & IEEE80211_CONF_CHANGE_POWER) |
| 2852 | − rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band, | |
| 2906 | + rt2800_config_txpower(rt2x00dev, libconf->conf->channel, | |
| 2853 | 2907 | libconf->conf->power_level); |
| 2854 | 2908 | if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) |
| 2855 | 2909 | rt2800_config_retry_limit(rt2x00dev, libconf); |
| @@ -52,11 +52,8 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, · 51 unmodified lines | ||
| 52 | 52 | u32 target_content = 0; |
| 53 | 53 | u8 entry_i; |
| 54 | 54 | |
| 55 | − RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, | |
| 56 | − "key_cont_128:\n %x:%x:%x:%x:%x:%x\n", | |
| 57 | − key_cont_128[0], key_cont_128[1], | |
| 58 | − key_cont_128[2], key_cont_128[3], | |
| 59 | − key_cont_128[4], key_cont_128[5]); | |
| 55 | + RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "key_cont_128: %6phC\n", | |
| 56 | + key_cont_128); | |
| 60 | 57 | |
| 61 | 58 | for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) { |
| 62 | 59 | target_command = entry_i + CAM_CONTENT_COUNT * entry_no; |
| @@ -43,8 +43,8 @@ · 42 unmodified lines | ||
| 43 | 43 | #define GET_UNDECORATED_AVERAGE_RSSI(_priv) \ |
| 44 | 44 | ((RTLPRIV(_priv))->mac80211.opmode == \ |
| 45 | 45 | NL80211_IFTYPE_ADHOC) ? \ |
| 46 | − ((RTLPRIV(_priv))->dm.entry_min_undecoratedsmoothed_pwdb) : \ | |
| 47 | − ((RTLPRIV(_priv))->dm.undecorated_smoothed_pwdb) | |
| 46 | + ((RTLPRIV(_priv))->dm.entry_min_undec_sm_pwdb) : \ | |
| 47 | + ((RTLPRIV(_priv))->dm.undec_sm_pwdb) | |
| 48 | 48 | |
| 49 | 49 | static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = { |
| 50 | 50 | 0x7f8001fe, |
| @@ -167,18 +167,18 @@ static void rtl92c_dm_diginit(struct ieee80211_hw *hw) · 116 unmodified lines | ||
| 167 | 167 | dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; |
| 168 | 168 | dm_digtable->cur_igvalue = 0x20; |
| 169 | 169 | dm_digtable->pre_igvalue = 0x0; |
| 170 | − dm_digtable->cursta_connectstate = DIG_STA_DISCONNECT; | |
| 171 | − dm_digtable->presta_connectstate = DIG_STA_DISCONNECT; | |
| 172 | − dm_digtable->curmultista_connectstate = DIG_MULTISTA_DISCONNECT; | |
| 170 | + dm_digtable->cursta_cstate = DIG_STA_DISCONNECT; | |
| 171 | + dm_digtable->presta_cstate = DIG_STA_DISCONNECT; | |
| 172 | + dm_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT; | |
| 173 | 173 | dm_digtable->rssi_lowthresh = DM_DIG_THRESH_LOW; |
| 174 | 174 | dm_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; |
| 175 | 175 | dm_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; |
| 176 | 176 | dm_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; |
| 177 | 177 | dm_digtable->rx_gain_range_max = DM_DIG_MAX; |
| 178 | 178 | dm_digtable->rx_gain_range_min = DM_DIG_MIN; |
| 179 | − dm_digtable->backoff_val = DM_DIG_BACKOFF_DEFAULT; | |
| 180 | − dm_digtable->backoff_val_range_max = DM_DIG_BACKOFF_MAX; | |
| 181 | − dm_digtable->backoff_val_range_min = DM_DIG_BACKOFF_MIN; | |
| 179 | + dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; | |
| 180 | + dm_digtable->back_range_max = DM_DIG_BACKOFF_MAX; | |
| 181 | + dm_digtable->back_range_min = DM_DIG_BACKOFF_MIN; | |
| 182 | 182 | dm_digtable->pre_cck_pd_state = CCK_PD_STAGE_MAX; |
| 183 | 183 | dm_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX; |
| 184 | 184 | } |
| @@ -189,22 +189,21 @@ static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw) · 4 unmodified lines | ||
| 189 | 189 | struct dig_t *dm_digtable = &rtlpriv->dm_digtable; |
| 190 | 190 | long rssi_val_min = 0; |
| 191 | 191 | |
| 192 | − if ((dm_digtable->curmultista_connectstate == DIG_MULTISTA_CONNECT) && | |
| 193 | − (dm_digtable->cursta_connectstate == DIG_STA_CONNECT)) { | |
| 194 | − if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb != 0) | |
| 192 | + if ((dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) && | |
| 193 | + (dm_digtable->cursta_cstate == DIG_STA_CONNECT)) { | |
| 194 | + if (rtlpriv->dm.entry_min_undec_sm_pwdb != 0) | |
| 195 | 195 | rssi_val_min = |
| 196 | − (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb > | |
| 197 | − rtlpriv->dm.undecorated_smoothed_pwdb) ? | |
| 198 | − rtlpriv->dm.undecorated_smoothed_pwdb : | |
| 199 | − rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; | |
| 196 | + (rtlpriv->dm.entry_min_undec_sm_pwdb > | |
| 197 | + rtlpriv->dm.undec_sm_pwdb) ? | |
| 198 | + rtlpriv->dm.undec_sm_pwdb : | |
| 199 | + rtlpriv->dm.entry_min_undec_sm_pwdb; | |
| 200 | 200 | else |
| 201 | − rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb; | |
| 202 | − } else if (dm_digtable->cursta_connectstate == DIG_STA_CONNECT || | |
| 203 | − dm_digtable->cursta_connectstate == DIG_STA_BEFORE_CONNECT) { | |
| 204 | − rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb; | |
| 205 | − } else if (dm_digtable->curmultista_connectstate == | |
| 206 | − DIG_MULTISTA_CONNECT) { | |
| 207 | − rssi_val_min = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; | |
| 201 | + rssi_val_min = rtlpriv->dm.undec_sm_pwdb; | |
| 202 | + } else if (dm_digtable->cursta_cstate == DIG_STA_CONNECT || | |
| 203 | + dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT) { | |
| 204 | + rssi_val_min = rtlpriv->dm.undec_sm_pwdb; | |
| 205 | + } else if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) { | |
| 206 | + rssi_val_min = rtlpriv->dm.entry_min_undec_sm_pwdb; | |
| 208 | 207 | } |
| 209 | 208 | |
| 210 | 209 | return (u8) rssi_val_min; |
| @@ -286,37 +285,33 @@ static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw) · 75 unmodified lines | ||
| 286 | 285 | static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw) |
| 287 | 286 | { |
| 288 | 287 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 289 | − struct dig_t *dm_digtable = &rtlpriv->dm_digtable; | |
| 288 | + struct dig_t *digtable = &rtlpriv->dm_digtable; | |
| 290 | 289 | |
| 291 | − if (rtlpriv->falsealm_cnt.cnt_all > dm_digtable->fa_highthresh) { | |
| 292 | − if ((dm_digtable->backoff_val - 2) < | |
| 293 | − dm_digtable->backoff_val_range_min) | |
| 294 | − dm_digtable->backoff_val = | |
| 295 | − dm_digtable->backoff_val_range_min; | |
| 290 | + if (rtlpriv->falsealm_cnt.cnt_all > digtable->fa_highthresh) { | |
| 291 | + if ((digtable->back_val - 2) < digtable->back_range_min) | |
| 292 | + digtable->back_val = digtable->back_range_min; | |
| 296 | 293 | else |
| 297 | − dm_digtable->backoff_val -= 2; | |
| 298 | − } else if (rtlpriv->falsealm_cnt.cnt_all < dm_digtable->fa_lowthresh) { | |
| 299 | − if ((dm_digtable->backoff_val + 2) > | |
| 300 | − dm_digtable->backoff_val_range_max) | |
| 301 | − dm_digtable->backoff_val = | |
| 302 | − dm_digtable->backoff_val_range_max; | |
| 294 | + digtable->back_val -= 2; | |
| 295 | + } else if (rtlpriv->falsealm_cnt.cnt_all < digtable->fa_lowthresh) { | |
| 296 | + if ((digtable->back_val + 2) > digtable->back_range_max) | |
| 297 | + digtable->back_val = digtable->back_range_max; | |
| 303 | 298 | else |
| 304 | − dm_digtable->backoff_val += 2; | |
| 299 | + digtable->back_val += 2; | |
| 305 | 300 | } |
| 306 | 301 | |
| 307 | − if ((dm_digtable->rssi_val_min + 10 - dm_digtable->backoff_val) > | |
| 308 | − dm_digtable->rx_gain_range_max) | |
| 309 | − dm_digtable->cur_igvalue = dm_digtable->rx_gain_range_max; | |
| 310 | − else if ((dm_digtable->rssi_val_min + 10 - | |
| 311 | − dm_digtable->backoff_val) < dm_digtable->rx_gain_range_min) | |
| 312 | − dm_digtable->cur_igvalue = dm_digtable->rx_gain_range_min; | |
| 302 | + if ((digtable->rssi_val_min + 10 - digtable->back_val) > | |
| 303 | + digtable->rx_gain_range_max) | |
| 304 | + digtable->cur_igvalue = digtable->rx_gain_range_max; | |
| 305 | + else if ((digtable->rssi_val_min + 10 - | |
| 306 | + digtable->back_val) < digtable->rx_gain_range_min) | |
| 307 | + digtable->cur_igvalue = digtable->rx_gain_range_min; | |
| 313 | 308 | else |
| 314 | − dm_digtable->cur_igvalue = dm_digtable->rssi_val_min + 10 - | |
| 315 | − dm_digtable->backoff_val; | |
| 309 | + digtable->cur_igvalue = digtable->rssi_val_min + 10 - | |
| 310 | + digtable->back_val; | |
| 316 | 311 | |
| 317 | 312 | RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, |
| 318 | − "rssi_val_min = %x backoff_val %x\n", | |
| 319 | − dm_digtable->rssi_val_min, dm_digtable->backoff_val); | |
| 313 | + "rssi_val_min = %x back_val %x\n", | |
| 314 | + digtable->rssi_val_min, digtable->back_val); | |
| 320 | 315 | |
| 321 | 316 | rtl92c_dm_write_dig(hw); |
| 322 | 317 | } |
| @@ -327,14 +322,14 @@ static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw) · 4 unmodified lines | ||
| 327 | 322 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 328 | 323 | struct dig_t *dm_digtable = &rtlpriv->dm_digtable; |
| 329 | 324 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
| 330 | − long rssi_strength = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; | |
| 325 | + long rssi_strength = rtlpriv->dm.entry_min_undec_sm_pwdb; | |
| 331 | 326 | bool multi_sta = false; |
| 332 | 327 | |
| 333 | 328 | if (mac->opmode == NL80211_IFTYPE_ADHOC) |
| 334 | 329 | multi_sta = true; |
| 335 | 330 | |
| 336 | 331 | if (!multi_sta || |
| 337 | − dm_digtable->cursta_connectstate != DIG_STA_DISCONNECT) { | |
| 332 | + dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) { | |
| 338 | 333 | initialized = false; |
| 339 | 334 | dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; |
| 340 | 335 | return; |
| @@ -345,7 +340,7 @@ static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw) · 4 unmodified lines | ||
| 345 | 340 | rtl92c_dm_write_dig(hw); |
| 346 | 341 | } |
| 347 | 342 | |
| 348 | − if (dm_digtable->curmultista_connectstate == DIG_MULTISTA_CONNECT) { | |
| 343 | + if (dm_digtable->curmultista_cstate == DIG_MULTISTA_CONNECT) { | |
| 349 | 344 | if ((rssi_strength < dm_digtable->rssi_lowthresh) && |
| 350 | 345 | (dm_digtable->dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) { |
| 351 | 346 | |
| @@ -367,8 +362,8 @@ static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw) · 15 unmodified lines | ||
| 367 | 362 | } |
| 368 | 363 | |
| 369 | 364 | RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, |
| 370 | − "curmultista_connectstate = %x dig_ext_port_stage %x\n", | |
| 371 | − dm_digtable->curmultista_connectstate, | |
| 365 | + "curmultista_cstate = %x dig_ext_port_stage %x\n", | |
| 366 | + dm_digtable->curmultista_cstate, | |
| 372 | 367 | dm_digtable->dig_ext_port_stage); |
| 373 | 368 | } |
| 374 | 369 | |
| @@ -378,15 +373,14 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw) · 3 unmodified lines | ||
| 378 | 373 | struct dig_t *dm_digtable = &rtlpriv->dm_digtable; |
| 379 | 374 | |
| 380 | 375 | RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE, |
| 381 | − "presta_connectstate = %x, cursta_connectstate = %x\n", | |
| 382 | − dm_digtable->presta_connectstate, | |
| 383 | − dm_digtable->cursta_connectstate); | |
| 376 | + "presta_cstate = %x, cursta_cstate = %x\n", | |
| 377 | + dm_digtable->presta_cstate, dm_digtable->cursta_cstate); | |
| 384 | 378 | |
| 385 | − if (dm_digtable->presta_connectstate == dm_digtable->cursta_connectstate | |
| 386 | − || dm_digtable->cursta_connectstate == DIG_STA_BEFORE_CONNECT | |
| 387 | − || dm_digtable->cursta_connectstate == DIG_STA_CONNECT) { | |
| 379 | + if (dm_digtable->presta_cstate == dm_digtable->cursta_cstate || | |
| 380 | + dm_digtable->cursta_cstate == DIG_STA_BEFORE_CONNECT || | |
| 381 | + dm_digtable->cursta_cstate == DIG_STA_CONNECT) { | |
| 388 | 382 | |
| 389 | − if (dm_digtable->cursta_connectstate != DIG_STA_DISCONNECT) { | |
| 383 | + if (dm_digtable->cursta_cstate != DIG_STA_DISCONNECT) { | |
| 390 | 384 | dm_digtable->rssi_val_min = |
| 391 | 385 | rtl92c_dm_initial_gain_min_pwdb(hw); |
| 392 | 386 | rtl92c_dm_ctrl_initgain_by_rssi(hw); |
| @@ -394,7 +388,7 @@ static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw) · 1 unmodified line | ||
| 394 | 388 | } else { |
| 395 | 389 | dm_digtable->rssi_val_min = 0; |
| 396 | 390 | dm_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; |
| 397 | − dm_digtable->backoff_val = DM_DIG_BACKOFF_DEFAULT; | |
| 391 | + dm_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; | |
| 398 | 392 | dm_digtable->cur_igvalue = 0x20; |
| 399 | 393 | dm_digtable->pre_igvalue = 0; |
| 400 | 394 | rtl92c_dm_write_dig(hw); |
| @@ -407,7 +401,7 @@ static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) · 6 unmodified lines | ||
| 407 | 401 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
| 408 | 402 | struct dig_t *dm_digtable = &rtlpriv->dm_digtable; |
| 409 | 403 | |
| 410 | − if (dm_digtable->cursta_connectstate == DIG_STA_CONNECT) { | |
| 404 | + if (dm_digtable->cursta_cstate == DIG_STA_CONNECT) { | |
| 411 | 405 | dm_digtable->rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw); |
| 412 | 406 | |
| 413 | 407 | if (dm_digtable->pre_cck_pd_state == CCK_PD_STAGE_LowRssi) { |
| @@ -484,15 +478,15 @@ static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw) · 70 unmodified lines | ||
| 484 | 478 | return; |
| 485 | 479 | |
| 486 | 480 | if (mac->link_state >= MAC80211_LINKED) |
| 487 | − dm_digtable->cursta_connectstate = DIG_STA_CONNECT; | |
| 481 | + dm_digtable->cursta_cstate = DIG_STA_CONNECT; | |
| 488 | 482 | else |
| 489 | − dm_digtable->cursta_connectstate = DIG_STA_DISCONNECT; | |
| 483 | + dm_digtable->cursta_cstate = DIG_STA_DISCONNECT; | |
| 490 | 484 | |
| 491 | 485 | rtl92c_dm_initial_gain_sta(hw); |
| 492 | 486 | rtl92c_dm_initial_gain_multi_sta(hw); |
| 493 | 487 | rtl92c_dm_cck_packet_detection_thresh(hw); |
| 494 | 488 | |
| 495 | − dm_digtable->presta_connectstate = dm_digtable->cursta_connectstate; | |
| 489 | + dm_digtable->presta_cstate = dm_digtable->cursta_cstate; | |
| 496 | 490 | |
| 497 | 491 | } |
| 498 | 492 | |
| @@ -526,9 +520,9 @@ void rtl92c_dm_write_dig(struct ieee80211_hw *hw) · 27 unmodified lines | ||
| 526 | 520 | struct dig_t *dm_digtable = &rtlpriv->dm_digtable; |
| 527 | 521 | |
| 528 | 522 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, |
| 529 | − "cur_igvalue = 0x%x, pre_igvalue = 0x%x, backoff_val = %d\n", | |
| 523 | + "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n", | |
| 530 | 524 | dm_digtable->cur_igvalue, dm_digtable->pre_igvalue, |
| 531 | − dm_digtable->backoff_val); | |
| 525 | + dm_digtable->back_val); | |
| 532 | 526 | |
| 533 | 527 | dm_digtable->cur_igvalue += 2; |
| 534 | 528 | if (dm_digtable->cur_igvalue > 0x3f) |
| @@ -555,20 +549,18 @@ static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw) · 20 unmodified lines | ||
| 555 | 549 | return; |
| 556 | 550 | |
| 557 | 551 | if (tmpentry_max_pwdb != 0) { |
| 558 | − rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb = | |
| 559 | − tmpentry_max_pwdb; | |
| 552 | + rtlpriv->dm.entry_max_undec_sm_pwdb = tmpentry_max_pwdb; | |
| 560 | 553 | } else { |
| 561 | − rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb = 0; | |
| 554 | + rtlpriv->dm.entry_max_undec_sm_pwdb = 0; | |
| 562 | 555 | } |
| 563 | 556 | |
| 564 | 557 | if (tmpentry_min_pwdb != 0xff) { |
| 565 | − rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb = | |
| 566 | − tmpentry_min_pwdb; | |
| 558 | + rtlpriv->dm.entry_min_undec_sm_pwdb = tmpentry_min_pwdb; | |
| 567 | 559 | } else { |
| 568 | − rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb = 0; | |
| 560 | + rtlpriv->dm.entry_min_undec_sm_pwdb = 0; | |
| 569 | 561 | } |
| 570 | 562 | |
| 571 | − h2c_parameter[2] = (u8) (rtlpriv->dm.undecorated_smoothed_pwdb & 0xFF); | |
| 563 | + h2c_parameter[2] = (u8) (rtlpriv->dm.undec_sm_pwdb & 0xFF); | |
| 572 | 564 | h2c_parameter[0] = 0; |
| 573 | 565 | |
| 574 | 566 | rtl92c_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, h2c_parameter); |
| @@ -1160,7 +1152,7 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) · 585 unmodified lines | ||
| 1160 | 1152 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
| 1161 | 1153 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
| 1162 | 1154 | struct rate_adaptive *p_ra = &(rtlpriv->ra); |
| 1163 | − u32 low_rssithresh_for_ra, high_rssithresh_for_ra; | |
| 1155 | + u32 low_rssi_thresh, high_rssi_thresh; | |
| 1164 | 1156 | struct ieee80211_sta *sta = NULL; |
| 1165 | 1157 | |
| 1166 | 1158 | if (is_hal_stop(rtlhal)) { |
| @@ -1179,35 +1171,33 @@ static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw) · 12 unmodified lines | ||
| 1179 | 1171 | mac->opmode == NL80211_IFTYPE_STATION) { |
| 1180 | 1172 | switch (p_ra->pre_ratr_state) { |
| 1181 | 1173 | case DM_RATR_STA_HIGH: |
| 1182 | − high_rssithresh_for_ra = 50; | |
| 1183 | − low_rssithresh_for_ra = 20; | |
| 1174 | + high_rssi_thresh = 50; | |
| 1175 | + low_rssi_thresh = 20; | |
| 1184 | 1176 | break; |
| 1185 | 1177 | case DM_RATR_STA_MIDDLE: |
| 1186 | − high_rssithresh_for_ra = 55; | |
| 1187 | − low_rssithresh_for_ra = 20; | |
| 1178 | + high_rssi_thresh = 55; | |
| 1179 | + low_rssi_thresh = 20; | |
| 1188 | 1180 | break; |
| 1189 | 1181 | case DM_RATR_STA_LOW: |
| 1190 | − high_rssithresh_for_ra = 50; | |
| 1191 | − low_rssithresh_for_ra = 25; | |
| 1182 | + high_rssi_thresh = 50; | |
| 1183 | + low_rssi_thresh = 25; | |
| 1192 | 1184 | break; |
| 1193 | 1185 | default: |
| 1194 | − high_rssithresh_for_ra = 50; | |
| 1195 | − low_rssithresh_for_ra = 20; | |
| 1186 | + high_rssi_thresh = 50; | |
| 1187 | + low_rssi_thresh = 20; | |
| 1196 | 1188 | break; |
| 1197 | 1189 | } |
| 1198 | 1190 | |
| 1199 | − if (rtlpriv->dm.undecorated_smoothed_pwdb > | |
| 1200 | − (long)high_rssithresh_for_ra) | |
| 1191 | + if (rtlpriv->dm.undec_sm_pwdb > (long)high_rssi_thresh) | |
| 1201 | 1192 | p_ra->ratr_state = DM_RATR_STA_HIGH; |
| 1202 | − else if (rtlpriv->dm.undecorated_smoothed_pwdb > | |
| 1203 | − (long)low_rssithresh_for_ra) | |
| 1193 | + else if (rtlpriv->dm.undec_sm_pwdb > (long)low_rssi_thresh) | |
| 1204 | 1194 | p_ra->ratr_state = DM_RATR_STA_MIDDLE; |
| 1205 | 1195 | else |
| 1206 | 1196 | p_ra->ratr_state = DM_RATR_STA_LOW; |
| 1207 | 1197 | |
| 1208 | 1198 | if (p_ra->pre_ratr_state != p_ra->ratr_state) { |
| 1209 | 1199 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, "RSSI = %ld\n", |
| 1210 | − rtlpriv->dm.undecorated_smoothed_pwdb); | |
| 1200 | + rtlpriv->dm.undec_sm_pwdb); | |
| 1211 | 1201 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, |
| 1212 | 1202 | "RSSI_LEVEL = %d\n", p_ra->ratr_state); |
| 1213 | 1203 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, |
| @@ -1315,7 +1305,7 @@ static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw) · 101 unmodified lines | ||
| 1315 | 1305 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); |
| 1316 | 1306 | |
| 1317 | 1307 | if (((mac->link_state == MAC80211_NOLINK)) && |
| 1318 | − (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) { | |
| 1308 | + (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { | |
| 1319 | 1309 | dm_pstable->rssi_val_min = 0; |
| 1320 | 1310 | RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, "Not connected to any\n"); |
| 1321 | 1311 | } |
| @@ -1323,20 +1313,19 @@ static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw) · 1 unmodified line | ||
| 1323 | 1313 | if (mac->link_state == MAC80211_LINKED) { |
| 1324 | 1314 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { |
| 1325 | 1315 | dm_pstable->rssi_val_min = |
| 1326 | − rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; | |
| 1316 | + rtlpriv->dm.entry_min_undec_sm_pwdb; | |
| 1327 | 1317 | RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, |
| 1328 | 1318 | "AP Client PWDB = 0x%lx\n", |
| 1329 | 1319 | dm_pstable->rssi_val_min); |
| 1330 | 1320 | } else { |
| 1331 | − dm_pstable->rssi_val_min = | |
| 1332 | − rtlpriv->dm.undecorated_smoothed_pwdb; | |
| 1321 | + dm_pstable->rssi_val_min = rtlpriv->dm.undec_sm_pwdb; | |
| 1333 | 1322 | RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, |
| 1334 | 1323 | "STA Default Port PWDB = 0x%lx\n", |
| 1335 | 1324 | dm_pstable->rssi_val_min); |
| 1336 | 1325 | } |
| 1337 | 1326 | } else { |
| 1338 | 1327 | dm_pstable->rssi_val_min = |
| 1339 | − rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; | |
| 1328 | + rtlpriv->dm.entry_min_undec_sm_pwdb; | |
| 1340 | 1329 | |
| 1341 | 1330 | RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, |
| 1342 | 1331 | "AP Ext Port PWDB = 0x%lx\n", |
| @@ -1368,7 +1357,7 @@ void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) · 25 unmodified lines | ||
| 1368 | 1357 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 1369 | 1358 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
| 1370 | 1359 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
| 1371 | − long undecorated_smoothed_pwdb; | |
| 1360 | + long undec_sm_pwdb; | |
| 1372 | 1361 | |
| 1373 | 1362 | if (!rtlpriv->dm.dynamic_txpower_enable) |
| 1374 | 1363 | return; |
| @@ -1379,7 +1368,7 @@ void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) · 4 unmodified lines | ||
| 1379 | 1368 | } |
| 1380 | 1369 | |
| 1381 | 1370 | if ((mac->link_state < MAC80211_LINKED) && |
| 1382 | − (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) { | |
| 1371 | + (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { | |
| 1383 | 1372 | RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, |
| 1384 | 1373 | "Not connected to any\n"); |
| 1385 | 1374 | |
| @@ -1391,41 +1380,35 @@ void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw) · 5 unmodified lines | ||
| 1391 | 1380 | |
| 1392 | 1381 | if (mac->link_state >= MAC80211_LINKED) { |
| 1393 | 1382 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { |
| 1394 | − undecorated_smoothed_pwdb = | |
| 1395 | − rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; | |
| 1383 | + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; | |
| 1396 | 1384 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 1397 | 1385 | "AP Client PWDB = 0x%lx\n", |
| 1398 | − undecorated_smoothed_pwdb); | |
| 1386 | + undec_sm_pwdb); | |
| 1399 | 1387 | } else { |
| 1400 | − undecorated_smoothed_pwdb = | |
| 1401 | − rtlpriv->dm.undecorated_smoothed_pwdb; | |
| 1388 | + undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; | |
| 1402 | 1389 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 1403 | 1390 | "STA Default Port PWDB = 0x%lx\n", |
| 1404 | − undecorated_smoothed_pwdb); | |
| 1391 | + undec_sm_pwdb); | |
| 1405 | 1392 | } |
| 1406 | 1393 | } else { |
| 1407 | − undecorated_smoothed_pwdb = | |
| 1408 | − rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; | |
| 1394 | + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; | |
| 1409 | 1395 | |
| 1410 | 1396 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 1411 | 1397 | "AP Ext Port PWDB = 0x%lx\n", |
| 1412 | − undecorated_smoothed_pwdb); | |
| 1398 | + undec_sm_pwdb); | |
| 1413 | 1399 | } |
| 1414 | 1400 | |
| 1415 | − if (undecorated_smoothed_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { | |
| 1401 | + if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { | |
| 1416 | 1402 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; |
| 1417 | 1403 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 1418 | 1404 | "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); |
| 1419 | − } else if ((undecorated_smoothed_pwdb < | |
| 1420 | − (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && | |
| 1421 | − (undecorated_smoothed_pwdb >= | |
| 1422 | − TX_POWER_NEAR_FIELD_THRESH_LVL1)) { | |
| 1405 | + } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && | |
| 1406 | + (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) { | |
| 1423 | 1407 | |
| 1424 | 1408 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; |
| 1425 | 1409 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 1426 | 1410 | "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"); |
| 1427 | − } else if (undecorated_smoothed_pwdb < | |
| 1428 | − (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { | |
| 1411 | + } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { | |
| 1429 | 1412 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; |
| 1430 | 1413 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 1431 | 1414 | "TXHIGHPWRLEVEL_NORMAL\n"); |
| @@ -1473,48 +1456,46 @@ u8 rtl92c_bt_rssi_state_change(struct ieee80211_hw *hw) · 41 unmodified lines | ||
| 1473 | 1456 | { |
| 1474 | 1457 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 1475 | 1458 | struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); |
| 1476 | − long undecorated_smoothed_pwdb; | |
| 1459 | + long undec_sm_pwdb; | |
| 1477 | 1460 | u8 curr_bt_rssi_state = 0x00; |
| 1478 | 1461 | |
| 1479 | 1462 | if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { |
| 1480 | − undecorated_smoothed_pwdb = | |
| 1481 | − GET_UNDECORATED_AVERAGE_RSSI(rtlpriv); | |
| 1463 | + undec_sm_pwdb = GET_UNDECORATED_AVERAGE_RSSI(rtlpriv); | |
| 1482 | 1464 | } else { |
| 1483 | − if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0) | |
| 1484 | − undecorated_smoothed_pwdb = 100; | |
| 1465 | + if (rtlpriv->dm.entry_min_undec_sm_pwdb == 0) | |
| 1466 | + undec_sm_pwdb = 100; | |
| 1485 | 1467 | else |
| 1486 | − undecorated_smoothed_pwdb = | |
| 1487 | − rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; | |
| 1468 | + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; | |
| 1488 | 1469 | } |
| 1489 | 1470 | |
| 1490 | 1471 | /* Check RSSI to determine HighPower/NormalPower state for |
| 1491 | 1472 | * BT coexistence. */ |
| 1492 | − if (undecorated_smoothed_pwdb >= 67) | |
| 1473 | + if (undec_sm_pwdb >= 67) | |
| 1493 | 1474 | curr_bt_rssi_state &= (~BT_RSSI_STATE_NORMAL_POWER); |
| 1494 | − else if (undecorated_smoothed_pwdb < 62) | |
| 1475 | + else if (undec_sm_pwdb < 62) | |
| 1495 | 1476 | curr_bt_rssi_state |= BT_RSSI_STATE_NORMAL_POWER; |
| 1496 | 1477 | |
| 1497 | 1478 | /* Check RSSI to determine AMPDU setting for BT coexistence. */ |
| 1498 | − if (undecorated_smoothed_pwdb >= 40) | |
| 1479 | + if (undec_sm_pwdb >= 40) | |
| 1499 | 1480 | curr_bt_rssi_state &= (~BT_RSSI_STATE_AMDPU_OFF); |
| 1500 | − else if (undecorated_smoothed_pwdb <= 32) | |
| 1481 | + else if (undec_sm_pwdb <= 32) | |
| 1501 | 1482 | curr_bt_rssi_state |= BT_RSSI_STATE_AMDPU_OFF; |
| 1502 | 1483 | |
| 1503 | 1484 | /* Marked RSSI state. It will be used to determine BT coexistence |
| 1504 | 1485 | * setting later. */ |
| 1505 | − if (undecorated_smoothed_pwdb < 35) | |
| 1486 | + if (undec_sm_pwdb < 35) | |
| 1506 | 1487 | curr_bt_rssi_state |= BT_RSSI_STATE_SPECIAL_LOW; |
| 1507 | 1488 | else |
| 1508 | 1489 | curr_bt_rssi_state &= (~BT_RSSI_STATE_SPECIAL_LOW); |
| 1509 | 1490 | |
| 1510 | 1491 | /* Set Tx Power according to BT status. */ |
| 1511 | − if (undecorated_smoothed_pwdb >= 30) | |
| 1492 | + if (undec_sm_pwdb >= 30) | |
| 1512 | 1493 | curr_bt_rssi_state |= BT_RSSI_STATE_TXPOWER_LOW; |
| 1513 | − else if (undecorated_smoothed_pwdb < 25) | |
| 1494 | + else if (undec_sm_pwdb < 25) | |
| 1514 | 1495 | curr_bt_rssi_state &= (~BT_RSSI_STATE_TXPOWER_LOW); |
| 1515 | 1496 | |
| 1516 | 1497 | /* Check BT state related to BT_Idle in B/G mode. */ |
| 1517 | − if (undecorated_smoothed_pwdb < 15) | |
| 1498 | + if (undec_sm_pwdb < 15) | |
| 1518 | 1499 | curr_bt_rssi_state |= BT_RSSI_STATE_BG_EDCA_LOW; |
| 1519 | 1500 | else |
| 1520 | 1501 | curr_bt_rssi_state &= (~BT_RSSI_STATE_BG_EDCA_LOW); |
| @@ -34,9 +34,6 @@ · 33 unmodified lines | ||
| 34 | 34 | #include "dm_common.h" |
| 35 | 35 | #include "phy_common.h" |
| 36 | 36 | |
| 37 | −/* Define macro to shorten lines */ | |
| 38 | −#define MCS_TXPWR mcs_txpwrlevel_origoffset | |
| 39 | − | |
| 40 | 37 | u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) |
| 41 | 38 | { |
| 42 | 39 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| @@ -138,13 +135,13 @@ u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw, · 95 unmodified lines | ||
| 138 | 135 | rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, |
| 139 | 136 | BIT(8)); |
| 140 | 137 | if (rfpi_enable) |
| 141 | − retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi, | |
| 138 | + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi, | |
| 142 | 139 | BLSSIREADBACKDATA); |
| 143 | 140 | else |
| 144 | − retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback, | |
| 141 | + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, | |
| 145 | 142 | BLSSIREADBACKDATA); |
| 146 | 143 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]=0x%x\n", |
| 147 | − rfpath, pphyreg->rflssi_readback, retvalue); | |
| 144 | + rfpath, pphyreg->rf_rb, retvalue); | |
| 148 | 145 | return retvalue; |
| 149 | 146 | } |
| 150 | 147 | EXPORT_SYMBOL(_rtl92c_phy_rf_serial_read); |
| @@ -290,11 +287,11 @@ void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw, · 139 unmodified lines | ||
| 290 | 287 | else |
| 291 | 288 | return; |
| 292 | 289 | |
| 293 | − rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][index] = data; | |
| 290 | + rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index] = data; | |
| 294 | 291 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
| 295 | 292 | "MCSTxPowerLevelOriginalOffset[%d][%d] = 0x%x\n", |
| 296 | 293 | rtlphy->pwrgroup_cnt, index, |
| 297 | − rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][index]); | |
| 294 | + rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index]); | |
| 298 | 295 | |
| 299 | 296 | if (index == 13) |
| 300 | 297 | rtlphy->pwrgroup_cnt++; |
| @@ -374,14 +371,10 @@ void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) · 73 unmodified lines | ||
| 374 | 371 | rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; |
| 375 | 372 | rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; |
| 376 | 373 | |
| 377 | − rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control = | |
| 378 | − RFPGA0_XAB_SWITCHCONTROL; | |
| 379 | − rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control = | |
| 380 | − RFPGA0_XAB_SWITCHCONTROL; | |
| 381 | − rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control = | |
| 382 | − RFPGA0_XCD_SWITCHCONTROL; | |
| 383 | − rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control = | |
| 384 | − RFPGA0_XCD_SWITCHCONTROL; | |
| 374 | + rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; | |
| 375 | + rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; | |
| 376 | + rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; | |
| 377 | + rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; | |
| 385 | 378 | |
| 386 | 379 | rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; |
| 387 | 380 | rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1; |
| @@ -393,47 +386,33 @@ void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) · 5 unmodified lines | ||
| 393 | 386 | rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; |
| 394 | 387 | rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; |
| 395 | 388 | |
| 396 | − rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance = | |
| 397 | − ROFDM0_XARXIQIMBALANCE; | |
| 398 | − rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance = | |
| 399 | − ROFDM0_XBRXIQIMBALANCE; | |
| 400 | − rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance = | |
| 401 | − ROFDM0_XCRXIQIMBANLANCE; | |
| 402 | − rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance = | |
| 403 | − ROFDM0_XDRXIQIMBALANCE; | |
| 389 | + rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE; | |
| 390 | + rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE; | |
| 391 | + rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBANLANCE; | |
| 392 | + rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE; | |
| 404 | 393 | |
| 405 | 394 | rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; |
| 406 | 395 | rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE; |
| 407 | 396 | rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; |
| 408 | 397 | rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; |
| 409 | 398 | |
| 410 | − rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance = | |
| 411 | − ROFDM0_XATXIQIMBALANCE; | |
| 412 | − rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance = | |
| 413 | − ROFDM0_XBTXIQIMBALANCE; | |
| 414 | − rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance = | |
| 415 | − ROFDM0_XCTXIQIMBALANCE; | |
| 416 | − rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance = | |
| 417 | − ROFDM0_XDTXIQIMBALANCE; | |
| 399 | + rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE; | |
| 400 | + rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE; | |
| 401 | + rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE; | |
| 402 | + rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE; | |
| 418 | 403 | |
| 419 | 404 | rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE; |
| 420 | 405 | rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE; |
| 421 | 406 | rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE; |
| 422 | 407 | rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE; |
| 423 | 408 | |
| 424 | − rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback = | |
| 425 | − RFPGA0_XA_LSSIREADBACK; | |
| 426 | − rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback = | |
| 427 | − RFPGA0_XB_LSSIREADBACK; | |
| 428 | − rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback = | |
| 429 | − RFPGA0_XC_LSSIREADBACK; | |
| 430 | − rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback = | |
| 431 | − RFPGA0_XD_LSSIREADBACK; | |
| 409 | + rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK; | |
| 410 | + rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK; | |
| 411 | + rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK; | |
| 412 | + rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK; | |
| 432 | 413 | |
| 433 | − rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi = | |
| 434 | − TRANSCEIVEA_HSPI_READBACK; | |
| 435 | − rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi = | |
| 436 | − TRANSCEIVEB_HSPI_READBACK; | |
| 414 | + rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVEA_HSPI_READBACK; | |
| 415 | + rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVEB_HSPI_READBACK; | |
| 437 | 416 | |
| 438 | 417 | } |
| 439 | 418 | EXPORT_SYMBOL(_rtl92c_phy_init_bb_rf_register_definition); |
| @@ -724,6 +703,26 @@ u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw) · 284 unmodified lines | ||
| 724 | 703 | } |
| 725 | 704 | EXPORT_SYMBOL(rtl92c_phy_sw_chnl); |
| 726 | 705 | |
| 706 | +static void _rtl92c_phy_sw_rf_setting(struct ieee80211_hw *hw, u8 channel) | |
| 707 | +{ | |
| 708 | + struct rtl_priv *rtlpriv = rtl_priv(hw); | |
| 709 | + struct rtl_phy *rtlphy = &(rtlpriv->phy); | |
| 710 | + struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | |
| 711 | + | |
| 712 | + if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) { | |
| 713 | + if (channel == 6 && rtlphy->current_chan_bw == | |
| 714 | + HT_CHANNEL_WIDTH_20) | |
| 715 | + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, | |
| 716 | + 0x00255); | |
| 717 | + else{ | |
| 718 | + u32 backupRF0x1A = (u32)rtl_get_rfreg(hw, RF90_PATH_A, | |
| 719 | + RF_RX_G1, RFREG_OFFSET_MASK); | |
| 720 | + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, | |
| 721 | + backupRF0x1A); | |
| 722 | + } | |
| 723 | + } | |
| 724 | +} | |
| 725 | + | |
| 727 | 726 | static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, |
| 728 | 727 | u32 cmdtableidx, u32 cmdtablesz, |
| 729 | 728 | enum swchnlcmd_id cmdid, |
| @@ -837,6 +836,7 @@ bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, · 107 unmodified lines | ||
| 837 | 836 | currentcmd->para1, |
| 838 | 837 | RFREG_OFFSET_MASK, |
| 839 | 838 | rtlphy->rfreg_chnlval[rfpath]); |
| 839 | + _rtl92c_phy_sw_rf_setting(hw, channel); | |
| 840 | 840 | } |
| 841 | 841 | break; |
| 842 | 842 | default: |
| @@ -116,6 +116,9 @@ · 115 unmodified lines | ||
| 116 | 116 | LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) |
| 117 | 117 | |
| 118 | 118 | #define CHIP_VER_B BIT(4) |
| 119 | +#define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3) | |
| 120 | +#define CHIP_BONDING_92C_1T2R 0x1 | |
| 121 | +#define RF_TYPE_1T2R BIT(1) | |
| 119 | 122 | #define CHIP_92C_BITMASK BIT(0) |
| 120 | 123 | #define CHIP_UNKNOWN BIT(7) |
| 121 | 124 | #define CHIP_92C_1T2R 0x03 |
| @@ -41,7 +41,7 @@ void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw) · 40 unmodified lines | ||
| 41 | 41 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 42 | 42 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
| 43 | 43 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
| 44 | − long undecorated_smoothed_pwdb; | |
| 44 | + long undec_sm_pwdb; | |
| 45 | 45 | |
| 46 | 46 | if (!rtlpriv->dm.dynamic_txpower_enable) |
| 47 | 47 | return; |
| @@ -52,7 +52,7 @@ void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw) · 4 unmodified lines | ||
| 52 | 52 | } |
| 53 | 53 | |
| 54 | 54 | if ((mac->link_state < MAC80211_LINKED) && |
| 55 | − (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) { | |
| 55 | + (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { | |
| 56 | 56 | RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, |
| 57 | 57 | "Not connected to any\n"); |
| 58 | 58 | |
| @@ -64,41 +64,35 @@ void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw) · 5 unmodified lines | ||
| 64 | 64 | |
| 65 | 65 | if (mac->link_state >= MAC80211_LINKED) { |
| 66 | 66 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { |
| 67 | − undecorated_smoothed_pwdb = | |
| 68 | − rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; | |
| 67 | + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; | |
| 69 | 68 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 70 | 69 | "AP Client PWDB = 0x%lx\n", |
| 71 | − undecorated_smoothed_pwdb); | |
| 70 | + undec_sm_pwdb); | |
| 72 | 71 | } else { |
| 73 | − undecorated_smoothed_pwdb = | |
| 74 | − rtlpriv->dm.undecorated_smoothed_pwdb; | |
| 72 | + undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; | |
| 75 | 73 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 76 | 74 | "STA Default Port PWDB = 0x%lx\n", |
| 77 | − undecorated_smoothed_pwdb); | |
| 75 | + undec_sm_pwdb); | |
| 78 | 76 | } |
| 79 | 77 | } else { |
| 80 | − undecorated_smoothed_pwdb = | |
| 81 | − rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; | |
| 78 | + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; | |
| 82 | 79 | |
| 83 | 80 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 84 | 81 | "AP Ext Port PWDB = 0x%lx\n", |
| 85 | − undecorated_smoothed_pwdb); | |
| 82 | + undec_sm_pwdb); | |
| 86 | 83 | } |
| 87 | 84 | |
| 88 | − if (undecorated_smoothed_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { | |
| 85 | + if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { | |
| 89 | 86 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; |
| 90 | 87 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 91 | 88 | "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); |
| 92 | − } else if ((undecorated_smoothed_pwdb < | |
| 93 | − (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && | |
| 94 | − (undecorated_smoothed_pwdb >= | |
| 95 | − TX_POWER_NEAR_FIELD_THRESH_LVL1)) { | |
| 89 | + } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && | |
| 90 | + (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) { | |
| 96 | 91 | |
| 97 | 92 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; |
| 98 | 93 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 99 | 94 | "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"); |
| 100 | − } else if (undecorated_smoothed_pwdb < | |
| 101 | − (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { | |
| 95 | + } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { | |
| 102 | 96 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; |
| 103 | 97 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 104 | 98 | "TXHIGHPWRLEVEL_NORMAL\n"); |
| @@ -896,7 +896,6 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) · 895 unmodified lines | ||
| 896 | 896 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
| 897 | 897 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); |
| 898 | 898 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); |
| 899 | − static bool iqk_initialized; /* initialized to false */ | |
| 900 | 899 | bool rtstatus = true; |
| 901 | 900 | bool is92c; |
| 902 | 901 | int err; |
| @@ -921,9 +920,28 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) · 18 unmodified lines | ||
| 921 | 920 | |
| 922 | 921 | rtlhal->last_hmeboxnum = 0; |
| 923 | 922 | rtl92c_phy_mac_config(hw); |
| 923 | + /* because last function modify RCR, so we update | |
| 924 | + * rcr var here, or TP will unstable for receive_config | |
| 925 | + * is wrong, RX RCR_ACRC32 will cause TP unstabel & Rx | |
| 926 | + * RCR_APP_ICV will cause mac80211 unassoc for cisco 1252*/ | |
| 927 | + rtlpci->receive_config = rtl_read_dword(rtlpriv, REG_RCR); | |
| 928 | + rtlpci->receive_config &= ~(RCR_ACRC32 | RCR_AICV); | |
| 929 | + rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config); | |
| 924 | 930 | rtl92c_phy_bb_config(hw); |
| 925 | 931 | rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; |
| 926 | 932 | rtl92c_phy_rf_config(hw); |
| 933 | + if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && | |
| 934 | + !IS_92C_SERIAL(rtlhal->version)) { | |
| 935 | + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255); | |
| 936 | + rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00); | |
| 937 | + } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) { | |
| 938 | + rtl_set_rfreg(hw, RF90_PATH_A, 0x0C, MASKDWORD, 0x894AE); | |
| 939 | + rtl_set_rfreg(hw, RF90_PATH_A, 0x0A, MASKDWORD, 0x1AF31); | |
| 940 | + rtl_set_rfreg(hw, RF90_PATH_A, RF_IPA, MASKDWORD, 0x8F425); | |
| 941 | + rtl_set_rfreg(hw, RF90_PATH_A, RF_SYN_G2, MASKDWORD, 0x4F200); | |
| 942 | + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK1, MASKDWORD, 0x44053); | |
| 943 | + rtl_set_rfreg(hw, RF90_PATH_A, RF_RCK2, MASKDWORD, 0x80201); | |
| 944 | + } | |
| 927 | 945 | rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0, |
| 928 | 946 | RF_CHNLBW, RFREG_OFFSET_MASK); |
| 929 | 947 | rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1, |
| @@ -945,11 +963,11 @@ int rtl92ce_hw_init(struct ieee80211_hw *hw) · 15 unmodified lines | ||
| 945 | 963 | |
| 946 | 964 | if (ppsc->rfpwr_state == ERFON) { |
| 947 | 965 | rtl92c_phy_set_rfpath_switch(hw, 1); |
| 948 | − if (iqk_initialized) { | |
| 966 | + if (rtlphy->iqk_initialized) { | |
| 949 | 967 | rtl92c_phy_iq_calibrate(hw, true); |
| 950 | 968 | } else { |
| 951 | 969 | rtl92c_phy_iq_calibrate(hw, false); |
| 952 | − iqk_initialized = true; | |
| 970 | + rtlphy->iqk_initialized = true; | |
| 953 | 971 | } |
| 954 | 972 | |
| 955 | 973 | rtl92c_dm_check_txpower_tracking(hw); |
| @@ -1004,6 +1022,13 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw) · 48 unmodified lines | ||
| 1004 | 1022 | ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) | |
| 1005 | 1023 | CHIP_VENDOR_UMC)); |
| 1006 | 1024 | } |
| 1025 | + if (IS_92C_SERIAL(version)) { | |
| 1026 | + value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM); | |
| 1027 | + version = (enum version_8192c)(version | | |
| 1028 | + ((CHIP_BONDING_IDENTIFIER(value32) | |
| 1029 | + == CHIP_BONDING_92C_1T2R) ? | |
| 1030 | + RF_TYPE_1T2R : 0)); | |
| 1031 | + } | |
| 1007 | 1032 | } |
| 1008 | 1033 | |
| 1009 | 1034 | switch (version) { |
| @@ -1019,12 +1044,30 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw) · 9 unmodified lines | ||
| 1019 | 1044 | case VERSION_A_CHIP_88C: |
| 1020 | 1045 | versionid = "A_CHIP_88C"; |
| 1021 | 1046 | break; |
| 1047 | + case VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT: | |
| 1048 | + versionid = "A_CUT_92C_1T2R"; | |
| 1049 | + break; | |
| 1050 | + case VERSION_NORMAL_UMC_CHIP_92C_A_CUT: | |
| 1051 | + versionid = "A_CUT_92C"; | |
| 1052 | + break; | |
| 1053 | + case VERSION_NORMAL_UMC_CHIP_88C_A_CUT: | |
| 1054 | + versionid = "A_CUT_88C"; | |
| 1055 | + break; | |
| 1056 | + case VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT: | |
| 1057 | + versionid = "B_CUT_92C_1T2R"; | |
| 1058 | + break; | |
| 1059 | + case VERSION_NORMAL_UMC_CHIP_92C_B_CUT: | |
| 1060 | + versionid = "B_CUT_92C"; | |
| 1061 | + break; | |
| 1062 | + case VERSION_NORMAL_UMC_CHIP_88C_B_CUT: | |
| 1063 | + versionid = "B_CUT_88C"; | |
| 1064 | + break; | |
| 1022 | 1065 | default: |
| 1023 | 1066 | versionid = "Unknown. Bug?"; |
| 1024 | 1067 | break; |
| 1025 | 1068 | } |
| 1026 | 1069 | |
| 1027 | − RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | |
| 1070 | + RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, | |
| 1028 | 1071 | "Chip Version ID: %s\n", versionid); |
| 1029 | 1072 | |
| 1030 | 1073 | switch (version & 0x3) { |
| @@ -1197,6 +1240,7 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw) · 166 unmodified lines | ||
| 1197 | 1240 | { |
| 1198 | 1241 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 1199 | 1242 | struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); |
| 1243 | + struct rtl_hal *rtlhal = rtl_hal(rtlpriv); | |
| 1200 | 1244 | u8 u1b_tmp; |
| 1201 | 1245 | u32 u4b_tmp; |
| 1202 | 1246 | |
| @@ -1225,7 +1269,8 @@ static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw) · 22 unmodified lines | ||
| 1225 | 1269 | rtl_write_word(rtlpriv, REG_GPIO_IO_SEL, 0x0790); |
| 1226 | 1270 | rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080); |
| 1227 | 1271 | rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80); |
| 1228 | − rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23); | |
| 1272 | + if (!IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) | |
| 1273 | + rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23); | |
| 1229 | 1274 | if (rtlpcipriv->bt_coexist.bt_coexistence) { |
| 1230 | 1275 | u4b_tmp = rtl_read_dword(rtlpriv, REG_AFE_XTAL_CTRL); |
| 1231 | 1276 | u4b_tmp |= 0x03824800; |
| @@ -1254,6 +1299,9 @@ void rtl92ce_card_disable(struct ieee80211_hw *hw) · 22 unmodified lines | ||
| 1254 | 1299 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); |
| 1255 | 1300 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); |
| 1256 | 1301 | _rtl92ce_poweroff_adapter(hw); |
| 1302 | + | |
| 1303 | + /* after power off we should do iqk again */ | |
| 1304 | + rtlpriv->phy.iqk_initialized = false; | |
| 1257 | 1305 | } |
| 1258 | 1306 | |
| 1259 | 1307 | void rtl92ce_interrupt_recognized(struct ieee80211_hw *hw, |
| @@ -1355,9 +1403,9 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, · 95 unmodified lines | ||
| 1355 | 1403 | tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i]; |
| 1356 | 1404 | else |
| 1357 | 1405 | tempval = EEPROM_DEFAULT_HT40_2SDIFF; |
| 1358 | − rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_A][i] = | |
| 1406 | + rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_A][i] = | |
| 1359 | 1407 | (tempval & 0xf); |
| 1360 | − rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_B][i] = | |
| 1408 | + rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_B][i] = | |
| 1361 | 1409 | ((tempval & 0xf0) >> 4); |
| 1362 | 1410 | } |
| 1363 | 1411 | |
| @@ -1381,7 +1429,7 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, · 17 unmodified lines | ||
| 1381 | 1429 | "RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n", |
| 1382 | 1430 | rf_path, i, |
| 1383 | 1431 | rtlefuse-> |
| 1384 | − eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][i]); | |
| 1432 | + eprom_chnl_txpwr_ht40_2sdf[rf_path][i]); | |
| 1385 | 1433 | |
| 1386 | 1434 | for (rf_path = 0; rf_path < 2; rf_path++) { |
| 1387 | 1435 | for (i = 0; i < 14; i++) { |
| @@ -1396,14 +1444,14 @@ static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, · 8 unmodified lines | ||
| 1396 | 1444 | if ((rtlefuse-> |
| 1397 | 1445 | eeprom_chnlarea_txpwr_ht40_1s[rf_path][index] - |
| 1398 | 1446 | rtlefuse-> |
| 1399 | − eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][index]) | |
| 1447 | + eprom_chnl_txpwr_ht40_2sdf[rf_path][index]) | |
| 1400 | 1448 | > 0) { |
| 1401 | 1449 | rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = |
| 1402 | 1450 | rtlefuse-> |
| 1403 | 1451 | eeprom_chnlarea_txpwr_ht40_1s[rf_path] |
| 1404 | 1452 | [index] - |
| 1405 | 1453 | rtlefuse-> |
| 1406 | − eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path] | |
| 1454 | + eprom_chnl_txpwr_ht40_2sdf[rf_path] | |
| 1407 | 1455 | [index]; |
| 1408 | 1456 | } else { |
| 1409 | 1457 | rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0; |
| @@ -1912,16 +1960,16 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, · 502 unmodified lines | ||
| 1912 | 1960 | ratr_bitmap &= 0x0f0ff0ff; |
| 1913 | 1961 | break; |
| 1914 | 1962 | } |
| 1963 | + sta_entry->ratr_index = ratr_index; | |
| 1964 | + | |
| 1915 | 1965 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, |
| 1916 | 1966 | "ratr_bitmap :%x\n", ratr_bitmap); |
| 1917 | 1967 | *(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) | |
| 1918 | 1968 | (ratr_index << 28); |
| 1919 | 1969 | rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; |
| 1920 | 1970 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, |
| 1921 | − "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n", | |
| 1922 | − ratr_index, ratr_bitmap, | |
| 1923 | − rate_mask[0], rate_mask[1], rate_mask[2], rate_mask[3], | |
| 1924 | − rate_mask[4]); | |
| 1971 | + "Rate_index:%x, ratr_val:%x, %5phC\n", | |
| 1972 | + ratr_index, ratr_bitmap, rate_mask); | |
| 1925 | 1973 | rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask); |
| 1926 | 1974 | |
| 1927 | 1975 | if (macid != 0) |
| @@ -2176,7 +2224,7 @@ static void rtl8192ce_bt_var_init(struct ieee80211_hw *hw) · 248 unmodified lines | ||
| 2176 | 2224 | |
| 2177 | 2225 | if (rtlpcipriv->bt_coexist.reg_bt_iso == 2) |
| 2178 | 2226 | rtlpcipriv->bt_coexist.bt_ant_isolation = |
| 2179 | − rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation; | |
| 2227 | + rtlpcipriv->bt_coexist.eeprom_bt_ant_isol; | |
| 2180 | 2228 | else |
| 2181 | 2229 | rtlpcipriv->bt_coexist.bt_ant_isolation = |
| 2182 | 2230 | rtlpcipriv->bt_coexist.reg_bt_iso; |
| @@ -2207,23 +2255,22 @@ void rtl8192ce_read_bt_coexist_info_from_hwpg(struct ieee80211_hw *hw, · 24 unmodified lines | ||
| 2207 | 2255 | bool auto_load_fail, u8 *hwinfo) |
| 2208 | 2256 | { |
| 2209 | 2257 | struct rtl_pci_priv *rtlpcipriv = rtl_pcipriv(hw); |
| 2210 | − u8 value; | |
| 2258 | + u8 val; | |
| 2211 | 2259 | |
| 2212 | 2260 | if (!auto_load_fail) { |
| 2213 | 2261 | rtlpcipriv->bt_coexist.eeprom_bt_coexist = |
| 2214 | 2262 | ((hwinfo[RF_OPTION1] & 0xe0) >> 5); |
| 2215 | − value = hwinfo[RF_OPTION4]; | |
| 2216 | − rtlpcipriv->bt_coexist.eeprom_bt_type = ((value & 0xe) >> 1); | |
| 2217 | − rtlpcipriv->bt_coexist.eeprom_bt_ant_num = (value & 0x1); | |
| 2218 | − rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation = | |
| 2219 | − ((value & 0x10) >> 4); | |
| 2263 | + val = hwinfo[RF_OPTION4]; | |
| 2264 | + rtlpcipriv->bt_coexist.eeprom_bt_type = ((val & 0xe) >> 1); | |
| 2265 | + rtlpcipriv->bt_coexist.eeprom_bt_ant_num = (val & 0x1); | |
| 2266 | + rtlpcipriv->bt_coexist.eeprom_bt_ant_isol = ((val & 0x10) >> 4); | |
| 2220 | 2267 | rtlpcipriv->bt_coexist.eeprom_bt_radio_shared = |
| 2221 | − ((value & 0x20) >> 5); | |
| 2268 | + ((val & 0x20) >> 5); | |
| 2222 | 2269 | } else { |
| 2223 | 2270 | rtlpcipriv->bt_coexist.eeprom_bt_coexist = 0; |
| 2224 | 2271 | rtlpcipriv->bt_coexist.eeprom_bt_type = BT_2WIRE; |
| 2225 | 2272 | rtlpcipriv->bt_coexist.eeprom_bt_ant_num = ANT_X2; |
| 2226 | − rtlpcipriv->bt_coexist.eeprom_bt_ant_isolation = 0; | |
| 2273 | + rtlpcipriv->bt_coexist.eeprom_bt_ant_isol = 0; | |
| 2227 | 2274 | rtlpcipriv->bt_coexist.eeprom_bt_radio_shared = BT_RADIO_SHARED; |
| 2228 | 2275 | } |
| 2229 | 2276 | |
| @@ -82,6 +82,8 @@ bool rtl92c_phy_mac_config(struct ieee80211_hw *hw) · 81 unmodified lines | ||
| 82 | 82 | |
| 83 | 83 | if (is92c) |
| 84 | 84 | rtl_write_byte(rtlpriv, 0x14, 0x71); |
| 85 | + else | |
| 86 | + rtl_write_byte(rtlpriv, 0x04CA, 0x0A); | |
| 85 | 87 | return rtstatus; |
| 86 | 88 | } |
| 87 | 89 | |
| @@ -97,15 +97,12 @@ void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, · 96 unmodified lines | ||
| 97 | 97 | } |
| 98 | 98 | |
| 99 | 99 | if (rtlefuse->eeprom_regulatory == 0) { |
| 100 | − tmpval = | |
| 101 | − (rtlphy->mcs_txpwrlevel_origoffset[0][6]) + | |
| 102 | − (rtlphy->mcs_txpwrlevel_origoffset[0][7] << | |
| 103 | − 8); | |
| 100 | + tmpval = (rtlphy->mcs_offset[0][6]) + | |
| 101 | + (rtlphy->mcs_offset[0][7] << 8); | |
| 104 | 102 | tx_agc[RF90_PATH_A] += tmpval; |
| 105 | 103 | |
| 106 | − tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) + | |
| 107 | − (rtlphy->mcs_txpwrlevel_origoffset[0][15] << | |
| 108 | − 24); | |
| 104 | + tmpval = (rtlphy->mcs_offset[0][14]) + | |
| 105 | + (rtlphy->mcs_offset[0][15] << 24); | |
| 109 | 106 | tx_agc[RF90_PATH_B] += tmpval; |
| 110 | 107 | } |
| 111 | 108 | } |
| @@ -209,8 +206,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, · 97 unmodified lines | ||
| 209 | 206 | case 0: |
| 210 | 207 | chnlgroup = 0; |
| 211 | 208 | |
| 212 | − writeVal = | |
| 213 | − rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index + | |
| 209 | + writeVal = rtlphy->mcs_offset[chnlgroup][index + | |
| 214 | 210 | (rf ? 8 : 0)] |
| 215 | 211 | + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); |
| 216 | 212 | |
| @@ -240,8 +236,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, · 23 unmodified lines | ||
| 240 | 236 | chnlgroup++; |
| 241 | 237 | } |
| 242 | 238 | |
| 243 | − writeVal = | |
| 244 | − rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] | |
| 239 | + writeVal = rtlphy->mcs_offset[chnlgroup] | |
| 245 | 240 | [index + (rf ? 8 : 0)] + ((index < 2) ? |
| 246 | 241 | powerBase0[rf] : |
| 247 | 242 | powerBase1[rf]); |
| @@ -276,8 +271,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, · 28 unmodified lines | ||
| 276 | 271 | 1]); |
| 277 | 272 | } |
| 278 | 273 | for (i = 0; i < 4; i++) { |
| 279 | − pwr_diff_limit[i] = | |
| 280 | − (u8) ((rtlphy->mcs_txpwrlevel_origoffset | |
| 274 | + pwr_diff_limit[i] = (u8) ((rtlphy->mcs_offset | |
| 281 | 275 | [chnlgroup][index + |
| 282 | 276 | (rf ? 8 : 0)] & (0x7f << (i * 8))) >> |
| 283 | 277 | (i * 8)); |
| @@ -317,8 +311,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, · 33 unmodified lines | ||
| 317 | 311 | break; |
| 318 | 312 | default: |
| 319 | 313 | chnlgroup = 0; |
| 320 | − writeVal = | |
| 321 | − rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] | |
| 314 | + writeVal = rtlphy->mcs_offset[chnlgroup] | |
| 322 | 315 | [index + (rf ? 8 : 0)] |
| 323 | 316 | + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); |
| 324 | 317 | |
| @@ -162,12 +162,10 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) · 161 unmodified lines | ||
| 162 | 162 | |
| 163 | 163 | /* request fw */ |
| 164 | 164 | if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && |
| 165 | − !IS_92C_SERIAL(rtlhal->version)) { | |
| 165 | + !IS_92C_SERIAL(rtlhal->version)) | |
| 166 | 166 | rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin"; |
| 167 | − } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) { | |
| 167 | + else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) | |
| 168 | 168 | rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin"; |
| 169 | − pr_info("****** This B_CUT device may not work with kernels 3.6 and earlier\n"); | |
| 170 | − } | |
| 171 | 169 | |
| 172 | 170 | rtlpriv->max_fw_size = 0x4000; |
| 173 | 171 | pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); |
| @@ -127,11 +127,11 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, · 126 unmodified lines | ||
| 127 | 127 | { |
| 128 | 128 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 129 | 129 | struct phy_sts_cck_8192s_t *cck_buf; |
| 130 | + struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv); | |
| 130 | 131 | s8 rx_pwr_all = 0, rx_pwr[4]; |
| 131 | 132 | u8 evm, pwdb_all, rf_rx_num = 0; |
| 132 | 133 | u8 i, max_spatial_stream; |
| 133 | 134 | u32 rssi, total_rssi = 0; |
| 134 | − bool in_powersavemode = false; | |
| 135 | 135 | bool is_cck_rate; |
| 136 | 136 | |
| 137 | 137 | is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc); |
| @@ -140,14 +140,14 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, · 2 unmodified lines | ||
| 140 | 140 | pstats->is_cck = is_cck_rate; |
| 141 | 141 | pstats->packet_beacon = packet_beacon; |
| 142 | 142 | pstats->is_cck = is_cck_rate; |
| 143 | − pstats->rx_mimo_signalquality[0] = -1; | |
| 144 | − pstats->rx_mimo_signalquality[1] = -1; | |
| 143 | + pstats->rx_mimo_sig_qual[0] = -1; | |
| 144 | + pstats->rx_mimo_sig_qual[1] = -1; | |
| 145 | 145 | |
| 146 | 146 | if (is_cck_rate) { |
| 147 | 147 | u8 report, cck_highpwr; |
| 148 | 148 | cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; |
| 149 | 149 | |
| 150 | − if (!in_powersavemode) | |
| 150 | + if (ppsc->rfpwr_state == ERFON) | |
| 151 | 151 | cck_highpwr = (u8) rtl_get_bbreg(hw, |
| 152 | 152 | RFPGA0_XA_HSSIPARAMETER2, |
| 153 | 153 | BIT(9)); |
| @@ -211,8 +211,8 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, · 57 unmodified lines | ||
| 211 | 211 | } |
| 212 | 212 | |
| 213 | 213 | pstats->signalquality = sq; |
| 214 | − pstats->rx_mimo_signalquality[0] = sq; | |
| 215 | − pstats->rx_mimo_signalquality[1] = -1; | |
| 214 | + pstats->rx_mimo_sig_qual[0] = sq; | |
| 215 | + pstats->rx_mimo_sig_qual[1] = -1; | |
| 216 | 216 | } |
| 217 | 217 | } else { |
| 218 | 218 | rtlpriv->dm.rfpath_rxenable[0] = |
| @@ -251,8 +251,7 @@ static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw, · 32 unmodified lines | ||
| 251 | 251 | if (i == 0) |
| 252 | 252 | pstats->signalquality = |
| 253 | 253 | (u8) (evm & 0xff); |
| 254 | − pstats->rx_mimo_signalquality[i] = | |
| 255 | − (u8) (evm & 0xff); | |
| 254 | + pstats->rx_mimo_sig_qual[i] = (u8) (evm & 0xff); | |
| 256 | 255 | } |
| 257 | 256 | } |
| 258 | 257 | } |
| @@ -362,36 +361,31 @@ static void _rtl92ce_process_pwdb(struct ieee80211_hw *hw, · 103 unmodified lines | ||
| 362 | 361 | { |
| 363 | 362 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 364 | 363 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
| 365 | − long undecorated_smoothed_pwdb; | |
| 364 | + long undec_sm_pwdb; | |
| 366 | 365 | |
| 367 | 366 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { |
| 368 | 367 | return; |
| 369 | 368 | } else { |
| 370 | − undecorated_smoothed_pwdb = | |
| 371 | − rtlpriv->dm.undecorated_smoothed_pwdb; | |
| 369 | + undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; | |
| 372 | 370 | } |
| 373 | 371 | |
| 374 | 372 | if (pstats->packet_toself || pstats->packet_beacon) { |
| 375 | − if (undecorated_smoothed_pwdb < 0) | |
| 376 | − undecorated_smoothed_pwdb = pstats->rx_pwdb_all; | |
| 373 | + if (undec_sm_pwdb < 0) | |
| 374 | + undec_sm_pwdb = pstats->rx_pwdb_all; | |
| 377 | 375 | |
| 378 | − if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) { | |
| 379 | − undecorated_smoothed_pwdb = | |
| 380 | − (((undecorated_smoothed_pwdb) * | |
| 376 | + if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) { | |
| 377 | + undec_sm_pwdb = (((undec_sm_pwdb) * | |
| 381 | 378 | (RX_SMOOTH_FACTOR - 1)) + |
| 382 | 379 | (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); |
| 383 | 380 | |
| 384 | − undecorated_smoothed_pwdb = undecorated_smoothed_pwdb | |
| 385 | − + 1; | |
| 381 | + undec_sm_pwdb += 1; | |
| 386 | 382 | } else { |
| 387 | − undecorated_smoothed_pwdb = | |
| 388 | − (((undecorated_smoothed_pwdb) * | |
| 383 | + undec_sm_pwdb = (((undec_sm_pwdb) * | |
| 389 | 384 | (RX_SMOOTH_FACTOR - 1)) + |
| 390 | 385 | (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); |
| 391 | 386 | } |
| 392 | 387 | |
| 393 | − rtlpriv->dm.undecorated_smoothed_pwdb = | |
| 394 | − undecorated_smoothed_pwdb; | |
| 388 | + rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb; | |
| 395 | 389 | _rtl92ce_update_rxsignalstatistics(hw, pstats); |
| 396 | 390 | } |
| 397 | 391 | } |
| @@ -438,15 +432,14 @@ static void _rtl92ce_process_ui_link_quality(struct ieee80211_hw *hw, · 40 unmodified lines | ||
| 438 | 432 | for (n_spatialstream = 0; n_spatialstream < 2; |
| 439 | 433 | n_spatialstream++) { |
| 440 | 434 | if (pstats-> |
| 441 | − rx_mimo_signalquality[n_spatialstream] != | |
| 442 | − -1) { | |
| 435 | + rx_mimo_sig_qual[n_spatialstream] != -1) { | |
| 443 | 436 | if (rtlpriv->stats. |
| 444 | 437 | rx_evm_percentage[n_spatialstream] |
| 445 | 438 | == 0) { |
| 446 | 439 | rtlpriv->stats. |
| 447 | 440 | rx_evm_percentage |
| 448 | 441 | [n_spatialstream] = |
| 449 | − pstats->rx_mimo_signalquality | |
| 442 | + pstats->rx_mimo_sig_qual | |
| 450 | 443 | [n_spatialstream]; |
| 451 | 444 | } |
| 452 | 445 | |
| @@ -456,8 +449,7 @@ static void _rtl92ce_process_ui_link_quality(struct ieee80211_hw *hw, · 3 unmodified lines | ||
| 456 | 449 | stats.rx_evm_percentage |
| 457 | 450 | [n_spatialstream] * |
| 458 | 451 | (RX_SMOOTH_FACTOR - 1)) + |
| 459 | − (pstats-> | |
| 460 | − rx_mimo_signalquality | |
| 452 | + (pstats->rx_mimo_sig_qual | |
| 461 | 453 | [n_spatialstream] * 1)) / |
| 462 | 454 | (RX_SMOOTH_FACTOR); |
| 463 | 455 | } |
| @@ -39,7 +39,7 @@ void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw) · 38 unmodified lines | ||
| 39 | 39 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 40 | 40 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
| 41 | 41 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
| 42 | − long undecorated_smoothed_pwdb; | |
| 42 | + long undec_sm_pwdb; | |
| 43 | 43 | |
| 44 | 44 | if (!rtlpriv->dm.dynamic_txpower_enable) |
| 45 | 45 | return; |
| @@ -50,7 +50,7 @@ void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw) · 4 unmodified lines | ||
| 50 | 50 | } |
| 51 | 51 | |
| 52 | 52 | if ((mac->link_state < MAC80211_LINKED) && |
| 53 | − (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) { | |
| 53 | + (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { | |
| 54 | 54 | RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, |
| 55 | 55 | "Not connected to any\n"); |
| 56 | 56 | |
| @@ -62,41 +62,35 @@ void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw) · 5 unmodified lines | ||
| 62 | 62 | |
| 63 | 63 | if (mac->link_state >= MAC80211_LINKED) { |
| 64 | 64 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { |
| 65 | − undecorated_smoothed_pwdb = | |
| 66 | − rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; | |
| 65 | + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; | |
| 67 | 66 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 68 | 67 | "AP Client PWDB = 0x%lx\n", |
| 69 | − undecorated_smoothed_pwdb); | |
| 68 | + undec_sm_pwdb); | |
| 70 | 69 | } else { |
| 71 | − undecorated_smoothed_pwdb = | |
| 72 | − rtlpriv->dm.undecorated_smoothed_pwdb; | |
| 70 | + undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; | |
| 73 | 71 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 74 | 72 | "STA Default Port PWDB = 0x%lx\n", |
| 75 | − undecorated_smoothed_pwdb); | |
| 73 | + undec_sm_pwdb); | |
| 76 | 74 | } |
| 77 | 75 | } else { |
| 78 | − undecorated_smoothed_pwdb = | |
| 79 | − rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; | |
| 76 | + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; | |
| 80 | 77 | |
| 81 | 78 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 82 | 79 | "AP Ext Port PWDB = 0x%lx\n", |
| 83 | − undecorated_smoothed_pwdb); | |
| 80 | + undec_sm_pwdb); | |
| 84 | 81 | } |
| 85 | 82 | |
| 86 | − if (undecorated_smoothed_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { | |
| 83 | + if (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) { | |
| 87 | 84 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; |
| 88 | 85 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 89 | 86 | "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); |
| 90 | − } else if ((undecorated_smoothed_pwdb < | |
| 91 | − (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && | |
| 92 | − (undecorated_smoothed_pwdb >= | |
| 93 | − TX_POWER_NEAR_FIELD_THRESH_LVL1)) { | |
| 87 | + } else if ((undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) && | |
| 88 | + (undec_sm_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL1)) { | |
| 94 | 89 | |
| 95 | 90 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1; |
| 96 | 91 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 97 | 92 | "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"); |
| 98 | − } else if (undecorated_smoothed_pwdb < | |
| 99 | − (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { | |
| 93 | + } else if (undec_sm_pwdb < (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { | |
| 100 | 94 | rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL; |
| 101 | 95 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 102 | 96 | "TXHIGHPWRLEVEL_NORMAL\n"); |
| @@ -152,9 +152,9 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, · 151 unmodified lines | ||
| 152 | 152 | tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i]; |
| 153 | 153 | else |
| 154 | 154 | tempval = EEPROM_DEFAULT_HT40_2SDIFF; |
| 155 | − rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_A][i] = | |
| 155 | + rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_A][i] = | |
| 156 | 156 | (tempval & 0xf); |
| 157 | − rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_B][i] = | |
| 157 | + rtlefuse->eprom_chnl_txpwr_ht40_2sdf[RF90_PATH_B][i] = | |
| 158 | 158 | ((tempval & 0xf0) >> 4); |
| 159 | 159 | } |
| 160 | 160 | for (rf_path = 0; rf_path < 2; rf_path++) |
| @@ -177,7 +177,7 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, · 16 unmodified lines | ||
| 177 | 177 | "RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n", |
| 178 | 178 | rf_path, i, |
| 179 | 179 | rtlefuse-> |
| 180 | − eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][i]); | |
| 180 | + eprom_chnl_txpwr_ht40_2sdf[rf_path][i]); | |
| 181 | 181 | for (rf_path = 0; rf_path < 2; rf_path++) { |
| 182 | 182 | for (i = 0; i < 14; i++) { |
| 183 | 183 | index = _rtl92c_get_chnl_group((u8) i); |
| @@ -189,13 +189,13 @@ static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw, · 5 unmodified lines | ||
| 189 | 189 | if ((rtlefuse-> |
| 190 | 190 | eeprom_chnlarea_txpwr_ht40_1s[rf_path][index] - |
| 191 | 191 | rtlefuse-> |
| 192 | − eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][index]) | |
| 192 | + eprom_chnl_txpwr_ht40_2sdf[rf_path][index]) | |
| 193 | 193 | > 0) { |
| 194 | 194 | rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = |
| 195 | 195 | rtlefuse-> |
| 196 | 196 | eeprom_chnlarea_txpwr_ht40_1s[rf_path] |
| 197 | 197 | [index] - rtlefuse-> |
| 198 | − eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path] | |
| 198 | + eprom_chnl_txpwr_ht40_2sdf[rf_path] | |
| 199 | 199 | [index]; |
| 200 | 200 | } else { |
| 201 | 201 | rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0; |
| @@ -2169,10 +2169,8 @@ void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) · 1967 unmodified lines | ||
| 2169 | 2169 | ratr_index << 28); |
| 2170 | 2170 | rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; |
| 2171 | 2171 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, |
| 2172 | − "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n", | |
| 2173 | − ratr_index, ratr_bitmap, | |
| 2174 | − rate_mask[0], rate_mask[1], rate_mask[2], rate_mask[3], | |
| 2175 | − rate_mask[4]); | |
| 2172 | + "Rate_index:%x, ratr_val:%x, %5phC\n", | |
| 2173 | + ratr_index, ratr_bitmap, rate_mask); | |
| 2176 | 2174 | rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask); |
| 2177 | 2175 | } |
| 2178 | 2176 | |
| @@ -46,7 +46,7 @@ · 45 unmodified lines | ||
| 46 | 46 | |
| 47 | 47 | #define LINK_Q ui_link_quality |
| 48 | 48 | #define RX_EVM rx_evm_percentage |
| 49 | −#define RX_SIGQ rx_mimo_signalquality | |
| 49 | +#define RX_SIGQ rx_mimo_sig_qual | |
| 50 | 50 | |
| 51 | 51 | |
| 52 | 52 | void rtl92c_read_chip_version(struct ieee80211_hw *hw) |
| @@ -982,32 +982,27 @@ static void _rtl92c_process_pwdb(struct ieee80211_hw *hw, · 929 unmodified lines | ||
| 982 | 982 | { |
| 983 | 983 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 984 | 984 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
| 985 | − long undecorated_smoothed_pwdb = 0; | |
| 985 | + long undec_sm_pwdb = 0; | |
| 986 | 986 | |
| 987 | 987 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { |
| 988 | 988 | return; |
| 989 | 989 | } else { |
| 990 | − undecorated_smoothed_pwdb = | |
| 991 | − rtlpriv->dm.undecorated_smoothed_pwdb; | |
| 990 | + undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; | |
| 992 | 991 | } |
| 993 | 992 | if (pstats->packet_toself || pstats->packet_beacon) { |
| 994 | − if (undecorated_smoothed_pwdb < 0) | |
| 995 | − undecorated_smoothed_pwdb = pstats->rx_pwdb_all; | |
| 996 | − if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) { | |
| 997 | − undecorated_smoothed_pwdb = | |
| 998 | − (((undecorated_smoothed_pwdb) * | |
| 993 | + if (undec_sm_pwdb < 0) | |
| 994 | + undec_sm_pwdb = pstats->rx_pwdb_all; | |
| 995 | + if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) { | |
| 996 | + undec_sm_pwdb = (((undec_sm_pwdb) * | |
| 999 | 997 | (RX_SMOOTH_FACTOR - 1)) + |
| 1000 | 998 | (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); |
| 1001 | − undecorated_smoothed_pwdb = undecorated_smoothed_pwdb | |
| 1002 | − + 1; | |
| 999 | + undec_sm_pwdb += 1; | |
| 1003 | 1000 | } else { |
| 1004 | − undecorated_smoothed_pwdb = | |
| 1005 | − (((undecorated_smoothed_pwdb) * | |
| 1001 | + undec_sm_pwdb = (((undec_sm_pwdb) * | |
| 1006 | 1002 | (RX_SMOOTH_FACTOR - 1)) + |
| 1007 | 1003 | (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); |
| 1008 | 1004 | } |
| 1009 | − rtlpriv->dm.undecorated_smoothed_pwdb = | |
| 1010 | − undecorated_smoothed_pwdb; | |
| 1005 | + rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb; | |
| 1011 | 1006 | _rtl92c_update_rxsignalstatistics(hw, pstats); |
| 1012 | 1007 | } |
| 1013 | 1008 | } |
| @@ -115,15 +115,11 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, · 114 unmodified lines | ||
| 115 | 115 | (ppowerlevel[idx1] << 24); |
| 116 | 116 | } |
| 117 | 117 | if (rtlefuse->eeprom_regulatory == 0) { |
| 118 | − tmpval = (rtlphy->mcs_txpwrlevel_origoffset | |
| 119 | − [0][6]) + | |
| 120 | − (rtlphy->mcs_txpwrlevel_origoffset | |
| 121 | − [0][7] << 8); | |
| 118 | + tmpval = (rtlphy->mcs_offset[0][6]) + | |
| 119 | + (rtlphy->mcs_offset[0][7] << 8); | |
| 122 | 120 | tx_agc[RF90_PATH_A] += tmpval; |
| 123 | − tmpval = (rtlphy->mcs_txpwrlevel_origoffset | |
| 124 | − [0][14]) + | |
| 125 | − (rtlphy->mcs_txpwrlevel_origoffset | |
| 126 | − [0][15] << 24); | |
| 121 | + tmpval = (rtlphy->mcs_offset[0][14]) + | |
| 122 | + (rtlphy->mcs_offset[0][15] << 24); | |
| 127 | 123 | tx_agc[RF90_PATH_B] += tmpval; |
| 128 | 124 | } |
| 129 | 125 | } |
| @@ -215,7 +211,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, · 85 unmodified lines | ||
| 215 | 211 | switch (rtlefuse->eeprom_regulatory) { |
| 216 | 212 | case 0: |
| 217 | 213 | chnlgroup = 0; |
| 218 | − writeVal = rtlphy->mcs_txpwrlevel_origoffset | |
| 214 | + writeVal = rtlphy->mcs_offset | |
| 219 | 215 | [chnlgroup][index + (rf ? 8 : 0)] |
| 220 | 216 | + ((index < 2) ? powerBase0[rf] : powerBase1[rf]); |
| 221 | 217 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, |
| @@ -238,8 +234,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, · 16 unmodified lines | ||
| 238 | 234 | else |
| 239 | 235 | chnlgroup += 4; |
| 240 | 236 | } |
| 241 | − writeVal = rtlphy->mcs_txpwrlevel_origoffset | |
| 242 | − [chnlgroup][index + | |
| 237 | + writeVal = rtlphy->mcs_offset[chnlgroup][index + | |
| 243 | 238 | (rf ? 8 : 0)] + |
| 244 | 239 | ((index < 2) ? powerBase0[rf] : |
| 245 | 240 | powerBase1[rf]); |
| @@ -271,8 +266,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, · 25 unmodified lines | ||
| 271 | 266 | [channel - 1]); |
| 272 | 267 | } |
| 273 | 268 | for (i = 0; i < 4; i++) { |
| 274 | − pwr_diff_limit[i] = | |
| 275 | − (u8) ((rtlphy->mcs_txpwrlevel_origoffset | |
| 269 | + pwr_diff_limit[i] = (u8) ((rtlphy->mcs_offset | |
| 276 | 270 | [chnlgroup][index + (rf ? 8 : 0)] |
| 277 | 271 | & (0x7f << (i * 8))) >> (i * 8)); |
| 278 | 272 | if (rtlphy->current_chan_bw == |
| @@ -306,7 +300,7 @@ static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, · 27 unmodified lines | ||
| 306 | 300 | break; |
| 307 | 301 | default: |
| 308 | 302 | chnlgroup = 0; |
| 309 | − writeVal = rtlphy->mcs_txpwrlevel_origoffset[chnlgroup] | |
| 303 | + writeVal = rtlphy->mcs_offset[chnlgroup] | |
| 310 | 304 | [index + (rf ? 8 : 0)] + ((index < 2) ? |
| 311 | 305 | powerBase0[rf] : powerBase1[rf]); |
| 312 | 306 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, |
| @@ -35,7 +35,7 @@ · 34 unmodified lines | ||
| 35 | 35 | #include "dm.h" |
| 36 | 36 | #include "fw.h" |
| 37 | 37 | |
| 38 | −#define UNDEC_SM_PWDB entry_min_undecoratedsmoothed_pwdb | |
| 38 | +#define UNDEC_SM_PWDB entry_min_undec_sm_pwdb | |
| 39 | 39 | |
| 40 | 40 | static const u32 ofdmswing_table[OFDM_TABLE_SIZE_92D] = { |
| 41 | 41 | 0x7f8001fe, /* 0, +6.0dB */ |
| @@ -164,18 +164,18 @@ static void rtl92d_dm_diginit(struct ieee80211_hw *hw) · 122 unmodified lines | ||
| 164 | 164 | de_digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; |
| 165 | 165 | de_digtable->cur_igvalue = 0x20; |
| 166 | 166 | de_digtable->pre_igvalue = 0x0; |
| 167 | − de_digtable->cursta_connectstate = DIG_STA_DISCONNECT; | |
| 168 | − de_digtable->presta_connectstate = DIG_STA_DISCONNECT; | |
| 169 | − de_digtable->curmultista_connectstate = DIG_MULTISTA_DISCONNECT; | |
| 167 | + de_digtable->cursta_cstate = DIG_STA_DISCONNECT; | |
| 168 | + de_digtable->presta_cstate = DIG_STA_DISCONNECT; | |
| 169 | + de_digtable->curmultista_cstate = DIG_MULTISTA_DISCONNECT; | |
| 170 | 170 | de_digtable->rssi_lowthresh = DM_DIG_THRESH_LOW; |
| 171 | 171 | de_digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; |
| 172 | 172 | de_digtable->fa_lowthresh = DM_FALSEALARM_THRESH_LOW; |
| 173 | 173 | de_digtable->fa_highthresh = DM_FALSEALARM_THRESH_HIGH; |
| 174 | 174 | de_digtable->rx_gain_range_max = DM_DIG_FA_UPPER; |
| 175 | 175 | de_digtable->rx_gain_range_min = DM_DIG_FA_LOWER; |
| 176 | − de_digtable->backoff_val = DM_DIG_BACKOFF_DEFAULT; | |
| 177 | − de_digtable->backoff_val_range_max = DM_DIG_BACKOFF_MAX; | |
| 178 | − de_digtable->backoff_val_range_min = DM_DIG_BACKOFF_MIN; | |
| 176 | + de_digtable->back_val = DM_DIG_BACKOFF_DEFAULT; | |
| 177 | + de_digtable->back_range_max = DM_DIG_BACKOFF_MAX; | |
| 178 | + de_digtable->back_range_min = DM_DIG_BACKOFF_MIN; | |
| 179 | 179 | de_digtable->pre_cck_pd_state = CCK_PD_STAGE_LOWRSSI; |
| 180 | 180 | de_digtable->cur_cck_pd_state = CCK_PD_STAGE_MAX; |
| 181 | 181 | de_digtable->large_fa_hit = 0; |
| @@ -273,35 +273,34 @@ static void rtl92d_dm_find_minimum_rssi(struct ieee80211_hw *hw) · 91 unmodified lines | ||
| 273 | 273 | /* Determine the minimum RSSI */ |
| 274 | 274 | if ((mac->link_state < MAC80211_LINKED) && |
| 275 | 275 | (rtlpriv->dm.UNDEC_SM_PWDB == 0)) { |
| 276 | − de_digtable->min_undecorated_pwdb_for_dm = 0; | |
| 276 | + de_digtable->min_undec_pwdb_for_dm = 0; | |
| 277 | 277 | RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, |
| 278 | 278 | "Not connected to any\n"); |
| 279 | 279 | } |
| 280 | 280 | if (mac->link_state >= MAC80211_LINKED) { |
| 281 | 281 | if (mac->opmode == NL80211_IFTYPE_AP || |
| 282 | 282 | mac->opmode == NL80211_IFTYPE_ADHOC) { |
| 283 | − de_digtable->min_undecorated_pwdb_for_dm = | |
| 283 | + de_digtable->min_undec_pwdb_for_dm = | |
| 284 | 284 | rtlpriv->dm.UNDEC_SM_PWDB; |
| 285 | 285 | RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, |
| 286 | 286 | "AP Client PWDB = 0x%lx\n", |
| 287 | 287 | rtlpriv->dm.UNDEC_SM_PWDB); |
| 288 | 288 | } else { |
| 289 | − de_digtable->min_undecorated_pwdb_for_dm = | |
| 290 | − rtlpriv->dm.undecorated_smoothed_pwdb; | |
| 289 | + de_digtable->min_undec_pwdb_for_dm = | |
| 290 | + rtlpriv->dm.undec_sm_pwdb; | |
| 291 | 291 | RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, |
| 292 | 292 | "STA Default Port PWDB = 0x%x\n", |
| 293 | − de_digtable->min_undecorated_pwdb_for_dm); | |
| 293 | + de_digtable->min_undec_pwdb_for_dm); | |
| 294 | 294 | } |
| 295 | 295 | } else { |
| 296 | − de_digtable->min_undecorated_pwdb_for_dm = | |
| 297 | − rtlpriv->dm.UNDEC_SM_PWDB; | |
| 296 | + de_digtable->min_undec_pwdb_for_dm = rtlpriv->dm.UNDEC_SM_PWDB; | |
| 298 | 297 | RT_TRACE(rtlpriv, COMP_BB_POWERSAVING, DBG_LOUD, |
| 299 | 298 | "AP Ext Port or disconnect PWDB = 0x%x\n", |
| 300 | − de_digtable->min_undecorated_pwdb_for_dm); | |
| 299 | + de_digtable->min_undec_pwdb_for_dm); | |
| 301 | 300 | } |
| 302 | 301 | |
| 303 | 302 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "MinUndecoratedPWDBForDM =%d\n", |
| 304 | − de_digtable->min_undecorated_pwdb_for_dm); | |
| 303 | + de_digtable->min_undec_pwdb_for_dm); | |
| 305 | 304 | } |
| 306 | 305 | |
| 307 | 306 | static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) |
| @@ -310,16 +309,16 @@ static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) · 2 unmodified lines | ||
| 310 | 309 | struct dig_t *de_digtable = &rtlpriv->dm_digtable; |
| 311 | 310 | unsigned long flag = 0; |
| 312 | 311 | |
| 313 | − if (de_digtable->cursta_connectstate == DIG_STA_CONNECT) { | |
| 312 | + if (de_digtable->cursta_cstate == DIG_STA_CONNECT) { | |
| 314 | 313 | if (de_digtable->pre_cck_pd_state == CCK_PD_STAGE_LOWRSSI) { |
| 315 | − if (de_digtable->min_undecorated_pwdb_for_dm <= 25) | |
| 314 | + if (de_digtable->min_undec_pwdb_for_dm <= 25) | |
| 316 | 315 | de_digtable->cur_cck_pd_state = |
| 317 | 316 | CCK_PD_STAGE_LOWRSSI; |
| 318 | 317 | else |
| 319 | 318 | de_digtable->cur_cck_pd_state = |
| 320 | 319 | CCK_PD_STAGE_HIGHRSSI; |
| 321 | 320 | } else { |
| 322 | − if (de_digtable->min_undecorated_pwdb_for_dm <= 20) | |
| 321 | + if (de_digtable->min_undec_pwdb_for_dm <= 20) | |
| 323 | 322 | de_digtable->cur_cck_pd_state = |
| 324 | 323 | CCK_PD_STAGE_LOWRSSI; |
| 325 | 324 | else |
| @@ -342,7 +341,7 @@ static void rtl92d_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw) · 16 unmodified lines | ||
| 342 | 341 | de_digtable->pre_cck_pd_state = de_digtable->cur_cck_pd_state; |
| 343 | 342 | } |
| 344 | 343 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "CurSTAConnectState=%s\n", |
| 345 | − de_digtable->cursta_connectstate == DIG_STA_CONNECT ? | |
| 344 | + de_digtable->cursta_cstate == DIG_STA_CONNECT ? | |
| 346 | 345 | "DIG_STA_CONNECT " : "DIG_STA_DISCONNECT"); |
| 347 | 346 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "CCKPDStage=%s\n", |
| 348 | 347 | de_digtable->cur_cck_pd_state == CCK_PD_STAGE_LOWRSSI ? |
| @@ -358,9 +357,9 @@ void rtl92d_dm_write_dig(struct ieee80211_hw *hw) · 9 unmodified lines | ||
| 358 | 357 | struct dig_t *de_digtable = &rtlpriv->dm_digtable; |
| 359 | 358 | |
| 360 | 359 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, |
| 361 | − "cur_igvalue = 0x%x, pre_igvalue = 0x%x, backoff_val = %d\n", | |
| 360 | + "cur_igvalue = 0x%x, pre_igvalue = 0x%x, back_val = %d\n", | |
| 362 | 361 | de_digtable->cur_igvalue, de_digtable->pre_igvalue, |
| 363 | − de_digtable->backoff_val); | |
| 362 | + de_digtable->back_val); | |
| 364 | 363 | if (de_digtable->dig_enable_flag == false) { |
| 365 | 364 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "DIG is disabled\n"); |
| 366 | 365 | de_digtable->pre_igvalue = 0x17; |
| @@ -382,13 +381,13 @@ static void rtl92d_early_mode_enabled(struct rtl_priv *rtlpriv) · 15 unmodified lines | ||
| 382 | 381 | if ((rtlpriv->mac80211.link_state >= MAC80211_LINKED) && |
| 383 | 382 | (rtlpriv->mac80211.vendor == PEER_CISCO)) { |
| 384 | 383 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "IOT_PEER = CISCO\n"); |
| 385 | − if (de_digtable->last_min_undecorated_pwdb_for_dm >= 50 | |
| 386 | − && de_digtable->min_undecorated_pwdb_for_dm < 50) { | |
| 384 | + if (de_digtable->last_min_undec_pwdb_for_dm >= 50 | |
| 385 | + && de_digtable->min_undec_pwdb_for_dm < 50) { | |
| 387 | 386 | rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x00); |
| 388 | 387 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, |
| 389 | 388 | "Early Mode Off\n"); |
| 390 | − } else if (de_digtable->last_min_undecorated_pwdb_for_dm <= 55 && | |
| 391 | − de_digtable->min_undecorated_pwdb_for_dm > 55) { | |
| 389 | + } else if (de_digtable->last_min_undec_pwdb_for_dm <= 55 && | |
| 390 | + de_digtable->min_undec_pwdb_for_dm > 55) { | |
| 392 | 391 | rtl_write_byte(rtlpriv, REG_EARLY_MODE_CONTROL, 0x0f); |
| 393 | 392 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, |
| 394 | 393 | "Early Mode On\n"); |
| @@ -409,8 +408,8 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw) · 14 unmodified lines | ||
| 409 | 408 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "==>\n"); |
| 410 | 409 | if (rtlpriv->rtlhal.earlymode_enable) { |
| 411 | 410 | rtl92d_early_mode_enabled(rtlpriv); |
| 412 | − de_digtable->last_min_undecorated_pwdb_for_dm = | |
| 413 | − de_digtable->min_undecorated_pwdb_for_dm; | |
| 411 | + de_digtable->last_min_undec_pwdb_for_dm = | |
| 412 | + de_digtable->min_undec_pwdb_for_dm; | |
| 414 | 413 | } |
| 415 | 414 | if (!rtlpriv->dm.dm_initialgain_enable) |
| 416 | 415 | return; |
| @@ -428,9 +427,9 @@ static void rtl92d_dm_dig(struct ieee80211_hw *hw) · 11 unmodified lines | ||
| 428 | 427 | RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD, "progress\n"); |
| 429 | 428 | /* Decide the current status and if modify initial gain or not */ |
| 430 | 429 | if (rtlpriv->mac80211.link_state >= MAC80211_LINKED) |
| 431 | − de_digtable->cursta_connectstate = DIG_STA_CONNECT; | |
| 430 | + de_digtable->cursta_cstate = DIG_STA_CONNECT; | |
| 432 | 431 | else |
| 433 | − de_digtable->cursta_connectstate = DIG_STA_DISCONNECT; | |
| 432 | + de_digtable->cursta_cstate = DIG_STA_DISCONNECT; | |
| 434 | 433 | |
| 435 | 434 | /* adjust initial gain according to false alarm counter */ |
| 436 | 435 | if (falsealm_cnt->cnt_all < DM_DIG_FA_TH0) |
| @@ -522,7 +521,7 @@ static void rtl92d_dm_dynamic_txpower(struct ieee80211_hw *hw) · 85 unmodified lines | ||
| 522 | 521 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
| 523 | 522 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); |
| 524 | 523 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
| 525 | − long undecorated_smoothed_pwdb; | |
| 524 | + long undec_sm_pwdb; | |
| 526 | 525 | |
| 527 | 526 | if ((!rtlpriv->dm.dynamic_txpower_enable) |
| 528 | 527 | || rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { |
| @@ -539,62 +538,62 @@ static void rtl92d_dm_dynamic_txpower(struct ieee80211_hw *hw) · 10 unmodified lines | ||
| 539 | 538 | } |
| 540 | 539 | if (mac->link_state >= MAC80211_LINKED) { |
| 541 | 540 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { |
| 542 | − undecorated_smoothed_pwdb = | |
| 541 | + undec_sm_pwdb = | |
| 543 | 542 | rtlpriv->dm.UNDEC_SM_PWDB; |
| 544 | 543 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 545 | 544 | "IBSS Client PWDB = 0x%lx\n", |
| 546 | − undecorated_smoothed_pwdb); | |
| 545 | + undec_sm_pwdb); | |
| 547 | 546 | } else { |
| 548 | − undecorated_smoothed_pwdb = | |
| 549 | − rtlpriv->dm.undecorated_smoothed_pwdb; | |
| 547 | + undec_sm_pwdb = | |
| 548 | + rtlpriv->dm.undec_sm_pwdb; | |
| 550 | 549 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 551 | 550 | "STA Default Port PWDB = 0x%lx\n", |
| 552 | − undecorated_smoothed_pwdb); | |
| 551 | + undec_sm_pwdb); | |
| 553 | 552 | } |
| 554 | 553 | } else { |
| 555 | − undecorated_smoothed_pwdb = | |
| 554 | + undec_sm_pwdb = | |
| 556 | 555 | rtlpriv->dm.UNDEC_SM_PWDB; |
| 557 | 556 | |
| 558 | 557 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 559 | 558 | "AP Ext Port PWDB = 0x%lx\n", |
| 560 | − undecorated_smoothed_pwdb); | |
| 559 | + undec_sm_pwdb); | |
| 561 | 560 | } |
| 562 | 561 | if (rtlhal->current_bandtype == BAND_ON_5G) { |
| 563 | − if (undecorated_smoothed_pwdb >= 0x33) { | |
| 562 | + if (undec_sm_pwdb >= 0x33) { | |
| 564 | 563 | rtlpriv->dm.dynamic_txhighpower_lvl = |
| 565 | 564 | TXHIGHPWRLEVEL_LEVEL2; |
| 566 | 565 | RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD, |
| 567 | 566 | "5G:TxHighPwrLevel_Level2 (TxPwr=0x0)\n"); |
| 568 | − } else if ((undecorated_smoothed_pwdb < 0x33) | |
| 569 | − && (undecorated_smoothed_pwdb >= 0x2b)) { | |
| 567 | + } else if ((undec_sm_pwdb < 0x33) | |
| 568 | + && (undec_sm_pwdb >= 0x2b)) { | |
| 570 | 569 | rtlpriv->dm.dynamic_txhighpower_lvl = |
| 571 | 570 | TXHIGHPWRLEVEL_LEVEL1; |
| 572 | 571 | RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD, |
| 573 | 572 | "5G:TxHighPwrLevel_Level1 (TxPwr=0x10)\n"); |
| 574 | − } else if (undecorated_smoothed_pwdb < 0x2b) { | |
| 573 | + } else if (undec_sm_pwdb < 0x2b) { | |
| 575 | 574 | rtlpriv->dm.dynamic_txhighpower_lvl = |
| 576 | 575 | TXHIGHPWRLEVEL_NORMAL; |
| 577 | 576 | RT_TRACE(rtlpriv, COMP_HIPWR, DBG_LOUD, |
| 578 | 577 | "5G:TxHighPwrLevel_Normal\n"); |
| 579 | 578 | } |
| 580 | 579 | } else { |
| 581 | − if (undecorated_smoothed_pwdb >= | |
| 580 | + if (undec_sm_pwdb >= | |
| 582 | 581 | TX_POWER_NEAR_FIELD_THRESH_LVL2) { |
| 583 | 582 | rtlpriv->dm.dynamic_txhighpower_lvl = |
| 584 | 583 | TXHIGHPWRLEVEL_LEVEL2; |
| 585 | 584 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 586 | 585 | "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"); |
| 587 | 586 | } else |
| 588 | − if ((undecorated_smoothed_pwdb < | |
| 587 | + if ((undec_sm_pwdb < | |
| 589 | 588 | (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) |
| 590 | − && (undecorated_smoothed_pwdb >= | |
| 589 | + && (undec_sm_pwdb >= | |
| 591 | 590 | TX_POWER_NEAR_FIELD_THRESH_LVL1)) { |
| 592 | 591 | |
| 593 | 592 | rtlpriv->dm.dynamic_txhighpower_lvl = |
| 594 | 593 | TXHIGHPWRLEVEL_LEVEL1; |
| 595 | 594 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 596 | 595 | "TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"); |
| 597 | − } else if (undecorated_smoothed_pwdb < | |
| 596 | + } else if (undec_sm_pwdb < | |
| 598 | 597 | (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) { |
| 599 | 598 | rtlpriv->dm.dynamic_txhighpower_lvl = |
| 600 | 599 | TXHIGHPWRLEVEL_NORMAL; |
| @@ -620,7 +619,7 @@ static void rtl92d_dm_pwdb_monitor(struct ieee80211_hw *hw) · 19 unmodified lines | ||
| 620 | 619 | return; |
| 621 | 620 | /* Indicate Rx signal strength to FW. */ |
| 622 | 621 | if (rtlpriv->dm.useramask) { |
| 623 | − u32 temp = rtlpriv->dm.undecorated_smoothed_pwdb; | |
| 622 | + u32 temp = rtlpriv->dm.undec_sm_pwdb; | |
| 624 | 623 | |
| 625 | 624 | temp <<= 16; |
| 626 | 625 | temp |= 0x100; |
| @@ -629,7 +628,7 @@ static void rtl92d_dm_pwdb_monitor(struct ieee80211_hw *hw) · 2 unmodified lines | ||
| 629 | 628 | rtl92d_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, (u8 *) (&temp)); |
| 630 | 629 | } else { |
| 631 | 630 | rtl_write_byte(rtlpriv, 0x4fe, |
| 632 | − (u8) rtlpriv->dm.undecorated_smoothed_pwdb); | |
| 631 | + (u8) rtlpriv->dm.undec_sm_pwdb); | |
| 633 | 632 | } |
| 634 | 633 | } |
| 635 | 634 | |
| @@ -298,13 +298,13 @@ static u32 _rtl92d_phy_rf_serial_read(struct ieee80211_hw *hw, · 297 unmodified lines | ||
| 298 | 298 | rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, |
| 299 | 299 | BIT(8)); |
| 300 | 300 | if (rfpi_enable) |
| 301 | − retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi, | |
| 301 | + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi, | |
| 302 | 302 | BLSSIREADBACKDATA); |
| 303 | 303 | else |
| 304 | − retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback, | |
| 304 | + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, | |
| 305 | 305 | BLSSIREADBACKDATA); |
| 306 | 306 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x] = 0x%x\n", |
| 307 | − rfpath, pphyreg->rflssi_readback, retvalue); | |
| 307 | + rfpath, pphyreg->rf_rb, retvalue); | |
| 308 | 308 | return retvalue; |
| 309 | 309 | } |
| 310 | 310 | |
| @@ -478,14 +478,10 @@ static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) · 167 unmodified lines | ||
| 478 | 478 | |
| 479 | 479 | /* RF switch Control */ |
| 480 | 480 | /* TR/Ant switch control */ |
| 481 | − rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control = | |
| 482 | − RFPGA0_XAB_SWITCHCONTROL; | |
| 483 | − rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control = | |
| 484 | − RFPGA0_XAB_SWITCHCONTROL; | |
| 485 | − rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control = | |
| 486 | − RFPGA0_XCD_SWITCHCONTROL; | |
| 487 | − rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control = | |
| 488 | − RFPGA0_XCD_SWITCHCONTROL; | |
| 481 | + rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; | |
| 482 | + rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; | |
| 483 | + rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; | |
| 484 | + rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; | |
| 489 | 485 | |
| 490 | 486 | /* AGC control 1 */ |
| 491 | 487 | rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; |
| @@ -500,14 +496,10 @@ static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) · 8 unmodified lines | ||
| 500 | 496 | rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; |
| 501 | 497 | |
| 502 | 498 | /* RX AFE control 1 */ |
| 503 | − rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance = | |
| 504 | − ROFDM0_XARXIQIMBALANCE; | |
| 505 | − rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance = | |
| 506 | − ROFDM0_XBRXIQIMBALANCE; | |
| 507 | − rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance = | |
| 508 | − ROFDM0_XCRXIQIMBALANCE; | |
| 509 | − rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance = | |
| 510 | − ROFDM0_XDRXIQIMBALANCE; | |
| 499 | + rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE; | |
| 500 | + rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE; | |
| 501 | + rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBALANCE; | |
| 502 | + rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE; | |
| 511 | 503 | |
| 512 | 504 | /*RX AFE control 1 */ |
| 513 | 505 | rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; |
| @@ -516,14 +508,10 @@ static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) · 2 unmodified lines | ||
| 516 | 508 | rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; |
| 517 | 509 | |
| 518 | 510 | /* Tx AFE control 1 */ |
| 519 | − rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance = | |
| 520 | − ROFDM0_XATxIQIMBALANCE; | |
| 521 | − rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance = | |
| 522 | − ROFDM0_XBTxIQIMBALANCE; | |
| 523 | − rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance = | |
| 524 | − ROFDM0_XCTxIQIMBALANCE; | |
| 525 | − rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance = | |
| 526 | − ROFDM0_XDTxIQIMBALANCE; | |
| 511 | + rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATxIQIMBALANCE; | |
| 512 | + rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTxIQIMBALANCE; | |
| 513 | + rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTxIQIMBALANCE; | |
| 514 | + rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTxIQIMBALANCE; | |
| 527 | 515 | |
| 528 | 516 | /* Tx AFE control 2 */ |
| 529 | 517 | rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATxAFE; |
| @@ -532,20 +520,14 @@ static void _rtl92d_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw) · 2 unmodified lines | ||
| 532 | 520 | rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTxAFE; |
| 533 | 521 | |
| 534 | 522 | /* Tranceiver LSSI Readback SI mode */ |
| 535 | − rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback = | |
| 536 | − RFPGA0_XA_LSSIREADBACK; | |
| 537 | − rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback = | |
| 538 | − RFPGA0_XB_LSSIREADBACK; | |
| 539 | − rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback = | |
| 540 | − RFPGA0_XC_LSSIREADBACK; | |
| 541 | − rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback = | |
| 542 | − RFPGA0_XD_LSSIREADBACK; | |
| 523 | + rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK; | |
| 524 | + rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK; | |
| 525 | + rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK; | |
| 526 | + rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK; | |
| 543 | 527 | |
| 544 | 528 | /* Tranceiver LSSI Readback PI mode */ |
| 545 | − rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi = | |
| 546 | − TRANSCEIVERA_HSPI_READBACK; | |
| 547 | − rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi = | |
| 548 | − TRANSCEIVERB_HSPI_READBACK; | |
| 529 | + rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVERA_HSPI_READBACK; | |
| 530 | + rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVERB_HSPI_READBACK; | |
| 549 | 531 | } |
| 550 | 532 | |
| 551 | 533 | static bool _rtl92d_phy_config_bb_with_headerfile(struct ieee80211_hw *hw, |
| @@ -702,12 +684,11 @@ static void _rtl92d_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, · 150 unmodified lines | ||
| 702 | 684 | else |
| 703 | 685 | return; |
| 704 | 686 | |
| 705 | − rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][index] = data; | |
| 687 | + rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index] = data; | |
| 706 | 688 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, |
| 707 | 689 | "MCSTxPowerLevelOriginalOffset[%d][%d] = 0x%ulx\n", |
| 708 | 690 | rtlphy->pwrgroup_cnt, index, |
| 709 | − rtlphy->mcs_txpwrlevel_origoffset | |
| 710 | − [rtlphy->pwrgroup_cnt][index]); | |
| 691 | + rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index]); | |
| 711 | 692 | if (index == 13) |
| 712 | 693 | rtlphy->pwrgroup_cnt++; |
| 713 | 694 | } |
| @@ -106,11 +106,11 @@ void rtl92d_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, · 105 unmodified lines | ||
| 106 | 106 | (ppowerlevel[idx1] << 24); |
| 107 | 107 | } |
| 108 | 108 | if (rtlefuse->eeprom_regulatory == 0) { |
| 109 | − tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][6]) + | |
| 110 | − (rtlphy->mcs_txpwrlevel_origoffset[0][7] << 8); | |
| 109 | + tmpval = (rtlphy->mcs_offset[0][6]) + | |
| 110 | + (rtlphy->mcs_offset[0][7] << 8); | |
| 111 | 111 | tx_agc[RF90_PATH_A] += tmpval; |
| 112 | − tmpval = (rtlphy->mcs_txpwrlevel_origoffset[0][14]) + | |
| 113 | − (rtlphy->mcs_txpwrlevel_origoffset[0][15] << 24); | |
| 112 | + tmpval = (rtlphy->mcs_offset[0][14]) + | |
| 113 | + (rtlphy->mcs_offset[0][15] << 24); | |
| 114 | 114 | tx_agc[RF90_PATH_B] += tmpval; |
| 115 | 115 | } |
| 116 | 116 | } |
| @@ -227,7 +227,7 @@ static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, · 110 unmodified lines | ||
| 227 | 227 | switch (rtlefuse->eeprom_regulatory) { |
| 228 | 228 | case 0: |
| 229 | 229 | chnlgroup = 0; |
| 230 | − writeval = rtlphy->mcs_txpwrlevel_origoffset | |
| 230 | + writeval = rtlphy->mcs_offset | |
| 231 | 231 | [chnlgroup][index + |
| 232 | 232 | (rf ? 8 : 0)] + ((index < 2) ? |
| 233 | 233 | powerbase0[rf] : |
| @@ -247,7 +247,7 @@ static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, · 13 unmodified lines | ||
| 247 | 247 | chnlgroup++; |
| 248 | 248 | else |
| 249 | 249 | chnlgroup += 4; |
| 250 | − writeval = rtlphy->mcs_txpwrlevel_origoffset | |
| 250 | + writeval = rtlphy->mcs_offset | |
| 251 | 251 | [chnlgroup][index + |
| 252 | 252 | (rf ? 8 : 0)] + ((index < 2) ? |
| 253 | 253 | powerbase0[rf] : |
| @@ -280,8 +280,7 @@ static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, · 26 unmodified lines | ||
| 280 | 280 | [channel - 1]); |
| 281 | 281 | } |
| 282 | 282 | for (i = 0; i < 4; i++) { |
| 283 | − pwr_diff_limit[i] = | |
| 284 | − (u8)((rtlphy->mcs_txpwrlevel_origoffset | |
| 283 | + pwr_diff_limit[i] = (u8)((rtlphy->mcs_offset | |
| 285 | 284 | [chnlgroup][index + (rf ? 8 : 0)] & |
| 286 | 285 | (0x7f << (i * 8))) >> (i * 8)); |
| 287 | 286 | if (rtlphy->current_chan_bw == |
| @@ -316,8 +315,7 @@ static void _rtl92d_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw, · 28 unmodified lines | ||
| 316 | 315 | break; |
| 317 | 316 | default: |
| 318 | 317 | chnlgroup = 0; |
| 319 | − writeval = rtlphy->mcs_txpwrlevel_origoffset | |
| 320 | − [chnlgroup][index + | |
| 318 | + writeval = rtlphy->mcs_offset[chnlgroup][index + | |
| 321 | 319 | (rf ? 8 : 0)] + ((index < 2) ? |
| 322 | 320 | powerbase0[rf] : powerbase1[rf]); |
| 323 | 321 | RTPRINT(rtlpriv, FPHY, PHY_TXPWR, |
| @@ -132,8 +132,8 @@ static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw, · 131 unmodified lines | ||
| 132 | 132 | pstats->packet_toself = packet_toself; |
| 133 | 133 | pstats->packet_beacon = packet_beacon; |
| 134 | 134 | pstats->is_cck = is_cck_rate; |
| 135 | − pstats->rx_mimo_signalquality[0] = -1; | |
| 136 | − pstats->rx_mimo_signalquality[1] = -1; | |
| 135 | + pstats->rx_mimo_sig_qual[0] = -1; | |
| 136 | + pstats->rx_mimo_sig_qual[1] = -1; | |
| 137 | 137 | |
| 138 | 138 | if (is_cck_rate) { |
| 139 | 139 | u8 report, cck_highpwr; |
| @@ -212,8 +212,8 @@ static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw, · 72 unmodified lines | ||
| 212 | 212 | sq = ((64 - sq) * 100) / 44; |
| 213 | 213 | } |
| 214 | 214 | pstats->signalquality = sq; |
| 215 | − pstats->rx_mimo_signalquality[0] = sq; | |
| 216 | − pstats->rx_mimo_signalquality[1] = -1; | |
| 215 | + pstats->rx_mimo_sig_qual[0] = sq; | |
| 216 | + pstats->rx_mimo_sig_qual[1] = -1; | |
| 217 | 217 | } |
| 218 | 218 | } else { |
| 219 | 219 | rtlpriv->dm.rfpath_rxenable[0] = true; |
| @@ -246,7 +246,7 @@ static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw, · 26 unmodified lines | ||
| 246 | 246 | if (i == 0) |
| 247 | 247 | pstats->signalquality = |
| 248 | 248 | (u8)(evm & 0xff); |
| 249 | − pstats->rx_mimo_signalquality[i] = | |
| 249 | + pstats->rx_mimo_sig_qual[i] = | |
| 250 | 250 | (u8)(evm & 0xff); |
| 251 | 251 | } |
| 252 | 252 | } |
| @@ -345,33 +345,28 @@ static void _rtl92de_process_pwdb(struct ieee80211_hw *hw, · 92 unmodified lines | ||
| 345 | 345 | { |
| 346 | 346 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 347 | 347 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
| 348 | − long undecorated_smoothed_pwdb; | |
| 348 | + long undec_sm_pwdb; | |
| 349 | 349 | |
| 350 | 350 | if (mac->opmode == NL80211_IFTYPE_ADHOC || |
| 351 | 351 | mac->opmode == NL80211_IFTYPE_AP) |
| 352 | 352 | return; |
| 353 | 353 | else |
| 354 | − undecorated_smoothed_pwdb = | |
| 355 | − rtlpriv->dm.undecorated_smoothed_pwdb; | |
| 354 | + undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; | |
| 356 | 355 | |
| 357 | 356 | if (pstats->packet_toself || pstats->packet_beacon) { |
| 358 | − if (undecorated_smoothed_pwdb < 0) | |
| 359 | − undecorated_smoothed_pwdb = pstats->rx_pwdb_all; | |
| 360 | − if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) { | |
| 361 | − undecorated_smoothed_pwdb = | |
| 362 | − (((undecorated_smoothed_pwdb) * | |
| 357 | + if (undec_sm_pwdb < 0) | |
| 358 | + undec_sm_pwdb = pstats->rx_pwdb_all; | |
| 359 | + if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) { | |
| 360 | + undec_sm_pwdb = (((undec_sm_pwdb) * | |
| 363 | 361 | (RX_SMOOTH_FACTOR - 1)) + |
| 364 | 362 | (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); |
| 365 | − undecorated_smoothed_pwdb = | |
| 366 | − undecorated_smoothed_pwdb + 1; | |
| 363 | + undec_sm_pwdb = undec_sm_pwdb + 1; | |
| 367 | 364 | } else { |
| 368 | − undecorated_smoothed_pwdb = | |
| 369 | − (((undecorated_smoothed_pwdb) * | |
| 365 | + undec_sm_pwdb = (((undec_sm_pwdb) * | |
| 370 | 366 | (RX_SMOOTH_FACTOR - 1)) + |
| 371 | 367 | (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); |
| 372 | 368 | } |
| 373 | − rtlpriv->dm.undecorated_smoothed_pwdb = | |
| 374 | − undecorated_smoothed_pwdb; | |
| 369 | + rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb; | |
| 375 | 370 | _rtl92de_update_rxsignalstatistics(hw, pstats); |
| 376 | 371 | } |
| 377 | 372 | } |
| @@ -383,15 +378,15 @@ static void rtl92d_loop_over_streams(struct ieee80211_hw *hw, · 5 unmodified lines | ||
| 383 | 378 | int stream; |
| 384 | 379 | |
| 385 | 380 | for (stream = 0; stream < 2; stream++) { |
| 386 | − if (pstats->rx_mimo_signalquality[stream] != -1) { | |
| 381 | + if (pstats->rx_mimo_sig_qual[stream] != -1) { | |
| 387 | 382 | if (rtlpriv->stats.rx_evm_percentage[stream] == 0) { |
| 388 | 383 | rtlpriv->stats.rx_evm_percentage[stream] = |
| 389 | − pstats->rx_mimo_signalquality[stream]; | |
| 384 | + pstats->rx_mimo_sig_qual[stream]; | |
| 390 | 385 | } |
| 391 | 386 | rtlpriv->stats.rx_evm_percentage[stream] = |
| 392 | 387 | ((rtlpriv->stats.rx_evm_percentage[stream] |
| 393 | 388 | * (RX_SMOOTH_FACTOR - 1)) + |
| 394 | − (pstats->rx_mimo_signalquality[stream] * 1)) / | |
| 389 | + (pstats->rx_mimo_sig_qual[stream] * 1)) / | |
| 395 | 390 | (RX_SMOOTH_FACTOR); |
| 396 | 391 | } |
| 397 | 392 | } |
| @@ -267,13 +267,12 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw) · 266 unmodified lines | ||
| 267 | 267 | break; |
| 268 | 268 | } |
| 269 | 269 | |
| 270 | − if (rtlpriv->dm.undecorated_smoothed_pwdb > | |
| 271 | − (long)high_rssi_thresh) { | |
| 270 | + if (rtlpriv->dm.undec_sm_pwdb > (long)high_rssi_thresh) { | |
| 272 | 271 | ra->ratr_state = DM_RATR_STA_HIGH; |
| 273 | − } else if (rtlpriv->dm.undecorated_smoothed_pwdb > | |
| 272 | + } else if (rtlpriv->dm.undec_sm_pwdb > | |
| 274 | 273 | (long)middle_rssi_thresh) { |
| 275 | 274 | ra->ratr_state = DM_RATR_STA_LOW; |
| 276 | − } else if (rtlpriv->dm.undecorated_smoothed_pwdb > | |
| 275 | + } else if (rtlpriv->dm.undec_sm_pwdb > | |
| 277 | 276 | (long)low_rssi_thresh) { |
| 278 | 277 | ra->ratr_state = DM_RATR_STA_LOW; |
| 279 | 278 | } else { |
| @@ -283,8 +282,7 @@ static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw) · 3 unmodified lines | ||
| 283 | 282 | if (ra->pre_ratr_state != ra->ratr_state) { |
| 284 | 283 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, |
| 285 | 284 | "RSSI = %ld RSSI_LEVEL = %d PreState = %d, CurState = %d\n", |
| 286 | − rtlpriv->dm.undecorated_smoothed_pwdb, | |
| 287 | − ra->ratr_state, | |
| 285 | + rtlpriv->dm.undec_sm_pwdb, ra->ratr_state, | |
| 288 | 286 | ra->pre_ratr_state, ra->ratr_state); |
| 289 | 287 | |
| 290 | 288 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, |
| @@ -316,7 +314,7 @@ static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw) · 25 unmodified lines | ||
| 316 | 314 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MRC, (u8 *)(¤t_mrc)); |
| 317 | 315 | |
| 318 | 316 | if (mac->link_state >= MAC80211_LINKED) { |
| 319 | − if (rtlpriv->dm.undecorated_smoothed_pwdb > tmpentry_maxpwdb) { | |
| 317 | + if (rtlpriv->dm.undec_sm_pwdb > tmpentry_maxpwdb) { | |
| 320 | 318 | rssi_a = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_A]; |
| 321 | 319 | rssi_b = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_B]; |
| 322 | 320 | } |
| @@ -424,18 +422,18 @@ static void rtl92s_backoff_enable_flag(struct ieee80211_hw *hw) · 101 unmodified lines | ||
| 424 | 422 | struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); |
| 425 | 423 | |
| 426 | 424 | if (falsealm_cnt->cnt_all > digtable->fa_highthresh) { |
| 427 | − if ((digtable->backoff_val - 6) < | |
| 425 | + if ((digtable->back_val - 6) < | |
| 428 | 426 | digtable->backoffval_range_min) |
| 429 | − digtable->backoff_val = digtable->backoffval_range_min; | |
| 427 | + digtable->back_val = digtable->backoffval_range_min; | |
| 430 | 428 | else |
| 431 | − digtable->backoff_val -= 6; | |
| 429 | + digtable->back_val -= 6; | |
| 432 | 430 | } else if (falsealm_cnt->cnt_all < digtable->fa_lowthresh) { |
| 433 | − if ((digtable->backoff_val + 6) > | |
| 431 | + if ((digtable->back_val + 6) > | |
| 434 | 432 | digtable->backoffval_range_max) |
| 435 | − digtable->backoff_val = | |
| 433 | + digtable->back_val = | |
| 436 | 434 | digtable->backoffval_range_max; |
| 437 | 435 | else |
| 438 | − digtable->backoff_val += 6; | |
| 436 | + digtable->back_val += 6; | |
| 439 | 437 | } |
| 440 | 438 | } |
| 441 | 439 | |
| @@ -447,28 +445,28 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw) · 5 unmodified lines | ||
| 447 | 445 | static u8 initialized, force_write; |
| 448 | 446 | u8 initial_gain = 0; |
| 449 | 447 | |
| 450 | − if ((digtable->pre_sta_connectstate == digtable->cur_sta_connectstate) || | |
| 451 | − (digtable->cur_sta_connectstate == DIG_STA_BEFORE_CONNECT)) { | |
| 452 | − if (digtable->cur_sta_connectstate == DIG_STA_BEFORE_CONNECT) { | |
| 448 | + if ((digtable->pre_sta_cstate == digtable->cur_sta_cstate) || | |
| 449 | + (digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT)) { | |
| 450 | + if (digtable->cur_sta_cstate == DIG_STA_BEFORE_CONNECT) { | |
| 453 | 451 | if (rtlpriv->psc.rfpwr_state != ERFON) |
| 454 | 452 | return; |
| 455 | 453 | |
| 456 | 454 | if (digtable->backoff_enable_flag) |
| 457 | 455 | rtl92s_backoff_enable_flag(hw); |
| 458 | 456 | else |
| 459 | − digtable->backoff_val = DM_DIG_BACKOFF; | |
| 457 | + digtable->back_val = DM_DIG_BACKOFF; | |
| 460 | 458 | |
| 461 | − if ((digtable->rssi_val + 10 - digtable->backoff_val) > | |
| 459 | + if ((digtable->rssi_val + 10 - digtable->back_val) > | |
| 462 | 460 | digtable->rx_gain_range_max) |
| 463 | 461 | digtable->cur_igvalue = |
| 464 | 462 | digtable->rx_gain_range_max; |
| 465 | − else if ((digtable->rssi_val + 10 - digtable->backoff_val) | |
| 463 | + else if ((digtable->rssi_val + 10 - digtable->back_val) | |
| 466 | 464 | < digtable->rx_gain_range_min) |
| 467 | 465 | digtable->cur_igvalue = |
| 468 | 466 | digtable->rx_gain_range_min; |
| 469 | 467 | else |
| 470 | 468 | digtable->cur_igvalue = digtable->rssi_val + 10 - |
| 471 | − digtable->backoff_val; | |
| 469 | + digtable->back_val; | |
| 472 | 470 | |
| 473 | 471 | if (falsealm_cnt->cnt_all > 10000) |
| 474 | 472 | digtable->cur_igvalue = |
| @@ -490,7 +488,7 @@ static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw) · 15 unmodified lines | ||
| 490 | 488 | digtable->dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; |
| 491 | 489 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_ENABLE); |
| 492 | 490 | |
| 493 | − digtable->backoff_val = DM_DIG_BACKOFF; | |
| 491 | + digtable->back_val = DM_DIG_BACKOFF; | |
| 494 | 492 | digtable->cur_igvalue = rtlpriv->phy.default_initialgain[0]; |
| 495 | 493 | digtable->pre_igvalue = 0; |
| 496 | 494 | return; |
| @@ -528,14 +526,14 @@ static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw) · 31 unmodified lines | ||
| 528 | 526 | /* Decide the current status and if modify initial gain or not */ |
| 529 | 527 | if (rtlpriv->mac80211.link_state >= MAC80211_LINKED || |
| 530 | 528 | rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) |
| 531 | − digtable->cur_sta_connectstate = DIG_STA_CONNECT; | |
| 529 | + digtable->cur_sta_cstate = DIG_STA_CONNECT; | |
| 532 | 530 | else |
| 533 | − digtable->cur_sta_connectstate = DIG_STA_DISCONNECT; | |
| 531 | + digtable->cur_sta_cstate = DIG_STA_DISCONNECT; | |
| 534 | 532 | |
| 535 | − digtable->rssi_val = rtlpriv->dm.undecorated_smoothed_pwdb; | |
| 533 | + digtable->rssi_val = rtlpriv->dm.undec_sm_pwdb; | |
| 536 | 534 | |
| 537 | 535 | /* Change dig mode to rssi */ |
| 538 | − if (digtable->cur_sta_connectstate != DIG_STA_DISCONNECT) { | |
| 536 | + if (digtable->cur_sta_cstate != DIG_STA_DISCONNECT) { | |
| 539 | 537 | if (digtable->dig_twoport_algorithm == |
| 540 | 538 | DIG_TWO_PORT_ALGO_FALSE_ALARM) { |
| 541 | 539 | digtable->dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI; |
| @@ -546,7 +544,7 @@ static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw) · 4 unmodified lines | ||
| 546 | 544 | _rtl92s_dm_false_alarm_counter_statistics(hw); |
| 547 | 545 | _rtl92s_dm_initial_gain_sta_beforeconnect(hw); |
| 548 | 546 | |
| 549 | − digtable->pre_sta_connectstate = digtable->cur_sta_connectstate; | |
| 547 | + digtable->pre_sta_cstate = digtable->cur_sta_cstate; | |
| 550 | 548 | } |
| 551 | 549 | |
| 552 | 550 | static void _rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw *hw) |
| @@ -573,7 +571,7 @@ static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw) · 20 unmodified lines | ||
| 573 | 571 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 574 | 572 | struct rtl_phy *rtlphy = &(rtlpriv->phy); |
| 575 | 573 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
| 576 | − long undecorated_smoothed_pwdb; | |
| 574 | + long undec_sm_pwdb; | |
| 577 | 575 | long txpwr_threshold_lv1, txpwr_threshold_lv2; |
| 578 | 576 | |
| 579 | 577 | /* 2T2R TP issue */ |
| @@ -587,7 +585,7 @@ static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw) · 7 unmodified lines | ||
| 587 | 585 | } |
| 588 | 586 | |
| 589 | 587 | if ((mac->link_state < MAC80211_LINKED) && |
| 590 | − (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) { | |
| 588 | + (rtlpriv->dm.entry_min_undec_sm_pwdb == 0)) { | |
| 591 | 589 | RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, |
| 592 | 590 | "Not connected to any\n"); |
| 593 | 591 | |
| @@ -599,25 +597,22 @@ static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw) · 5 unmodified lines | ||
| 599 | 597 | |
| 600 | 598 | if (mac->link_state >= MAC80211_LINKED) { |
| 601 | 599 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { |
| 602 | − undecorated_smoothed_pwdb = | |
| 603 | − rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; | |
| 600 | + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; | |
| 604 | 601 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 605 | 602 | "AP Client PWDB = 0x%lx\n", |
| 606 | − undecorated_smoothed_pwdb); | |
| 603 | + undec_sm_pwdb); | |
| 607 | 604 | } else { |
| 608 | − undecorated_smoothed_pwdb = | |
| 609 | − rtlpriv->dm.undecorated_smoothed_pwdb; | |
| 605 | + undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb; | |
| 610 | 606 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 611 | 607 | "STA Default Port PWDB = 0x%lx\n", |
| 612 | − undecorated_smoothed_pwdb); | |
| 608 | + undec_sm_pwdb); | |
| 613 | 609 | } |
| 614 | 610 | } else { |
| 615 | − undecorated_smoothed_pwdb = | |
| 616 | − rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; | |
| 611 | + undec_sm_pwdb = rtlpriv->dm.entry_min_undec_sm_pwdb; | |
| 617 | 612 | |
| 618 | 613 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 619 | 614 | "AP Ext Port PWDB = 0x%lx\n", |
| 620 | − undecorated_smoothed_pwdb); | |
| 615 | + undec_sm_pwdb); | |
| 621 | 616 | } |
| 622 | 617 | |
| 623 | 618 | txpwr_threshold_lv2 = TX_POWER_NEAR_FIELD_THRESH_LVL2; |
| @@ -625,12 +620,12 @@ static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw) · 1 unmodified line | ||
| 625 | 620 | |
| 626 | 621 | if (rtl_get_bbreg(hw, 0xc90, MASKBYTE0) == 1) |
| 627 | 622 | rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; |
| 628 | − else if (undecorated_smoothed_pwdb >= txpwr_threshold_lv2) | |
| 623 | + else if (undec_sm_pwdb >= txpwr_threshold_lv2) | |
| 629 | 624 | rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL2; |
| 630 | − else if ((undecorated_smoothed_pwdb < (txpwr_threshold_lv2 - 3)) && | |
| 631 | − (undecorated_smoothed_pwdb >= txpwr_threshold_lv1)) | |
| 625 | + else if ((undec_sm_pwdb < (txpwr_threshold_lv2 - 3)) && | |
| 626 | + (undec_sm_pwdb >= txpwr_threshold_lv1)) | |
| 632 | 627 | rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL1; |
| 633 | − else if (undecorated_smoothed_pwdb < (txpwr_threshold_lv1 - 3)) | |
| 628 | + else if (undec_sm_pwdb < (txpwr_threshold_lv1 - 3)) | |
| 634 | 629 | rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; |
| 635 | 630 | |
| 636 | 631 | if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) |
| @@ -665,10 +660,10 @@ static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw) · 28 unmodified lines | ||
| 665 | 660 | digtable->dig_state = DM_STA_DIG_MAX; |
| 666 | 661 | digtable->dig_highpwrstate = DM_STA_DIG_MAX; |
| 667 | 662 | |
| 668 | − digtable->cur_sta_connectstate = DIG_STA_DISCONNECT; | |
| 669 | − digtable->pre_sta_connectstate = DIG_STA_DISCONNECT; | |
| 670 | − digtable->cur_ap_connectstate = DIG_AP_DISCONNECT; | |
| 671 | − digtable->pre_ap_connectstate = DIG_AP_DISCONNECT; | |
| 663 | + digtable->cur_sta_cstate = DIG_STA_DISCONNECT; | |
| 664 | + digtable->pre_sta_cstate = DIG_STA_DISCONNECT; | |
| 665 | + digtable->cur_ap_cstate = DIG_AP_DISCONNECT; | |
| 666 | + digtable->pre_ap_cstate = DIG_AP_DISCONNECT; | |
| 672 | 667 | |
| 673 | 668 | digtable->rssi_lowthresh = DM_DIG_THRESH_LOW; |
| 674 | 669 | digtable->rssi_highthresh = DM_DIG_THRESH_HIGH; |
| @@ -681,7 +676,7 @@ static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw) · 6 unmodified lines | ||
| 681 | 676 | |
| 682 | 677 | /* for dig debug rssi value */ |
| 683 | 678 | digtable->rssi_val = 50; |
| 684 | − digtable->backoff_val = DM_DIG_BACKOFF; | |
| 679 | + digtable->back_val = DM_DIG_BACKOFF; | |
| 685 | 680 | digtable->rx_gain_range_max = DM_DIG_MAX; |
| 686 | 681 | |
| 687 | 682 | digtable->rx_gain_range_min = DM_DIG_MIN; |
| @@ -709,7 +704,7 @@ void rtl92s_dm_init(struct ieee80211_hw *hw) · 21 unmodified lines | ||
| 709 | 704 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
| 710 | 705 | |
| 711 | 706 | rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; |
| 712 | − rtlpriv->dm.undecorated_smoothed_pwdb = -1; | |
| 707 | + rtlpriv->dm.undec_sm_pwdb = -1; | |
| 713 | 708 | |
| 714 | 709 | _rtl92s_dm_init_dynamic_txpower(hw); |
| 715 | 710 | rtl92s_dm_init_edca_turbo(hw); |
| @@ -1697,7 +1697,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) · 1696 unmodified lines | ||
| 1697 | 1697 | hwinfo[EEPROM_TXPOWERBASE + 6 + rf_path * 3 + i]; |
| 1698 | 1698 | |
| 1699 | 1699 | /* Read OFDM RF A & B Tx power for 2T */ |
| 1700 | − rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][i] | |
| 1700 | + rtlefuse->eprom_chnl_txpwr_ht40_2sdf[rf_path][i] | |
| 1701 | 1701 | = hwinfo[EEPROM_TXPOWERBASE + 12 + |
| 1702 | 1702 | rf_path * 3 + i]; |
| 1703 | 1703 | } |
| @@ -1722,7 +1722,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) · 18 unmodified lines | ||
| 1722 | 1722 | RTPRINT(rtlpriv, FINIT, INIT_EEPROM, |
| 1723 | 1723 | "RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n", |
| 1724 | 1724 | rf_path, i, |
| 1725 | − rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif | |
| 1725 | + rtlefuse->eprom_chnl_txpwr_ht40_2sdf | |
| 1726 | 1726 | [rf_path][i]); |
| 1727 | 1727 | |
| 1728 | 1728 | for (rf_path = 0; rf_path < 2; rf_path++) { |
| @@ -1748,7 +1748,7 @@ static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) · 19 unmodified lines | ||
| 1748 | 1748 | rtlefuse->eeprom_chnlarea_txpwr_ht40_1s |
| 1749 | 1749 | [rf_path][index]; |
| 1750 | 1750 | rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = |
| 1751 | − rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif | |
| 1751 | + rtlefuse->eprom_chnl_txpwr_ht40_2sdf | |
| 1752 | 1752 | [rf_path][index]; |
| 1753 | 1753 | } |
| 1754 | 1754 | |
| @@ -139,17 +139,17 @@ static u32 _rtl92s_phy_rf_serial_read(struct ieee80211_hw *hw, · 138 unmodified lines | ||
| 139 | 139 | BIT(8)); |
| 140 | 140 | |
| 141 | 141 | if (rfpi_enable) |
| 142 | − retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi, | |
| 142 | + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rbpi, | |
| 143 | 143 | BLSSI_READBACK_DATA); |
| 144 | 144 | else |
| 145 | − retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback, | |
| 145 | + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, | |
| 146 | 146 | BLSSI_READBACK_DATA); |
| 147 | 147 | |
| 148 | − retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback, | |
| 148 | + retvalue = rtl_get_bbreg(hw, pphyreg->rf_rb, | |
| 149 | 149 | BLSSI_READBACK_DATA); |
| 150 | 150 | |
| 151 | 151 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, "RFR-%d Addr[0x%x]=0x%x\n", |
| 152 | − rfpath, pphyreg->rflssi_readback, retvalue); | |
| 152 | + rfpath, pphyreg->rf_rb, retvalue); | |
| 153 | 153 | |
| 154 | 154 | return retvalue; |
| 155 | 155 | |
| @@ -696,7 +696,7 @@ static void _rtl92s_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, · 540 unmodified lines | ||
| 696 | 696 | else |
| 697 | 697 | return; |
| 698 | 698 | |
| 699 | − rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][index] = data; | |
| 699 | + rtlphy->mcs_offset[rtlphy->pwrgroup_cnt][index] = data; | |
| 700 | 700 | if (index == 5) |
| 701 | 701 | rtlphy->pwrgroup_cnt++; |
| 702 | 702 | } |
| @@ -765,14 +765,10 @@ static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw) · 62 unmodified lines | ||
| 765 | 765 | rtlphy->phyreg_def[RF90_PATH_D].rfhssi_para2 = RFPGA0_XD_HSSIPARAMETER2; |
| 766 | 766 | |
| 767 | 767 | /* RF switch Control */ |
| 768 | − rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control = | |
| 769 | − RFPGA0_XAB_SWITCHCONTROL; | |
| 770 | − rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control = | |
| 771 | − RFPGA0_XAB_SWITCHCONTROL; | |
| 772 | − rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control = | |
| 773 | − RFPGA0_XCD_SWITCHCONTROL; | |
| 774 | − rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control = | |
| 775 | − RFPGA0_XCD_SWITCHCONTROL; | |
| 768 | + rtlphy->phyreg_def[RF90_PATH_A].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; | |
| 769 | + rtlphy->phyreg_def[RF90_PATH_B].rfsw_ctrl = RFPGA0_XAB_SWITCHCONTROL; | |
| 770 | + rtlphy->phyreg_def[RF90_PATH_C].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; | |
| 771 | + rtlphy->phyreg_def[RF90_PATH_D].rfsw_ctrl = RFPGA0_XCD_SWITCHCONTROL; | |
| 776 | 772 | |
| 777 | 773 | /* AGC control 1 */ |
| 778 | 774 | rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; |
| @@ -787,14 +783,10 @@ static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw) · 8 unmodified lines | ||
| 787 | 783 | rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; |
| 788 | 784 | |
| 789 | 785 | /* RX AFE control 1 */ |
| 790 | − rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance = | |
| 791 | − ROFDM0_XARXIQIMBALANCE; | |
| 792 | − rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance = | |
| 793 | − ROFDM0_XBRXIQIMBALANCE; | |
| 794 | − rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance = | |
| 795 | − ROFDM0_XCRXIQIMBALANCE; | |
| 796 | − rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance = | |
| 797 | − ROFDM0_XDRXIQIMBALANCE; | |
| 786 | + rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbal = ROFDM0_XARXIQIMBALANCE; | |
| 787 | + rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbal = ROFDM0_XBRXIQIMBALANCE; | |
| 788 | + rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbal = ROFDM0_XCRXIQIMBALANCE; | |
| 789 | + rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbal = ROFDM0_XDRXIQIMBALANCE; | |
| 798 | 790 | |
| 799 | 791 | /* RX AFE control 1 */ |
| 800 | 792 | rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; |
| @@ -803,14 +795,10 @@ static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw) · 2 unmodified lines | ||
| 803 | 795 | rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; |
| 804 | 796 | |
| 805 | 797 | /* Tx AFE control 1 */ |
| 806 | − rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance = | |
| 807 | − ROFDM0_XATXIQIMBALANCE; | |
| 808 | − rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance = | |
| 809 | − ROFDM0_XBTXIQIMBALANCE; | |
| 810 | − rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance = | |
| 811 | − ROFDM0_XCTXIQIMBALANCE; | |
| 812 | − rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance = | |
| 813 | − ROFDM0_XDTXIQIMBALANCE; | |
| 798 | + rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbal = ROFDM0_XATXIQIMBALANCE; | |
| 799 | + rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbal = ROFDM0_XBTXIQIMBALANCE; | |
| 800 | + rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbal = ROFDM0_XCTXIQIMBALANCE; | |
| 801 | + rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbal = ROFDM0_XDTXIQIMBALANCE; | |
| 814 | 802 | |
| 815 | 803 | /* Tx AFE control 2 */ |
| 816 | 804 | rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE; |
| @@ -819,20 +807,14 @@ static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw) · 2 unmodified lines | ||
| 819 | 807 | rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE; |
| 820 | 808 | |
| 821 | 809 | /* Tranceiver LSSI Readback */ |
| 822 | − rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback = | |
| 823 | − RFPGA0_XA_LSSIREADBACK; | |
| 824 | − rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback = | |
| 825 | − RFPGA0_XB_LSSIREADBACK; | |
| 826 | − rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback = | |
| 827 | − RFPGA0_XC_LSSIREADBACK; | |
| 828 | − rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback = | |
| 829 | − RFPGA0_XD_LSSIREADBACK; | |
| 810 | + rtlphy->phyreg_def[RF90_PATH_A].rf_rb = RFPGA0_XA_LSSIREADBACK; | |
| 811 | + rtlphy->phyreg_def[RF90_PATH_B].rf_rb = RFPGA0_XB_LSSIREADBACK; | |
| 812 | + rtlphy->phyreg_def[RF90_PATH_C].rf_rb = RFPGA0_XC_LSSIREADBACK; | |
| 813 | + rtlphy->phyreg_def[RF90_PATH_D].rf_rb = RFPGA0_XD_LSSIREADBACK; | |
| 830 | 814 | |
| 831 | 815 | /* Tranceiver LSSI Readback PI mode */ |
| 832 | − rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi = | |
| 833 | − TRANSCEIVERA_HSPI_READBACK; | |
| 834 | − rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi = | |
| 835 | − TRANSCEIVERB_HSPI_READBACK; | |
| 816 | + rtlphy->phyreg_def[RF90_PATH_A].rf_rbpi = TRANSCEIVERA_HSPI_READBACK; | |
| 817 | + rtlphy->phyreg_def[RF90_PATH_B].rf_rbpi = TRANSCEIVERB_HSPI_READBACK; | |
| 836 | 818 | } |
| 837 | 819 | |
| 838 | 820 | |
| @@ -192,8 +192,7 @@ static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw, · 191 unmodified lines | ||
| 192 | 192 | * defined by Realtek for large power */ |
| 193 | 193 | chnlgroup = 0; |
| 194 | 194 | |
| 195 | − writeval = rtlphy->mcs_txpwrlevel_origoffset | |
| 196 | − [chnlgroup][index] + | |
| 195 | + writeval = rtlphy->mcs_offset[chnlgroup][index] + | |
| 197 | 196 | ((index < 2) ? pwrbase0 : pwrbase1); |
| 198 | 197 | |
| 199 | 198 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| @@ -223,8 +222,7 @@ static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw, · 23 unmodified lines | ||
| 223 | 222 | chnlgroup++; |
| 224 | 223 | } |
| 225 | 224 | |
| 226 | − writeval = rtlphy->mcs_txpwrlevel_origoffset | |
| 227 | − [chnlgroup][index] | |
| 225 | + writeval = rtlphy->mcs_offset[chnlgroup][index] | |
| 228 | 226 | + ((index < 2) ? |
| 229 | 227 | pwrbase0 : pwrbase1); |
| 230 | 228 | |
| @@ -257,8 +255,7 @@ static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw, · 26 unmodified lines | ||
| 257 | 255 | } |
| 258 | 256 | |
| 259 | 257 | for (i = 0; i < 4; i++) { |
| 260 | − pwrdiff_limit[i] = | |
| 261 | − (u8)((rtlphy->mcs_txpwrlevel_origoffset | |
| 258 | + pwrdiff_limit[i] = (u8)((rtlphy->mcs_offset | |
| 262 | 259 | [chnlgroup][index] & (0x7f << (i * 8))) |
| 263 | 260 | >> (i * 8)); |
| 264 | 261 | |
| @@ -296,7 +293,7 @@ static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw, · 31 unmodified lines | ||
| 296 | 293 | break; |
| 297 | 294 | default: |
| 298 | 295 | chnlgroup = 0; |
| 299 | − writeval = rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index] + | |
| 296 | + writeval = rtlphy->mcs_offset[chnlgroup][index] + | |
| 300 | 297 | ((index < 2) ? pwrbase0 : pwrbase1); |
| 301 | 298 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, |
| 302 | 299 | "RTK better performance, writeval = 0x%x\n", writeval); |
| @@ -129,8 +129,8 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, · 128 unmodified lines | ||
| 129 | 129 | pstats->packet_matchbssid = packet_match_bssid; |
| 130 | 130 | pstats->packet_toself = packet_toself; |
| 131 | 131 | pstats->packet_beacon = packet_beacon; |
| 132 | − pstats->rx_mimo_signalquality[0] = -1; | |
| 133 | − pstats->rx_mimo_signalquality[1] = -1; | |
| 132 | + pstats->rx_mimo_sig_qual[0] = -1; | |
| 133 | + pstats->rx_mimo_sig_qual[1] = -1; | |
| 134 | 134 | |
| 135 | 135 | if (is_cck) { |
| 136 | 136 | u8 report, cck_highpwr; |
| @@ -216,8 +216,8 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, · 79 unmodified lines | ||
| 216 | 216 | } |
| 217 | 217 | |
| 218 | 218 | pstats->signalquality = sq; |
| 219 | − pstats->rx_mimo_signalquality[0] = sq; | |
| 220 | − pstats->rx_mimo_signalquality[1] = -1; | |
| 219 | + pstats->rx_mimo_sig_qual[0] = sq; | |
| 220 | + pstats->rx_mimo_sig_qual[1] = -1; | |
| 221 | 221 | } |
| 222 | 222 | } else { |
| 223 | 223 | rtlpriv->dm.rfpath_rxenable[0] = |
| @@ -256,8 +256,7 @@ static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, · 32 unmodified lines | ||
| 256 | 256 | if (i == 0) |
| 257 | 257 | pstats->signalquality = (u8)(evm & |
| 258 | 258 | 0xff); |
| 259 | − pstats->rx_mimo_signalquality[i] = | |
| 260 | − (u8) (evm & 0xff); | |
| 259 | + pstats->rx_mimo_sig_qual[i] = (u8) (evm & 0xff); | |
| 261 | 260 | } |
| 262 | 261 | } |
| 263 | 262 | } |
| @@ -366,7 +365,7 @@ static void _rtl92se_process_pwdb(struct ieee80211_hw *hw, · 102 unmodified lines | ||
| 366 | 365 | return; |
| 367 | 366 | } else { |
| 368 | 367 | undec_sm_pwdb = |
| 369 | − rtlpriv->dm.undecorated_smoothed_pwdb; | |
| 368 | + rtlpriv->dm.undec_sm_pwdb; | |
| 370 | 369 | } |
| 371 | 370 | |
| 372 | 371 | if (pstats->packet_toself || pstats->packet_beacon) { |
| @@ -386,7 +385,7 @@ static void _rtl92se_process_pwdb(struct ieee80211_hw *hw, · 13 unmodified lines | ||
| 386 | 385 | (RX_SMOOTH_FACTOR); |
| 387 | 386 | } |
| 388 | 387 | |
| 389 | − rtlpriv->dm.undecorated_smoothed_pwdb = undec_sm_pwdb; | |
| 388 | + rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb; | |
| 390 | 389 | _rtl92se_update_rxsignalstatistics(hw, pstats); |
| 391 | 390 | } |
| 392 | 391 | } |
| @@ -398,16 +397,16 @@ static void rtl_92s_process_streams(struct ieee80211_hw *hw, · 5 unmodified lines | ||
| 398 | 397 | u32 stream; |
| 399 | 398 | |
| 400 | 399 | for (stream = 0; stream < 2; stream++) { |
| 401 | − if (pstats->rx_mimo_signalquality[stream] != -1) { | |
| 400 | + if (pstats->rx_mimo_sig_qual[stream] != -1) { | |
| 402 | 401 | if (rtlpriv->stats.rx_evm_percentage[stream] == 0) { |
| 403 | 402 | rtlpriv->stats.rx_evm_percentage[stream] = |
| 404 | − pstats->rx_mimo_signalquality[stream]; | |
| 403 | + pstats->rx_mimo_sig_qual[stream]; | |
| 405 | 404 | } |
| 406 | 405 | |
| 407 | 406 | rtlpriv->stats.rx_evm_percentage[stream] = |
| 408 | 407 | ((rtlpriv->stats.rx_evm_percentage[stream] * |
| 409 | 408 | (RX_SMOOTH_FACTOR - 1)) + |
| 410 | − (pstats->rx_mimo_signalquality[stream] * | |
| 409 | + (pstats->rx_mimo_sig_qual[stream] * | |
| 411 | 410 | 1)) / (RX_SMOOTH_FACTOR); |
| 412 | 411 | } |
| 413 | 412 | } |
| @@ -198,15 +198,15 @@ struct bb_reg_def { · 197 unmodified lines | ||
| 198 | 198 | u32 rftxgain_stage; |
| 199 | 199 | u32 rfhssi_para1; |
| 200 | 200 | u32 rfhssi_para2; |
| 201 | − u32 rfswitch_control; | |
| 201 | + u32 rfsw_ctrl; | |
| 202 | 202 | u32 rfagc_control1; |
| 203 | 203 | u32 rfagc_control2; |
| 204 | − u32 rfrxiq_imbalance; | |
| 204 | + u32 rfrxiq_imbal; | |
| 205 | 205 | u32 rfrx_afe; |
| 206 | − u32 rftxiq_imbalance; | |
| 206 | + u32 rftxiq_imbal; | |
| 207 | 207 | u32 rftx_afe; |
| 208 | − u32 rflssi_readback; | |
| 209 | − u32 rflssi_readbackpi; | |
| 208 | + u32 rf_rb; /* rflssi_readback */ | |
| 209 | + u32 rf_rbpi; /* rflssi_readbackpi */ | |
| 210 | 210 | }; |
| 211 | 211 | |
| 212 | 212 | enum io_type { |
| @@ -885,7 +885,7 @@ struct rtl_phy { · 672 unmodified lines | ||
| 885 | 885 | u8 pwrgroup_cnt; |
| 886 | 886 | u8 cck_high_power; |
| 887 | 887 | /* MAX_PG_GROUP groups of pwr diff by rates */ |
| 888 | − u32 mcs_txpwrlevel_origoffset[MAX_PG_GROUP][16]; | |
| 888 | + u32 mcs_offset[MAX_PG_GROUP][16]; | |
| 889 | 889 | u8 default_initialgain[4]; |
| 890 | 890 | |
| 891 | 891 | /* the current Tx power level */ |
| @@ -933,7 +933,7 @@ struct rtl_tid_data { · 41 unmodified lines | ||
| 933 | 933 | }; |
| 934 | 934 | |
| 935 | 935 | struct rssi_sta { |
| 936 | − long undecorated_smoothed_pwdb; | |
| 936 | + long undec_sm_pwdb; | |
| 937 | 937 | }; |
| 938 | 938 | |
| 939 | 939 | struct rtl_sta_info { |
| @@ -1131,9 +1131,9 @@ struct rtl_security { · 191 unmodified lines | ||
| 1131 | 1131 | |
| 1132 | 1132 | struct rtl_dm { |
| 1133 | 1133 | /*PHY status for Dynamic Management */ |
| 1134 | − long entry_min_undecoratedsmoothed_pwdb; | |
| 1135 | − long undecorated_smoothed_pwdb; /*out dm */ | |
| 1136 | − long entry_max_undecoratedsmoothed_pwdb; | |
| 1134 | + long entry_min_undec_sm_pwdb; | |
| 1135 | + long undec_sm_pwdb; /*out dm */ | |
| 1136 | + long entry_max_undec_sm_pwdb; | |
| 1137 | 1137 | bool dm_initialgain_enable; |
| 1138 | 1138 | bool dynamic_txpower_enable; |
| 1139 | 1139 | bool current_turbo_edca; |
| @@ -1209,7 +1209,7 @@ struct rtl_efuse { · 69 unmodified lines | ||
| 1209 | 1209 | u8 eeprom_pwrlimit_ht40[CHANNEL_GROUP_MAX]; |
| 1210 | 1210 | u8 eeprom_chnlarea_txpwr_cck[2][CHANNEL_GROUP_MAX_2G]; |
| 1211 | 1211 | u8 eeprom_chnlarea_txpwr_ht40_1s[2][CHANNEL_GROUP_MAX]; |
| 1212 | − u8 eeprom_chnlarea_txpwr_ht40_2sdiif[2][CHANNEL_GROUP_MAX]; | |
| 1212 | + u8 eprom_chnl_txpwr_ht40_2sdf[2][CHANNEL_GROUP_MAX]; | |
| 1213 | 1213 | u8 txpwrlevel_cck[2][CHANNEL_MAX_NUMBER_2G]; |
| 1214 | 1214 | u8 txpwrlevel_ht40_1s[2][CHANNEL_MAX_NUMBER]; /*For HT 40MHZ pwr */ |
| 1215 | 1215 | u8 txpwrlevel_ht40_2s[2][CHANNEL_MAX_NUMBER]; /*For HT 40MHZ pwr */ |
| @@ -1351,7 +1351,7 @@ struct rtl_stats { · 135 unmodified lines | ||
| 1351 | 1351 | bool rx_is40Mhzpacket; |
| 1352 | 1352 | u32 rx_pwdb_all; |
| 1353 | 1353 | u8 rx_mimo_signalstrength[4]; /*in 0~100 index */ |
| 1354 | − s8 rx_mimo_signalquality[2]; | |
| 1354 | + s8 rx_mimo_sig_qual[2]; | |
| 1355 | 1355 | bool packet_matchbssid; |
| 1356 | 1356 | bool is_cck; |
| 1357 | 1357 | bool is_ht; |
| @@ -1503,6 +1503,9 @@ struct rtl_hal_ops { · 145 unmodified lines | ||
| 1503 | 1503 | void (*phy_lc_calibrate) (struct ieee80211_hw *hw, bool is2t); |
| 1504 | 1504 | void (*phy_set_bw_mode_callback) (struct ieee80211_hw *hw); |
| 1505 | 1505 | void (*dm_dynamic_txpower) (struct ieee80211_hw *hw); |
| 1506 | + void (*bt_wifi_media_status_notify) (struct ieee80211_hw *hw, | |
| 1507 | + bool mstate); | |
| 1508 | + void (*bt_coex_off_before_lps) (struct ieee80211_hw *hw); | |
| 1506 | 1509 | }; |
| 1507 | 1510 | |
| 1508 | 1511 | struct rtl_intf_ops { |
| @@ -1679,7 +1682,7 @@ struct dig_t { · 170 unmodified lines | ||
| 1679 | 1682 | u32 rssi_highthresh; |
| 1680 | 1683 | u32 fa_lowthresh; |
| 1681 | 1684 | u32 fa_highthresh; |
| 1682 | − long last_min_undecorated_pwdb_for_dm; | |
| 1685 | + long last_min_undec_pwdb_for_dm; | |
| 1683 | 1686 | long rssi_highpower_lowthresh; |
| 1684 | 1687 | long rssi_highpower_highthresh; |
| 1685 | 1688 | u32 recover_cnt; |
| @@ -1692,15 +1695,15 @@ struct dig_t { · 6 unmodified lines | ||
| 1692 | 1695 | u8 dig_twoport_algorithm; |
| 1693 | 1696 | u8 dig_dbgmode; |
| 1694 | 1697 | u8 dig_slgorithm_switch; |
| 1695 | − u8 cursta_connectstate; | |
| 1696 | − u8 presta_connectstate; | |
| 1697 | − u8 curmultista_connectstate; | |
| 1698 | − char backoff_val; | |
| 1699 | − char backoff_val_range_max; | |
| 1700 | − char backoff_val_range_min; | |
| 1698 | + u8 cursta_cstate; | |
| 1699 | + u8 presta_cstate; | |
| 1700 | + u8 curmultista_cstate; | |
| 1701 | + char back_val; | |
| 1702 | + char back_range_max; | |
| 1703 | + char back_range_min; | |
| 1701 | 1704 | u8 rx_gain_range_max; |
| 1702 | 1705 | u8 rx_gain_range_min; |
| 1703 | − u8 min_undecorated_pwdb_for_dm; | |
| 1706 | + u8 min_undec_pwdb_for_dm; | |
| 1704 | 1707 | u8 rssi_val_min; |
| 1705 | 1708 | u8 pre_cck_pd_state; |
| 1706 | 1709 | u8 cur_cck_pd_state; |
| @@ -1712,10 +1715,10 @@ struct dig_t { · 5 unmodified lines | ||
| 1712 | 1715 | u8 forbidden_igi; |
| 1713 | 1716 | u8 dig_state; |
| 1714 | 1717 | u8 dig_highpwrstate; |
| 1715 | − u8 cur_sta_connectstate; | |
| 1716 | − u8 pre_sta_connectstate; | |
| 1717 | − u8 cur_ap_connectstate; | |
| 1718 | − u8 pre_ap_connectstate; | |
| 1718 | + u8 cur_sta_cstate; | |
| 1719 | + u8 pre_sta_cstate; | |
| 1720 | + u8 cur_ap_cstate; | |
| 1721 | + u8 pre_ap_cstate; | |
| 1719 | 1722 | u8 cur_pd_thstate; |
| 1720 | 1723 | u8 pre_pd_thstate; |
| 1721 | 1724 | u8 cur_cs_ratiostate; |
| @@ -1846,7 +1849,7 @@ struct bt_coexist_info { · 124 unmodified lines | ||
| 1846 | 1849 | u8 eeprom_bt_coexist; |
| 1847 | 1850 | u8 eeprom_bt_type; |
| 1848 | 1851 | u8 eeprom_bt_ant_num; |
| 1849 | − u8 eeprom_bt_ant_isolation; | |
| 1852 | + u8 eeprom_bt_ant_isol; | |
| 1850 | 1853 | u8 eeprom_bt_radio_shared; |
| 1851 | 1854 | |
| 1852 | 1855 | u8 bt_coexistence; |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | # Makefile for nfc devices |
| 3 | 3 | # |
| 4 | 4 | |
| 5 | −obj-$(CONFIG_PN544_HCI_NFC) += pn544_hci.o | |
| 5 | +obj-$(CONFIG_PN544_HCI_NFC) += pn544/ | |
| 6 | 6 | obj-$(CONFIG_NFC_PN533) += pn533.o |
| 7 | 7 | obj-$(CONFIG_NFC_WILINK) += nfcwilink.o |
| 8 | 8 | |
| @@ -84,6 +84,10 @@ MODULE_DEVICE_TABLE(usb, pn533_table); · 83 unmodified lines | ||
| 84 | 84 | #define PN533_LISTEN_TIME 2 |
| 85 | 85 | |
| 86 | 86 | /* frame definitions */ |
| 87 | +#define PN533_NORMAL_FRAME_MAX_LEN 262 /* 6 (PREAMBLE, SOF, LEN, LCS, TFI) | |
| 88 | + 254 (DATA) | |
| 89 | + 2 (DCS, postamble) */ | |
| 90 | + | |
| 87 | 91 | #define PN533_FRAME_TAIL_SIZE 2 |
| 88 | 92 | #define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \ |
| 89 | 93 | PN533_FRAME_TAIL_SIZE) |
| @@ -1165,8 +1169,7 @@ static void pn533_poll_create_mod_list(struct pn533 *dev, · 1075 unmodified lines | ||
| 1165 | 1169 | pn533_poll_add_mod(dev, PN533_LISTEN_MOD); |
| 1166 | 1170 | } |
| 1167 | 1171 | |
| 1168 | −static int pn533_start_poll_complete(struct pn533 *dev, void *arg, | |
| 1169 | − u8 *params, int params_len) | |
| 1172 | +static int pn533_start_poll_complete(struct pn533 *dev, u8 *params, int params_len) | |
| 1170 | 1173 | { |
| 1171 | 1174 | struct pn533_poll_response *resp; |
| 1172 | 1175 | int rc; |
| @@ -1304,8 +1307,7 @@ static void pn533_wq_tg_get_data(struct work_struct *work) · 131 unmodified lines | ||
| 1304 | 1307 | } |
| 1305 | 1308 | |
| 1306 | 1309 | #define ATR_REQ_GB_OFFSET 17 |
| 1307 | −static int pn533_init_target_complete(struct pn533 *dev, void *arg, | |
| 1308 | − u8 *params, int params_len) | |
| 1310 | +static int pn533_init_target_complete(struct pn533 *dev, u8 *params, int params_len) | |
| 1309 | 1311 | { |
| 1310 | 1312 | struct pn533_cmd_init_target_response *resp; |
| 1311 | 1313 | u8 frame, comm_mode = NFC_COMM_PASSIVE, *gb; |
| @@ -1402,9 +1404,9 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, · 90 unmodified lines | ||
| 1402 | 1404 | if (cur_mod->len == 0) { |
| 1403 | 1405 | del_timer(&dev->listen_timer); |
| 1404 | 1406 | |
| 1405 | − return pn533_init_target_complete(dev, arg, params, params_len); | |
| 1407 | + return pn533_init_target_complete(dev, params, params_len); | |
| 1406 | 1408 | } else { |
| 1407 | − rc = pn533_start_poll_complete(dev, arg, params, params_len); | |
| 1409 | + rc = pn533_start_poll_complete(dev, params, params_len); | |
| 1408 | 1410 | if (!rc) |
| 1409 | 1411 | return rc; |
| 1410 | 1412 | } |
| @@ -2373,9 +2375,9 @@ static int pn533_probe(struct usb_interface *interface, · 962 unmodified lines | ||
| 2373 | 2375 | goto error; |
| 2374 | 2376 | } |
| 2375 | 2377 | |
| 2376 | − dev->in_frame = kmalloc(dev->in_maxlen, GFP_KERNEL); | |
| 2378 | + dev->in_frame = kmalloc(PN533_NORMAL_FRAME_MAX_LEN, GFP_KERNEL); | |
| 2377 | 2379 | dev->in_urb = usb_alloc_urb(0, GFP_KERNEL); |
| 2378 | − dev->out_frame = kmalloc(dev->out_maxlen, GFP_KERNEL); | |
| 2380 | + dev->out_frame = kmalloc(PN533_NORMAL_FRAME_MAX_LEN, GFP_KERNEL); | |
| 2379 | 2381 | dev->out_urb = usb_alloc_urb(0, GFP_KERNEL); |
| 2380 | 2382 | |
| 2381 | 2383 | if (!dev->in_frame || !dev->out_frame || |
| @@ -0,0 +1,7 @@ | ||
| 1 | +# | |
| 2 | +# Makefile for PN544 HCI based NFC driver | |
| 3 | +# | |
| 4 | + | |
| 5 | +obj-$(CONFIG_PN544_HCI_NFC) += pn544_i2c.o | |
| 6 | + | |
| 7 | +pn544_i2c-y := pn544.o i2c.o | |
| @@ -0,0 +1,500 @@ | ||
| 1 | +/* | |
| 2 | + * I2C Link Layer for PN544 HCI based Driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2012 Intel Corporation. All rights reserved. | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify it | |
| 7 | + * under the terms and conditions of the GNU General Public License, | |
| 8 | + * version 2, as published by the Free Software Foundation. | |
| 9 | + * | |
| 10 | + * This program is distributed in the hope that it will be useful, | |
| 11 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 12 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 13 | + * GNU General Public License for more details. | |
| 14 | + * | |
| 15 | + * You should have received a copy of the GNU General Public License | |
| 16 | + * along with this program; if not, write to the | |
| 17 | + * Free Software Foundation, Inc., | |
| 18 | + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
| 19 | + */ | |
| 20 | + | |
| 21 | +#include <linux/crc-ccitt.h> | |
| 22 | +#include <linux/module.h> | |
| 23 | +#include <linux/i2c.h> | |
| 24 | +#include <linux/gpio.h> | |
| 25 | +#include <linux/miscdevice.h> | |
| 26 | +#include <linux/interrupt.h> | |
| 27 | +#include <linux/delay.h> | |
| 28 | + | |
| 29 | +#include <linux/nfc/pn544.h> | |
| 30 | + | |
| 31 | +#include <net/nfc/hci.h> | |
| 32 | +#include <net/nfc/llc.h> | |
| 33 | + | |
| 34 | +#include "pn544.h" | |
| 35 | + | |
| 36 | +#define PN544_I2C_FRAME_HEADROOM 1 | |
| 37 | +#define PN544_I2C_FRAME_TAILROOM 2 | |
| 38 | + | |
| 39 | +/* framing in HCI mode */ | |
| 40 | +#define PN544_HCI_I2C_LLC_LEN 1 | |
| 41 | +#define PN544_HCI_I2C_LLC_CRC 2 | |
| 42 | +#define PN544_HCI_I2C_LLC_LEN_CRC (PN544_HCI_I2C_LLC_LEN + \ | |
| 43 | + PN544_HCI_I2C_LLC_CRC) | |
| 44 | +#define PN544_HCI_I2C_LLC_MIN_SIZE (1 + PN544_HCI_I2C_LLC_LEN_CRC) | |
| 45 | +#define PN544_HCI_I2C_LLC_MAX_PAYLOAD 29 | |
| 46 | +#define PN544_HCI_I2C_LLC_MAX_SIZE (PN544_HCI_I2C_LLC_LEN_CRC + 1 + \ | |
| 47 | + PN544_HCI_I2C_LLC_MAX_PAYLOAD) | |
| 48 | + | |
| 49 | +static struct i2c_device_id pn544_hci_i2c_id_table[] = { | |
| 50 | + {"pn544", 0}, | |
| 51 | + {} | |
| 52 | +}; | |
| 53 | + | |
| 54 | +MODULE_DEVICE_TABLE(i2c, pn544_hci_i2c_id_table); | |
| 55 | + | |
| 56 | +#define PN544_HCI_I2C_DRIVER_NAME "pn544_hci_i2c" | |
| 57 | + | |
| 58 | +struct pn544_i2c_phy { | |
| 59 | + struct i2c_client *i2c_dev; | |
| 60 | + struct nfc_hci_dev *hdev; | |
| 61 | + | |
| 62 | + unsigned int gpio_en; | |
| 63 | + unsigned int gpio_irq; | |
| 64 | + unsigned int gpio_fw; | |
| 65 | + unsigned int en_polarity; | |
| 66 | + | |
| 67 | + int powered; | |
| 68 | + | |
| 69 | + int hard_fault; /* | |
| 70 | + * < 0 if hardware error occured (e.g. i2c err) | |
| 71 | + * and prevents normal operation. | |
| 72 | + */ | |
| 73 | +}; | |
| 74 | + | |
| 75 | +#define I2C_DUMP_SKB(info, skb) \ | |
| 76 | +do { \ | |
| 77 | + pr_debug("%s:\n", info); \ | |
| 78 | + print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET, \ | |
| 79 | + 16, 1, (skb)->data, (skb)->len, 0); \ | |
| 80 | +} while (0) | |
| 81 | + | |
| 82 | +static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy) | |
| 83 | +{ | |
| 84 | + int polarity, retry, ret; | |
| 85 | + char rset_cmd[] = { 0x05, 0xF9, 0x04, 0x00, 0xC3, 0xE5 }; | |
| 86 | + int count = sizeof(rset_cmd); | |
| 87 | + | |
| 88 | + pr_info(DRIVER_DESC ": %s\n", __func__); | |
| 89 | + dev_info(&phy->i2c_dev->dev, "Detecting nfc_en polarity\n"); | |
| 90 | + | |
| 91 | + /* Disable fw download */ | |
| 92 | + gpio_set_value(phy->gpio_fw, 0); | |
| 93 | + | |
| 94 | + for (polarity = 0; polarity < 2; polarity++) { | |
| 95 | + phy->en_polarity = polarity; | |
| 96 | + retry = 3; | |
| 97 | + while (retry--) { | |
| 98 | + /* power off */ | |
| 99 | + gpio_set_value(phy->gpio_en, !phy->en_polarity); | |
| 100 | + usleep_range(10000, 15000); | |
| 101 | + | |
| 102 | + /* power on */ | |
| 103 | + gpio_set_value(phy->gpio_en, phy->en_polarity); | |
| 104 | + usleep_range(10000, 15000); | |
| 105 | + | |
| 106 | + /* send reset */ | |
| 107 | + dev_dbg(&phy->i2c_dev->dev, "Sending reset cmd\n"); | |
| 108 | + ret = i2c_master_send(phy->i2c_dev, rset_cmd, count); | |
| 109 | + if (ret == count) { | |
| 110 | + dev_info(&phy->i2c_dev->dev, | |
| 111 | + "nfc_en polarity : active %s\n", | |
| 112 | + (polarity == 0 ? "low" : "high")); | |
| 113 | + goto out; | |
| 114 | + } | |
| 115 | + } | |
| 116 | + } | |
| 117 | + | |
| 118 | + dev_err(&phy->i2c_dev->dev, | |
| 119 | + "Could not detect nfc_en polarity, fallback to active high\n"); | |
| 120 | + | |
| 121 | +out: | |
| 122 | + gpio_set_value(phy->gpio_en, !phy->en_polarity); | |
| 123 | +} | |
| 124 | + | |
| 125 | +static int pn544_hci_i2c_enable(void *phy_id) | |
| 126 | +{ | |
| 127 | + struct pn544_i2c_phy *phy = phy_id; | |
| 128 | + | |
| 129 | + pr_info(DRIVER_DESC ": %s\n", __func__); | |
| 130 | + | |
| 131 | + gpio_set_value(phy->gpio_fw, 0); | |
| 132 | + gpio_set_value(phy->gpio_en, phy->en_polarity); | |
| 133 | + usleep_range(10000, 15000); | |
| 134 | + | |
| 135 | + phy->powered = 1; | |
| 136 | + | |
| 137 | + return 0; | |
| 138 | +} | |
| 139 | + | |
| 140 | +static void pn544_hci_i2c_disable(void *phy_id) | |
| 141 | +{ | |
| 142 | + struct pn544_i2c_phy *phy = phy_id; | |
| 143 | + | |
| 144 | + pr_info(DRIVER_DESC ": %s\n", __func__); | |
| 145 | + | |
| 146 | + gpio_set_value(phy->gpio_fw, 0); | |
| 147 | + gpio_set_value(phy->gpio_en, !phy->en_polarity); | |
| 148 | + usleep_range(10000, 15000); | |
| 149 | + | |
| 150 | + gpio_set_value(phy->gpio_en, phy->en_polarity); | |
| 151 | + usleep_range(10000, 15000); | |
| 152 | + | |
| 153 | + gpio_set_value(phy->gpio_en, !phy->en_polarity); | |
| 154 | + usleep_range(10000, 15000); | |
| 155 | + | |
| 156 | + phy->powered = 0; | |
| 157 | +} | |
| 158 | + | |
| 159 | +static void pn544_hci_i2c_add_len_crc(struct sk_buff *skb) | |
| 160 | +{ | |
| 161 | + u16 crc; | |
| 162 | + int len; | |
| 163 | + | |
| 164 | + len = skb->len + 2; | |
| 165 | + *skb_push(skb, 1) = len; | |
| 166 | + | |
| 167 | + crc = crc_ccitt(0xffff, skb->data, skb->len); | |
| 168 | + crc = ~crc; | |
| 169 | + *skb_put(skb, 1) = crc & 0xff; | |
| 170 | + *skb_put(skb, 1) = crc >> 8; | |
| 171 | +} | |
| 172 | + | |
| 173 | +static void pn544_hci_i2c_remove_len_crc(struct sk_buff *skb) | |
| 174 | +{ | |
| 175 | + skb_pull(skb, PN544_I2C_FRAME_HEADROOM); | |
| 176 | + skb_trim(skb, PN544_I2C_FRAME_TAILROOM); | |
| 177 | +} | |
| 178 | + | |
| 179 | +/* | |
| 180 | + * Writing a frame must not return the number of written bytes. | |
| 181 | + * It must return either zero for success, or <0 for error. | |
| 182 | + * In addition, it must not alter the skb | |
| 183 | + */ | |
| 184 | +static int pn544_hci_i2c_write(void *phy_id, struct sk_buff *skb) | |
| 185 | +{ | |
| 186 | + int r; | |
| 187 | + struct pn544_i2c_phy *phy = phy_id; | |
| 188 | + struct i2c_client *client = phy->i2c_dev; | |
| 189 | + | |
| 190 | + if (phy->hard_fault != 0) | |
| 191 | + return phy->hard_fault; | |
| 192 | + | |
| 193 | + usleep_range(3000, 6000); | |
| 194 | + | |
| 195 | + pn544_hci_i2c_add_len_crc(skb); | |
| 196 | + | |
| 197 | + I2C_DUMP_SKB("i2c frame written", skb); | |
| 198 | + | |
| 199 | + r = i2c_master_send(client, skb->data, skb->len); | |
| 200 | + | |
| 201 | + if (r == -EREMOTEIO) { /* Retry, chip was in standby */ | |
| 202 | + usleep_range(6000, 10000); | |
| 203 | + r = i2c_master_send(client, skb->data, skb->len); | |
| 204 | + } | |
| 205 | + | |
| 206 | + if (r >= 0) { | |
| 207 | + if (r != skb->len) | |
| 208 | + r = -EREMOTEIO; | |
| 209 | + else | |
| 210 | + r = 0; | |
| 211 | + } | |
| 212 | + | |
| 213 | + pn544_hci_i2c_remove_len_crc(skb); | |
| 214 | + | |
| 215 | + return r; | |
| 216 | +} | |
| 217 | + | |
| 218 | +static int check_crc(u8 *buf, int buflen) | |
| 219 | +{ | |
| 220 | + int len; | |
| 221 | + u16 crc; | |
| 222 | + | |
| 223 | + len = buf[0] + 1; | |
| 224 | + crc = crc_ccitt(0xffff, buf, len - 2); | |
| 225 | + crc = ~crc; | |
| 226 | + | |
| 227 | + if (buf[len - 2] != (crc & 0xff) || buf[len - 1] != (crc >> 8)) { | |
| 228 | + pr_err(PN544_HCI_I2C_DRIVER_NAME | |
| 229 | + ": CRC error 0x%x != 0x%x 0x%x\n", | |
| 230 | + crc, buf[len - 1], buf[len - 2]); | |
| 231 | + | |
| 232 | + pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__); | |
| 233 | + print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE, | |
| 234 | + 16, 2, buf, buflen, false); | |
| 235 | + return -EPERM; | |
| 236 | + } | |
| 237 | + return 0; | |
| 238 | +} | |
| 239 | + | |
| 240 | +/* | |
| 241 | + * Reads an shdlc frame and returns it in a newly allocated sk_buff. Guarantees | |
| 242 | + * that i2c bus will be flushed and that next read will start on a new frame. | |
| 243 | + * returned skb contains only LLC header and payload. | |
| 244 | + * returns: | |
| 245 | + * -EREMOTEIO : i2c read error (fatal) | |
| 246 | + * -EBADMSG : frame was incorrect and discarded | |
| 247 | + * -ENOMEM : cannot allocate skb, frame dropped | |
| 248 | + */ | |
| 249 | +static int pn544_hci_i2c_read(struct pn544_i2c_phy *phy, struct sk_buff **skb) | |
| 250 | +{ | |
| 251 | + int r; | |
| 252 | + u8 len; | |
| 253 | + u8 tmp[PN544_HCI_I2C_LLC_MAX_SIZE - 1]; | |
| 254 | + struct i2c_client *client = phy->i2c_dev; | |
| 255 | + | |
| 256 | + r = i2c_master_recv(client, &len, 1); | |
| 257 | + if (r != 1) { | |
| 258 | + dev_err(&client->dev, "cannot read len byte\n"); | |
| 259 | + return -EREMOTEIO; | |
| 260 | + } | |
| 261 | + | |
| 262 | + if ((len < (PN544_HCI_I2C_LLC_MIN_SIZE - 1)) || | |
| 263 | + (len > (PN544_HCI_I2C_LLC_MAX_SIZE - 1))) { | |
| 264 | + dev_err(&client->dev, "invalid len byte\n"); | |
| 265 | + r = -EBADMSG; | |
| 266 | + goto flush; | |
| 267 | + } | |
| 268 | + | |
| 269 | + *skb = alloc_skb(1 + len, GFP_KERNEL); | |
| 270 | + if (*skb == NULL) { | |
| 271 | + r = -ENOMEM; | |
| 272 | + goto flush; | |
| 273 | + } | |
| 274 | + | |
| 275 | + *skb_put(*skb, 1) = len; | |
| 276 | + | |
| 277 | + r = i2c_master_recv(client, skb_put(*skb, len), len); | |
| 278 | + if (r != len) { | |
| 279 | + kfree_skb(*skb); | |
| 280 | + return -EREMOTEIO; | |
| 281 | + } | |
| 282 | + | |
| 283 | + I2C_DUMP_SKB("i2c frame read", *skb); | |
| 284 | + | |
| 285 | + r = check_crc((*skb)->data, (*skb)->len); | |
| 286 | + if (r != 0) { | |
| 287 | + kfree_skb(*skb); | |
| 288 | + r = -EBADMSG; | |
| 289 | + goto flush; | |
| 290 | + } | |
| 291 | + | |
| 292 | + skb_pull(*skb, 1); | |
| 293 | + skb_trim(*skb, (*skb)->len - 2); | |
| 294 | + | |
| 295 | + usleep_range(3000, 6000); | |
| 296 | + | |
| 297 | + return 0; | |
| 298 | + | |
| 299 | +flush: | |
| 300 | + if (i2c_master_recv(client, tmp, sizeof(tmp)) < 0) | |
| 301 | + r = -EREMOTEIO; | |
| 302 | + | |
| 303 | + usleep_range(3000, 6000); | |
| 304 | + | |
| 305 | + return r; | |
| 306 | +} | |
| 307 | + | |
| 308 | +/* | |
| 309 | + * Reads an shdlc frame from the chip. This is not as straightforward as it | |
| 310 | + * seems. There are cases where we could loose the frame start synchronization. | |
| 311 | + * The frame format is len-data-crc, and corruption can occur anywhere while | |
| 312 | + * transiting on i2c bus, such that we could read an invalid len. | |
| 313 | + * In order to recover synchronization with the next frame, we must be sure | |
| 314 | + * to read the real amount of data without using the len byte. We do this by | |
| 315 | + * assuming the following: | |
| 316 | + * - the chip will always present only one single complete frame on the bus | |
| 317 | + * before triggering the interrupt | |
| 318 | + * - the chip will not present a new frame until we have completely read | |
| 319 | + * the previous one (or until we have handled the interrupt). | |
| 320 | + * The tricky case is when we read a corrupted len that is less than the real | |
| 321 | + * len. We must detect this here in order to determine that we need to flush | |
| 322 | + * the bus. This is the reason why we check the crc here. | |
| 323 | + */ | |
| 324 | +static irqreturn_t pn544_hci_i2c_irq_thread_fn(int irq, void *phy_id) | |
| 325 | +{ | |
| 326 | + struct pn544_i2c_phy *phy = phy_id; | |
| 327 | + struct i2c_client *client; | |
| 328 | + struct sk_buff *skb = NULL; | |
| 329 | + int r; | |
| 330 | + | |
| 331 | + if (!phy || irq != phy->i2c_dev->irq) { | |
| 332 | + WARN_ON_ONCE(1); | |
| 333 | + return IRQ_NONE; | |
| 334 | + } | |
| 335 | + | |
| 336 | + client = phy->i2c_dev; | |
| 337 | + dev_dbg(&client->dev, "IRQ\n"); | |
| 338 | + | |
| 339 | + if (phy->hard_fault != 0) | |
| 340 | + return IRQ_HANDLED; | |
| 341 | + | |
| 342 | + r = pn544_hci_i2c_read(phy, &skb); | |
| 343 | + if (r == -EREMOTEIO) { | |
| 344 | + phy->hard_fault = r; | |
| 345 | + | |
| 346 | + nfc_hci_recv_frame(phy->hdev, NULL); | |
| 347 | + | |
| 348 | + return IRQ_HANDLED; | |
| 349 | + } else if ((r == -ENOMEM) || (r == -EBADMSG)) { | |
| 350 | + return IRQ_HANDLED; | |
| 351 | + } | |
| 352 | + | |
| 353 | + nfc_hci_recv_frame(phy->hdev, skb); | |
| 354 | + | |
| 355 | + return IRQ_HANDLED; | |
| 356 | +} | |
| 357 | + | |
| 358 | +static struct nfc_phy_ops i2c_phy_ops = { | |
| 359 | + .write = pn544_hci_i2c_write, | |
| 360 | + .enable = pn544_hci_i2c_enable, | |
| 361 | + .disable = pn544_hci_i2c_disable, | |
| 362 | +}; | |
| 363 | + | |
| 364 | +static int __devinit pn544_hci_i2c_probe(struct i2c_client *client, | |
| 365 | + const struct i2c_device_id *id) | |
| 366 | +{ | |
| 367 | + struct pn544_i2c_phy *phy; | |
| 368 | + struct pn544_nfc_platform_data *pdata; | |
| 369 | + int r = 0; | |
| 370 | + | |
| 371 | + dev_dbg(&client->dev, "%s\n", __func__); | |
| 372 | + dev_dbg(&client->dev, "IRQ: %d\n", client->irq); | |
| 373 | + | |
| 374 | + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | |
| 375 | + dev_err(&client->dev, "Need I2C_FUNC_I2C\n"); | |
| 376 | + return -ENODEV; | |
| 377 | + } | |
| 378 | + | |
| 379 | + phy = kzalloc(sizeof(struct pn544_i2c_phy), GFP_KERNEL); | |
| 380 | + if (!phy) { | |
| 381 | + dev_err(&client->dev, | |
| 382 | + "Cannot allocate memory for pn544 i2c phy.\n"); | |
| 383 | + r = -ENOMEM; | |
| 384 | + goto err_phy_alloc; | |
| 385 | + } | |
| 386 | + | |
| 387 | + phy->i2c_dev = client; | |
| 388 | + i2c_set_clientdata(client, phy); | |
| 389 | + | |
| 390 | + pdata = client->dev.platform_data; | |
| 391 | + if (pdata == NULL) { | |
| 392 | + dev_err(&client->dev, "No platform data\n"); | |
| 393 | + r = -EINVAL; | |
| 394 | + goto err_pdata; | |
| 395 | + } | |
| 396 | + | |
| 397 | + if (pdata->request_resources == NULL) { | |
| 398 | + dev_err(&client->dev, "request_resources() missing\n"); | |
| 399 | + r = -EINVAL; | |
| 400 | + goto err_pdata; | |
| 401 | + } | |
| 402 | + | |
| 403 | + r = pdata->request_resources(client); | |
| 404 | + if (r) { | |
| 405 | + dev_err(&client->dev, "Cannot get platform resources\n"); | |
| 406 | + goto err_pdata; | |
| 407 | + } | |
| 408 | + | |
| 409 | + phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE); | |
| 410 | + phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET); | |
| 411 | + phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ); | |
| 412 | + | |
| 413 | + pn544_hci_i2c_platform_init(phy); | |
| 414 | + | |
| 415 | + r = request_threaded_irq(client->irq, NULL, pn544_hci_i2c_irq_thread_fn, | |
| 416 | + IRQF_TRIGGER_RISING | IRQF_ONESHOT, | |
| 417 | + PN544_HCI_I2C_DRIVER_NAME, phy); | |
| 418 | + if (r < 0) { | |
| 419 | + dev_err(&client->dev, "Unable to register IRQ handler\n"); | |
| 420 | + goto err_rti; | |
| 421 | + } | |
| 422 | + | |
| 423 | + r = pn544_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME, | |
| 424 | + PN544_I2C_FRAME_HEADROOM, PN544_I2C_FRAME_TAILROOM, | |
| 425 | + PN544_HCI_I2C_LLC_MAX_PAYLOAD, &phy->hdev); | |
| 426 | + if (r < 0) | |
| 427 | + goto err_hci; | |
| 428 | + | |
| 429 | + return 0; | |
| 430 | + | |
| 431 | +err_hci: | |
| 432 | + free_irq(client->irq, phy); | |
| 433 | + | |
| 434 | +err_rti: | |
| 435 | + if (pdata->free_resources != NULL) | |
| 436 | + pdata->free_resources(); | |
| 437 | + | |
| 438 | +err_pdata: | |
| 439 | + kfree(phy); | |
| 440 | + | |
| 441 | +err_phy_alloc: | |
| 442 | + return r; | |
| 443 | +} | |
| 444 | + | |
| 445 | +static __devexit int pn544_hci_i2c_remove(struct i2c_client *client) | |
| 446 | +{ | |
| 447 | + struct pn544_i2c_phy *phy = i2c_get_clientdata(client); | |
| 448 | + struct pn544_nfc_platform_data *pdata = client->dev.platform_data; | |
| 449 | + | |
| 450 | + dev_dbg(&client->dev, "%s\n", __func__); | |
| 451 | + | |
| 452 | + pn544_hci_remove(phy->hdev); | |
| 453 | + | |
| 454 | + if (phy->powered) | |
| 455 | + pn544_hci_i2c_disable(phy); | |
| 456 | + | |
| 457 | + free_irq(client->irq, phy); | |
| 458 | + if (pdata->free_resources) | |
| 459 | + pdata->free_resources(); | |
| 460 | + | |
| 461 | + kfree(phy); | |
| 462 | + | |
| 463 | + return 0; | |
| 464 | +} | |
| 465 | + | |
| 466 | +static struct i2c_driver pn544_hci_i2c_driver = { | |
| 467 | + .driver = { | |
| 468 | + .name = PN544_HCI_I2C_DRIVER_NAME, | |
| 469 | + }, | |
| 470 | + .probe = pn544_hci_i2c_probe, | |
| 471 | + .id_table = pn544_hci_i2c_id_table, | |
| 472 | + .remove = __devexit_p(pn544_hci_i2c_remove), | |
| 473 | +}; | |
| 474 | + | |
| 475 | +static int __init pn544_hci_i2c_init(void) | |
| 476 | +{ | |
| 477 | + int r; | |
| 478 | + | |
| 479 | + pr_debug(DRIVER_DESC ": %s\n", __func__); | |
| 480 | + | |
| 481 | + r = i2c_add_driver(&pn544_hci_i2c_driver); | |
| 482 | + if (r) { | |
| 483 | + pr_err(PN544_HCI_I2C_DRIVER_NAME | |
| 484 | + ": driver registration failed\n"); | |
| 485 | + return r; | |
| 486 | + } | |
| 487 | + | |
| 488 | + return 0; | |
| 489 | +} | |
| 490 | + | |
| 491 | +static void __exit pn544_hci_i2c_exit(void) | |
| 492 | +{ | |
| 493 | + i2c_del_driver(&pn544_hci_i2c_driver); | |
| 494 | +} | |
| 495 | + | |
| 496 | +module_init(pn544_hci_i2c_init); | |
| 497 | +module_exit(pn544_hci_i2c_exit); | |
| 498 | + | |
| 499 | +MODULE_LICENSE("GPL"); | |
| 500 | +MODULE_DESCRIPTION(DRIVER_DESC); | |
| @@ -18,47 +18,21 @@ · 17 unmodified lines | ||
| 18 | 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 19 | 19 | */ |
| 20 | 20 | |
| 21 | −#include <linux/crc-ccitt.h> | |
| 22 | −#include <linux/module.h> | |
| 23 | 21 | #include <linux/delay.h> |
| 24 | 22 | #include <linux/slab.h> |
| 25 | −#include <linux/miscdevice.h> | |
| 26 | −#include <linux/interrupt.h> | |
| 27 | −#include <linux/gpio.h> | |
| 28 | −#include <linux/i2c.h> | |
| 29 | 23 | |
| 30 | 24 | #include <linux/nfc.h> |
| 31 | 25 | #include <net/nfc/hci.h> |
| 32 | 26 | #include <net/nfc/llc.h> |
| 33 | 27 | |
| 34 | −#include <linux/nfc/pn544.h> | |
| 35 | − | |
| 36 | −#define DRIVER_DESC "HCI NFC driver for PN544" | |
| 37 | − | |
| 38 | −#define PN544_HCI_DRIVER_NAME "pn544_hci" | |
| 28 | +#include "pn544.h" | |
| 39 | 29 | |
| 40 | 30 | /* Timing restrictions (ms) */ |
| 41 | 31 | #define PN544_HCI_RESETVEN_TIME 30 |
| 42 | 32 | |
| 43 | −static struct i2c_device_id pn544_hci_id_table[] = { | |
| 44 | − {"pn544", 0}, | |
| 45 | − {} | |
| 46 | −}; | |
| 47 | − | |
| 48 | −MODULE_DEVICE_TABLE(i2c, pn544_hci_id_table); | |
| 49 | − | |
| 50 | 33 | #define HCI_MODE 0 |
| 51 | 34 | #define FW_MODE 1 |
| 52 | 35 | |
| 53 | −/* framing in HCI mode */ | |
| 54 | −#define PN544_HCI_LLC_LEN 1 | |
| 55 | −#define PN544_HCI_LLC_CRC 2 | |
| 56 | −#define PN544_HCI_LLC_LEN_CRC (PN544_HCI_LLC_LEN + PN544_HCI_LLC_CRC) | |
| 57 | −#define PN544_HCI_LLC_MIN_SIZE (1 + PN544_HCI_LLC_LEN_CRC) | |
| 58 | −#define PN544_HCI_LLC_MAX_PAYLOAD 29 | |
| 59 | −#define PN544_HCI_LLC_MAX_SIZE (PN544_HCI_LLC_LEN_CRC + 1 + \ | |
| 60 | − PN544_HCI_LLC_MAX_PAYLOAD) | |
| 61 | − | |
| 62 | 36 | enum pn544_state { |
| 63 | 37 | PN544_ST_COLD, |
| 64 | 38 | PN544_ST_FW_READY, |
| @@ -100,6 +74,10 @@ enum pn544_state { · 35 unmodified lines | ||
| 100 | 74 | #define PN544_SYS_MGMT_INFO_NOTIFICATION 0x02 |
| 101 | 75 | |
| 102 | 76 | #define PN544_POLLING_LOOP_MGMT_GATE 0x94 |
| 77 | +#define PN544_DEP_MODE 0x01 | |
| 78 | +#define PN544_DEP_ATR_REQ 0x02 | |
| 79 | +#define PN544_DEP_ATR_RES 0x03 | |
| 80 | +#define PN544_DEP_MERGE 0x0D | |
| 103 | 81 | #define PN544_PL_RDPHASES 0x06 |
| 104 | 82 | #define PN544_PL_EMULATION 0x07 |
| 105 | 83 | #define PN544_PL_NFCT_DEACTIVATED 0x09 |
| @@ -108,6 +86,15 @@ enum pn544_state { · 2 unmodified lines | ||
| 108 | 86 | |
| 109 | 87 | #define PN544_NFC_WI_MGMT_GATE 0xA1 |
| 110 | 88 | |
| 89 | +#define PN544_HCI_EVT_SND_DATA 0x01 | |
| 90 | +#define PN544_HCI_EVT_ACTIVATED 0x02 | |
| 91 | +#define PN544_HCI_EVT_DEACTIVATED 0x03 | |
| 92 | +#define PN544_HCI_EVT_RCV_DATA 0x04 | |
| 93 | +#define PN544_HCI_EVT_CONTINUE_MI 0x05 | |
| 94 | + | |
| 95 | +#define PN544_HCI_CMD_ATTREQUEST 0x12 | |
| 96 | +#define PN544_HCI_CMD_CONTINUE_ACTIVATION 0x13 | |
| 97 | + | |
| 111 | 98 | static struct nfc_hci_gate pn544_gates[] = { |
| 112 | 99 | {NFC_HCI_ADMIN_GATE, NFC_HCI_INVALID_PIPE}, |
| 113 | 100 | {NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE}, |
| @@ -128,259 +115,22 @@ static struct nfc_hci_gate pn544_gates[] = { · 14 unmodified lines | ||
| 128 | 115 | |
| 129 | 116 | /* Largest headroom needed for outgoing custom commands */ |
| 130 | 117 | #define PN544_CMDS_HEADROOM 2 |
| 131 | −#define PN544_FRAME_HEADROOM 1 | |
| 132 | −#define PN544_FRAME_TAILROOM 2 | |
| 133 | 118 | |
| 134 | 119 | struct pn544_hci_info { |
| 135 | − struct i2c_client *i2c_dev; | |
| 120 | + struct nfc_phy_ops *phy_ops; | |
| 121 | + void *phy_id; | |
| 122 | + | |
| 136 | 123 | struct nfc_hci_dev *hdev; |
| 137 | 124 | |
| 138 | 125 | enum pn544_state state; |
| 139 | 126 | |
| 140 | 127 | struct mutex info_lock; |
| 141 | 128 | |
| 142 | − unsigned int gpio_en; | |
| 143 | − unsigned int gpio_irq; | |
| 144 | − unsigned int gpio_fw; | |
| 145 | − unsigned int en_polarity; | |
| 146 | − | |
| 147 | − int hard_fault; /* | |
| 148 | − * < 0 if hardware error occured (e.g. i2c err) | |
| 149 | − * and prevents normal operation. | |
| 150 | − */ | |
| 151 | 129 | int async_cb_type; |
| 152 | 130 | data_exchange_cb_t async_cb; |
| 153 | 131 | void *async_cb_context; |
| 154 | 132 | }; |
| 155 | 133 | |
| 156 | −static void pn544_hci_platform_init(struct pn544_hci_info *info) | |
| 157 | −{ | |
| 158 | − int polarity, retry, ret; | |
| 159 | − char rset_cmd[] = { 0x05, 0xF9, 0x04, 0x00, 0xC3, 0xE5 }; | |
| 160 | − int count = sizeof(rset_cmd); | |
| 161 | − | |
| 162 | − pr_info(DRIVER_DESC ": %s\n", __func__); | |
| 163 | − dev_info(&info->i2c_dev->dev, "Detecting nfc_en polarity\n"); | |
| 164 | − | |
| 165 | − /* Disable fw download */ | |
| 166 | − gpio_set_value(info->gpio_fw, 0); | |
| 167 | − | |
| 168 | − for (polarity = 0; polarity < 2; polarity++) { | |
| 169 | − info->en_polarity = polarity; | |
| 170 | − retry = 3; | |
| 171 | − while (retry--) { | |
| 172 | − /* power off */ | |
| 173 | − gpio_set_value(info->gpio_en, !info->en_polarity); | |
| 174 | − usleep_range(10000, 15000); | |
| 175 | − | |
| 176 | − /* power on */ | |
| 177 | − gpio_set_value(info->gpio_en, info->en_polarity); | |
| 178 | − usleep_range(10000, 15000); | |
| 179 | − | |
| 180 | − /* send reset */ | |
| 181 | − dev_dbg(&info->i2c_dev->dev, "Sending reset cmd\n"); | |
| 182 | − ret = i2c_master_send(info->i2c_dev, rset_cmd, count); | |
| 183 | − if (ret == count) { | |
| 184 | − dev_info(&info->i2c_dev->dev, | |
| 185 | − "nfc_en polarity : active %s\n", | |
| 186 | − (polarity == 0 ? "low" : "high")); | |
| 187 | − goto out; | |
| 188 | − } | |
| 189 | − } | |
| 190 | − } | |
| 191 | − | |
| 192 | − dev_err(&info->i2c_dev->dev, | |
| 193 | − "Could not detect nfc_en polarity, fallback to active high\n"); | |
| 194 | − | |
| 195 | −out: | |
| 196 | − gpio_set_value(info->gpio_en, !info->en_polarity); | |
| 197 | −} | |
| 198 | − | |
| 199 | −static int pn544_hci_enable(struct pn544_hci_info *info, int mode) | |
| 200 | −{ | |
| 201 | − pr_info(DRIVER_DESC ": %s\n", __func__); | |
| 202 | − | |
| 203 | − gpio_set_value(info->gpio_fw, 0); | |
| 204 | − gpio_set_value(info->gpio_en, info->en_polarity); | |
| 205 | − usleep_range(10000, 15000); | |
| 206 | − | |
| 207 | − return 0; | |
| 208 | −} | |
| 209 | − | |
| 210 | −static void pn544_hci_disable(struct pn544_hci_info *info) | |
| 211 | −{ | |
| 212 | − pr_info(DRIVER_DESC ": %s\n", __func__); | |
| 213 | − | |
| 214 | − gpio_set_value(info->gpio_fw, 0); | |
| 215 | − gpio_set_value(info->gpio_en, !info->en_polarity); | |
| 216 | − usleep_range(10000, 15000); | |
| 217 | − | |
| 218 | − gpio_set_value(info->gpio_en, info->en_polarity); | |
| 219 | − usleep_range(10000, 15000); | |
| 220 | − | |
| 221 | − gpio_set_value(info->gpio_en, !info->en_polarity); | |
| 222 | − usleep_range(10000, 15000); | |
| 223 | −} | |
| 224 | − | |
| 225 | −static int pn544_hci_i2c_write(struct i2c_client *client, u8 *buf, int len) | |
| 226 | −{ | |
| 227 | − int r; | |
| 228 | − | |
| 229 | − usleep_range(3000, 6000); | |
| 230 | − | |
| 231 | − r = i2c_master_send(client, buf, len); | |
| 232 | − | |
| 233 | − if (r == -EREMOTEIO) { /* Retry, chip was in standby */ | |
| 234 | − usleep_range(6000, 10000); | |
| 235 | − r = i2c_master_send(client, buf, len); | |
| 236 | − } | |
| 237 | − | |
| 238 | − if (r >= 0) { | |
| 239 | − if (r != len) | |
| 240 | − return -EREMOTEIO; | |
| 241 | − else | |
| 242 | − return 0; | |
| 243 | − } | |
| 244 | − | |
| 245 | − return r; | |
| 246 | −} | |
| 247 | − | |
| 248 | −static int check_crc(u8 *buf, int buflen) | |
| 249 | −{ | |
| 250 | − int len; | |
| 251 | − u16 crc; | |
| 252 | − | |
| 253 | − len = buf[0] + 1; | |
| 254 | − crc = crc_ccitt(0xffff, buf, len - 2); | |
| 255 | − crc = ~crc; | |
| 256 | − | |
| 257 | − if (buf[len - 2] != (crc & 0xff) || buf[len - 1] != (crc >> 8)) { | |
| 258 | − pr_err(PN544_HCI_DRIVER_NAME ": CRC error 0x%x != 0x%x 0x%x\n", | |
| 259 | − crc, buf[len - 1], buf[len - 2]); | |
| 260 | − | |
| 261 | − pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__); | |
| 262 | − print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE, | |
| 263 | − 16, 2, buf, buflen, false); | |
| 264 | − return -EPERM; | |
| 265 | − } | |
| 266 | − return 0; | |
| 267 | −} | |
| 268 | − | |
| 269 | −/* | |
| 270 | − * Reads an shdlc frame and returns it in a newly allocated sk_buff. Guarantees | |
| 271 | − * that i2c bus will be flushed and that next read will start on a new frame. | |
| 272 | − * returned skb contains only LLC header and payload. | |
| 273 | − * returns: | |
| 274 | − * -EREMOTEIO : i2c read error (fatal) | |
| 275 | − * -EBADMSG : frame was incorrect and discarded | |
| 276 | − * -ENOMEM : cannot allocate skb, frame dropped | |
| 277 | − */ | |
| 278 | −static int pn544_hci_i2c_read(struct i2c_client *client, struct sk_buff **skb) | |
| 279 | −{ | |
| 280 | − int r; | |
| 281 | − u8 len; | |
| 282 | − u8 tmp[PN544_HCI_LLC_MAX_SIZE - 1]; | |
| 283 | − | |
| 284 | − r = i2c_master_recv(client, &len, 1); | |
| 285 | − if (r != 1) { | |
| 286 | − dev_err(&client->dev, "cannot read len byte\n"); | |
| 287 | − return -EREMOTEIO; | |
| 288 | − } | |
| 289 | − | |
| 290 | − if ((len < (PN544_HCI_LLC_MIN_SIZE - 1)) || | |
| 291 | − (len > (PN544_HCI_LLC_MAX_SIZE - 1))) { | |
| 292 | − dev_err(&client->dev, "invalid len byte\n"); | |
| 293 | − r = -EBADMSG; | |
| 294 | − goto flush; | |
| 295 | − } | |
| 296 | − | |
| 297 | − *skb = alloc_skb(1 + len, GFP_KERNEL); | |
| 298 | − if (*skb == NULL) { | |
| 299 | − r = -ENOMEM; | |
| 300 | − goto flush; | |
| 301 | − } | |
| 302 | − | |
| 303 | − *skb_put(*skb, 1) = len; | |
| 304 | − | |
| 305 | − r = i2c_master_recv(client, skb_put(*skb, len), len); | |
| 306 | − if (r != len) { | |
| 307 | − kfree_skb(*skb); | |
| 308 | − return -EREMOTEIO; | |
| 309 | − } | |
| 310 | − | |
| 311 | − r = check_crc((*skb)->data, (*skb)->len); | |
| 312 | − if (r != 0) { | |
| 313 | − kfree_skb(*skb); | |
| 314 | − r = -EBADMSG; | |
| 315 | − goto flush; | |
| 316 | − } | |
| 317 | − | |
| 318 | − skb_pull(*skb, 1); | |
| 319 | − skb_trim(*skb, (*skb)->len - 2); | |
| 320 | − | |
| 321 | − usleep_range(3000, 6000); | |
| 322 | − | |
| 323 | − return 0; | |
| 324 | − | |
| 325 | −flush: | |
| 326 | − if (i2c_master_recv(client, tmp, sizeof(tmp)) < 0) | |
| 327 | − r = -EREMOTEIO; | |
| 328 | − | |
| 329 | − usleep_range(3000, 6000); | |
| 330 | − | |
| 331 | − return r; | |
| 332 | −} | |
| 333 | − | |
| 334 | −/* | |
| 335 | − * Reads an shdlc frame from the chip. This is not as straightforward as it | |
| 336 | − * seems. There are cases where we could loose the frame start synchronization. | |
| 337 | − * The frame format is len-data-crc, and corruption can occur anywhere while | |
| 338 | − * transiting on i2c bus, such that we could read an invalid len. | |
| 339 | − * In order to recover synchronization with the next frame, we must be sure | |
| 340 | − * to read the real amount of data without using the len byte. We do this by | |
| 341 | − * assuming the following: | |
| 342 | − * - the chip will always present only one single complete frame on the bus | |
| 343 | − * before triggering the interrupt | |
| 344 | − * - the chip will not present a new frame until we have completely read | |
| 345 | − * the previous one (or until we have handled the interrupt). | |
| 346 | − * The tricky case is when we read a corrupted len that is less than the real | |
| 347 | − * len. We must detect this here in order to determine that we need to flush | |
| 348 | − * the bus. This is the reason why we check the crc here. | |
| 349 | − */ | |
| 350 | −static irqreturn_t pn544_hci_irq_thread_fn(int irq, void *dev_id) | |
| 351 | −{ | |
| 352 | − struct pn544_hci_info *info = dev_id; | |
| 353 | − struct i2c_client *client; | |
| 354 | − struct sk_buff *skb = NULL; | |
| 355 | − int r; | |
| 356 | − | |
| 357 | − if (!info || irq != info->i2c_dev->irq) { | |
| 358 | − WARN_ON_ONCE(1); | |
| 359 | − return IRQ_NONE; | |
| 360 | − } | |
| 361 | − | |
| 362 | − client = info->i2c_dev; | |
| 363 | − dev_dbg(&client->dev, "IRQ\n"); | |
| 364 | − | |
| 365 | − if (info->hard_fault != 0) | |
| 366 | − return IRQ_HANDLED; | |
| 367 | − | |
| 368 | − r = pn544_hci_i2c_read(client, &skb); | |
| 369 | − if (r == -EREMOTEIO) { | |
| 370 | − info->hard_fault = r; | |
| 371 | − | |
| 372 | − nfc_hci_recv_frame(info->hdev, NULL); | |
| 373 | − | |
| 374 | − return IRQ_HANDLED; | |
| 375 | − } else if ((r == -ENOMEM) || (r == -EBADMSG)) { | |
| 376 | − return IRQ_HANDLED; | |
| 377 | − } | |
| 378 | − | |
| 379 | − nfc_hci_recv_frame(info->hdev, skb); | |
| 380 | − | |
| 381 | − return IRQ_HANDLED; | |
| 382 | −} | |
| 383 | − | |
| 384 | 134 | static int pn544_hci_open(struct nfc_hci_dev *hdev) |
| 385 | 135 | { |
| 386 | 136 | struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); |
| @@ -393,7 +143,7 @@ static int pn544_hci_open(struct nfc_hci_dev *hdev) · 6 unmodified lines | ||
| 393 | 143 | goto out; |
| 394 | 144 | } |
| 395 | 145 | |
| 396 | − r = pn544_hci_enable(info, HCI_MODE); | |
| 146 | + r = info->phy_ops->enable(info->phy_id); | |
| 397 | 147 | |
| 398 | 148 | if (r == 0) |
| 399 | 149 | info->state = PN544_ST_READY; |
| @@ -412,7 +162,7 @@ static void pn544_hci_close(struct nfc_hci_dev *hdev) · 12 unmodified lines | ||
| 412 | 162 | if (info->state == PN544_ST_COLD) |
| 413 | 163 | goto out; |
| 414 | 164 | |
| 415 | − pn544_hci_disable(info); | |
| 165 | + info->phy_ops->disable(info->phy_id); | |
| 416 | 166 | |
| 417 | 167 | info->state = PN544_ST_COLD; |
| 418 | 168 | |
| @@ -587,40 +337,11 @@ static int pn544_hci_ready(struct nfc_hci_dev *hdev) · 168 unmodified lines | ||
| 587 | 337 | return 0; |
| 588 | 338 | } |
| 589 | 339 | |
| 590 | −static void pn544_hci_add_len_crc(struct sk_buff *skb) | |
| 591 | −{ | |
| 592 | − u16 crc; | |
| 593 | − int len; | |
| 594 | − | |
| 595 | − len = skb->len + 2; | |
| 596 | − *skb_push(skb, 1) = len; | |
| 597 | − | |
| 598 | − crc = crc_ccitt(0xffff, skb->data, skb->len); | |
| 599 | − crc = ~crc; | |
| 600 | − *skb_put(skb, 1) = crc & 0xff; | |
| 601 | − *skb_put(skb, 1) = crc >> 8; | |
| 602 | −} | |
| 603 | − | |
| 604 | −static void pn544_hci_remove_len_crc(struct sk_buff *skb) | |
| 605 | −{ | |
| 606 | − skb_pull(skb, PN544_FRAME_HEADROOM); | |
| 607 | − skb_trim(skb, PN544_FRAME_TAILROOM); | |
| 608 | −} | |
| 609 | − | |
| 610 | 340 | static int pn544_hci_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) |
| 611 | 341 | { |
| 612 | 342 | struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); |
| 613 | − struct i2c_client *client = info->i2c_dev; | |
| 614 | − int r; | |
| 615 | 343 | |
| 616 | − if (info->hard_fault != 0) | |
| 617 | − return info->hard_fault; | |
| 618 | − | |
| 619 | − pn544_hci_add_len_crc(skb); | |
| 620 | − r = pn544_hci_i2c_write(client, skb->data, skb->len); | |
| 621 | − pn544_hci_remove_len_crc(skb); | |
| 622 | − | |
| 623 | − return r; | |
| 344 | + return info->phy_ops->write(info->phy_id, skb); | |
| 624 | 345 | } |
| 625 | 346 | |
| 626 | 347 | static int pn544_hci_start_poll(struct nfc_hci_dev *hdev, |
| @@ -630,6 +351,9 @@ static int pn544_hci_start_poll(struct nfc_hci_dev *hdev, · 3 unmodified lines | ||
| 630 | 351 | int r; |
| 631 | 352 | u8 duration[2]; |
| 632 | 353 | u8 activated; |
| 354 | + u8 i_mode = 0x3f; /* Enable all supported modes */ | |
| 355 | + u8 t_mode = 0x0f; | |
| 356 | + u8 t_merge = 0x01; /* Enable merge by default */ | |
| 633 | 357 | |
| 634 | 358 | pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n", |
| 635 | 359 | __func__, im_protocols, tm_protocols); |
| @@ -667,6 +391,61 @@ static int pn544_hci_start_poll(struct nfc_hci_dev *hdev, · 31 unmodified lines | ||
| 667 | 391 | if (r < 0) |
| 668 | 392 | return r; |
| 669 | 393 | |
| 394 | + if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) { | |
| 395 | + hdev->gb = nfc_get_local_general_bytes(hdev->ndev, | |
| 396 | + &hdev->gb_len); | |
| 397 | + pr_debug("generate local bytes %p", hdev->gb); | |
| 398 | + if (hdev->gb == NULL || hdev->gb_len == 0) { | |
| 399 | + im_protocols &= ~NFC_PROTO_NFC_DEP_MASK; | |
| 400 | + tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK; | |
| 401 | + } | |
| 402 | + } | |
| 403 | + | |
| 404 | + if (im_protocols & NFC_PROTO_NFC_DEP_MASK) { | |
| 405 | + r = nfc_hci_send_event(hdev, | |
| 406 | + PN544_RF_READER_NFCIP1_INITIATOR_GATE, | |
| 407 | + NFC_HCI_EVT_END_OPERATION, NULL, 0); | |
| 408 | + if (r < 0) | |
| 409 | + return r; | |
| 410 | + | |
| 411 | + r = nfc_hci_set_param(hdev, | |
| 412 | + PN544_RF_READER_NFCIP1_INITIATOR_GATE, | |
| 413 | + PN544_DEP_MODE, &i_mode, 1); | |
| 414 | + if (r < 0) | |
| 415 | + return r; | |
| 416 | + | |
| 417 | + r = nfc_hci_set_param(hdev, | |
| 418 | + PN544_RF_READER_NFCIP1_INITIATOR_GATE, | |
| 419 | + PN544_DEP_ATR_REQ, hdev->gb, hdev->gb_len); | |
| 420 | + if (r < 0) | |
| 421 | + return r; | |
| 422 | + | |
| 423 | + r = nfc_hci_send_event(hdev, | |
| 424 | + PN544_RF_READER_NFCIP1_INITIATOR_GATE, | |
| 425 | + NFC_HCI_EVT_READER_REQUESTED, NULL, 0); | |
| 426 | + if (r < 0) | |
| 427 | + nfc_hci_send_event(hdev, | |
| 428 | + PN544_RF_READER_NFCIP1_INITIATOR_GATE, | |
| 429 | + NFC_HCI_EVT_END_OPERATION, NULL, 0); | |
| 430 | + } | |
| 431 | + | |
| 432 | + if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) { | |
| 433 | + r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, | |
| 434 | + PN544_DEP_MODE, &t_mode, 1); | |
| 435 | + if (r < 0) | |
| 436 | + return r; | |
| 437 | + | |
| 438 | + r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, | |
| 439 | + PN544_DEP_ATR_RES, hdev->gb, hdev->gb_len); | |
| 440 | + if (r < 0) | |
| 441 | + return r; | |
| 442 | + | |
| 443 | + r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, | |
| 444 | + PN544_DEP_MERGE, &t_merge, 1); | |
| 445 | + if (r < 0) | |
| 446 | + return r; | |
| 447 | + } | |
| 448 | + | |
| 670 | 449 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, |
| 671 | 450 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); |
| 672 | 451 | if (r < 0) |
| @@ -676,6 +455,43 @@ static int pn544_hci_start_poll(struct nfc_hci_dev *hdev, · 3 unmodified lines | ||
| 676 | 455 | return r; |
| 677 | 456 | } |
| 678 | 457 | |
| 458 | +static int pn544_hci_dep_link_up(struct nfc_hci_dev *hdev, | |
| 459 | + struct nfc_target *target, u8 comm_mode, | |
| 460 | + u8 *gb, size_t gb_len) | |
| 461 | +{ | |
| 462 | + struct sk_buff *rgb_skb = NULL; | |
| 463 | + int r; | |
| 464 | + | |
| 465 | + r = nfc_hci_get_param(hdev, target->hci_reader_gate, | |
| 466 | + PN544_DEP_ATR_RES, &rgb_skb); | |
| 467 | + if (r < 0) | |
| 468 | + return r; | |
| 469 | + | |
| 470 | + if (rgb_skb->len == 0 || rgb_skb->len > NFC_GB_MAXSIZE) { | |
| 471 | + r = -EPROTO; | |
| 472 | + goto exit; | |
| 473 | + } | |
| 474 | + print_hex_dump(KERN_DEBUG, "remote gb: ", DUMP_PREFIX_OFFSET, | |
| 475 | + 16, 1, rgb_skb->data, rgb_skb->len, true); | |
| 476 | + | |
| 477 | + r = nfc_set_remote_general_bytes(hdev->ndev, rgb_skb->data, | |
| 478 | + rgb_skb->len); | |
| 479 | + | |
| 480 | + if (r == 0) | |
| 481 | + r = nfc_dep_link_is_up(hdev->ndev, target->idx, comm_mode, | |
| 482 | + NFC_RF_INITIATOR); | |
| 483 | +exit: | |
| 484 | + kfree_skb(rgb_skb); | |
| 485 | + return r; | |
| 486 | +} | |
| 487 | + | |
| 488 | +static int pn544_hci_dep_link_down(struct nfc_hci_dev *hdev) | |
| 489 | +{ | |
| 490 | + | |
| 491 | + return nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_INITIATOR_GATE, | |
| 492 | + NFC_HCI_EVT_END_OPERATION, NULL, 0); | |
| 493 | +} | |
| 494 | + | |
| 679 | 495 | static int pn544_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, |
| 680 | 496 | struct nfc_target *target) |
| 681 | 497 | { |
| @@ -687,6 +503,9 @@ static int pn544_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, · 5 unmodified lines | ||
| 687 | 503 | target->supported_protocols = NFC_PROTO_JEWEL_MASK; |
| 688 | 504 | target->sens_res = 0x0c00; |
| 689 | 505 | break; |
| 506 | + case PN544_RF_READER_NFCIP1_INITIATOR_GATE: | |
| 507 | + target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; | |
| 508 | + break; | |
| 690 | 509 | default: |
| 691 | 510 | return -EPROTO; |
| 692 | 511 | } |
| @@ -701,7 +520,18 @@ static int pn544_hci_complete_target_discovered(struct nfc_hci_dev *hdev, · 8 unmodified lines | ||
| 701 | 520 | struct sk_buff *uid_skb; |
| 702 | 521 | int r = 0; |
| 703 | 522 | |
| 704 | − if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) { | |
| 523 | + if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) | |
| 524 | + return r; | |
| 525 | + | |
| 526 | + if (target->supported_protocols & NFC_PROTO_NFC_DEP_MASK) { | |
| 527 | + r = nfc_hci_send_cmd(hdev, | |
| 528 | + PN544_RF_READER_NFCIP1_INITIATOR_GATE, | |
| 529 | + PN544_HCI_CMD_CONTINUE_ACTIVATION, NULL, 0, NULL); | |
| 530 | + if (r < 0) | |
| 531 | + return r; | |
| 532 | + | |
| 533 | + target->hci_reader_gate = PN544_RF_READER_NFCIP1_INITIATOR_GATE; | |
| 534 | + } else if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) { | |
| 705 | 535 | if (target->nfcid1_len != 4 && target->nfcid1_len != 7 && |
| 706 | 536 | target->nfcid1_len != 10) |
| 707 | 537 | return -EPROTO; |
| @@ -724,6 +554,16 @@ static int pn544_hci_complete_target_discovered(struct nfc_hci_dev *hdev, · 16 unmodified lines | ||
| 724 | 554 | PN544_RF_READER_CMD_ACTIVATE_NEXT, |
| 725 | 555 | uid_skb->data, uid_skb->len, NULL); |
| 726 | 556 | kfree_skb(uid_skb); |
| 557 | + | |
| 558 | + r = nfc_hci_send_cmd(hdev, | |
| 559 | + PN544_RF_READER_NFCIP1_INITIATOR_GATE, | |
| 560 | + PN544_HCI_CMD_CONTINUE_ACTIVATION, | |
| 561 | + NULL, 0, NULL); | |
| 562 | + if (r < 0) | |
| 563 | + return r; | |
| 564 | + | |
| 565 | + target->hci_reader_gate = PN544_RF_READER_NFCIP1_INITIATOR_GATE; | |
| 566 | + target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; | |
| 727 | 567 | } else if (target->supported_protocols & NFC_PROTO_ISO14443_MASK) { |
| 728 | 568 | /* |
| 729 | 569 | * TODO: maybe other ISO 14443 require some kind of continue |
| @@ -769,7 +609,7 @@ static void pn544_hci_data_exchange_cb(void *context, struct sk_buff *skb, · 39 unmodified lines | ||
| 769 | 609 | * <= 0: driver handled the data exchange |
| 770 | 610 | * 1: driver doesn't especially handle, please do standard processing |
| 771 | 611 | */ |
| 772 | −static int pn544_hci_data_exchange(struct nfc_hci_dev *hdev, | |
| 612 | +static int pn544_hci_im_transceive(struct nfc_hci_dev *hdev, | |
| 773 | 613 | struct nfc_target *target, |
| 774 | 614 | struct sk_buff *skb, data_exchange_cb_t cb, |
| 775 | 615 | void *cb_context) |
| @@ -822,17 +662,110 @@ static int pn544_hci_data_exchange(struct nfc_hci_dev *hdev, · 46 unmodified lines | ||
| 822 | 662 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, |
| 823 | 663 | PN544_JEWEL_RAW_CMD, skb->data, |
| 824 | 664 | skb->len, cb, cb_context); |
| 665 | + case PN544_RF_READER_NFCIP1_INITIATOR_GATE: | |
| 666 | + *skb_push(skb, 1) = 0; | |
| 667 | + | |
| 668 | + return nfc_hci_send_event(hdev, target->hci_reader_gate, | |
| 669 | + PN544_HCI_EVT_SND_DATA, skb->data, | |
| 670 | + skb->len); | |
| 825 | 671 | default: |
| 826 | 672 | return 1; |
| 827 | 673 | } |
| 828 | 674 | } |
| 829 | 675 | |
| 676 | +static int pn544_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb) | |
| 677 | +{ | |
| 678 | + /* Set default false for multiple information chaining */ | |
| 679 | + *skb_push(skb, 1) = 0; | |
| 680 | + | |
| 681 | + return nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, | |
| 682 | + PN544_HCI_EVT_SND_DATA, skb->data, skb->len); | |
| 683 | +} | |
| 684 | + | |
| 830 | 685 | static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, |
| 831 | 686 | struct nfc_target *target) |
| 832 | 687 | { |
| 833 | − return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | |
| 834 | − PN544_RF_READER_CMD_PRESENCE_CHECK, | |
| 835 | − NULL, 0, NULL); | |
| 688 | + pr_debug("supported protocol %d", target->supported_protocols); | |
| 689 | + if (target->supported_protocols & (NFC_PROTO_ISO14443_MASK | | |
| 690 | + NFC_PROTO_ISO14443_B_MASK)) { | |
| 691 | + return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | |
| 692 | + PN544_RF_READER_CMD_PRESENCE_CHECK, | |
| 693 | + NULL, 0, NULL); | |
| 694 | + } else if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) { | |
| 695 | + if (target->nfcid1_len != 4 && target->nfcid1_len != 7 && | |
| 696 | + target->nfcid1_len != 10) | |
| 697 | + return -EOPNOTSUPP; | |
| 698 | + | |
| 699 | + return nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE, | |
| 700 | + PN544_RF_READER_CMD_ACTIVATE_NEXT, | |
| 701 | + target->nfcid1, target->nfcid1_len, NULL); | |
| 702 | + } else if (target->supported_protocols & NFC_PROTO_JEWEL_MASK) { | |
| 703 | + return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | |
| 704 | + PN544_JEWEL_RAW_CMD, NULL, 0, NULL); | |
| 705 | + } else if (target->supported_protocols & NFC_PROTO_FELICA_MASK) { | |
| 706 | + return nfc_hci_send_cmd(hdev, PN544_RF_READER_F_GATE, | |
| 707 | + PN544_FELICA_RAW, NULL, 0, NULL); | |
| 708 | + } else if (target->supported_protocols & NFC_PROTO_NFC_DEP_MASK) { | |
| 709 | + return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | |
| 710 | + PN544_HCI_CMD_ATTREQUEST, | |
| 711 | + NULL, 0, NULL); | |
| 712 | + } | |
| 713 | + | |
| 714 | + return 0; | |
| 715 | +} | |
| 716 | + | |
| 717 | +static void pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, | |
| 718 | + u8 event, struct sk_buff *skb) | |
| 719 | +{ | |
| 720 | + struct sk_buff *rgb_skb = NULL; | |
| 721 | + int r = 0; | |
| 722 | + | |
| 723 | + pr_debug("hci event %d", event); | |
| 724 | + switch (event) { | |
| 725 | + case PN544_HCI_EVT_ACTIVATED: | |
| 726 | + if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) | |
| 727 | + nfc_hci_target_discovered(hdev, gate); | |
| 728 | + else if (gate == PN544_RF_READER_NFCIP1_TARGET_GATE) { | |
| 729 | + r = nfc_hci_get_param(hdev, gate, PN544_DEP_ATR_REQ, | |
| 730 | + &rgb_skb); | |
| 731 | + | |
| 732 | + if (r < 0) | |
| 733 | + goto exit; | |
| 734 | + | |
| 735 | + nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK, | |
| 736 | + NFC_COMM_PASSIVE, rgb_skb->data, | |
| 737 | + rgb_skb->len); | |
| 738 | + | |
| 739 | + kfree_skb(rgb_skb); | |
| 740 | + } | |
| 741 | + | |
| 742 | + break; | |
| 743 | + case PN544_HCI_EVT_DEACTIVATED: | |
| 744 | + nfc_hci_send_event(hdev, gate, | |
| 745 | + NFC_HCI_EVT_END_OPERATION, NULL, 0); | |
| 746 | + break; | |
| 747 | + case PN544_HCI_EVT_RCV_DATA: | |
| 748 | + if (skb->len < 2) { | |
| 749 | + r = -EPROTO; | |
| 750 | + goto exit; | |
| 751 | + } | |
| 752 | + | |
| 753 | + if (skb->data[0] != 0) { | |
| 754 | + pr_debug("data0 %d", skb->data[0]); | |
| 755 | + r = -EPROTO; | |
| 756 | + goto exit; | |
| 757 | + } | |
| 758 | + | |
| 759 | + skb_pull(skb, 2); | |
| 760 | + nfc_tm_data_received(hdev->ndev, skb); | |
| 761 | + | |
| 762 | + return; | |
| 763 | + default: | |
| 764 | + break; | |
| 765 | + } | |
| 766 | + | |
| 767 | +exit: | |
| 768 | + kfree_skb(skb); | |
| 836 | 769 | } |
| 837 | 770 | |
| 838 | 771 | static struct nfc_hci_ops pn544_hci_ops = { |
| @@ -841,74 +774,36 @@ static struct nfc_hci_ops pn544_hci_ops = { · 2 unmodified lines | ||
| 841 | 774 | .hci_ready = pn544_hci_ready, |
| 842 | 775 | .xmit = pn544_hci_xmit, |
| 843 | 776 | .start_poll = pn544_hci_start_poll, |
| 777 | + .dep_link_up = pn544_hci_dep_link_up, | |
| 778 | + .dep_link_down = pn544_hci_dep_link_down, | |
| 844 | 779 | .target_from_gate = pn544_hci_target_from_gate, |
| 845 | 780 | .complete_target_discovered = pn544_hci_complete_target_discovered, |
| 846 | − .data_exchange = pn544_hci_data_exchange, | |
| 781 | + .im_transceive = pn544_hci_im_transceive, | |
| 782 | + .tm_send = pn544_hci_tm_send, | |
| 847 | 783 | .check_presence = pn544_hci_check_presence, |
| 784 | + .event_received = pn544_hci_event_received, | |
| 848 | 785 | }; |
| 849 | 786 | |
| 850 | −static int __devinit pn544_hci_probe(struct i2c_client *client, | |
| 851 | − const struct i2c_device_id *id) | |
| 787 | +int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, | |
| 788 | + int phy_headroom, int phy_tailroom, int phy_payload, | |
| 789 | + struct nfc_hci_dev **hdev) | |
| 852 | 790 | { |
| 853 | 791 | struct pn544_hci_info *info; |
| 854 | − struct pn544_nfc_platform_data *pdata; | |
| 855 | − int r = 0; | |
| 856 | 792 | u32 protocols; |
| 857 | 793 | struct nfc_hci_init_data init_data; |
| 858 | − | |
| 859 | − dev_dbg(&client->dev, "%s\n", __func__); | |
| 860 | − dev_dbg(&client->dev, "IRQ: %d\n", client->irq); | |
| 861 | − | |
| 862 | − if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | |
| 863 | − dev_err(&client->dev, "Need I2C_FUNC_I2C\n"); | |
| 864 | − return -ENODEV; | |
| 865 | − } | |
| 794 | + int r; | |
| 866 | 795 | |
| 867 | 796 | info = kzalloc(sizeof(struct pn544_hci_info), GFP_KERNEL); |
| 868 | 797 | if (!info) { |
| 869 | − dev_err(&client->dev, | |
| 870 | − "Cannot allocate memory for pn544_hci_info.\n"); | |
| 798 | + pr_err("Cannot allocate memory for pn544_hci_info.\n"); | |
| 871 | 799 | r = -ENOMEM; |
| 872 | 800 | goto err_info_alloc; |
| 873 | 801 | } |
| 874 | 802 | |
| 875 | − info->i2c_dev = client; | |
| 803 | + info->phy_ops = phy_ops; | |
| 804 | + info->phy_id = phy_id; | |
| 876 | 805 | info->state = PN544_ST_COLD; |
| 877 | 806 | mutex_init(&info->info_lock); |
| 878 | − i2c_set_clientdata(client, info); | |
| 879 | − | |
| 880 | − pdata = client->dev.platform_data; | |
| 881 | − if (pdata == NULL) { | |
| 882 | − dev_err(&client->dev, "No platform data\n"); | |
| 883 | − r = -EINVAL; | |
| 884 | − goto err_pdata; | |
| 885 | − } | |
| 886 | − | |
| 887 | − if (pdata->request_resources == NULL) { | |
| 888 | − dev_err(&client->dev, "request_resources() missing\n"); | |
| 889 | − r = -EINVAL; | |
| 890 | − goto err_pdata; | |
| 891 | − } | |
| 892 | − | |
| 893 | − r = pdata->request_resources(client); | |
| 894 | − if (r) { | |
| 895 | − dev_err(&client->dev, "Cannot get platform resources\n"); | |
| 896 | − goto err_pdata; | |
| 897 | − } | |
| 898 | − | |
| 899 | − info->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE); | |
| 900 | − info->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET); | |
| 901 | − info->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ); | |
| 902 | − | |
| 903 | − pn544_hci_platform_init(info); | |
| 904 | − | |
| 905 | − r = request_threaded_irq(client->irq, NULL, pn544_hci_irq_thread_fn, | |
| 906 | − IRQF_TRIGGER_RISING | IRQF_ONESHOT, | |
| 907 | − PN544_HCI_DRIVER_NAME, info); | |
| 908 | − if (r < 0) { | |
| 909 | − dev_err(&client->dev, "Unable to register IRQ handler\n"); | |
| 910 | − goto err_rti; | |
| 911 | − } | |
| 912 | 807 | |
| 913 | 808 | init_data.gate_count = ARRAY_SIZE(pn544_gates); |
| 914 | 809 | |
| @@ -928,13 +823,11 @@ static int __devinit pn544_hci_probe(struct i2c_client *client, · 13 unmodified lines | ||
| 928 | 823 | NFC_PROTO_NFC_DEP_MASK; |
| 929 | 824 | |
| 930 | 825 | info->hdev = nfc_hci_allocate_device(&pn544_hci_ops, &init_data, |
| 931 | − protocols, LLC_SHDLC_NAME, | |
| 932 | − PN544_FRAME_HEADROOM + | |
| 933 | − PN544_CMDS_HEADROOM, | |
| 934 | − PN544_FRAME_TAILROOM, | |
| 935 | − PN544_HCI_LLC_MAX_PAYLOAD); | |
| 826 | + protocols, llc_name, | |
| 827 | + phy_headroom + PN544_CMDS_HEADROOM, | |
| 828 | + phy_tailroom, phy_payload); | |
| 936 | 829 | if (!info->hdev) { |
| 937 | − dev_err(&client->dev, "Cannot allocate nfc hdev.\n"); | |
| 830 | + pr_err("Cannot allocate nfc hdev.\n"); | |
| 938 | 831 | r = -ENOMEM; |
| 939 | 832 | goto err_alloc_hdev; |
| 940 | 833 | } |
| @@ -945,79 +838,25 @@ static int __devinit pn544_hci_probe(struct i2c_client *client, · 4 unmodified lines | ||
| 945 | 838 | if (r) |
| 946 | 839 | goto err_regdev; |
| 947 | 840 | |
| 841 | + *hdev = info->hdev; | |
| 842 | + | |
| 948 | 843 | return 0; |
| 949 | 844 | |
| 950 | 845 | err_regdev: |
| 951 | 846 | nfc_hci_free_device(info->hdev); |
| 952 | 847 | |
| 953 | 848 | err_alloc_hdev: |
| 954 | − free_irq(client->irq, info); | |
| 955 | − | |
| 956 | −err_rti: | |
| 957 | − if (pdata->free_resources != NULL) | |
| 958 | − pdata->free_resources(); | |
| 959 | − | |
| 960 | −err_pdata: | |
| 961 | 849 | kfree(info); |
| 962 | 850 | |
| 963 | 851 | err_info_alloc: |
| 964 | 852 | return r; |
| 965 | 853 | } |
| 966 | 854 | |
| 967 | −static __devexit int pn544_hci_remove(struct i2c_client *client) | |
| 855 | +void pn544_hci_remove(struct nfc_hci_dev *hdev) | |
| 968 | 856 | { |
| 969 | − struct pn544_hci_info *info = i2c_get_clientdata(client); | |
| 970 | − struct pn544_nfc_platform_data *pdata = client->dev.platform_data; | |
| 971 | − | |
| 972 | − dev_dbg(&client->dev, "%s\n", __func__); | |
| 973 | − | |
| 974 | − nfc_hci_free_device(info->hdev); | |
| 975 | − | |
| 976 | − if (info->state != PN544_ST_COLD) { | |
| 977 | − if (pdata->disable) | |
| 978 | − pdata->disable(); | |
| 979 | − } | |
| 980 | − | |
| 981 | − free_irq(client->irq, info); | |
| 982 | − if (pdata->free_resources) | |
| 983 | − pdata->free_resources(); | |
| 857 | + struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); | |
| 984 | 858 | |
| 859 | + nfc_hci_unregister_device(hdev); | |
| 860 | + nfc_hci_free_device(hdev); | |
| 985 | 861 | kfree(info); |
| 986 | − | |
| 987 | − return 0; | |
| 988 | 862 | } |
| 989 | − | |
| 990 | −static struct i2c_driver pn544_hci_driver = { | |
| 991 | − .driver = { | |
| 992 | − .name = PN544_HCI_DRIVER_NAME, | |
| 993 | − }, | |
| 994 | − .probe = pn544_hci_probe, | |
| 995 | − .id_table = pn544_hci_id_table, | |
| 996 | − .remove = __devexit_p(pn544_hci_remove), | |
| 997 | −}; | |
| 998 | − | |
| 999 | −static int __init pn544_hci_init(void) | |
| 1000 | −{ | |
| 1001 | − int r; | |
| 1002 | − | |
| 1003 | − pr_debug(DRIVER_DESC ": %s\n", __func__); | |
| 1004 | − | |
| 1005 | − r = i2c_add_driver(&pn544_hci_driver); | |
| 1006 | − if (r) { | |
| 1007 | − pr_err(PN544_HCI_DRIVER_NAME ": driver registration failed\n"); | |
| 1008 | − return r; | |
| 1009 | − } | |
| 1010 | − | |
| 1011 | − return 0; | |
| 1012 | −} | |
| 1013 | − | |
| 1014 | −static void __exit pn544_hci_exit(void) | |
| 1015 | −{ | |
| 1016 | − i2c_del_driver(&pn544_hci_driver); | |
| 1017 | −} | |
| 1018 | − | |
| 1019 | −module_init(pn544_hci_init); | |
| 1020 | −module_exit(pn544_hci_exit); | |
| 1021 | − | |
| 1022 | −MODULE_LICENSE("GPL"); | |
| 1023 | −MODULE_DESCRIPTION(DRIVER_DESC); | |
| @@ -0,0 +1,32 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2011 - 2012 Intel Corporation. All rights reserved. | |
| 3 | + * | |
| 4 | + * This program is free software; you can redistribute it and/or modify | |
| 5 | + * it under the terms of the GNU General Public License as published by | |
| 6 | + * the Free Software Foundation; either version 2 of the License, or | |
| 7 | + * (at your option) any later version. | |
| 8 | + * | |
| 9 | + * This program is distributed in the hope that it will be useful, | |
| 10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | + * GNU General Public License for more details. | |
| 13 | + * | |
| 14 | + * You should have received a copy of the GNU General Public License | |
| 15 | + * along with this program; if not, write to the | |
| 16 | + * Free Software Foundation, Inc., | |
| 17 | + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
| 18 | + */ | |
| 19 | + | |
| 20 | +#ifndef __LOCAL_PN544_H_ | |
| 21 | +#define __LOCAL_PN544_H_ | |
| 22 | + | |
| 23 | +#include <net/nfc/hci.h> | |
| 24 | + | |
| 25 | +#define DRIVER_DESC "HCI NFC driver for PN544" | |
| 26 | + | |
| 27 | +int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, | |
| 28 | + int phy_headroom, int phy_tailroom, int phy_payload, | |
| 29 | + struct nfc_hci_dev **hdev); | |
| 30 | +void pn544_hci_remove(struct nfc_hci_dev *hdev); | |
| 31 | + | |
| 32 | +#endif /* __LOCAL_PN544_H_ */ | |
| @@ -37,6 +37,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = { · 36 unmodified lines | ||
| 37 | 37 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4329) }, |
| 38 | 38 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) }, |
| 39 | 39 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432c) }, |
| 40 | + { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4350) }, | |
| 40 | 41 | { 0, }, |
| 41 | 42 | }; |
| 42 | 43 | MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl); |
| @@ -346,6 +346,8 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc) · 345 unmodified lines | ||
| 346 | 346 | chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, 0x380005C0); |
| 347 | 347 | } |
| 348 | 348 | break; |
| 349 | + case 43222: | |
| 350 | + break; | |
| 349 | 351 | default: |
| 350 | 352 | ssb_printk(KERN_ERR PFX |
| 351 | 353 | "ERROR: PLL init unknown for device %04X\n", |
| @@ -434,6 +436,7 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc) · 82 unmodified lines | ||
| 434 | 436 | min_msk = 0xCBB; |
| 435 | 437 | break; |
| 436 | 438 | case 0x4322: |
| 439 | + case 43222: | |
| 437 | 440 | /* We keep the default settings: |
| 438 | 441 | * min_msk = 0xCBB |
| 439 | 442 | * max_msk = 0x7FFFF |
| @@ -192,9 +192,10 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore) · 191 unmodified lines | ||
| 192 | 192 | |
| 193 | 193 | /* When there is no chipcommon on the bus there is 4MB flash */ |
| 194 | 194 | if (!bus->chipco.dev) { |
| 195 | − mcore->flash_buswidth = 2; | |
| 196 | − mcore->flash_window = SSB_FLASH1; | |
| 197 | − mcore->flash_window_size = SSB_FLASH1_SZ; | |
| 195 | + mcore->pflash.present = true; | |
| 196 | + mcore->pflash.buswidth = 2; | |
| 197 | + mcore->pflash.window = SSB_FLASH1; | |
| 198 | + mcore->pflash.window_size = SSB_FLASH1_SZ; | |
| 198 | 199 | return; |
| 199 | 200 | } |
| 200 | 201 | |
| @@ -206,13 +207,14 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore) · 5 unmodified lines | ||
| 206 | 207 | break; |
| 207 | 208 | case SSB_CHIPCO_FLASHT_PARA: |
| 208 | 209 | pr_debug("Found parallel flash\n"); |
| 209 | − mcore->flash_window = SSB_FLASH2; | |
| 210 | − mcore->flash_window_size = SSB_FLASH2_SZ; | |
| 210 | + mcore->pflash.present = true; | |
| 211 | + mcore->pflash.window = SSB_FLASH2; | |
| 212 | + mcore->pflash.window_size = SSB_FLASH2_SZ; | |
| 211 | 213 | if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG) |
| 212 | 214 | & SSB_CHIPCO_CFG_DS16) == 0) |
| 213 | − mcore->flash_buswidth = 1; | |
| 215 | + mcore->pflash.buswidth = 1; | |
| 214 | 216 | else |
| 215 | − mcore->flash_buswidth = 2; | |
| 217 | + mcore->pflash.buswidth = 2; | |
| 216 | 218 | break; |
| 217 | 219 | } |
| 218 | 220 | } |
| @@ -251,7 +251,7 @@ struct bcma_bus { · 250 unmodified lines | ||
| 251 | 251 | u8 num; |
| 252 | 252 | |
| 253 | 253 | struct bcma_drv_cc drv_cc; |
| 254 | − struct bcma_drv_pci drv_pci; | |
| 254 | + struct bcma_drv_pci drv_pci[2]; | |
| 255 | 255 | struct bcma_drv_mips drv_mips; |
| 256 | 256 | struct bcma_drv_gmac_cmn drv_gmac_cmn; |
| 257 | 257 | |
| @@ -510,6 +510,7 @@ struct bcma_chipcommon_pmu { · 509 unmodified lines | ||
| 510 | 510 | |
| 511 | 511 | #ifdef CONFIG_BCMA_DRIVER_MIPS |
| 512 | 512 | struct bcma_pflash { |
| 513 | + bool present; | |
| 513 | 514 | u8 buswidth; |
| 514 | 515 | u32 window; |
| 515 | 516 | u32 window_size; |
| @@ -532,6 +533,7 @@ struct mtd_info; · 16 unmodified lines | ||
| 532 | 533 | |
| 533 | 534 | struct bcma_nflash { |
| 534 | 535 | bool present; |
| 536 | + bool boot; /* This is the flash the SoC boots from */ | |
| 535 | 537 | |
| 536 | 538 | struct mtd_info *mtd; |
| 537 | 539 | }; |
| @@ -552,6 +554,7 @@ struct bcma_drv_cc { · 14 unmodified lines | ||
| 552 | 554 | u32 capabilities; |
| 553 | 555 | u32 capabilities_ext; |
| 554 | 556 | u8 setup_done:1; |
| 557 | + u8 early_setup_done:1; | |
| 555 | 558 | /* Fast Powerup Delay constant */ |
| 556 | 559 | u16 fast_pwrup_delay; |
| 557 | 560 | struct bcma_chipcommon_pmu pmu; |
| @@ -583,6 +586,7 @@ struct bcma_drv_cc { · 25 unmodified lines | ||
| 583 | 586 | bcma_cc_write32(cc, offset, (bcma_cc_read32(cc, offset) & (mask)) | (set)) |
| 584 | 587 | |
| 585 | 588 | extern void bcma_core_chipcommon_init(struct bcma_drv_cc *cc); |
| 589 | +extern void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc); | |
| 586 | 590 | |
| 587 | 591 | extern void bcma_chipco_suspend(struct bcma_drv_cc *cc); |
| 588 | 592 | extern void bcma_chipco_resume(struct bcma_drv_cc *cc); |
| @@ -606,6 +610,7 @@ u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value); · 17 unmodified lines | ||
| 606 | 610 | |
| 607 | 611 | /* PMU support */ |
| 608 | 612 | extern void bcma_pmu_init(struct bcma_drv_cc *cc); |
| 613 | +extern void bcma_pmu_early_init(struct bcma_drv_cc *cc); | |
| 609 | 614 | |
| 610 | 615 | extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, |
| 611 | 616 | u32 value); |
| @@ -35,13 +35,16 @@ struct bcma_device; · 34 unmodified lines | ||
| 35 | 35 | struct bcma_drv_mips { |
| 36 | 36 | struct bcma_device *core; |
| 37 | 37 | u8 setup_done:1; |
| 38 | + u8 early_setup_done:1; | |
| 38 | 39 | unsigned int assigned_irqs; |
| 39 | 40 | }; |
| 40 | 41 | |
| 41 | 42 | #ifdef CONFIG_BCMA_DRIVER_MIPS |
| 42 | 43 | extern void bcma_core_mips_init(struct bcma_drv_mips *mcore); |
| 44 | +extern void bcma_core_mips_early_init(struct bcma_drv_mips *mcore); | |
| 43 | 45 | #else |
| 44 | 46 | static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { } |
| 47 | +static inline void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) { } | |
| 45 | 48 | #endif |
| 46 | 49 | |
| 47 | 50 | extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore); |
| @@ -85,6 +85,9 @@ · 84 unmodified lines | ||
| 85 | 85 | * (2 ZettaBytes), high 32 bits |
| 86 | 86 | */ |
| 87 | 87 | |
| 88 | −#define BCMA_SFLASH 0x1c000000 | |
| 88 | +#define BCMA_SOC_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */ | |
| 89 | +#define BCMA_SOC_FLASH1_SZ 0x00400000 /* MIPS Size of Flash Region 1 */ | |
| 90 | +#define BCMA_SOC_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */ | |
| 91 | +#define BCMA_SOC_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */ | |
| 89 | 92 | |
| 90 | 93 | #endif /* LINUX_BCMA_REGS_H_ */ |
| @@ -1107,20 +1107,6 @@ struct ieee80211_ht_operation { · 1106 unmodified lines | ||
| 1107 | 1107 | #define WLAN_HT_SMPS_CONTROL_STATIC 1 |
| 1108 | 1108 | #define WLAN_HT_SMPS_CONTROL_DYNAMIC 3 |
| 1109 | 1109 | |
| 1110 | −#define VHT_MCS_SUPPORTED_SET_SIZE 8 | |
| 1111 | − | |
| 1112 | −struct ieee80211_vht_capabilities { | |
| 1113 | − __le32 vht_capabilities_info; | |
| 1114 | − u8 vht_supported_mcs_set[VHT_MCS_SUPPORTED_SET_SIZE]; | |
| 1115 | −} __packed; | |
| 1116 | − | |
| 1117 | −struct ieee80211_vht_operation { | |
| 1118 | − u8 vht_op_info_chwidth; | |
| 1119 | − u8 vht_op_info_chan_center_freq_seg1_idx; | |
| 1120 | − u8 vht_op_info_chan_center_freq_seg2_idx; | |
| 1121 | − __le16 vht_basic_mcs_set; | |
| 1122 | −} __packed; | |
| 1123 | − | |
| 1124 | 1110 | /** |
| 1125 | 1111 | * struct ieee80211_vht_mcs_info - VHT MCS information |
| 1126 | 1112 | * @rx_mcs_map: RX MCS map 2 bits for each stream, total 8 streams |
| @@ -1141,6 +1127,37 @@ struct ieee80211_vht_mcs_info { · 14 unmodified lines | ||
| 1141 | 1127 | __le16 tx_highest; |
| 1142 | 1128 | } __packed; |
| 1143 | 1129 | |
| 1130 | +/** | |
| 1131 | + * struct ieee80211_vht_cap - VHT capabilities | |
| 1132 | + * | |
| 1133 | + * This structure is the "VHT capabilities element" as | |
| 1134 | + * described in 802.11ac D3.0 8.4.2.160 | |
| 1135 | + * @vht_cap_info: VHT capability info | |
| 1136 | + * @supp_mcs: VHT MCS supported rates | |
| 1137 | + */ | |
| 1138 | +struct ieee80211_vht_cap { | |
| 1139 | + __le32 vht_cap_info; | |
| 1140 | + struct ieee80211_vht_mcs_info supp_mcs; | |
| 1141 | +} __packed; | |
| 1142 | + | |
| 1143 | +/** | |
| 1144 | + * struct ieee80211_vht_operation - VHT operation IE | |
| 1145 | + * | |
| 1146 | + * This structure is the "VHT operation element" as | |
| 1147 | + * described in 802.11ac D3.0 8.4.2.161 | |
| 1148 | + * @chan_width: Operating channel width | |
| 1149 | + * @center_freq_seg1_idx: center freq segment 1 index | |
| 1150 | + * @center_freq_seg2_idx: center freq segment 2 index | |
| 1151 | + * @basic_mcs_set: VHT Basic MCS rate set | |
| 1152 | + */ | |
| 1153 | +struct ieee80211_vht_operation { | |
| 1154 | + u8 chan_width; | |
| 1155 | + u8 center_freq_seg1_idx; | |
| 1156 | + u8 center_freq_seg2_idx; | |
| 1157 | + __le16 basic_mcs_set; | |
| 1158 | +} __packed; | |
| 1159 | + | |
| 1160 | + | |
| 1144 | 1161 | #define IEEE80211_VHT_MCS_ZERO_TO_SEVEN_SUPPORT 0 |
| 1145 | 1162 | #define IEEE80211_VHT_MCS_ZERO_TO_EIGHT_SUPPORT 1 |
| 1146 | 1163 | #define IEEE80211_VHT_MCS_ZERO_TO_NINE_SUPPORT 2 |
| @@ -1440,8 +1457,6 @@ enum ieee80211_eid { · 293 unmodified lines | ||
| 1440 | 1457 | |
| 1441 | 1458 | WLAN_EID_RSN = 48, |
| 1442 | 1459 | WLAN_EID_MMIE = 76, |
| 1443 | − WLAN_EID_WPA = 221, | |
| 1444 | − WLAN_EID_GENERIC = 221, | |
| 1445 | 1460 | WLAN_EID_VENDOR_SPECIFIC = 221, |
| 1446 | 1461 | WLAN_EID_QOS_PARAMETER = 222, |
| 1447 | 1462 | |
| @@ -13,6 +13,12 @@ struct ssb_serial_port { · 12 unmodified lines | ||
| 13 | 13 | unsigned int reg_shift; |
| 14 | 14 | }; |
| 15 | 15 | |
| 16 | +struct ssb_pflash { | |
| 17 | + bool present; | |
| 18 | + u8 buswidth; | |
| 19 | + u32 window; | |
| 20 | + u32 window_size; | |
| 21 | +}; | |
| 16 | 22 | |
| 17 | 23 | struct ssb_mipscore { |
| 18 | 24 | struct ssb_device *dev; |
| @@ -20,9 +26,7 @@ struct ssb_mipscore { · 1 unmodified line | ||
| 20 | 26 | int nr_serial_ports; |
| 21 | 27 | struct ssb_serial_port serial_ports[4]; |
| 22 | 28 | |
| 23 | − u8 flash_buswidth; | |
| 24 | − u32 flash_window; | |
| 25 | − u32 flash_window_size; | |
| 29 | + struct ssb_pflash pflash; | |
| 26 | 30 | }; |
| 27 | 31 | |
| 28 | 32 | extern void ssb_mipscore_init(struct ssb_mipscore *mcore); |
| @@ -19,13 +19,25 @@ · 18 unmodified lines | ||
| 19 | 19 | |
| 20 | 20 | #define A2MP_FEAT_EXT 0x8000 |
| 21 | 21 | |
| 22 | +enum amp_mgr_state { | |
| 23 | + READ_LOC_AMP_INFO, | |
| 24 | + READ_LOC_AMP_ASSOC, | |
| 25 | + READ_LOC_AMP_ASSOC_FINAL, | |
| 26 | +}; | |
| 27 | + | |
| 22 | 28 | struct amp_mgr { |
| 29 | + struct list_head list; | |
| 23 | 30 | struct l2cap_conn *l2cap_conn; |
| 24 | 31 | struct l2cap_chan *a2mp_chan; |
| 32 | + struct l2cap_chan *bredr_chan; | |
| 25 | 33 | struct kref kref; |
| 26 | 34 | __u8 ident; |
| 27 | 35 | __u8 handle; |
| 36 | + enum amp_mgr_state state; | |
| 28 | 37 | unsigned long flags; |
| 38 | + | |
| 39 | + struct list_head amp_ctrls; | |
| 40 | + struct mutex amp_ctrls_lock; | |
| 29 | 41 | }; |
| 30 | 42 | |
| 31 | 43 | struct a2mp_cmd { |
| @@ -118,9 +130,19 @@ struct a2mp_physlink_rsp { · 86 unmodified lines | ||
| 118 | 130 | #define A2MP_STATUS_PHYS_LINK_EXISTS 0x05 |
| 119 | 131 | #define A2MP_STATUS_SECURITY_VIOLATION 0x06 |
| 120 | 132 | |
| 121 | −void amp_mgr_get(struct amp_mgr *mgr); | |
| 133 | +extern struct list_head amp_mgr_list; | |
| 134 | +extern struct mutex amp_mgr_list_lock; | |
| 135 | + | |
| 136 | +struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr); | |
| 122 | 137 | int amp_mgr_put(struct amp_mgr *mgr); |
| 138 | +u8 __next_ident(struct amp_mgr *mgr); | |
| 123 | 139 | struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, |
| 124 | 140 | struct sk_buff *skb); |
| 141 | +struct amp_mgr *amp_mgr_lookup_by_state(u8 state); | |
| 142 | +void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data); | |
| 143 | +void a2mp_discover_amp(struct l2cap_chan *chan); | |
| 144 | +void a2mp_send_getinfo_rsp(struct hci_dev *hdev); | |
| 145 | +void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status); | |
| 146 | +void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status); | |
| 125 | 147 | |
| 126 | 148 | #endif /* __A2MP_H */ |
| @@ -0,0 +1,50 @@ | ||
| 1 | +/* | |
| 2 | + Copyright (c) 2011,2012 Intel Corp. | |
| 3 | + | |
| 4 | + This program is free software; you can redistribute it and/or modify | |
| 5 | + it under the terms of the GNU General Public License version 2 and | |
| 6 | + only version 2 as published by the Free Software Foundation. | |
| 7 | + | |
| 8 | + This program is distributed in the hope that it will be useful, | |
| 9 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 10 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 11 | + GNU General Public License for more details. | |
| 12 | +*/ | |
| 13 | + | |
| 14 | +#ifndef __AMP_H | |
| 15 | +#define __AMP_H | |
| 16 | + | |
| 17 | +struct amp_ctrl { | |
| 18 | + struct list_head list; | |
| 19 | + struct kref kref; | |
| 20 | + __u8 id; | |
| 21 | + __u16 assoc_len_so_far; | |
| 22 | + __u16 assoc_rem_len; | |
| 23 | + __u16 assoc_len; | |
| 24 | + __u8 *assoc; | |
| 25 | +}; | |
| 26 | + | |
| 27 | +int amp_ctrl_put(struct amp_ctrl *ctrl); | |
| 28 | +void amp_ctrl_get(struct amp_ctrl *ctrl); | |
| 29 | +struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id); | |
| 30 | +struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id); | |
| 31 | +void amp_ctrl_list_flush(struct amp_mgr *mgr); | |
| 32 | + | |
| 33 | +struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, | |
| 34 | + u8 remote_id, bool out); | |
| 35 | + | |
| 36 | +int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type); | |
| 37 | + | |
| 38 | +void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr); | |
| 39 | +void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle); | |
| 40 | +void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr); | |
| 41 | +void amp_read_loc_assoc_final_data(struct hci_dev *hdev, | |
| 42 | + struct hci_conn *hcon); | |
| 43 | +void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, | |
| 44 | + struct hci_conn *hcon); | |
| 45 | +void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, | |
| 46 | + struct hci_conn *hcon); | |
| 47 | +void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle); | |
| 48 | +void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle); | |
| 49 | + | |
| 50 | +#endif /* __AMP_H */ | |
| @@ -180,7 +180,6 @@ static inline void bacpy(bdaddr_t *dst, bdaddr_t *src) · 179 unmodified lines | ||
| 180 | 180 | } |
| 181 | 181 | |
| 182 | 182 | void baswap(bdaddr_t *dst, bdaddr_t *src); |
| 183 | −char *batostr(bdaddr_t *ba); | |
| 184 | 183 | |
| 185 | 184 | /* Common socket structures and functions */ |
| 186 | 185 | |
| @@ -33,6 +33,8 @@ · 32 unmodified lines | ||
| 33 | 33 | #define HCI_LINK_KEY_SIZE 16 |
| 34 | 34 | #define HCI_AMP_LINK_KEY_SIZE (2 * HCI_LINK_KEY_SIZE) |
| 35 | 35 | |
| 36 | +#define HCI_MAX_AMP_ASSOC_SIZE 672 | |
| 37 | + | |
| 36 | 38 | /* HCI dev events */ |
| 37 | 39 | #define HCI_DEV_REG 1 |
| 38 | 40 | #define HCI_DEV_UNREG 2 |
| @@ -196,6 +198,7 @@ enum { · 157 unmodified lines | ||
| 196 | 198 | #define ACL_START_NO_FLUSH 0x00 |
| 197 | 199 | #define ACL_CONT 0x01 |
| 198 | 200 | #define ACL_START 0x02 |
| 201 | +#define ACL_COMPLETE 0x03 | |
| 199 | 202 | #define ACL_ACTIVE_BCAST 0x04 |
| 200 | 203 | #define ACL_PICO_BCAST 0x08 |
| 201 | 204 | |
| @@ -205,6 +208,7 @@ enum { · 3 unmodified lines | ||
| 205 | 208 | #define ESCO_LINK 0x02 |
| 206 | 209 | /* Low Energy links do not have defined link type. Use invented one */ |
| 207 | 210 | #define LE_LINK 0x80 |
| 211 | +#define AMP_LINK 0x81 | |
| 208 | 212 | |
| 209 | 213 | /* LMP features */ |
| 210 | 214 | #define LMP_3SLOT 0x01 |
| @@ -556,12 +560,46 @@ struct hci_cp_accept_phy_link { · 345 unmodified lines | ||
| 556 | 560 | __u8 key[HCI_AMP_LINK_KEY_SIZE]; |
| 557 | 561 | } __packed; |
| 558 | 562 | |
| 559 | −#define HCI_OP_DISCONN_PHY_LINK 0x0437 | |
| 563 | +#define HCI_OP_DISCONN_PHY_LINK 0x0437 | |
| 560 | 564 | struct hci_cp_disconn_phy_link { |
| 561 | 565 | __u8 phy_handle; |
| 562 | 566 | __u8 reason; |
| 563 | 567 | } __packed; |
| 564 | 568 | |
| 569 | +struct ext_flow_spec { | |
| 570 | + __u8 id; | |
| 571 | + __u8 stype; | |
| 572 | + __le16 msdu; | |
| 573 | + __le32 sdu_itime; | |
| 574 | + __le32 acc_lat; | |
| 575 | + __le32 flush_to; | |
| 576 | +} __packed; | |
| 577 | + | |
| 578 | +#define HCI_OP_CREATE_LOGICAL_LINK 0x0438 | |
| 579 | +#define HCI_OP_ACCEPT_LOGICAL_LINK 0x0439 | |
| 580 | +struct hci_cp_create_accept_logical_link { | |
| 581 | + __u8 phy_handle; | |
| 582 | + struct ext_flow_spec tx_flow_spec; | |
| 583 | + struct ext_flow_spec rx_flow_spec; | |
| 584 | +} __packed; | |
| 585 | + | |
| 586 | +#define HCI_OP_DISCONN_LOGICAL_LINK 0x043a | |
| 587 | +struct hci_cp_disconn_logical_link { | |
| 588 | + __le16 log_handle; | |
| 589 | +} __packed; | |
| 590 | + | |
| 591 | +#define HCI_OP_LOGICAL_LINK_CANCEL 0x043b | |
| 592 | +struct hci_cp_logical_link_cancel { | |
| 593 | + __u8 phy_handle; | |
| 594 | + __u8 flow_spec_id; | |
| 595 | +} __packed; | |
| 596 | + | |
| 597 | +struct hci_rp_logical_link_cancel { | |
| 598 | + __u8 status; | |
| 599 | + __u8 phy_handle; | |
| 600 | + __u8 flow_spec_id; | |
| 601 | +} __packed; | |
| 602 | + | |
| 565 | 603 | #define HCI_OP_SNIFF_MODE 0x0803 |
| 566 | 604 | struct hci_cp_sniff_mode { |
| 567 | 605 | __le16 handle; |
| @@ -73,6 +73,7 @@ struct discovery_state { · 72 unmodified lines | ||
| 73 | 73 | struct hci_conn_hash { |
| 74 | 74 | struct list_head list; |
| 75 | 75 | unsigned int acl_num; |
| 76 | + unsigned int amp_num; | |
| 76 | 77 | unsigned int sco_num; |
| 77 | 78 | unsigned int le_num; |
| 78 | 79 | }; |
| @@ -124,6 +125,14 @@ struct le_scan_params { · 45 unmodified lines | ||
| 124 | 125 | |
| 125 | 126 | #define HCI_MAX_SHORT_NAME_LENGTH 10 |
| 126 | 127 | |
| 128 | +struct amp_assoc { | |
| 129 | + __u16 len; | |
| 130 | + __u16 offset; | |
| 131 | + __u16 rem_len; | |
| 132 | + __u16 len_so_far; | |
| 133 | + __u8 data[HCI_MAX_AMP_ASSOC_SIZE]; | |
| 134 | +}; | |
| 135 | + | |
| 127 | 136 | #define NUM_REASSEMBLY 4 |
| 128 | 137 | struct hci_dev { |
| 129 | 138 | struct list_head list; |
| @@ -177,6 +186,8 @@ struct hci_dev { · 47 unmodified lines | ||
| 177 | 186 | __u32 amp_max_flush_to; |
| 178 | 187 | __u32 amp_be_flush_to; |
| 179 | 188 | |
| 189 | + struct amp_assoc loc_assoc; | |
| 190 | + | |
| 180 | 191 | __u8 flow_ctl_mode; |
| 181 | 192 | |
| 182 | 193 | unsigned int auto_accept_delay; |
| @@ -252,8 +263,6 @@ struct hci_dev { · 69 unmodified lines | ||
| 252 | 263 | |
| 253 | 264 | struct sk_buff_head driver_init; |
| 254 | 265 | |
| 255 | − void *core_data; | |
| 256 | − | |
| 257 | 266 | atomic_t promisc; |
| 258 | 267 | |
| 259 | 268 | struct dentry *debugfs; |
| @@ -277,6 +286,8 @@ struct hci_dev { · 17 unmodified lines | ||
| 277 | 286 | int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg); |
| 278 | 287 | }; |
| 279 | 288 | |
| 289 | +#define HCI_PHY_HANDLE(handle) (handle & 0xff) | |
| 290 | + | |
| 280 | 291 | struct hci_conn { |
| 281 | 292 | struct list_head list; |
| 282 | 293 | |
| @@ -310,6 +321,7 @@ struct hci_conn { · 27 unmodified lines | ||
| 310 | 321 | |
| 311 | 322 | __u8 remote_cap; |
| 312 | 323 | __u8 remote_auth; |
| 324 | + __u8 remote_id; | |
| 313 | 325 | bool flush_key; |
| 314 | 326 | |
| 315 | 327 | unsigned int sent; |
| @@ -339,7 +351,7 @@ struct hci_conn { · 23 unmodified lines | ||
| 339 | 351 | |
| 340 | 352 | struct hci_chan { |
| 341 | 353 | struct list_head list; |
| 342 | − | |
| 354 | + __u16 handle; | |
| 343 | 355 | struct hci_conn *conn; |
| 344 | 356 | struct sk_buff_head data_q; |
| 345 | 357 | unsigned int sent; |
| @@ -438,6 +450,9 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) · 92 unmodified lines | ||
| 438 | 450 | case ACL_LINK: |
| 439 | 451 | h->acl_num++; |
| 440 | 452 | break; |
| 453 | + case AMP_LINK: | |
| 454 | + h->amp_num++; | |
| 455 | + break; | |
| 441 | 456 | case LE_LINK: |
| 442 | 457 | h->le_num++; |
| 443 | 458 | break; |
| @@ -459,6 +474,9 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) · 15 unmodified lines | ||
| 459 | 474 | case ACL_LINK: |
| 460 | 475 | h->acl_num--; |
| 461 | 476 | break; |
| 477 | + case AMP_LINK: | |
| 478 | + h->amp_num--; | |
| 479 | + break; | |
| 462 | 480 | case LE_LINK: |
| 463 | 481 | h->le_num--; |
| 464 | 482 | break; |
| @@ -475,6 +493,8 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type) · 10 unmodified lines | ||
| 475 | 493 | switch (type) { |
| 476 | 494 | case ACL_LINK: |
| 477 | 495 | return h->acl_num; |
| 496 | + case AMP_LINK: | |
| 497 | + return h->amp_num; | |
| 478 | 498 | case LE_LINK: |
| 479 | 499 | return h->le_num; |
| 480 | 500 | case SCO_LINK: |
| @@ -556,6 +576,7 @@ void hci_conn_check_pending(struct hci_dev *hdev); · 75 unmodified lines | ||
| 556 | 576 | struct hci_chan *hci_chan_create(struct hci_conn *conn); |
| 557 | 577 | void hci_chan_del(struct hci_chan *chan); |
| 558 | 578 | void hci_chan_list_flush(struct hci_conn *conn); |
| 579 | +struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle); | |
| 559 | 580 | |
| 560 | 581 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, |
| 561 | 582 | __u8 dst_type, __u8 sec_level, __u8 auth_type); |
| @@ -584,7 +605,10 @@ static inline void hci_conn_put(struct hci_conn *conn) · 22 unmodified lines | ||
| 584 | 605 | |
| 585 | 606 | if (atomic_dec_and_test(&conn->refcnt)) { |
| 586 | 607 | unsigned long timeo; |
| 587 | − if (conn->type == ACL_LINK || conn->type == LE_LINK) { | |
| 608 | + | |
| 609 | + switch (conn->type) { | |
| 610 | + case ACL_LINK: | |
| 611 | + case LE_LINK: | |
| 588 | 612 | del_timer(&conn->idle_timer); |
| 589 | 613 | if (conn->state == BT_CONNECTED) { |
| 590 | 614 | timeo = conn->disc_timeout; |
| @@ -593,12 +617,20 @@ static inline void hci_conn_put(struct hci_conn *conn) · 2 unmodified lines | ||
| 593 | 617 | } else { |
| 594 | 618 | timeo = msecs_to_jiffies(10); |
| 595 | 619 | } |
| 596 | − } else { | |
| 620 | + break; | |
| 621 | + | |
| 622 | + case AMP_LINK: | |
| 623 | + timeo = conn->disc_timeout; | |
| 624 | + break; | |
| 625 | + | |
| 626 | + default: | |
| 597 | 627 | timeo = msecs_to_jiffies(10); |
| 628 | + break; | |
| 598 | 629 | } |
| 630 | + | |
| 599 | 631 | cancel_delayed_work(&conn->disc_work); |
| 600 | 632 | queue_delayed_work(conn->hdev->workqueue, |
| 601 | − &conn->disc_work, timeo); | |
| 633 | + &conn->disc_work, timeo); | |
| 602 | 634 | } |
| 603 | 635 | } |
| 604 | 636 | |
| @@ -789,6 +821,10 @@ static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason) · 184 unmodified lines | ||
| 789 | 821 | sco_disconn_cfm(conn, reason); |
| 790 | 822 | break; |
| 791 | 823 | |
| 824 | + /* L2CAP would be handled for BREDR chan */ | |
| 825 | + case AMP_LINK: | |
| 826 | + break; | |
| 827 | + | |
| 792 | 828 | default: |
| 793 | 829 | BT_ERR("unknown link type %d", conn->type); |
| 794 | 830 | break; |
| @@ -32,13 +32,14 @@ · 31 unmodified lines | ||
| 32 | 32 | /* L2CAP defaults */ |
| 33 | 33 | #define L2CAP_DEFAULT_MTU 672 |
| 34 | 34 | #define L2CAP_DEFAULT_MIN_MTU 48 |
| 35 | −#define L2CAP_DEFAULT_FLUSH_TO 0xffff | |
| 35 | +#define L2CAP_DEFAULT_FLUSH_TO 0xFFFF | |
| 36 | +#define L2CAP_EFS_DEFAULT_FLUSH_TO 0xFFFFFFFF | |
| 36 | 37 | #define L2CAP_DEFAULT_TX_WINDOW 63 |
| 37 | 38 | #define L2CAP_DEFAULT_EXT_WINDOW 0x3FFF |
| 38 | 39 | #define L2CAP_DEFAULT_MAX_TX 3 |
| 39 | 40 | #define L2CAP_DEFAULT_RETRANS_TO 2000 /* 2 seconds */ |
| 40 | 41 | #define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */ |
| 41 | −#define L2CAP_DEFAULT_MAX_PDU_SIZE 1009 /* Sized for 3-DH5 packet */ | |
| 42 | +#define L2CAP_DEFAULT_MAX_PDU_SIZE 1492 /* Sized for AMP packet */ | |
| 42 | 43 | #define L2CAP_DEFAULT_ACK_TO 200 |
| 43 | 44 | #define L2CAP_DEFAULT_MAX_SDU_SIZE 0xFFFF |
| 44 | 45 | #define L2CAP_DEFAULT_SDU_ITIME 0xFFFFFFFF |
| @@ -508,6 +509,8 @@ struct l2cap_chan { · 463 unmodified lines | ||
| 508 | 509 | __u32 remote_acc_lat; |
| 509 | 510 | __u32 remote_flush_to; |
| 510 | 511 | |
| 512 | + __u8 ctrl_id; | |
| 513 | + | |
| 511 | 514 | struct delayed_work chan_timer; |
| 512 | 515 | struct delayed_work retrans_timer; |
| 513 | 516 | struct delayed_work monitor_timer; |
| @@ -538,6 +541,7 @@ struct l2cap_ops { · 24 unmodified lines | ||
| 538 | 541 | void (*state_change) (struct l2cap_chan *chan, |
| 539 | 542 | int state); |
| 540 | 543 | void (*ready) (struct l2cap_chan *chan); |
| 544 | + void (*defer) (struct l2cap_chan *chan); | |
| 541 | 545 | struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, |
| 542 | 546 | unsigned long len, int nb); |
| 543 | 547 | }; |
| @@ -745,6 +749,10 @@ static inline void l2cap_chan_no_ready(struct l2cap_chan *chan) · 201 unmodified lines | ||
| 745 | 749 | { |
| 746 | 750 | } |
| 747 | 751 | |
| 752 | +static inline void l2cap_chan_no_defer(struct l2cap_chan *chan) | |
| 753 | +{ | |
| 754 | +} | |
| 755 | + | |
| 748 | 756 | extern bool disable_ertm; |
| 749 | 757 | |
| 750 | 758 | int l2cap_init_sockets(void); |
| @@ -767,6 +775,8 @@ int l2cap_chan_check_security(struct l2cap_chan *chan); · 16 unmodified lines | ||
| 767 | 775 | void l2cap_chan_set_defaults(struct l2cap_chan *chan); |
| 768 | 776 | int l2cap_ertm_init(struct l2cap_chan *chan); |
| 769 | 777 | void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan); |
| 778 | +void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan); | |
| 770 | 779 | void l2cap_chan_del(struct l2cap_chan *chan, int err); |
| 780 | +void l2cap_send_conn_req(struct l2cap_chan *chan); | |
| 771 | 781 | |
| 772 | 782 | #endif /* __L2CAP_H */ |
| @@ -498,6 +498,7 @@ enum station_parameters_apply_mask { · 497 unmodified lines | ||
| 498 | 498 | * @plink_action: plink action to take |
| 499 | 499 | * @plink_state: set the peer link state for a station |
| 500 | 500 | * @ht_capa: HT capabilities of station |
| 501 | + * @vht_capa: VHT capabilities of station | |
| 501 | 502 | * @uapsd_queues: bitmap of queues configured for uapsd. same format |
| 502 | 503 | * as the AC bitmap in the QoS info field |
| 503 | 504 | * @max_sp: max Service Period. same format as the MAX_SP in the |
| @@ -517,6 +518,7 @@ struct station_parameters { · 13 unmodified lines | ||
| 517 | 518 | u8 plink_action; |
| 518 | 519 | u8 plink_state; |
| 519 | 520 | struct ieee80211_ht_cap *ht_capa; |
| 521 | + struct ieee80211_vht_cap *vht_capa; | |
| 520 | 522 | u8 uapsd_queues; |
| 521 | 523 | u8 max_sp; |
| 522 | 524 | }; |
| @@ -1000,8 +1002,10 @@ struct cfg80211_ssid { · 477 unmodified lines | ||
| 1000 | 1002 | * @n_channels: total number of channels to scan |
| 1001 | 1003 | * @ie: optional information element(s) to add into Probe Request or %NULL |
| 1002 | 1004 | * @ie_len: length of ie in octets |
| 1005 | + * @flags: bit field of flags controlling operation | |
| 1003 | 1006 | * @rates: bitmap of rates to advertise for each band |
| 1004 | 1007 | * @wiphy: the wiphy this was for |
| 1008 | + * @scan_start: time (in jiffies) when the scan started | |
| 1005 | 1009 | * @wdev: the wireless device to scan for |
| 1006 | 1010 | * @aborted: (internal) scan request was notified as aborted |
| 1007 | 1011 | * @no_cck: used to send probe requests at non CCK rate in 2GHz band |
| @@ -1012,6 +1016,7 @@ struct cfg80211_scan_request { · 4 unmodified lines | ||
| 1012 | 1016 | u32 n_channels; |
| 1013 | 1017 | const u8 *ie; |
| 1014 | 1018 | size_t ie_len; |
| 1019 | + u32 flags; | |
| 1015 | 1020 | |
| 1016 | 1021 | u32 rates[IEEE80211_NUM_BANDS]; |
| 1017 | 1022 | |
| @@ -1019,6 +1024,7 @@ struct cfg80211_scan_request { · 1 unmodified line | ||
| 1019 | 1024 | |
| 1020 | 1025 | /* internal */ |
| 1021 | 1026 | struct wiphy *wiphy; |
| 1027 | + unsigned long scan_start; | |
| 1022 | 1028 | bool aborted; |
| 1023 | 1029 | bool no_cck; |
| 1024 | 1030 | |
| @@ -1044,6 +1050,7 @@ struct cfg80211_match_set { · 19 unmodified lines | ||
| 1044 | 1050 | * @interval: interval between each scheduled scan cycle |
| 1045 | 1051 | * @ie: optional information element(s) to add into Probe Request or %NULL |
| 1046 | 1052 | * @ie_len: length of ie in octets |
| 1053 | + * @flags: bit field of flags controlling operation | |
| 1047 | 1054 | * @match_sets: sets of parameters to be matched for a scan result |
| 1048 | 1055 | * entry to be considered valid and to be passed to the host |
| 1049 | 1056 | * (others are filtered out). |
| @@ -1061,6 +1068,7 @@ struct cfg80211_sched_scan_request { · 11 unmodified lines | ||
| 1061 | 1068 | u32 interval; |
| 1062 | 1069 | const u8 *ie; |
| 1063 | 1070 | size_t ie_len; |
| 1071 | + u32 flags; | |
| 1064 | 1072 | struct cfg80211_match_set *match_sets; |
| 1065 | 1073 | int n_match_sets; |
| 1066 | 1074 | s32 rssi_thold; |
| @@ -1068,6 +1076,7 @@ struct cfg80211_sched_scan_request { · 1 unmodified line | ||
| 1068 | 1076 | /* internal */ |
| 1069 | 1077 | struct wiphy *wiphy; |
| 1070 | 1078 | struct net_device *dev; |
| 1079 | + unsigned long scan_start; | |
| 1071 | 1080 | |
| 1072 | 1081 | /* keep last */ |
| 1073 | 1082 | struct ieee80211_channel *channels[0]; |
| @@ -1152,6 +1161,9 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie); · 78 unmodified lines | ||
| 1152 | 1161 | * @key_len: length of WEP key for shared key authentication |
| 1153 | 1162 | * @key_idx: index of WEP key for shared key authentication |
| 1154 | 1163 | * @key: WEP key for shared key authentication |
| 1164 | + * @sae_data: Non-IE data to use with SAE or %NULL. This starts with | |
| 1165 | + * Authentication transaction sequence number field. | |
| 1166 | + * @sae_data_len: Length of sae_data buffer in octets | |
| 1155 | 1167 | */ |
| 1156 | 1168 | struct cfg80211_auth_request { |
| 1157 | 1169 | struct cfg80211_bss *bss; |
| @@ -1160,6 +1172,8 @@ struct cfg80211_auth_request { · 2 unmodified lines | ||
| 1160 | 1172 | enum nl80211_auth_type auth_type; |
| 1161 | 1173 | const u8 *key; |
| 1162 | 1174 | u8 key_len, key_idx; |
| 1175 | + const u8 *sae_data; | |
| 1176 | + size_t sae_data_len; | |
| 1163 | 1177 | }; |
| 1164 | 1178 | |
| 1165 | 1179 | /** |
| @@ -143,6 +143,41 @@ struct ieee80211_low_level_stats { · 142 unmodified lines | ||
| 143 | 143 | unsigned int dot11RTSSuccessCount; |
| 144 | 144 | }; |
| 145 | 145 | |
| 146 | +/** | |
| 147 | + * enum ieee80211_chanctx_change - change flag for channel context | |
| 148 | + * @IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE: The channel type was changed | |
| 149 | + * @IEEE80211_CHANCTX_CHANGE_RX_CHAINS: The number of RX chains changed | |
| 150 | + */ | |
| 151 | +enum ieee80211_chanctx_change { | |
| 152 | + IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE = BIT(0), | |
| 153 | + IEEE80211_CHANCTX_CHANGE_RX_CHAINS = BIT(1), | |
| 154 | +}; | |
| 155 | + | |
| 156 | +/** | |
| 157 | + * struct ieee80211_chanctx_conf - channel context that vifs may be tuned to | |
| 158 | + * | |
| 159 | + * This is the driver-visible part. The ieee80211_chanctx | |
| 160 | + * that contains it is visible in mac80211 only. | |
| 161 | + * | |
| 162 | + * @channel: the channel to tune to | |
| 163 | + * @channel_type: the channel (HT) type | |
| 164 | + * @rx_chains_static: The number of RX chains that must always be | |
| 165 | + * active on the channel to receive MIMO transmissions | |
| 166 | + * @rx_chains_dynamic: The number of RX chains that must be enabled | |
| 167 | + * after RTS/CTS handshake to receive SMPS MIMO transmissions; | |
| 168 | + * this will always be >= @rx_chains_always. | |
| 169 | + * @drv_priv: data area for driver use, will always be aligned to | |
| 170 | + * sizeof(void *), size is determined in hw information. | |
| 171 | + */ | |
| 172 | +struct ieee80211_chanctx_conf { | |
| 173 | + struct ieee80211_channel *channel; | |
| 174 | + enum nl80211_channel_type channel_type; | |
| 175 | + | |
| 176 | + u8 rx_chains_static, rx_chains_dynamic; | |
| 177 | + | |
| 178 | + u8 drv_priv[0] __attribute__((__aligned__(sizeof(void *)))); | |
| 179 | +}; | |
| 180 | + | |
| 146 | 181 | /** |
| 147 | 182 | * enum ieee80211_bss_change - BSS change notification flags |
| 148 | 183 | * |
| @@ -223,6 +258,7 @@ enum ieee80211_rssi_event { · 74 unmodified lines | ||
| 223 | 258 | * @assoc: association status |
| 224 | 259 | * @ibss_joined: indicates whether this station is part of an IBSS |
| 225 | 260 | * or not |
| 261 | + * @ibss_creator: indicates if a new IBSS network is being created | |
| 226 | 262 | * @aid: association ID number, valid only when @assoc is true |
| 227 | 263 | * @use_cts_prot: use CTS protection |
| 228 | 264 | * @use_short_preamble: use 802.11b short preamble; |
| @@ -278,6 +314,7 @@ struct ieee80211_bss_conf { · 49 unmodified lines | ||
| 278 | 314 | const u8 *bssid; |
| 279 | 315 | /* association related data */ |
| 280 | 316 | bool assoc, ibss_joined; |
| 317 | + bool ibss_creator; | |
| 281 | 318 | u16 aid; |
| 282 | 319 | /* erp related data */ |
| 283 | 320 | bool use_cts_prot; |
| @@ -794,6 +831,8 @@ enum ieee80211_conf_flags { · 510 unmodified lines | ||
| 794 | 831 | * @IEEE80211_CONF_CHANGE_RETRY_LIMITS: retry limits changed |
| 795 | 832 | * @IEEE80211_CONF_CHANGE_IDLE: Idle flag changed |
| 796 | 833 | * @IEEE80211_CONF_CHANGE_SMPS: Spatial multiplexing powersave mode changed |
| 834 | + * Note that this is only valid if channel contexts are not used, | |
| 835 | + * otherwise each channel context has the number of chains listed. | |
| 797 | 836 | */ |
| 798 | 837 | enum ieee80211_conf_changed { |
| 799 | 838 | IEEE80211_CONF_CHANGE_SMPS = BIT(1), |
| @@ -859,7 +898,9 @@ enum ieee80211_smps_mode { · 59 unmodified lines | ||
| 859 | 898 | * |
| 860 | 899 | * @smps_mode: spatial multiplexing powersave mode; note that |
| 861 | 900 | * %IEEE80211_SMPS_STATIC is used when the device is not |
| 862 | − * configured for an HT channel | |
| 901 | + * configured for an HT channel. | |
| 902 | + * Note that this is only valid if channel contexts are not used, | |
| 903 | + * otherwise each channel context has the number of chains listed. | |
| 863 | 904 | */ |
| 864 | 905 | struct ieee80211_conf { |
| 865 | 906 | u32 flags; |
| @@ -931,6 +972,11 @@ enum ieee80211_vif_flags { · 65 unmodified lines | ||
| 931 | 972 | * at runtime, mac80211 will never touch this field |
| 932 | 973 | * @hw_queue: hardware queue for each AC |
| 933 | 974 | * @cab_queue: content-after-beacon (DTIM beacon really) queue, AP mode only |
| 975 | + * @chanctx_conf: The channel context this interface is assigned to, or %NULL | |
| 976 | + * when it is not assigned. This pointer is RCU-protected due to the TX | |
| 977 | + * path needing to access it; even though the netdev carrier will always | |
| 978 | + * be off when it is %NULL there can still be races and packets could be | |
| 979 | + * processed after it switches back to %NULL. | |
| 934 | 980 | * @drv_priv: data area for driver use, will always be aligned to |
| 935 | 981 | * sizeof(void *). |
| 936 | 982 | */ |
| @@ -943,6 +989,8 @@ struct ieee80211_vif { · 6 unmodified lines | ||
| 943 | 989 | u8 cab_queue; |
| 944 | 990 | u8 hw_queue[IEEE80211_NUM_ACS]; |
| 945 | 991 | |
| 992 | + struct ieee80211_chanctx_conf __rcu *chanctx_conf; | |
| 993 | + | |
| 946 | 994 | u32 driver_flags; |
| 947 | 995 | |
| 948 | 996 | /* must be last */ |
| @@ -1076,6 +1124,8 @@ enum ieee80211_sta_state { · 127 unmodified lines | ||
| 1076 | 1124 | * @aid: AID we assigned to the station if we're an AP |
| 1077 | 1125 | * @supp_rates: Bitmap of supported rates (per band) |
| 1078 | 1126 | * @ht_cap: HT capabilities of this STA; restricted to our own TX capabilities |
| 1127 | + * @vht_cap: VHT capabilities of this STA; Not restricting any capabilities | |
| 1128 | + * of remote STA. Taking as is. | |
| 1079 | 1129 | * @wme: indicates whether the STA supports WME. Only valid during AP-mode. |
| 1080 | 1130 | * @drv_priv: data area for driver use, will always be aligned to |
| 1081 | 1131 | * sizeof(void *), size is determined in hw information. |
| @@ -1088,6 +1138,7 @@ struct ieee80211_sta { · 6 unmodified lines | ||
| 1088 | 1138 | u8 addr[ETH_ALEN]; |
| 1089 | 1139 | u16 aid; |
| 1090 | 1140 | struct ieee80211_sta_ht_cap ht_cap; |
| 1141 | + struct ieee80211_sta_vht_cap vht_cap; | |
| 1091 | 1142 | bool wme; |
| 1092 | 1143 | u8 uapsd_queues; |
| 1093 | 1144 | u8 max_sp; |
| @@ -1325,6 +1376,8 @@ enum ieee80211_hw_flags { · 231 unmodified lines | ||
| 1325 | 1376 | * within &struct ieee80211_vif. |
| 1326 | 1377 | * @sta_data_size: size (in bytes) of the drv_priv data area |
| 1327 | 1378 | * within &struct ieee80211_sta. |
| 1379 | + * @chanctx_data_size: size (in bytes) of the drv_priv data area | |
| 1380 | + * within &struct ieee80211_chanctx_conf. | |
| 1328 | 1381 | * |
| 1329 | 1382 | * @max_rates: maximum number of alternate rate retry stages the hw |
| 1330 | 1383 | * can handle. |
| @@ -1369,6 +1422,7 @@ struct ieee80211_hw { · 38 unmodified lines | ||
| 1369 | 1422 | int channel_change_time; |
| 1370 | 1423 | int vif_data_size; |
| 1371 | 1424 | int sta_data_size; |
| 1425 | + int chanctx_data_size; | |
| 1372 | 1426 | int napi_weight; |
| 1373 | 1427 | u16 queues; |
| 1374 | 1428 | u16 max_listen_interval; |
| @@ -2317,6 +2371,16 @@ enum ieee80211_rate_control_changed { · 942 unmodified lines | ||
| 2317 | 2371 | * The callback will be called before each transmission and upon return |
| 2318 | 2372 | * mac80211 will transmit the frame right away. |
| 2319 | 2373 | * The callback is optional and can (should!) sleep. |
| 2374 | + * | |
| 2375 | + * @add_chanctx: Notifies device driver about new channel context creation. | |
| 2376 | + * @remove_chanctx: Notifies device driver about channel context destruction. | |
| 2377 | + * @change_chanctx: Notifies device driver about channel context changes that | |
| 2378 | + * may happen when combining different virtual interfaces on the same | |
| 2379 | + * channel context with different settings | |
| 2380 | + * @assign_vif_chanctx: Notifies device driver about channel context being bound | |
| 2381 | + * to vif. Possible use is for hw queue remapping. | |
| 2382 | + * @unassign_vif_chanctx: Notifies device driver about channel context being | |
| 2383 | + * unbound from vif. | |
| 2320 | 2384 | */ |
| 2321 | 2385 | struct ieee80211_ops { |
| 2322 | 2386 | void (*tx)(struct ieee80211_hw *hw, |
| @@ -2461,6 +2525,20 @@ struct ieee80211_ops { · 138 unmodified lines | ||
| 2461 | 2525 | |
| 2462 | 2526 | void (*mgd_prepare_tx)(struct ieee80211_hw *hw, |
| 2463 | 2527 | struct ieee80211_vif *vif); |
| 2528 | + | |
| 2529 | + int (*add_chanctx)(struct ieee80211_hw *hw, | |
| 2530 | + struct ieee80211_chanctx_conf *ctx); | |
| 2531 | + void (*remove_chanctx)(struct ieee80211_hw *hw, | |
| 2532 | + struct ieee80211_chanctx_conf *ctx); | |
| 2533 | + void (*change_chanctx)(struct ieee80211_hw *hw, | |
| 2534 | + struct ieee80211_chanctx_conf *ctx, | |
| 2535 | + u32 changed); | |
| 2536 | + int (*assign_vif_chanctx)(struct ieee80211_hw *hw, | |
| 2537 | + struct ieee80211_vif *vif, | |
| 2538 | + struct ieee80211_chanctx_conf *ctx); | |
| 2539 | + void (*unassign_vif_chanctx)(struct ieee80211_hw *hw, | |
| 2540 | + struct ieee80211_vif *vif, | |
| 2541 | + struct ieee80211_chanctx_conf *ctx); | |
| 2464 | 2542 | }; |
| 2465 | 2543 | |
| 2466 | 2544 | /** |
| @@ -3144,6 +3222,19 @@ void ieee80211_get_tkip_rx_p1k(struct ieee80211_key_conf *keyconf, · 677 unmodified lines | ||
| 3144 | 3222 | void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf, |
| 3145 | 3223 | struct sk_buff *skb, u8 *p2k); |
| 3146 | 3224 | |
| 3225 | +/** | |
| 3226 | + * ieee80211_aes_cmac_calculate_k1_k2 - calculate the AES-CMAC sub keys | |
| 3227 | + * | |
| 3228 | + * This function computes the two AES-CMAC sub-keys, based on the | |
| 3229 | + * previously installed master key. | |
| 3230 | + * | |
| 3231 | + * @keyconf: the parameter passed with the set key | |
| 3232 | + * @k1: a buffer to be filled with the 1st sub-key | |
| 3233 | + * @k2: a buffer to be filled with the 2nd sub-key | |
| 3234 | + */ | |
| 3235 | +void ieee80211_aes_cmac_calculate_k1_k2(struct ieee80211_key_conf *keyconf, | |
| 3236 | + u8 *k1, u8 *k2); | |
| 3237 | + | |
| 3147 | 3238 | /** |
| 3148 | 3239 | * struct ieee80211_key_seq - key sequence counter |
| 3149 | 3240 | * |
| @@ -3523,6 +3614,27 @@ void ieee80211_iter_keys(struct ieee80211_hw *hw, · 373 unmodified lines | ||
| 3523 | 3614 | void *data), |
| 3524 | 3615 | void *iter_data); |
| 3525 | 3616 | |
| 3617 | +/** | |
| 3618 | + * ieee80211_iter_chan_contexts_atomic - iterate channel contexts | |
| 3619 | + * @hw: pointre obtained from ieee80211_alloc_hw(). | |
| 3620 | + * @iter: iterator function | |
| 3621 | + * @iter_data: data passed to iterator function | |
| 3622 | + * | |
| 3623 | + * Iterate all active channel contexts. This function is atomic and | |
| 3624 | + * doesn't acquire any locks internally that might be held in other | |
| 3625 | + * places while calling into the driver. | |
| 3626 | + * | |
| 3627 | + * The iterator will not find a context that's being added (during | |
| 3628 | + * the driver callback to add it) but will find it while it's being | |
| 3629 | + * removed. | |
| 3630 | + */ | |
| 3631 | +void ieee80211_iter_chan_contexts_atomic( | |
| 3632 | + struct ieee80211_hw *hw, | |
| 3633 | + void (*iter)(struct ieee80211_hw *hw, | |
| 3634 | + struct ieee80211_chanctx_conf *chanctx_conf, | |
| 3635 | + void *data), | |
| 3636 | + void *iter_data); | |
| 3637 | + | |
| 3526 | 3638 | /** |
| 3527 | 3639 | * ieee80211_ap_probereq_get - retrieve a Probe Request template |
| 3528 | 3640 | * @hw: pointer obtained from ieee80211_alloc_hw(). |
| @@ -24,6 +24,12 @@ · 23 unmodified lines | ||
| 24 | 24 | |
| 25 | 25 | #include <net/nfc/nfc.h> |
| 26 | 26 | |
| 27 | +struct nfc_phy_ops { | |
| 28 | + int (*write)(void *dev_id, struct sk_buff *skb); | |
| 29 | + int (*enable)(void *dev_id); | |
| 30 | + void (*disable)(void *dev_id); | |
| 31 | +}; | |
| 32 | + | |
| 27 | 33 | struct nfc_hci_dev; |
| 28 | 34 | |
| 29 | 35 | struct nfc_hci_ops { |
| @@ -38,15 +44,21 @@ struct nfc_hci_ops { · 8 unmodified lines | ||
| 38 | 44 | int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb); |
| 39 | 45 | int (*start_poll) (struct nfc_hci_dev *hdev, |
| 40 | 46 | u32 im_protocols, u32 tm_protocols); |
| 47 | + int (*dep_link_up)(struct nfc_hci_dev *hdev, struct nfc_target *target, | |
| 48 | + u8 comm_mode, u8 *gb, size_t gb_len); | |
| 49 | + int (*dep_link_down)(struct nfc_hci_dev *hdev); | |
| 41 | 50 | int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate, |
| 42 | 51 | struct nfc_target *target); |
| 43 | 52 | int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate, |
| 44 | 53 | struct nfc_target *target); |
| 45 | − int (*data_exchange) (struct nfc_hci_dev *hdev, | |
| 54 | + int (*im_transceive) (struct nfc_hci_dev *hdev, | |
| 46 | 55 | struct nfc_target *target, struct sk_buff *skb, |
| 47 | 56 | data_exchange_cb_t cb, void *cb_context); |
| 57 | + int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb); | |
| 48 | 58 | int (*check_presence)(struct nfc_hci_dev *hdev, |
| 49 | 59 | struct nfc_target *target); |
| 60 | + void (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event, | |
| 61 | + struct sk_buff *skb); | |
| 50 | 62 | }; |
| 51 | 63 | |
| 52 | 64 | /* Pipes */ |
| @@ -114,6 +126,9 @@ struct nfc_hci_dev { · 61 unmodified lines | ||
| 114 | 126 | int async_cb_type; |
| 115 | 127 | data_exchange_cb_t async_cb; |
| 116 | 128 | void *async_cb_context; |
| 129 | + | |
| 130 | + u8 *gb; | |
| 131 | + size_t gb_len; | |
| 117 | 132 | }; |
| 118 | 133 | |
| 119 | 134 | /* hci device allocation */ |
| @@ -219,5 +234,6 @@ int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 gate, u8 response, · 99 unmodified lines | ||
| 219 | 234 | const u8 *param, size_t param_len); |
| 220 | 235 | int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event, |
| 221 | 236 | const u8 *param, size_t param_len); |
| 237 | +int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate); | |
| 222 | 238 | |
| 223 | 239 | #endif /* __NET_HCI_H */ |
| @@ -95,7 +95,7 @@ struct nfc_genl_data { · 94 unmodified lines | ||
| 95 | 95 | }; |
| 96 | 96 | |
| 97 | 97 | struct nfc_dev { |
| 98 | − unsigned int idx; | |
| 98 | + int idx; | |
| 99 | 99 | u32 target_next_idx; |
| 100 | 100 | struct nfc_target *targets; |
| 101 | 101 | int n_targets; |
| @@ -60,6 +60,13 @@ · 59 unmodified lines | ||
| 60 | 60 | * target mode. |
| 61 | 61 | * @NFC_EVENT_DEVICE_DEACTIVATED: event emitted when the adapter is deactivated |
| 62 | 62 | * from target mode. |
| 63 | + * @NFC_CMD_LLC_GET_PARAMS: request LTO, RW, and MIUX parameters for a device | |
| 64 | + * @NFC_CMD_LLC_SET_PARAMS: set one or more of LTO, RW, and MIUX parameters for | |
| 65 | + * a device. LTO must be set before the link is up otherwise -EINPROGRESS | |
| 66 | + * is returned. RW and MIUX can be set at anytime and will be passed in | |
| 67 | + * subsequent CONNECT and CC messages. | |
| 68 | + * If one of the passed parameters is wrong none is set and -EINVAL is | |
| 69 | + * returned. | |
| 63 | 70 | */ |
| 64 | 71 | enum nfc_commands { |
| 65 | 72 | NFC_CMD_UNSPEC, |
| @@ -77,6 +84,8 @@ enum nfc_commands { · 11 unmodified lines | ||
| 77 | 84 | NFC_EVENT_TARGET_LOST, |
| 78 | 85 | NFC_EVENT_TM_ACTIVATED, |
| 79 | 86 | NFC_EVENT_TM_DEACTIVATED, |
| 87 | + NFC_CMD_LLC_GET_PARAMS, | |
| 88 | + NFC_CMD_LLC_SET_PARAMS, | |
| 80 | 89 | /* private: internal use only */ |
| 81 | 90 | __NFC_CMD_AFTER_LAST |
| 82 | 91 | }; |
| @@ -102,6 +111,9 @@ enum nfc_commands { · 19 unmodified lines | ||
| 102 | 111 | * @NFC_ATTR_RF_MODE: Initiator or target |
| 103 | 112 | * @NFC_ATTR_IM_PROTOCOLS: Initiator mode protocols to poll for |
| 104 | 113 | * @NFC_ATTR_TM_PROTOCOLS: Target mode protocols to listen for |
| 114 | + * @NFC_ATTR_LLC_PARAM_LTO: Link TimeOut parameter | |
| 115 | + * @NFC_ATTR_LLC_PARAM_RW: Receive Window size parameter | |
| 116 | + * @NFC_ATTR_LLC_PARAM_MIUX: MIU eXtension parameter | |
| 105 | 117 | */ |
| 106 | 118 | enum nfc_attrs { |
| 107 | 119 | NFC_ATTR_UNSPEC, |
| @@ -119,6 +131,9 @@ enum nfc_attrs { · 11 unmodified lines | ||
| 119 | 131 | NFC_ATTR_DEVICE_POWERED, |
| 120 | 132 | NFC_ATTR_IM_PROTOCOLS, |
| 121 | 133 | NFC_ATTR_TM_PROTOCOLS, |
| 134 | + NFC_ATTR_LLC_PARAM_LTO, | |
| 135 | + NFC_ATTR_LLC_PARAM_RW, | |
| 136 | + NFC_ATTR_LLC_PARAM_MIUX, | |
| 122 | 137 | /* private: internal use only */ |
| 123 | 138 | __NFC_ATTR_AFTER_LAST |
| 124 | 139 | }; |
| @@ -1273,6 +1273,14 @@ enum nl80211_commands { · 1272 unmodified lines | ||
| 1273 | 1273 | * the connection request from a station. nl80211_connect_failed_reason |
| 1274 | 1274 | * enum has different reasons of connection failure. |
| 1275 | 1275 | * |
| 1276 | + * @NL80211_ATTR_SAE_DATA: SAE elements in Authentication frames. This starts | |
| 1277 | + * with the Authentication transaction sequence number field. | |
| 1278 | + * | |
| 1279 | + * @NL80211_ATTR_VHT_CAPABILITY: VHT Capability information element (from | |
| 1280 | + * association request when used with NL80211_CMD_NEW_STATION) | |
| 1281 | + * | |
| 1282 | + * @NL80211_ATTR_SCAN_FLAGS: scan request control flags (u32) | |
| 1283 | + * | |
| 1276 | 1284 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
| 1277 | 1285 | * @__NL80211_ATTR_AFTER_LAST: internal use |
| 1278 | 1286 | */ |
| @@ -1530,6 +1538,12 @@ enum nl80211_attrs { · 251 unmodified lines | ||
| 1530 | 1538 | |
| 1531 | 1539 | NL80211_ATTR_CONN_FAILED_REASON, |
| 1532 | 1540 | |
| 1541 | + NL80211_ATTR_SAE_DATA, | |
| 1542 | + | |
| 1543 | + NL80211_ATTR_VHT_CAPABILITY, | |
| 1544 | + | |
| 1545 | + NL80211_ATTR_SCAN_FLAGS, | |
| 1546 | + | |
| 1533 | 1547 | /* add attributes here, update the policy in nl80211.c */ |
| 1534 | 1548 | |
| 1535 | 1549 | __NL80211_ATTR_AFTER_LAST, |
| @@ -1573,6 +1587,7 @@ enum nl80211_attrs { · 37 unmodified lines | ||
| 1573 | 1587 | #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 |
| 1574 | 1588 | #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 |
| 1575 | 1589 | #define NL80211_HT_CAPABILITY_LEN 26 |
| 1590 | +#define NL80211_VHT_CAPABILITY_LEN 12 | |
| 1576 | 1591 | |
| 1577 | 1592 | #define NL80211_MAX_NR_CIPHER_SUITES 5 |
| 1578 | 1593 | #define NL80211_MAX_NR_AKM_SUITES 2 |
| @@ -2489,6 +2504,7 @@ enum nl80211_bss_status { · 910 unmodified lines | ||
| 2489 | 2504 | * @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only) |
| 2490 | 2505 | * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r) |
| 2491 | 2506 | * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP) |
| 2507 | + * @NL80211_AUTHTYPE_SAE: Simultaneous authentication of equals | |
| 2492 | 2508 | * @__NL80211_AUTHTYPE_NUM: internal |
| 2493 | 2509 | * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm |
| 2494 | 2510 | * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by |
| @@ -2500,6 +2516,7 @@ enum nl80211_auth_type { · 5 unmodified lines | ||
| 2500 | 2516 | NL80211_AUTHTYPE_SHARED_KEY, |
| 2501 | 2517 | NL80211_AUTHTYPE_FT, |
| 2502 | 2518 | NL80211_AUTHTYPE_NETWORK_EAP, |
| 2519 | + NL80211_AUTHTYPE_SAE, | |
| 2503 | 2520 | |
| 2504 | 2521 | /* keep last */ |
| 2505 | 2522 | __NL80211_AUTHTYPE_NUM, |
| @@ -3028,6 +3045,12 @@ enum nl80211_ap_sme_features { · 522 unmodified lines | ||
| 3028 | 3045 | * in the interface combinations, even when it's only used for scan |
| 3029 | 3046 | * and remain-on-channel. This could be due to, for example, the |
| 3030 | 3047 | * remain-on-channel implementation requiring a channel context. |
| 3048 | + * @NL80211_FEATURE_SAE: This driver supports simultaneous authentication of | |
| 3049 | + * equals (SAE) with user space SME (NL80211_CMD_AUTHENTICATE) in station | |
| 3050 | + * mode | |
| 3051 | + * @NL80211_FEATURE_LOW_PRIORITY_SCAN: This driver supports low priority scan | |
| 3052 | + * @NL80211_FEATURE_SCAN_FLUSH: Scan flush is supported | |
| 3053 | + * @NL80211_FEATURE_AP_SCAN: Support scanning using an AP vif | |
| 3031 | 3054 | */ |
| 3032 | 3055 | enum nl80211_feature_flags { |
| 3033 | 3056 | NL80211_FEATURE_SK_TX_STATUS = 1 << 0, |
| @@ -3035,6 +3058,10 @@ enum nl80211_feature_flags { · 1 unmodified line | ||
| 3035 | 3058 | NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2, |
| 3036 | 3059 | NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3, |
| 3037 | 3060 | NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 1 << 4, |
| 3061 | + NL80211_FEATURE_SAE = 1 << 5, | |
| 3062 | + NL80211_FEATURE_LOW_PRIORITY_SCAN = 1 << 6, | |
| 3063 | + NL80211_FEATURE_SCAN_FLUSH = 1 << 7, | |
| 3064 | + NL80211_FEATURE_AP_SCAN = 1 << 8, | |
| 3038 | 3065 | }; |
| 3039 | 3066 | |
| 3040 | 3067 | /** |
| @@ -3069,4 +3096,25 @@ enum nl80211_connect_failed_reason { · 28 unmodified lines | ||
| 3069 | 3096 | NL80211_CONN_FAIL_BLOCKED_CLIENT, |
| 3070 | 3097 | }; |
| 3071 | 3098 | |
| 3099 | +/** | |
| 3100 | + * enum nl80211_scan_flags - scan request control flags | |
| 3101 | + * | |
| 3102 | + * Scan request control flags are used to control the handling | |
| 3103 | + * of NL80211_CMD_TRIGGER_SCAN and NL80211_CMD_START_SCHED_SCAN | |
| 3104 | + * requests. | |
| 3105 | + * | |
| 3106 | + * @NL80211_SCAN_FLAG_LOW_PRIORITY: scan request has low priority | |
| 3107 | + * @NL80211_SCAN_FLAG_FLUSH: flush cache before scanning | |
| 3108 | + * @NL80211_SCAN_FLAG_AP: force a scan even if the interface is configured | |
| 3109 | + * as AP and the beaconing has already been configured. This attribute is | |
| 3110 | + * dangerous because will destroy stations performance as a lot of frames | |
| 3111 | + * will be lost while scanning off-channel, therefore it must be used only | |
| 3112 | + * when really needed | |
| 3113 | + */ | |
| 3114 | +enum nl80211_scan_flags { | |
| 3115 | + NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0, | |
| 3116 | + NL80211_SCAN_FLAG_FLUSH = 1<<1, | |
| 3117 | + NL80211_SCAN_FLAG_AP = 1<<2, | |
| 3118 | +}; | |
| 3119 | + | |
| 3072 | 3120 | #endif /* __LINUX_NL80211_H */ |
| @@ -11,6 +11,7 @@ menuconfig BT · 10 unmodified lines | ||
| 11 | 11 | select CRYPTO_BLKCIPHER |
| 12 | 12 | select CRYPTO_AES |
| 13 | 13 | select CRYPTO_ECB |
| 14 | + select CRYPTO_SHA256 | |
| 14 | 15 | help |
| 15 | 16 | Bluetooth is low-cost, low-power, short-range wireless technology. |
| 16 | 17 | It was designed as a replacement for cables and other short-range |
| @@ -10,4 +10,4 @@ obj-$(CONFIG_BT_HIDP) += hidp/ · 9 unmodified lines | ||
| 10 | 10 | |
| 11 | 11 | bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ |
| 12 | 12 | hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \ |
| 13 | − a2mp.o | |
| 13 | + a2mp.o amp.o | |
| @@ -16,6 +16,11 @@ · 15 unmodified lines | ||
| 16 | 16 | #include <net/bluetooth/hci_core.h> |
| 17 | 17 | #include <net/bluetooth/l2cap.h> |
| 18 | 18 | #include <net/bluetooth/a2mp.h> |
| 19 | +#include <net/bluetooth/amp.h> | |
| 20 | + | |
| 21 | +/* Global AMP Manager list */ | |
| 22 | +LIST_HEAD(amp_mgr_list); | |
| 23 | +DEFINE_MUTEX(amp_mgr_list_lock); | |
| 19 | 24 | |
| 20 | 25 | /* A2MP build & send command helper functions */ |
| 21 | 26 | static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data) |
| @@ -37,8 +42,7 @@ static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data) · 15 unmodified lines | ||
| 37 | 42 | return cmd; |
| 38 | 43 | } |
| 39 | 44 | |
| 40 | −static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, | |
| 41 | − void *data) | |
| 45 | +void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data) | |
| 42 | 46 | { |
| 43 | 47 | struct l2cap_chan *chan = mgr->a2mp_chan; |
| 44 | 48 | struct a2mp_cmd *cmd; |
| @@ -63,6 +67,14 @@ static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, · 18 unmodified lines | ||
| 63 | 67 | kfree(cmd); |
| 64 | 68 | } |
| 65 | 69 | |
| 70 | +u8 __next_ident(struct amp_mgr *mgr) | |
| 71 | +{ | |
| 72 | + if (++mgr->ident == 0) | |
| 73 | + mgr->ident = 1; | |
| 74 | + | |
| 75 | + return mgr->ident; | |
| 76 | +} | |
| 77 | + | |
| 66 | 78 | static inline void __a2mp_cl_bredr(struct a2mp_cl *cl) |
| 67 | 79 | { |
| 68 | 80 | cl->id = 0; |
| @@ -161,6 +173,83 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb, · 92 unmodified lines | ||
| 161 | 173 | return 0; |
| 162 | 174 | } |
| 163 | 175 | |
| 176 | +static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | |
| 177 | + struct a2mp_cmd *hdr) | |
| 178 | +{ | |
| 179 | + struct a2mp_discov_rsp *rsp = (void *) skb->data; | |
| 180 | + u16 len = le16_to_cpu(hdr->len); | |
| 181 | + struct a2mp_cl *cl; | |
| 182 | + u16 ext_feat; | |
| 183 | + bool found = false; | |
| 184 | + | |
| 185 | + if (len < sizeof(*rsp)) | |
| 186 | + return -EINVAL; | |
| 187 | + | |
| 188 | + len -= sizeof(*rsp); | |
| 189 | + skb_pull(skb, sizeof(*rsp)); | |
| 190 | + | |
| 191 | + ext_feat = le16_to_cpu(rsp->ext_feat); | |
| 192 | + | |
| 193 | + BT_DBG("mtu %d efm 0x%4.4x", le16_to_cpu(rsp->mtu), ext_feat); | |
| 194 | + | |
| 195 | + /* check that packet is not broken for now */ | |
| 196 | + while (ext_feat & A2MP_FEAT_EXT) { | |
| 197 | + if (len < sizeof(ext_feat)) | |
| 198 | + return -EINVAL; | |
| 199 | + | |
| 200 | + ext_feat = get_unaligned_le16(skb->data); | |
| 201 | + BT_DBG("efm 0x%4.4x", ext_feat); | |
| 202 | + len -= sizeof(ext_feat); | |
| 203 | + skb_pull(skb, sizeof(ext_feat)); | |
| 204 | + } | |
| 205 | + | |
| 206 | + cl = (void *) skb->data; | |
| 207 | + while (len >= sizeof(*cl)) { | |
| 208 | + BT_DBG("Remote AMP id %d type %d status %d", cl->id, cl->type, | |
| 209 | + cl->status); | |
| 210 | + | |
| 211 | + if (cl->id != HCI_BREDR_ID && cl->type == HCI_AMP) { | |
| 212 | + struct a2mp_info_req req; | |
| 213 | + | |
| 214 | + found = true; | |
| 215 | + req.id = cl->id; | |
| 216 | + a2mp_send(mgr, A2MP_GETINFO_REQ, __next_ident(mgr), | |
| 217 | + sizeof(req), &req); | |
| 218 | + } | |
| 219 | + | |
| 220 | + len -= sizeof(*cl); | |
| 221 | + cl = (void *) skb_pull(skb, sizeof(*cl)); | |
| 222 | + } | |
| 223 | + | |
| 224 | + /* Fall back to L2CAP init sequence */ | |
| 225 | + if (!found) { | |
| 226 | + struct l2cap_conn *conn = mgr->l2cap_conn; | |
| 227 | + struct l2cap_chan *chan; | |
| 228 | + | |
| 229 | + mutex_lock(&conn->chan_lock); | |
| 230 | + | |
| 231 | + list_for_each_entry(chan, &conn->chan_l, list) { | |
| 232 | + | |
| 233 | + BT_DBG("chan %p state %s", chan, | |
| 234 | + state_to_string(chan->state)); | |
| 235 | + | |
| 236 | + if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) | |
| 237 | + continue; | |
| 238 | + | |
| 239 | + l2cap_chan_lock(chan); | |
| 240 | + | |
| 241 | + if (chan->state == BT_CONNECT) | |
| 242 | + l2cap_send_conn_req(chan); | |
| 243 | + | |
| 244 | + l2cap_chan_unlock(chan); | |
| 245 | + } | |
| 246 | + | |
| 247 | + mutex_unlock(&conn->chan_lock); | |
| 248 | + } | |
| 249 | + | |
| 250 | + return 0; | |
| 251 | +} | |
| 252 | + | |
| 164 | 253 | static int a2mp_change_notify(struct amp_mgr *mgr, struct sk_buff *skb, |
| 165 | 254 | struct a2mp_cmd *hdr) |
| 166 | 255 | { |
| @@ -181,7 +270,6 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb, · 14 unmodified lines | ||
| 181 | 270 | struct a2mp_cmd *hdr) |
| 182 | 271 | { |
| 183 | 272 | struct a2mp_info_req *req = (void *) skb->data; |
| 184 | − struct a2mp_info_rsp rsp; | |
| 185 | 273 | struct hci_dev *hdev; |
| 186 | 274 | |
| 187 | 275 | if (le16_to_cpu(hdr->len) < sizeof(*req)) |
| @@ -189,53 +277,93 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb, · 1 unmodified line | ||
| 189 | 277 | |
| 190 | 278 | BT_DBG("id %d", req->id); |
| 191 | 279 | |
| 192 | − rsp.id = req->id; | |
| 193 | − rsp.status = A2MP_STATUS_INVALID_CTRL_ID; | |
| 194 | − | |
| 195 | 280 | hdev = hci_dev_get(req->id); |
| 196 | − if (hdev && hdev->amp_type != HCI_BREDR) { | |
| 197 | − rsp.status = 0; | |
| 198 | − rsp.total_bw = cpu_to_le32(hdev->amp_total_bw); | |
| 199 | − rsp.max_bw = cpu_to_le32(hdev->amp_max_bw); | |
| 200 | − rsp.min_latency = cpu_to_le32(hdev->amp_min_latency); | |
| 201 | − rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap); | |
| 202 | − rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size); | |
| 281 | + if (!hdev || hdev->dev_type != HCI_AMP) { | |
| 282 | + struct a2mp_info_rsp rsp; | |
| 283 | + | |
| 284 | + rsp.id = req->id; | |
| 285 | + rsp.status = A2MP_STATUS_INVALID_CTRL_ID; | |
| 286 | + | |
| 287 | + a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp), | |
| 288 | + &rsp); | |
| 289 | + | |
| 290 | + goto done; | |
| 203 | 291 | } |
| 204 | 292 | |
| 293 | + mgr->state = READ_LOC_AMP_INFO; | |
| 294 | + hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); | |
| 295 | + | |
| 296 | +done: | |
| 205 | 297 | if (hdev) |
| 206 | 298 | hci_dev_put(hdev); |
| 207 | 299 | |
| 208 | − a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp), &rsp); | |
| 209 | − | |
| 210 | 300 | skb_pull(skb, sizeof(*req)); |
| 211 | 301 | return 0; |
| 212 | 302 | } |
| 213 | 303 | |
| 304 | +static int a2mp_getinfo_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | |
| 305 | + struct a2mp_cmd *hdr) | |
| 306 | +{ | |
| 307 | + struct a2mp_info_rsp *rsp = (struct a2mp_info_rsp *) skb->data; | |
| 308 | + struct a2mp_amp_assoc_req req; | |
| 309 | + struct amp_ctrl *ctrl; | |
| 310 | + | |
| 311 | + if (le16_to_cpu(hdr->len) < sizeof(*rsp)) | |
| 312 | + return -EINVAL; | |
| 313 | + | |
| 314 | + BT_DBG("id %d status 0x%2.2x", rsp->id, rsp->status); | |
| 315 | + | |
| 316 | + if (rsp->status) | |
| 317 | + return -EINVAL; | |
| 318 | + | |
| 319 | + ctrl = amp_ctrl_add(mgr, rsp->id); | |
| 320 | + if (!ctrl) | |
| 321 | + return -ENOMEM; | |
| 322 | + | |
| 323 | + req.id = rsp->id; | |
| 324 | + a2mp_send(mgr, A2MP_GETAMPASSOC_REQ, __next_ident(mgr), sizeof(req), | |
| 325 | + &req); | |
| 326 | + | |
| 327 | + skb_pull(skb, sizeof(*rsp)); | |
| 328 | + return 0; | |
| 329 | +} | |
| 330 | + | |
| 214 | 331 | static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb, |
| 215 | 332 | struct a2mp_cmd *hdr) |
| 216 | 333 | { |
| 217 | 334 | struct a2mp_amp_assoc_req *req = (void *) skb->data; |
| 218 | 335 | struct hci_dev *hdev; |
| 336 | + struct amp_mgr *tmp; | |
| 219 | 337 | |
| 220 | 338 | if (le16_to_cpu(hdr->len) < sizeof(*req)) |
| 221 | 339 | return -EINVAL; |
| 222 | 340 | |
| 223 | 341 | BT_DBG("id %d", req->id); |
| 224 | 342 | |
| 343 | + /* Make sure that other request is not processed */ | |
| 344 | + tmp = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC); | |
| 345 | + | |
| 225 | 346 | hdev = hci_dev_get(req->id); |
| 226 | − if (!hdev || hdev->amp_type == HCI_BREDR) { | |
| 347 | + if (!hdev || hdev->amp_type == HCI_BREDR || tmp) { | |
| 227 | 348 | struct a2mp_amp_assoc_rsp rsp; |
| 228 | 349 | rsp.id = req->id; |
| 229 | − rsp.status = A2MP_STATUS_INVALID_CTRL_ID; | |
| 350 | + | |
| 351 | + if (tmp) { | |
| 352 | + rsp.status = A2MP_STATUS_COLLISION_OCCURED; | |
| 353 | + amp_mgr_put(tmp); | |
| 354 | + } else { | |
| 355 | + rsp.status = A2MP_STATUS_INVALID_CTRL_ID; | |
| 356 | + } | |
| 230 | 357 | |
| 231 | 358 | a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, hdr->ident, sizeof(rsp), |
| 232 | 359 | &rsp); |
| 233 | − goto clean; | |
| 360 | + | |
| 361 | + goto done; | |
| 234 | 362 | } |
| 235 | 363 | |
| 236 | − /* Placeholder for HCI Read AMP Assoc */ | |
| 364 | + amp_read_loc_assoc(hdev, mgr); | |
| 237 | 365 | |
| 238 | −clean: | |
| 366 | +done: | |
| 239 | 367 | if (hdev) |
| 240 | 368 | hci_dev_put(hdev); |
| 241 | 369 | |
| @@ -243,6 +371,68 @@ clean: · 1 unmodified line | ||
| 243 | 371 | return 0; |
| 244 | 372 | } |
| 245 | 373 | |
| 374 | +static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | |
| 375 | + struct a2mp_cmd *hdr) | |
| 376 | +{ | |
| 377 | + struct a2mp_amp_assoc_rsp *rsp = (void *) skb->data; | |
| 378 | + u16 len = le16_to_cpu(hdr->len); | |
| 379 | + struct hci_dev *hdev; | |
| 380 | + struct amp_ctrl *ctrl; | |
| 381 | + struct hci_conn *hcon; | |
| 382 | + size_t assoc_len; | |
| 383 | + | |
| 384 | + if (len < sizeof(*rsp)) | |
| 385 | + return -EINVAL; | |
| 386 | + | |
| 387 | + assoc_len = len - sizeof(*rsp); | |
| 388 | + | |
| 389 | + BT_DBG("id %d status 0x%2.2x assoc len %zu", rsp->id, rsp->status, | |
| 390 | + assoc_len); | |
| 391 | + | |
| 392 | + if (rsp->status) | |
| 393 | + return -EINVAL; | |
| 394 | + | |
| 395 | + /* Save remote ASSOC data */ | |
| 396 | + ctrl = amp_ctrl_lookup(mgr, rsp->id); | |
| 397 | + if (ctrl) { | |
| 398 | + u8 *assoc; | |
| 399 | + | |
| 400 | + assoc = kzalloc(assoc_len, GFP_KERNEL); | |
| 401 | + if (!assoc) { | |
| 402 | + amp_ctrl_put(ctrl); | |
| 403 | + return -ENOMEM; | |
| 404 | + } | |
| 405 | + | |
| 406 | + memcpy(assoc, rsp->amp_assoc, assoc_len); | |
| 407 | + ctrl->assoc = assoc; | |
| 408 | + ctrl->assoc_len = assoc_len; | |
| 409 | + ctrl->assoc_rem_len = assoc_len; | |
| 410 | + ctrl->assoc_len_so_far = 0; | |
| 411 | + | |
| 412 | + amp_ctrl_put(ctrl); | |
| 413 | + } | |
| 414 | + | |
| 415 | + /* Create Phys Link */ | |
| 416 | + hdev = hci_dev_get(rsp->id); | |
| 417 | + if (!hdev) | |
| 418 | + return -EINVAL; | |
| 419 | + | |
| 420 | + hcon = phylink_add(hdev, mgr, rsp->id, true); | |
| 421 | + if (!hcon) | |
| 422 | + goto done; | |
| 423 | + | |
| 424 | + BT_DBG("Created hcon %p: loc:%d -> rem:%d", hcon, hdev->id, rsp->id); | |
| 425 | + | |
| 426 | + mgr->bredr_chan->ctrl_id = rsp->id; | |
| 427 | + | |
| 428 | + amp_create_phylink(hdev, mgr, hcon); | |
| 429 | + | |
| 430 | +done: | |
| 431 | + hci_dev_put(hdev); | |
| 432 | + skb_pull(skb, len); | |
| 433 | + return 0; | |
| 434 | +} | |
| 435 | + | |
| 246 | 436 | static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, |
| 247 | 437 | struct a2mp_cmd *hdr) |
| 248 | 438 | { |
| @@ -250,6 +440,8 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, · 1 unmodified line | ||
| 250 | 440 | |
| 251 | 441 | struct a2mp_physlink_rsp rsp; |
| 252 | 442 | struct hci_dev *hdev; |
| 443 | + struct hci_conn *hcon; | |
| 444 | + struct amp_ctrl *ctrl; | |
| 253 | 445 | |
| 254 | 446 | if (le16_to_cpu(hdr->len) < sizeof(*req)) |
| 255 | 447 | return -EINVAL; |
| @@ -265,9 +457,43 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, · 9 unmodified lines | ||
| 265 | 457 | goto send_rsp; |
| 266 | 458 | } |
| 267 | 459 | |
| 268 | − /* TODO process physlink create */ | |
| 460 | + ctrl = amp_ctrl_lookup(mgr, rsp.remote_id); | |
| 461 | + if (!ctrl) { | |
| 462 | + ctrl = amp_ctrl_add(mgr, rsp.remote_id); | |
| 463 | + if (ctrl) { | |
| 464 | + amp_ctrl_get(ctrl); | |
| 465 | + } else { | |
| 466 | + rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION; | |
| 467 | + goto send_rsp; | |
| 468 | + } | |
| 469 | + } | |
| 269 | 470 | |
| 270 | − rsp.status = A2MP_STATUS_SUCCESS; | |
| 471 | + if (ctrl) { | |
| 472 | + size_t assoc_len = le16_to_cpu(hdr->len) - sizeof(*req); | |
| 473 | + u8 *assoc; | |
| 474 | + | |
| 475 | + assoc = kzalloc(assoc_len, GFP_KERNEL); | |
| 476 | + if (!assoc) { | |
| 477 | + amp_ctrl_put(ctrl); | |
| 478 | + return -ENOMEM; | |
| 479 | + } | |
| 480 | + | |
| 481 | + memcpy(assoc, req->amp_assoc, assoc_len); | |
| 482 | + ctrl->assoc = assoc; | |
| 483 | + ctrl->assoc_len = assoc_len; | |
| 484 | + ctrl->assoc_rem_len = assoc_len; | |
| 485 | + ctrl->assoc_len_so_far = 0; | |
| 486 | + | |
| 487 | + amp_ctrl_put(ctrl); | |
| 488 | + } | |
| 489 | + | |
| 490 | + hcon = phylink_add(hdev, mgr, req->local_id, false); | |
| 491 | + if (hcon) { | |
| 492 | + amp_accept_phylink(hdev, mgr, hcon); | |
| 493 | + rsp.status = A2MP_STATUS_SUCCESS; | |
| 494 | + } else { | |
| 495 | + rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION; | |
| 496 | + } | |
| 271 | 497 | |
| 272 | 498 | send_rsp: |
| 273 | 499 | if (hdev) |
| @@ -286,6 +512,7 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, · 12 unmodified lines | ||
| 286 | 512 | struct a2mp_physlink_req *req = (void *) skb->data; |
| 287 | 513 | struct a2mp_physlink_rsp rsp; |
| 288 | 514 | struct hci_dev *hdev; |
| 515 | + struct hci_conn *hcon; | |
| 289 | 516 | |
| 290 | 517 | if (le16_to_cpu(hdr->len) < sizeof(*req)) |
| 291 | 518 | return -EINVAL; |
| @@ -296,14 +523,22 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, · 4 unmodified lines | ||
| 296 | 523 | rsp.remote_id = req->local_id; |
| 297 | 524 | rsp.status = A2MP_STATUS_SUCCESS; |
| 298 | 525 | |
| 299 | − hdev = hci_dev_get(req->local_id); | |
| 526 | + hdev = hci_dev_get(req->remote_id); | |
| 300 | 527 | if (!hdev) { |
| 301 | 528 | rsp.status = A2MP_STATUS_INVALID_CTRL_ID; |
| 302 | 529 | goto send_rsp; |
| 303 | 530 | } |
| 304 | 531 | |
| 532 | + hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, mgr->l2cap_conn->dst); | |
| 533 | + if (!hcon) { | |
| 534 | + BT_ERR("No phys link exist"); | |
| 535 | + rsp.status = A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS; | |
| 536 | + goto clean; | |
| 537 | + } | |
| 538 | + | |
| 305 | 539 | /* TODO Disconnect Phys Link here */ |
| 306 | 540 | |
| 541 | +clean: | |
| 307 | 542 | hci_dev_put(hdev); |
| 308 | 543 | |
| 309 | 544 | send_rsp: |
| @@ -377,10 +612,19 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) · 67 unmodified lines | ||
| 377 | 612 | err = a2mp_discphyslink_req(mgr, skb, hdr); |
| 378 | 613 | break; |
| 379 | 614 | |
| 380 | − case A2MP_CHANGE_RSP: | |
| 381 | 615 | case A2MP_DISCOVER_RSP: |
| 616 | + err = a2mp_discover_rsp(mgr, skb, hdr); | |
| 617 | + break; | |
| 618 | + | |
| 382 | 619 | case A2MP_GETINFO_RSP: |
| 620 | + err = a2mp_getinfo_rsp(mgr, skb, hdr); | |
| 621 | + break; | |
| 622 | + | |
| 383 | 623 | case A2MP_GETAMPASSOC_RSP: |
| 624 | + err = a2mp_getampassoc_rsp(mgr, skb, hdr); | |
| 625 | + break; | |
| 626 | + | |
| 627 | + case A2MP_CHANGE_RSP: | |
| 384 | 628 | case A2MP_CREATEPHYSLINK_RSP: |
| 385 | 629 | case A2MP_DISCONNPHYSLINK_RSP: |
| 386 | 630 | err = a2mp_cmd_rsp(mgr, skb, hdr); |
| @@ -455,9 +699,10 @@ static struct l2cap_ops a2mp_chan_ops = { · 68 unmodified lines | ||
| 455 | 699 | .new_connection = l2cap_chan_no_new_connection, |
| 456 | 700 | .teardown = l2cap_chan_no_teardown, |
| 457 | 701 | .ready = l2cap_chan_no_ready, |
| 702 | + .defer = l2cap_chan_no_defer, | |
| 458 | 703 | }; |
| 459 | 704 | |
| 460 | −static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn) | |
| 705 | +static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) | |
| 461 | 706 | { |
| 462 | 707 | struct l2cap_chan *chan; |
| 463 | 708 | int err; |
| @@ -492,7 +737,10 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn) · 28 unmodified lines | ||
| 492 | 737 | |
| 493 | 738 | chan->conf_state = 0; |
| 494 | 739 | |
| 495 | − l2cap_chan_add(conn, chan); | |
| 740 | + if (locked) | |
| 741 | + __l2cap_chan_add(conn, chan); | |
| 742 | + else | |
| 743 | + l2cap_chan_add(conn, chan); | |
| 496 | 744 | |
| 497 | 745 | chan->remote_mps = chan->omtu; |
| 498 | 746 | chan->mps = chan->omtu; |
| @@ -503,11 +751,13 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn) · 4 unmodified lines | ||
| 503 | 751 | } |
| 504 | 752 | |
| 505 | 753 | /* AMP Manager functions */ |
| 506 | −void amp_mgr_get(struct amp_mgr *mgr) | |
| 754 | +struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr) | |
| 507 | 755 | { |
| 508 | 756 | BT_DBG("mgr %p orig refcnt %d", mgr, atomic_read(&mgr->kref.refcount)); |
| 509 | 757 | |
| 510 | 758 | kref_get(&mgr->kref); |
| 759 | + | |
| 760 | + return mgr; | |
| 511 | 761 | } |
| 512 | 762 | |
| 513 | 763 | static void amp_mgr_destroy(struct kref *kref) |
| @@ -516,6 +766,11 @@ static void amp_mgr_destroy(struct kref *kref) · 2 unmodified lines | ||
| 516 | 766 | |
| 517 | 767 | BT_DBG("mgr %p", mgr); |
| 518 | 768 | |
| 769 | + mutex_lock(&_mgr_list_lock); | |
| 770 | + list_del(&mgr->list); | |
| 771 | + mutex_unlock(&_mgr_list_lock); | |
| 772 | + | |
| 773 | + amp_ctrl_list_flush(mgr); | |
| 519 | 774 | kfree(mgr); |
| 520 | 775 | } |
| 521 | 776 | |
| @@ -526,7 +781,7 @@ int amp_mgr_put(struct amp_mgr *mgr) · 4 unmodified lines | ||
| 526 | 781 | return kref_put(&mgr->kref, &_mgr_destroy); |
| 527 | 782 | } |
| 528 | 783 | |
| 529 | −static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn) | |
| 784 | +static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn, bool locked) | |
| 530 | 785 | { |
| 531 | 786 | struct amp_mgr *mgr; |
| 532 | 787 | struct l2cap_chan *chan; |
| @@ -539,7 +794,7 @@ static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn) · 6 unmodified lines | ||
| 539 | 794 | |
| 540 | 795 | mgr->l2cap_conn = conn; |
| 541 | 796 | |
| 542 | − chan = a2mp_chan_open(conn); | |
| 797 | + chan = a2mp_chan_open(conn, locked); | |
| 543 | 798 | if (!chan) { |
| 544 | 799 | kfree(mgr); |
| 545 | 800 | return NULL; |
| @@ -552,6 +807,14 @@ static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn) · 6 unmodified lines | ||
| 552 | 807 | |
| 553 | 808 | kref_init(&mgr->kref); |
| 554 | 809 | |
| 810 | + /* Remote AMP ctrl list initialization */ | |
| 811 | + INIT_LIST_HEAD(&mgr->amp_ctrls); | |
| 812 | + mutex_init(&mgr->amp_ctrls_lock); | |
| 813 | + | |
| 814 | + mutex_lock(&_mgr_list_lock); | |
| 815 | + list_add(&mgr->list, &_mgr_list); | |
| 816 | + mutex_unlock(&_mgr_list_lock); | |
| 817 | + | |
| 555 | 818 | return mgr; |
| 556 | 819 | } |
| 557 | 820 | |
| @@ -560,7 +823,7 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, · 2 unmodified lines | ||
| 560 | 823 | { |
| 561 | 824 | struct amp_mgr *mgr; |
| 562 | 825 | |
| 563 | − mgr = amp_mgr_create(conn); | |
| 826 | + mgr = amp_mgr_create(conn, false); | |
| 564 | 827 | if (!mgr) { |
| 565 | 828 | BT_ERR("Could not create AMP manager"); |
| 566 | 829 | return NULL; |
| @@ -570,3 +833,139 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, · 3 unmodified lines | ||
| 570 | 833 | |
| 571 | 834 | return mgr->a2mp_chan; |
| 572 | 835 | } |
| 836 | + | |
| 837 | +struct amp_mgr *amp_mgr_lookup_by_state(u8 state) | |
| 838 | +{ | |
| 839 | + struct amp_mgr *mgr; | |
| 840 | + | |
| 841 | + mutex_lock(&_mgr_list_lock); | |
| 842 | + list_for_each_entry(mgr, &_mgr_list, list) { | |
| 843 | + if (mgr->state == state) { | |
| 844 | + amp_mgr_get(mgr); | |
| 845 | + mutex_unlock(&_mgr_list_lock); | |
| 846 | + return mgr; | |
| 847 | + } | |
| 848 | + } | |
| 849 | + mutex_unlock(&_mgr_list_lock); | |
| 850 | + | |
| 851 | + return NULL; | |
| 852 | +} | |
| 853 | + | |
| 854 | +void a2mp_send_getinfo_rsp(struct hci_dev *hdev) | |
| 855 | +{ | |
| 856 | + struct amp_mgr *mgr; | |
| 857 | + struct a2mp_info_rsp rsp; | |
| 858 | + | |
| 859 | + mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_INFO); | |
| 860 | + if (!mgr) | |
| 861 | + return; | |
| 862 | + | |
| 863 | + BT_DBG("%s mgr %p", hdev->name, mgr); | |
| 864 | + | |
| 865 | + rsp.id = hdev->id; | |
| 866 | + rsp.status = A2MP_STATUS_INVALID_CTRL_ID; | |
| 867 | + | |
| 868 | + if (hdev->amp_type != HCI_BREDR) { | |
| 869 | + rsp.status = 0; | |
| 870 | + rsp.total_bw = cpu_to_le32(hdev->amp_total_bw); | |
| 871 | + rsp.max_bw = cpu_to_le32(hdev->amp_max_bw); | |
| 872 | + rsp.min_latency = cpu_to_le32(hdev->amp_min_latency); | |
| 873 | + rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap); | |
| 874 | + rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size); | |
| 875 | + } | |
| 876 | + | |
| 877 | + a2mp_send(mgr, A2MP_GETINFO_RSP, mgr->ident, sizeof(rsp), &rsp); | |
| 878 | + amp_mgr_put(mgr); | |
| 879 | +} | |
| 880 | + | |
| 881 | +void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status) | |
| 882 | +{ | |
| 883 | + struct amp_mgr *mgr; | |
| 884 | + struct amp_assoc *loc_assoc = &hdev->loc_assoc; | |
| 885 | + struct a2mp_amp_assoc_rsp *rsp; | |
| 886 | + size_t len; | |
| 887 | + | |
| 888 | + mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC); | |
| 889 | + if (!mgr) | |
| 890 | + return; | |
| 891 | + | |
| 892 | + BT_DBG("%s mgr %p", hdev->name, mgr); | |
| 893 | + | |
| 894 | + len = sizeof(struct a2mp_amp_assoc_rsp) + loc_assoc->len; | |
| 895 | + rsp = kzalloc(len, GFP_KERNEL); | |
| 896 | + if (!rsp) { | |
| 897 | + amp_mgr_put(mgr); | |
| 898 | + return; | |
| 899 | + } | |
| 900 | + | |
| 901 | + rsp->id = hdev->id; | |
| 902 | + | |
| 903 | + if (status) { | |
| 904 | + rsp->status = A2MP_STATUS_INVALID_CTRL_ID; | |
| 905 | + } else { | |
| 906 | + rsp->status = A2MP_STATUS_SUCCESS; | |
| 907 | + memcpy(rsp->amp_assoc, loc_assoc->data, loc_assoc->len); | |
| 908 | + } | |
| 909 | + | |
| 910 | + a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, mgr->ident, len, rsp); | |
| 911 | + amp_mgr_put(mgr); | |
| 912 | + kfree(rsp); | |
| 913 | +} | |
| 914 | + | |
| 915 | +void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status) | |
| 916 | +{ | |
| 917 | + struct amp_mgr *mgr; | |
| 918 | + struct amp_assoc *loc_assoc = &hdev->loc_assoc; | |
| 919 | + struct a2mp_physlink_req *req; | |
| 920 | + struct l2cap_chan *bredr_chan; | |
| 921 | + size_t len; | |
| 922 | + | |
| 923 | + mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC_FINAL); | |
| 924 | + if (!mgr) | |
| 925 | + return; | |
| 926 | + | |
| 927 | + len = sizeof(*req) + loc_assoc->len; | |
| 928 | + | |
| 929 | + BT_DBG("%s mgr %p assoc_len %zu", hdev->name, mgr, len); | |
| 930 | + | |
| 931 | + req = kzalloc(len, GFP_KERNEL); | |
| 932 | + if (!req) { | |
| 933 | + amp_mgr_put(mgr); | |
| 934 | + return; | |
| 935 | + } | |
| 936 | + | |
| 937 | + bredr_chan = mgr->bredr_chan; | |
| 938 | + if (!bredr_chan) | |
| 939 | + goto clean; | |
| 940 | + | |
| 941 | + req->local_id = hdev->id; | |
| 942 | + req->remote_id = bredr_chan->ctrl_id; | |
| 943 | + memcpy(req->amp_assoc, loc_assoc->data, loc_assoc->len); | |
| 944 | + | |
| 945 | + a2mp_send(mgr, A2MP_CREATEPHYSLINK_REQ, __next_ident(mgr), len, req); | |
| 946 | + | |
| 947 | +clean: | |
| 948 | + amp_mgr_put(mgr); | |
| 949 | + kfree(req); | |
| 950 | +} | |
| 951 | + | |
| 952 | +void a2mp_discover_amp(struct l2cap_chan *chan) | |
| 953 | +{ | |
| 954 | + struct l2cap_conn *conn = chan->conn; | |
| 955 | + struct amp_mgr *mgr = conn->hcon->amp_mgr; | |
| 956 | + struct a2mp_discov_req req; | |
| 957 | + | |
| 958 | + BT_DBG("chan %p conn %p mgr %p", chan, conn, mgr); | |
| 959 | + | |
| 960 | + if (!mgr) { | |
| 961 | + mgr = amp_mgr_create(conn, true); | |
| 962 | + if (!mgr) | |
| 963 | + return; | |
| 964 | + } | |
| 965 | + | |
| 966 | + mgr->bredr_chan = chan; | |
| 967 | + | |
| 968 | + req.mtu = cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU); | |
| 969 | + req.ext_feat = 0; | |
| 970 | + a2mp_send(mgr, A2MP_DISCOVER_REQ, 1, sizeof(req), &req); | |
| 971 | +} | |
| @@ -569,7 +569,6 @@ static int bt_seq_show(struct seq_file *seq, void *v) · 568 unmodified lines | ||
| 569 | 569 | { |
| 570 | 570 | struct bt_seq_state *s = seq->private; |
| 571 | 571 | struct bt_sock_list *l = s->l; |
| 572 | − bdaddr_t src_baswapped, dst_baswapped; | |
| 573 | 572 | |
| 574 | 573 | if (v == SEQ_START_TOKEN) { |
| 575 | 574 | seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent"); |
| @@ -583,18 +582,17 @@ static int bt_seq_show(struct seq_file *seq, void *v) · 7 unmodified lines | ||
| 583 | 582 | } else { |
| 584 | 583 | struct sock *sk = sk_entry(v); |
| 585 | 584 | struct bt_sock *bt = bt_sk(sk); |
| 586 | − baswap(&src_baswapped, &bt->src); | |
| 587 | − baswap(&dst_baswapped, &bt->dst); | |
| 588 | 585 | |
| 589 | − seq_printf(seq, "%pK %-6d %-6u %-6u %-6u %-6lu %pM %pM %-6lu", | |
| 586 | + seq_printf(seq, | |
| 587 | + "%pK %-6d %-6u %-6u %-6u %-6lu %pMR %pMR %-6lu", | |
| 590 | 588 | sk, |
| 591 | 589 | atomic_read(&sk->sk_refcnt), |
| 592 | 590 | sk_rmem_alloc_get(sk), |
| 593 | 591 | sk_wmem_alloc_get(sk), |
| 594 | 592 | from_kuid(seq_user_ns(seq), sock_i_uid(sk)), |
| 595 | 593 | sock_i_ino(sk), |
| 596 | − &src_baswapped, | |
| 597 | − &dst_baswapped, | |
| 594 | + &bt->src, | |
| 595 | + &bt->dst, | |
| 598 | 596 | bt->parent? sock_i_ino(bt->parent): 0LU); |
| 599 | 597 | |
| 600 | 598 | if (l->custom_seq_show) { |
| @@ -0,0 +1,374 @@ | ||
| 1 | +/* | |
| 2 | + Copyright (c) 2011,2012 Intel Corp. | |
| 3 | + | |
| 4 | + This program is free software; you can redistribute it and/or modify | |
| 5 | + it under the terms of the GNU General Public License version 2 and | |
| 6 | + only version 2 as published by the Free Software Foundation. | |
| 7 | + | |
| 8 | + This program is distributed in the hope that it will be useful, | |
| 9 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 10 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 11 | + GNU General Public License for more details. | |
| 12 | +*/ | |
| 13 | + | |
| 14 | +#include <net/bluetooth/bluetooth.h> | |
| 15 | +#include <net/bluetooth/hci.h> | |
| 16 | +#include <net/bluetooth/hci_core.h> | |
| 17 | +#include <net/bluetooth/a2mp.h> | |
| 18 | +#include <net/bluetooth/amp.h> | |
| 19 | +#include <crypto/hash.h> | |
| 20 | + | |
| 21 | +/* Remote AMP Controllers interface */ | |
| 22 | +void amp_ctrl_get(struct amp_ctrl *ctrl) | |
| 23 | +{ | |
| 24 | + BT_DBG("ctrl %p orig refcnt %d", ctrl, | |
| 25 | + atomic_read(&ctrl->kref.refcount)); | |
| 26 | + | |
| 27 | + kref_get(&ctrl->kref); | |
| 28 | +} | |
| 29 | + | |
| 30 | +static void amp_ctrl_destroy(struct kref *kref) | |
| 31 | +{ | |
| 32 | + struct amp_ctrl *ctrl = container_of(kref, struct amp_ctrl, kref); | |
| 33 | + | |
| 34 | + BT_DBG("ctrl %p", ctrl); | |
| 35 | + | |
| 36 | + kfree(ctrl->assoc); | |
| 37 | + kfree(ctrl); | |
| 38 | +} | |
| 39 | + | |
| 40 | +int amp_ctrl_put(struct amp_ctrl *ctrl) | |
| 41 | +{ | |
| 42 | + BT_DBG("ctrl %p orig refcnt %d", ctrl, | |
| 43 | + atomic_read(&ctrl->kref.refcount)); | |
| 44 | + | |
| 45 | + return kref_put(&ctrl->kref, &_ctrl_destroy); | |
| 46 | +} | |
| 47 | + | |
| 48 | +struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id) | |
| 49 | +{ | |
| 50 | + struct amp_ctrl *ctrl; | |
| 51 | + | |
| 52 | + ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); | |
| 53 | + if (!ctrl) | |
| 54 | + return NULL; | |
| 55 | + | |
| 56 | + kref_init(&ctrl->kref); | |
| 57 | + ctrl->id = id; | |
| 58 | + | |
| 59 | + mutex_lock(&mgr->amp_ctrls_lock); | |
| 60 | + list_add(&ctrl->list, &mgr->amp_ctrls); | |
| 61 | + mutex_unlock(&mgr->amp_ctrls_lock); | |
| 62 | + | |
| 63 | + BT_DBG("mgr %p ctrl %p", mgr, ctrl); | |
| 64 | + | |
| 65 | + return ctrl; | |
| 66 | +} | |
| 67 | + | |
| 68 | +void amp_ctrl_list_flush(struct amp_mgr *mgr) | |
| 69 | +{ | |
| 70 | + struct amp_ctrl *ctrl, *n; | |
| 71 | + | |
| 72 | + BT_DBG("mgr %p", mgr); | |
| 73 | + | |
| 74 | + mutex_lock(&mgr->amp_ctrls_lock); | |
| 75 | + list_for_each_entry_safe(ctrl, n, &mgr->amp_ctrls, list) { | |
| 76 | + list_del(&ctrl->list); | |
| 77 | + amp_ctrl_put(ctrl); | |
| 78 | + } | |
| 79 | + mutex_unlock(&mgr->amp_ctrls_lock); | |
| 80 | +} | |
| 81 | + | |
| 82 | +struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id) | |
| 83 | +{ | |
| 84 | + struct amp_ctrl *ctrl; | |
| 85 | + | |
| 86 | + BT_DBG("mgr %p id %d", mgr, id); | |
| 87 | + | |
| 88 | + mutex_lock(&mgr->amp_ctrls_lock); | |
| 89 | + list_for_each_entry(ctrl, &mgr->amp_ctrls, list) { | |
| 90 | + if (ctrl->id == id) { | |
| 91 | + amp_ctrl_get(ctrl); | |
| 92 | + mutex_unlock(&mgr->amp_ctrls_lock); | |
| 93 | + return ctrl; | |
| 94 | + } | |
| 95 | + } | |
| 96 | + mutex_unlock(&mgr->amp_ctrls_lock); | |
| 97 | + | |
| 98 | + return NULL; | |
| 99 | +} | |
| 100 | + | |
| 101 | +/* Physical Link interface */ | |
| 102 | +static u8 __next_handle(struct amp_mgr *mgr) | |
| 103 | +{ | |
| 104 | + if (++mgr->handle == 0) | |
| 105 | + mgr->handle = 1; | |
| 106 | + | |
| 107 | + return mgr->handle; | |
| 108 | +} | |
| 109 | + | |
| 110 | +struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, | |
| 111 | + u8 remote_id, bool out) | |
| 112 | +{ | |
| 113 | + bdaddr_t *dst = mgr->l2cap_conn->dst; | |
| 114 | + struct hci_conn *hcon; | |
| 115 | + | |
| 116 | + hcon = hci_conn_add(hdev, AMP_LINK, dst); | |
| 117 | + if (!hcon) | |
| 118 | + return NULL; | |
| 119 | + | |
| 120 | + BT_DBG("hcon %p dst %pMR", hcon, dst); | |
| 121 | + | |
| 122 | + hcon->state = BT_CONNECT; | |
| 123 | + hcon->attempt++; | |
| 124 | + hcon->handle = __next_handle(mgr); | |
| 125 | + hcon->remote_id = remote_id; | |
| 126 | + hcon->amp_mgr = amp_mgr_get(mgr); | |
| 127 | + hcon->out = out; | |
| 128 | + | |
| 129 | + return hcon; | |
| 130 | +} | |
| 131 | + | |
| 132 | +/* AMP crypto key generation interface */ | |
| 133 | +static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output) | |
| 134 | +{ | |
| 135 | + int ret = 0; | |
| 136 | + struct crypto_shash *tfm; | |
| 137 | + | |
| 138 | + if (!ksize) | |
| 139 | + return -EINVAL; | |
| 140 | + | |
| 141 | + tfm = crypto_alloc_shash("hmac(sha256)", 0, 0); | |
| 142 | + if (IS_ERR(tfm)) { | |
| 143 | + BT_DBG("crypto_alloc_ahash failed: err %ld", PTR_ERR(tfm)); | |
| 144 | + return PTR_ERR(tfm); | |
| 145 | + } | |
| 146 | + | |
| 147 | + ret = crypto_shash_setkey(tfm, key, ksize); | |
| 148 | + if (ret) { | |
| 149 | + BT_DBG("crypto_ahash_setkey failed: err %d", ret); | |
| 150 | + } else { | |
| 151 | + struct { | |
| 152 | + struct shash_desc shash; | |
| 153 | + char ctx[crypto_shash_descsize(tfm)]; | |
| 154 | + } desc; | |
| 155 | + | |
| 156 | + desc.shash.tfm = tfm; | |
| 157 | + desc.shash.flags = CRYPTO_TFM_REQ_MAY_SLEEP; | |
| 158 | + | |
| 159 | + ret = crypto_shash_digest(&desc.shash, plaintext, psize, | |
| 160 | + output); | |
| 161 | + } | |
| 162 | + | |
| 163 | + crypto_free_shash(tfm); | |
| 164 | + return ret; | |
| 165 | +} | |
| 166 | + | |
| 167 | +int phylink_gen_key(struct hci_conn *conn, u8 *data, u8 *len, u8 *type) | |
| 168 | +{ | |
| 169 | + struct hci_dev *hdev = conn->hdev; | |
| 170 | + struct link_key *key; | |
| 171 | + u8 keybuf[HCI_AMP_LINK_KEY_SIZE]; | |
| 172 | + u8 gamp_key[HCI_AMP_LINK_KEY_SIZE]; | |
| 173 | + int err; | |
| 174 | + | |
| 175 | + if (!hci_conn_check_link_mode(conn)) | |
| 176 | + return -EACCES; | |
| 177 | + | |
| 178 | + BT_DBG("conn %p key_type %d", conn, conn->key_type); | |
| 179 | + | |
| 180 | + /* Legacy key */ | |
| 181 | + if (conn->key_type < 3) { | |
| 182 | + BT_ERR("Legacy key type %d", conn->key_type); | |
| 183 | + return -EACCES; | |
| 184 | + } | |
| 185 | + | |
| 186 | + *type = conn->key_type; | |
| 187 | + *len = HCI_AMP_LINK_KEY_SIZE; | |
| 188 | + | |
| 189 | + key = hci_find_link_key(hdev, &conn->dst); | |
| 190 | + if (!key) { | |
| 191 | + BT_DBG("No Link key for conn %p dst %pMR", conn, &conn->dst); | |
| 192 | + return -EACCES; | |
| 193 | + } | |
| 194 | + | |
| 195 | + /* BR/EDR Link Key concatenated together with itself */ | |
| 196 | + memcpy(&keybuf[0], key->val, HCI_LINK_KEY_SIZE); | |
| 197 | + memcpy(&keybuf[HCI_LINK_KEY_SIZE], key->val, HCI_LINK_KEY_SIZE); | |
| 198 | + | |
| 199 | + /* Derive Generic AMP Link Key (gamp) */ | |
| 200 | + err = hmac_sha256(keybuf, HCI_AMP_LINK_KEY_SIZE, "gamp", 4, gamp_key); | |
| 201 | + if (err) { | |
| 202 | + BT_ERR("Could not derive Generic AMP Key: err %d", err); | |
| 203 | + return err; | |
| 204 | + } | |
| 205 | + | |
| 206 | + if (conn->key_type == HCI_LK_DEBUG_COMBINATION) { | |
| 207 | + BT_DBG("Use Generic AMP Key (gamp)"); | |
| 208 | + memcpy(data, gamp_key, HCI_AMP_LINK_KEY_SIZE); | |
| 209 | + return err; | |
| 210 | + } | |
| 211 | + | |
| 212 | + /* Derive Dedicated AMP Link Key: "802b" is 802.11 PAL keyID */ | |
| 213 | + return hmac_sha256(gamp_key, HCI_AMP_LINK_KEY_SIZE, "802b", 4, data); | |
| 214 | +} | |
| 215 | + | |
| 216 | +void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle) | |
| 217 | +{ | |
| 218 | + struct hci_cp_read_local_amp_assoc cp; | |
| 219 | + struct amp_assoc *loc_assoc = &hdev->loc_assoc; | |
| 220 | + | |
| 221 | + BT_DBG("%s handle %d", hdev->name, phy_handle); | |
| 222 | + | |
| 223 | + cp.phy_handle = phy_handle; | |
| 224 | + cp.max_len = cpu_to_le16(hdev->amp_assoc_size); | |
| 225 | + cp.len_so_far = cpu_to_le16(loc_assoc->offset); | |
| 226 | + | |
| 227 | + hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp); | |
| 228 | +} | |
| 229 | + | |
| 230 | +void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr) | |
| 231 | +{ | |
| 232 | + struct hci_cp_read_local_amp_assoc cp; | |
| 233 | + | |
| 234 | + memset(&hdev->loc_assoc, 0, sizeof(struct amp_assoc)); | |
| 235 | + memset(&cp, 0, sizeof(cp)); | |
| 236 | + | |
| 237 | + cp.max_len = cpu_to_le16(hdev->amp_assoc_size); | |
| 238 | + | |
| 239 | + mgr->state = READ_LOC_AMP_ASSOC; | |
| 240 | + hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp); | |
| 241 | +} | |
| 242 | + | |
| 243 | +void amp_read_loc_assoc_final_data(struct hci_dev *hdev, | |
| 244 | + struct hci_conn *hcon) | |
| 245 | +{ | |
| 246 | + struct hci_cp_read_local_amp_assoc cp; | |
| 247 | + struct amp_mgr *mgr = hcon->amp_mgr; | |
| 248 | + | |
| 249 | + cp.phy_handle = hcon->handle; | |
| 250 | + cp.len_so_far = cpu_to_le16(0); | |
| 251 | + cp.max_len = cpu_to_le16(hdev->amp_assoc_size); | |
| 252 | + | |
| 253 | + mgr->state = READ_LOC_AMP_ASSOC_FINAL; | |
| 254 | + | |
| 255 | + /* Read Local AMP Assoc final link information data */ | |
| 256 | + hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp); | |
| 257 | +} | |
| 258 | + | |
| 259 | +/* Write AMP Assoc data fragments, returns true with last fragment written*/ | |
| 260 | +static bool amp_write_rem_assoc_frag(struct hci_dev *hdev, | |
| 261 | + struct hci_conn *hcon) | |
| 262 | +{ | |
| 263 | + struct hci_cp_write_remote_amp_assoc *cp; | |
| 264 | + struct amp_mgr *mgr = hcon->amp_mgr; | |
| 265 | + struct amp_ctrl *ctrl; | |
| 266 | + u16 frag_len, len; | |
| 267 | + | |
| 268 | + ctrl = amp_ctrl_lookup(mgr, hcon->remote_id); | |
| 269 | + if (!ctrl) | |
| 270 | + return false; | |
| 271 | + | |
| 272 | + if (!ctrl->assoc_rem_len) { | |
| 273 | + BT_DBG("all fragments are written"); | |
| 274 | + ctrl->assoc_rem_len = ctrl->assoc_len; | |
| 275 | + ctrl->assoc_len_so_far = 0; | |
| 276 | + | |
| 277 | + amp_ctrl_put(ctrl); | |
| 278 | + return true; | |
| 279 | + } | |
| 280 | + | |
| 281 | + frag_len = min_t(u16, 248, ctrl->assoc_rem_len); | |
| 282 | + len = frag_len + sizeof(*cp); | |
| 283 | + | |
| 284 | + cp = kzalloc(len, GFP_KERNEL); | |
| 285 | + if (!cp) { | |
| 286 | + amp_ctrl_put(ctrl); | |
| 287 | + return false; | |
| 288 | + } | |
| 289 | + | |
| 290 | + BT_DBG("hcon %p ctrl %p frag_len %u assoc_len %u rem_len %u", | |
| 291 | + hcon, ctrl, frag_len, ctrl->assoc_len, ctrl->assoc_rem_len); | |
| 292 | + | |
| 293 | + cp->phy_handle = hcon->handle; | |
| 294 | + cp->len_so_far = cpu_to_le16(ctrl->assoc_len_so_far); | |
| 295 | + cp->rem_len = cpu_to_le16(ctrl->assoc_rem_len); | |
| 296 | + memcpy(cp->frag, ctrl->assoc, frag_len); | |
| 297 | + | |
| 298 | + ctrl->assoc_len_so_far += frag_len; | |
| 299 | + ctrl->assoc_rem_len -= frag_len; | |
| 300 | + | |
| 301 | + amp_ctrl_put(ctrl); | |
| 302 | + | |
| 303 | + hci_send_cmd(hdev, HCI_OP_WRITE_REMOTE_AMP_ASSOC, len, cp); | |
| 304 | + | |
| 305 | + kfree(cp); | |
| 306 | + | |
| 307 | + return false; | |
| 308 | +} | |
| 309 | + | |
| 310 | +void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle) | |
| 311 | +{ | |
| 312 | + struct hci_conn *hcon; | |
| 313 | + | |
| 314 | + BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle); | |
| 315 | + | |
| 316 | + hcon = hci_conn_hash_lookup_handle(hdev, handle); | |
| 317 | + if (!hcon) | |
| 318 | + return; | |
| 319 | + | |
| 320 | + amp_write_rem_assoc_frag(hdev, hcon); | |
| 321 | +} | |
| 322 | + | |
| 323 | +void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle) | |
| 324 | +{ | |
| 325 | + struct hci_conn *hcon; | |
| 326 | + | |
| 327 | + BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle); | |
| 328 | + | |
| 329 | + hcon = hci_conn_hash_lookup_handle(hdev, handle); | |
| 330 | + if (!hcon) | |
| 331 | + return; | |
| 332 | + | |
| 333 | + BT_DBG("%s phy handle 0x%2.2x hcon %p", hdev->name, handle, hcon); | |
| 334 | + | |
| 335 | + amp_write_rem_assoc_frag(hdev, hcon); | |
| 336 | +} | |
| 337 | + | |
| 338 | +void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, | |
| 339 | + struct hci_conn *hcon) | |
| 340 | +{ | |
| 341 | + struct hci_cp_create_phy_link cp; | |
| 342 | + | |
| 343 | + cp.phy_handle = hcon->handle; | |
| 344 | + | |
| 345 | + BT_DBG("%s hcon %p phy handle 0x%2.2x", hdev->name, hcon, | |
| 346 | + hcon->handle); | |
| 347 | + | |
| 348 | + if (phylink_gen_key(mgr->l2cap_conn->hcon, cp.key, &cp.key_len, | |
| 349 | + &cp.key_type)) { | |
| 350 | + BT_DBG("Cannot create link key"); | |
| 351 | + return; | |
| 352 | + } | |
| 353 | + | |
| 354 | + hci_send_cmd(hdev, HCI_OP_CREATE_PHY_LINK, sizeof(cp), &cp); | |
| 355 | +} | |
| 356 | + | |
| 357 | +void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, | |
| 358 | + struct hci_conn *hcon) | |
| 359 | +{ | |
| 360 | + struct hci_cp_accept_phy_link cp; | |
| 361 | + | |
| 362 | + cp.phy_handle = hcon->handle; | |
| 363 | + | |
| 364 | + BT_DBG("%s hcon %p phy handle 0x%2.2x", hdev->name, hcon, | |
| 365 | + hcon->handle); | |
| 366 | + | |
| 367 | + if (phylink_gen_key(mgr->l2cap_conn->hcon, cp.key, &cp.key_len, | |
| 368 | + &cp.key_type)) { | |
| 369 | + BT_DBG("Cannot create link key"); | |
| 370 | + return; | |
| 371 | + } | |
| 372 | + | |
| 373 | + hci_send_cmd(hdev, HCI_OP_ACCEPT_PHY_LINK, sizeof(cp), &cp); | |
| 374 | +} | |
| @@ -182,8 +182,7 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len) · 181 unmodified lines | ||
| 182 | 182 | a2 = data; |
| 183 | 183 | data += ETH_ALEN; |
| 184 | 184 | |
| 185 | − BT_DBG("mc filter %s -> %s", | |
| 186 | − batostr((void *) a1), batostr((void *) a2)); | |
| 185 | + BT_DBG("mc filter %pMR -> %pMR", a1, a2); | |
| 187 | 186 | |
| 188 | 187 | /* Iterate from a1 to a2 */ |
| 189 | 188 | set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter); |
| @@ -353,7 +353,7 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) · 352 unmodified lines | ||
| 353 | 353 | |
| 354 | 354 | BT_DBG("mtu %d", session->mtu); |
| 355 | 355 | |
| 356 | − sprintf(session->name, "%s", batostr(&bt_sk(sock->sk)->dst)); | |
| 356 | + sprintf(session->name, "%pMR", &bt_sk(sock->sk)->dst); | |
| 357 | 357 | |
| 358 | 358 | session->sock = sock; |
| 359 | 359 | session->state = BT_CONFIG; |
| @@ -130,6 +130,20 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason) · 129 unmodified lines | ||
| 130 | 130 | hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp); |
| 131 | 131 | } |
| 132 | 132 | |
| 133 | +static void hci_amp_disconn(struct hci_conn *conn, __u8 reason) | |
| 134 | +{ | |
| 135 | + struct hci_cp_disconn_phy_link cp; | |
| 136 | + | |
| 137 | + BT_DBG("hcon %p", conn); | |
| 138 | + | |
| 139 | + conn->state = BT_DISCONN; | |
| 140 | + | |
| 141 | + cp.phy_handle = HCI_PHY_HANDLE(conn->handle); | |
| 142 | + cp.reason = reason; | |
| 143 | + hci_send_cmd(conn->hdev, HCI_OP_DISCONN_PHY_LINK, | |
| 144 | + sizeof(cp), &cp); | |
| 145 | +} | |
| 146 | + | |
| 133 | 147 | static void hci_add_sco(struct hci_conn *conn, __u16 handle) |
| 134 | 148 | { |
| 135 | 149 | struct hci_dev *hdev = conn->hdev; |
| @@ -230,11 +244,24 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status) · 94 unmodified lines | ||
| 230 | 244 | } |
| 231 | 245 | } |
| 232 | 246 | |
| 247 | +static void hci_conn_disconnect(struct hci_conn *conn) | |
| 248 | +{ | |
| 249 | + __u8 reason = hci_proto_disconn_ind(conn); | |
| 250 | + | |
| 251 | + switch (conn->type) { | |
| 252 | + case ACL_LINK: | |
| 253 | + hci_acl_disconn(conn, reason); | |
| 254 | + break; | |
| 255 | + case AMP_LINK: | |
| 256 | + hci_amp_disconn(conn, reason); | |
| 257 | + break; | |
| 258 | + } | |
| 259 | +} | |
| 260 | + | |
| 233 | 261 | static void hci_conn_timeout(struct work_struct *work) |
| 234 | 262 | { |
| 235 | 263 | struct hci_conn *conn = container_of(work, struct hci_conn, |
| 236 | 264 | disc_work.work); |
| 237 | − __u8 reason; | |
| 238 | 265 | |
| 239 | 266 | BT_DBG("hcon %p state %s", conn, state_to_string(conn->state)); |
| 240 | 267 | |
| @@ -253,8 +280,7 @@ static void hci_conn_timeout(struct work_struct *work) · 12 unmodified lines | ||
| 253 | 280 | break; |
| 254 | 281 | case BT_CONFIG: |
| 255 | 282 | case BT_CONNECTED: |
| 256 | − reason = hci_proto_disconn_ind(conn); | |
| 257 | − hci_acl_disconn(conn, reason); | |
| 283 | + hci_conn_disconnect(conn); | |
| 258 | 284 | break; |
| 259 | 285 | default: |
| 260 | 286 | conn->state = BT_CLOSED; |
| @@ -320,7 +346,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) · 59 unmodified lines | ||
| 320 | 346 | { |
| 321 | 347 | struct hci_conn *conn; |
| 322 | 348 | |
| 323 | − BT_DBG("%s dst %s", hdev->name, batostr(dst)); | |
| 349 | + BT_DBG("%s dst %pMR", hdev->name, dst); | |
| 324 | 350 | |
| 325 | 351 | conn = kzalloc(sizeof(struct hci_conn), GFP_KERNEL); |
| 326 | 352 | if (!conn) |
| @@ -437,7 +463,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) · 110 unmodified lines | ||
| 437 | 463 | int use_src = bacmp(src, BDADDR_ANY); |
| 438 | 464 | struct hci_dev *hdev = NULL, *d; |
| 439 | 465 | |
| 440 | − BT_DBG("%s -> %s", batostr(src), batostr(dst)); | |
| 466 | + BT_DBG("%pMR -> %pMR", src, dst); | |
| 441 | 467 | |
| 442 | 468 | read_lock(&hci_dev_list_lock); |
| 443 | 469 | |
| @@ -567,7 +593,7 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, · 123 unmodified lines | ||
| 567 | 593 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, |
| 568 | 594 | __u8 dst_type, __u8 sec_level, __u8 auth_type) |
| 569 | 595 | { |
| 570 | − BT_DBG("%s dst %s type 0x%x", hdev->name, batostr(dst), type); | |
| 596 | + BT_DBG("%s dst %pMR type 0x%x", hdev->name, dst, type); | |
| 571 | 597 | |
| 572 | 598 | switch (type) { |
| 573 | 599 | case LE_LINK: |
| @@ -963,3 +989,35 @@ void hci_chan_list_flush(struct hci_conn *conn) · 389 unmodified lines | ||
| 963 | 989 | list_for_each_entry_safe(chan, n, &conn->chan_list, list) |
| 964 | 990 | hci_chan_del(chan); |
| 965 | 991 | } |
| 992 | + | |
| 993 | +static struct hci_chan *__hci_chan_lookup_handle(struct hci_conn *hcon, | |
| 994 | + __u16 handle) | |
| 995 | +{ | |
| 996 | + struct hci_chan *hchan; | |
| 997 | + | |
| 998 | + list_for_each_entry(hchan, &hcon->chan_list, list) { | |
| 999 | + if (hchan->handle == handle) | |
| 1000 | + return hchan; | |
| 1001 | + } | |
| 1002 | + | |
| 1003 | + return NULL; | |
| 1004 | +} | |
| 1005 | + | |
| 1006 | +struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle) | |
| 1007 | +{ | |
| 1008 | + struct hci_conn_hash *h = &hdev->conn_hash; | |
| 1009 | + struct hci_conn *hcon; | |
| 1010 | + struct hci_chan *hchan = NULL; | |
| 1011 | + | |
| 1012 | + rcu_read_lock(); | |
| 1013 | + | |
| 1014 | + list_for_each_entry_rcu(hcon, &h->list, list) { | |
| 1015 | + hchan = __hci_chan_lookup_handle(hcon, handle); | |
| 1016 | + if (hchan) | |
| 1017 | + break; | |
| 1018 | + } | |
| 1019 | + | |
| 1020 | + rcu_read_unlock(); | |
| 1021 | + | |
| 1022 | + return hchan; | |
| 1023 | +} | |
| @@ -405,7 +405,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, · 404 unmodified lines | ||
| 405 | 405 | struct discovery_state *cache = &hdev->discovery; |
| 406 | 406 | struct inquiry_entry *e; |
| 407 | 407 | |
| 408 | − BT_DBG("cache %p, %s", cache, batostr(bdaddr)); | |
| 408 | + BT_DBG("cache %p, %pMR", cache, bdaddr); | |
| 409 | 409 | |
| 410 | 410 | list_for_each_entry(e, &cache->all, all) { |
| 411 | 411 | if (!bacmp(&e->data.bdaddr, bdaddr)) |
| @@ -421,7 +421,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup_unknown(struct hci_dev *hdev, · 9 unmodified lines | ||
| 421 | 421 | struct discovery_state *cache = &hdev->discovery; |
| 422 | 422 | struct inquiry_entry *e; |
| 423 | 423 | |
| 424 | − BT_DBG("cache %p, %s", cache, batostr(bdaddr)); | |
| 424 | + BT_DBG("cache %p, %pMR", cache, bdaddr); | |
| 425 | 425 | |
| 426 | 426 | list_for_each_entry(e, &cache->unknown, list) { |
| 427 | 427 | if (!bacmp(&e->data.bdaddr, bdaddr)) |
| @@ -438,7 +438,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup_resolve(struct hci_dev *hdev, · 10 unmodified lines | ||
| 438 | 438 | struct discovery_state *cache = &hdev->discovery; |
| 439 | 439 | struct inquiry_entry *e; |
| 440 | 440 | |
| 441 | − BT_DBG("cache %p bdaddr %s state %d", cache, batostr(bdaddr), state); | |
| 441 | + BT_DBG("cache %p bdaddr %pMR state %d", cache, bdaddr, state); | |
| 442 | 442 | |
| 443 | 443 | list_for_each_entry(e, &cache->resolve, list) { |
| 444 | 444 | if (!bacmp(bdaddr, BDADDR_ANY) && e->name_state == state) |
| @@ -475,7 +475,7 @@ bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, · 30 unmodified lines | ||
| 475 | 475 | struct discovery_state *cache = &hdev->discovery; |
| 476 | 476 | struct inquiry_entry *ie; |
| 477 | 477 | |
| 478 | − BT_DBG("cache %p, %s", cache, batostr(&data->bdaddr)); | |
| 478 | + BT_DBG("cache %p, %pMR", cache, &data->bdaddr); | |
| 479 | 479 | |
| 480 | 480 | if (ssp) |
| 481 | 481 | *ssp = data->ssp_mode; |
| @@ -1259,7 +1259,7 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, · 777 unmodified lines | ||
| 1259 | 1259 | list_add(&key->list, &hdev->link_keys); |
| 1260 | 1260 | } |
| 1261 | 1261 | |
| 1262 | − BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type); | |
| 1262 | + BT_DBG("%s key for %pMR type %u", hdev->name, bdaddr, type); | |
| 1263 | 1263 | |
| 1264 | 1264 | /* Some buggy controller combinations generate a changed |
| 1265 | 1265 | * combination key for legacy pairing even when there's no |
| @@ -1338,7 +1338,7 @@ int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr) · 72 unmodified lines | ||
| 1338 | 1338 | if (!key) |
| 1339 | 1339 | return -ENOENT; |
| 1340 | 1340 | |
| 1341 | − BT_DBG("%s removing %s", hdev->name, batostr(bdaddr)); | |
| 1341 | + BT_DBG("%s removing %pMR", hdev->name, bdaddr); | |
| 1342 | 1342 | |
| 1343 | 1343 | list_del(&key->list); |
| 1344 | 1344 | kfree(key); |
| @@ -1354,7 +1354,7 @@ int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr) · 9 unmodified lines | ||
| 1354 | 1354 | if (bacmp(bdaddr, &k->bdaddr)) |
| 1355 | 1355 | continue; |
| 1356 | 1356 | |
| 1357 | − BT_DBG("%s removing %s", hdev->name, batostr(bdaddr)); | |
| 1357 | + BT_DBG("%s removing %pMR", hdev->name, bdaddr); | |
| 1358 | 1358 | |
| 1359 | 1359 | list_del(&k->list); |
| 1360 | 1360 | kfree(k); |
| @@ -1401,7 +1401,7 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr) · 40 unmodified lines | ||
| 1401 | 1401 | if (!data) |
| 1402 | 1402 | return -ENOENT; |
| 1403 | 1403 | |
| 1404 | − BT_DBG("%s removing %s", hdev->name, batostr(bdaddr)); | |
| 1404 | + BT_DBG("%s removing %pMR", hdev->name, bdaddr); | |
| 1405 | 1405 | |
| 1406 | 1406 | list_del(&data->list); |
| 1407 | 1407 | kfree(data); |
| @@ -1440,7 +1440,7 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, · 32 unmodified lines | ||
| 1440 | 1440 | memcpy(data->hash, hash, sizeof(data->hash)); |
| 1441 | 1441 | memcpy(data->randomizer, randomizer, sizeof(data->randomizer)); |
| 1442 | 1442 | |
| 1443 | − BT_DBG("%s for %s", hdev->name, batostr(bdaddr)); | |
| 1443 | + BT_DBG("%s for %pMR", hdev->name, bdaddr); | |
| 1444 | 1444 | |
| 1445 | 1445 | return 0; |
| 1446 | 1446 | } |
| @@ -2153,9 +2153,10 @@ static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags) · 706 unmodified lines | ||
| 2153 | 2153 | hdr->dlen = cpu_to_le16(len); |
| 2154 | 2154 | } |
| 2155 | 2155 | |
| 2156 | −static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue, | |
| 2156 | +static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue, | |
| 2157 | 2157 | struct sk_buff *skb, __u16 flags) |
| 2158 | 2158 | { |
| 2159 | + struct hci_conn *conn = chan->conn; | |
| 2159 | 2160 | struct hci_dev *hdev = conn->hdev; |
| 2160 | 2161 | struct sk_buff *list; |
| 2161 | 2162 | |
| @@ -2163,7 +2164,18 @@ static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue, · 1 unmodified line | ||
| 2163 | 2164 | skb->data_len = 0; |
| 2164 | 2165 | |
| 2165 | 2166 | bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; |
| 2166 | − hci_add_acl_hdr(skb, conn->handle, flags); | |
| 2167 | + | |
| 2168 | + switch (hdev->dev_type) { | |
| 2169 | + case HCI_BREDR: | |
| 2170 | + hci_add_acl_hdr(skb, conn->handle, flags); | |
| 2171 | + break; | |
| 2172 | + case HCI_AMP: | |
| 2173 | + hci_add_acl_hdr(skb, chan->handle, flags); | |
| 2174 | + break; | |
| 2175 | + default: | |
| 2176 | + BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type); | |
| 2177 | + return; | |
| 2178 | + } | |
| 2167 | 2179 | |
| 2168 | 2180 | list = skb_shinfo(skb)->frag_list; |
| 2169 | 2181 | if (!list) { |
| @@ -2202,14 +2214,13 @@ static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue, · 32 unmodified lines | ||
| 2202 | 2214 | |
| 2203 | 2215 | void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags) |
| 2204 | 2216 | { |
| 2205 | − struct hci_conn *conn = chan->conn; | |
| 2206 | − struct hci_dev *hdev = conn->hdev; | |
| 2217 | + struct hci_dev *hdev = chan->conn->hdev; | |
| 2207 | 2218 | |
| 2208 | 2219 | BT_DBG("%s chan %p flags 0x%4.4x", hdev->name, chan, flags); |
| 2209 | 2220 | |
| 2210 | 2221 | skb->dev = (void *) hdev; |
| 2211 | 2222 | |
| 2212 | − hci_queue_acl(conn, &chan->data_q, skb, flags); | |
| 2223 | + hci_queue_acl(chan, &chan->data_q, skb, flags); | |
| 2213 | 2224 | |
| 2214 | 2225 | queue_work(hdev->workqueue, &hdev->tx_work); |
| 2215 | 2226 | } |
| @@ -2311,8 +2322,8 @@ static void hci_link_tx_to(struct hci_dev *hdev, __u8 type) · 95 unmodified lines | ||
| 2311 | 2322 | /* Kill stalled connections */ |
| 2312 | 2323 | list_for_each_entry_rcu(c, &h->list, list) { |
| 2313 | 2324 | if (c->type == type && c->sent) { |
| 2314 | − BT_ERR("%s killing stalled connection %s", | |
| 2315 | − hdev->name, batostr(&c->dst)); | |
| 2325 | + BT_ERR("%s killing stalled connection %pMR", | |
| 2326 | + hdev->name, &c->dst); | |
| 2316 | 2327 | hci_acl_disconn(c, HCI_ERROR_REMOTE_USER_TERM); |
| 2317 | 2328 | } |
| 2318 | 2329 | } |
| @@ -2381,6 +2392,9 @@ static struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type, · 62 unmodified lines | ||
| 2381 | 2392 | case ACL_LINK: |
| 2382 | 2393 | cnt = hdev->acl_cnt; |
| 2383 | 2394 | break; |
| 2395 | + case AMP_LINK: | |
| 2396 | + cnt = hdev->block_cnt; | |
| 2397 | + break; | |
| 2384 | 2398 | case SCO_LINK: |
| 2385 | 2399 | case ESCO_LINK: |
| 2386 | 2400 | cnt = hdev->sco_cnt; |
| @@ -2510,11 +2524,19 @@ static void hci_sched_acl_blk(struct hci_dev *hdev) · 123 unmodified lines | ||
| 2510 | 2524 | struct hci_chan *chan; |
| 2511 | 2525 | struct sk_buff *skb; |
| 2512 | 2526 | int quote; |
| 2527 | + u8 type; | |
| 2513 | 2528 | |
| 2514 | 2529 | __check_timeout(hdev, cnt); |
| 2515 | 2530 | |
| 2531 | + BT_DBG("%s", hdev->name); | |
| 2532 | + | |
| 2533 | + if (hdev->dev_type == HCI_AMP) | |
| 2534 | + type = AMP_LINK; | |
| 2535 | + else | |
| 2536 | + type = ACL_LINK; | |
| 2537 | + | |
| 2516 | 2538 | while (hdev->block_cnt > 0 && |
| 2517 | − (chan = hci_chan_sent(hdev, ACL_LINK, "e))) { | |
| 2539 | + (chan = hci_chan_sent(hdev, type, "e))) { | |
| 2518 | 2540 | u32 priority = (skb_peek(&chan->data_q))->priority; |
| 2519 | 2541 | while (quote > 0 && (skb = skb_peek(&chan->data_q))) { |
| 2520 | 2542 | int blocks; |
| @@ -2547,14 +2569,19 @@ static void hci_sched_acl_blk(struct hci_dev *hdev) · 26 unmodified lines | ||
| 2547 | 2569 | } |
| 2548 | 2570 | |
| 2549 | 2571 | if (cnt != hdev->block_cnt) |
| 2550 | − hci_prio_recalculate(hdev, ACL_LINK); | |
| 2572 | + hci_prio_recalculate(hdev, type); | |
| 2551 | 2573 | } |
| 2552 | 2574 | |
| 2553 | 2575 | static void hci_sched_acl(struct hci_dev *hdev) |
| 2554 | 2576 | { |
| 2555 | 2577 | BT_DBG("%s", hdev->name); |
| 2556 | 2578 | |
| 2557 | − if (!hci_conn_num(hdev, ACL_LINK)) | |
| 2579 | + /* No ACL link over BR/EDR controller */ | |
| 2580 | + if (!hci_conn_num(hdev, ACL_LINK) && hdev->dev_type == HCI_BREDR) | |
| 2581 | + return; | |
| 2582 | + | |
| 2583 | + /* No AMP link over AMP controller */ | |
| 2584 | + if (!hci_conn_num(hdev, AMP_LINK) && hdev->dev_type == HCI_AMP) | |
| 2558 | 2585 | return; |
| 2559 | 2586 | |
| 2560 | 2587 | switch (hdev->flow_ctl_mode) { |
| @@ -30,6 +30,8 @@ · 29 unmodified lines | ||
| 30 | 30 | #include <net/bluetooth/bluetooth.h> |
| 31 | 31 | #include <net/bluetooth/hci_core.h> |
| 32 | 32 | #include <net/bluetooth/mgmt.h> |
| 33 | +#include <net/bluetooth/a2mp.h> | |
| 34 | +#include <net/bluetooth/amp.h> | |
| 33 | 35 | |
| 34 | 36 | /* Handle HCI Event packets */ |
| 35 | 37 | |
| @@ -846,7 +848,7 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev, · 810 unmodified lines | ||
| 846 | 848 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
| 847 | 849 | |
| 848 | 850 | if (rp->status) |
| 849 | − return; | |
| 851 | + goto a2mp_rsp; | |
| 850 | 852 | |
| 851 | 853 | hdev->amp_status = rp->amp_status; |
| 852 | 854 | hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); |
| @@ -860,6 +862,46 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev, · 7 unmodified lines | ||
| 860 | 862 | hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); |
| 861 | 863 | |
| 862 | 864 | hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); |
| 865 | + | |
| 866 | +a2mp_rsp: | |
| 867 | + a2mp_send_getinfo_rsp(hdev); | |
| 868 | +} | |
| 869 | + | |
| 870 | +static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev, | |
| 871 | + struct sk_buff *skb) | |
| 872 | +{ | |
| 873 | + struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data; | |
| 874 | + struct amp_assoc *assoc = &hdev->loc_assoc; | |
| 875 | + size_t rem_len, frag_len; | |
| 876 | + | |
| 877 | + BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | |
| 878 | + | |
| 879 | + if (rp->status) | |
| 880 | + goto a2mp_rsp; | |
| 881 | + | |
| 882 | + frag_len = skb->len - sizeof(*rp); | |
| 883 | + rem_len = __le16_to_cpu(rp->rem_len); | |
| 884 | + | |
| 885 | + if (rem_len > frag_len) { | |
| 886 | + BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len); | |
| 887 | + | |
| 888 | + memcpy(assoc->data + assoc->offset, rp->frag, frag_len); | |
| 889 | + assoc->offset += frag_len; | |
| 890 | + | |
| 891 | + /* Read other fragments */ | |
| 892 | + amp_read_loc_assoc_frag(hdev, rp->phy_handle); | |
| 893 | + | |
| 894 | + return; | |
| 895 | + } | |
| 896 | + | |
| 897 | + memcpy(assoc->data + assoc->offset, rp->frag, rem_len); | |
| 898 | + assoc->len = assoc->offset + rem_len; | |
| 899 | + assoc->offset = 0; | |
| 900 | + | |
| 901 | +a2mp_rsp: | |
| 902 | + /* Send A2MP Rsp when all fragments are received */ | |
| 903 | + a2mp_send_getampassoc_rsp(hdev, rp->status); | |
| 904 | + a2mp_send_create_phy_link_req(hdev, rp->status); | |
| 863 | 905 | } |
| 864 | 906 | |
| 865 | 907 | static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, |
| @@ -1174,6 +1216,20 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, · 308 unmodified lines | ||
| 1174 | 1216 | hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status); |
| 1175 | 1217 | } |
| 1176 | 1218 | |
| 1219 | +static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, | |
| 1220 | + struct sk_buff *skb) | |
| 1221 | +{ | |
| 1222 | + struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data; | |
| 1223 | + | |
| 1224 | + BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x", | |
| 1225 | + hdev->name, rp->status, rp->phy_handle); | |
| 1226 | + | |
| 1227 | + if (rp->status) | |
| 1228 | + return; | |
| 1229 | + | |
| 1230 | + amp_write_rem_assoc_continue(hdev, rp->phy_handle); | |
| 1231 | +} | |
| 1232 | + | |
| 1177 | 1233 | static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) |
| 1178 | 1234 | { |
| 1179 | 1235 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
| @@ -1210,7 +1266,7 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) · 30 unmodified lines | ||
| 1210 | 1266 | |
| 1211 | 1267 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); |
| 1212 | 1268 | |
| 1213 | − BT_DBG("%s bdaddr %s hcon %p", hdev->name, batostr(&cp->bdaddr), conn); | |
| 1269 | + BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn); | |
| 1214 | 1270 | |
| 1215 | 1271 | if (status) { |
| 1216 | 1272 | if (conn && conn->state == BT_CONNECT) { |
| @@ -1639,8 +1695,7 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) · 422 unmodified lines | ||
| 1639 | 1695 | return; |
| 1640 | 1696 | } |
| 1641 | 1697 | |
| 1642 | − BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst), | |
| 1643 | − conn); | |
| 1698 | + BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn); | |
| 1644 | 1699 | |
| 1645 | 1700 | conn->state = BT_CLOSED; |
| 1646 | 1701 | mgmt_connect_failed(hdev, &conn->dst, conn->type, |
| @@ -1657,6 +1712,38 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) · 10 unmodified lines | ||
| 1657 | 1712 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
| 1658 | 1713 | } |
| 1659 | 1714 | |
| 1715 | +static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) | |
| 1716 | +{ | |
| 1717 | + struct hci_cp_create_phy_link *cp; | |
| 1718 | + | |
| 1719 | + BT_DBG("%s status 0x%2.2x", hdev->name, status); | |
| 1720 | + | |
| 1721 | + if (status) | |
| 1722 | + return; | |
| 1723 | + | |
| 1724 | + cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); | |
| 1725 | + if (!cp) | |
| 1726 | + return; | |
| 1727 | + | |
| 1728 | + amp_write_remote_assoc(hdev, cp->phy_handle); | |
| 1729 | +} | |
| 1730 | + | |
| 1731 | +static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) | |
| 1732 | +{ | |
| 1733 | + struct hci_cp_accept_phy_link *cp; | |
| 1734 | + | |
| 1735 | + BT_DBG("%s status 0x%2.2x", hdev->name, status); | |
| 1736 | + | |
| 1737 | + if (status) | |
| 1738 | + return; | |
| 1739 | + | |
| 1740 | + cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK); | |
| 1741 | + if (!cp) | |
| 1742 | + return; | |
| 1743 | + | |
| 1744 | + amp_write_remote_assoc(hdev, cp->phy_handle); | |
| 1745 | +} | |
| 1746 | + | |
| 1660 | 1747 | static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
| 1661 | 1748 | { |
| 1662 | 1749 | __u8 status = *((__u8 *) skb->data); |
| @@ -1822,7 +1909,7 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) · 159 unmodified lines | ||
| 1822 | 1909 | struct hci_ev_conn_request *ev = (void *) skb->data; |
| 1823 | 1910 | int mask = hdev->link_mode; |
| 1824 | 1911 | |
| 1825 | − BT_DBG("%s bdaddr %s type 0x%x", hdev->name, batostr(&ev->bdaddr), | |
| 1912 | + BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, | |
| 1826 | 1913 | ev->link_type); |
| 1827 | 1914 | |
| 1828 | 1915 | mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); |
| @@ -2314,6 +2401,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) · 485 unmodified lines | ||
| 2314 | 2401 | hci_cc_read_local_amp_info(hdev, skb); |
| 2315 | 2402 | break; |
| 2316 | 2403 | |
| 2404 | + case HCI_OP_READ_LOCAL_AMP_ASSOC: | |
| 2405 | + hci_cc_read_local_amp_assoc(hdev, skb); | |
| 2406 | + break; | |
| 2407 | + | |
| 2317 | 2408 | case HCI_OP_DELETE_STORED_LINK_KEY: |
| 2318 | 2409 | hci_cc_delete_stored_link_key(hdev, skb); |
| 2319 | 2410 | break; |
| @@ -2386,6 +2477,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) · 66 unmodified lines | ||
| 2386 | 2477 | hci_cc_write_le_host_supported(hdev, skb); |
| 2387 | 2478 | break; |
| 2388 | 2479 | |
| 2480 | + case HCI_OP_WRITE_REMOTE_AMP_ASSOC: | |
| 2481 | + hci_cc_write_remote_amp_assoc(hdev, skb); | |
| 2482 | + break; | |
| 2483 | + | |
| 2389 | 2484 | default: |
| 2390 | 2485 | BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); |
| 2391 | 2486 | break; |
| @@ -2467,6 +2562,14 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) · 75 unmodified lines | ||
| 2467 | 2562 | hci_cs_le_start_enc(hdev, ev->status); |
| 2468 | 2563 | break; |
| 2469 | 2564 | |
| 2565 | + case HCI_OP_CREATE_PHY_LINK: | |
| 2566 | + hci_cs_create_phylink(hdev, ev->status); | |
| 2567 | + break; | |
| 2568 | + | |
| 2569 | + case HCI_OP_ACCEPT_PHY_LINK: | |
| 2570 | + hci_cs_accept_phylink(hdev, ev->status); | |
| 2571 | + break; | |
| 2572 | + | |
| 2470 | 2573 | default: |
| 2471 | 2574 | BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); |
| 2472 | 2575 | break; |
| @@ -2574,6 +2677,27 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) · 101 unmodified lines | ||
| 2574 | 2677 | queue_work(hdev->workqueue, &hdev->tx_work); |
| 2575 | 2678 | } |
| 2576 | 2679 | |
| 2680 | +static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, | |
| 2681 | + __u16 handle) | |
| 2682 | +{ | |
| 2683 | + struct hci_chan *chan; | |
| 2684 | + | |
| 2685 | + switch (hdev->dev_type) { | |
| 2686 | + case HCI_BREDR: | |
| 2687 | + return hci_conn_hash_lookup_handle(hdev, handle); | |
| 2688 | + case HCI_AMP: | |
| 2689 | + chan = hci_chan_lookup_handle(hdev, handle); | |
| 2690 | + if (chan) | |
| 2691 | + return chan->conn; | |
| 2692 | + break; | |
| 2693 | + default: | |
| 2694 | + BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type); | |
| 2695 | + break; | |
| 2696 | + } | |
| 2697 | + | |
| 2698 | + return NULL; | |
| 2699 | +} | |
| 2700 | + | |
| 2577 | 2701 | static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) |
| 2578 | 2702 | { |
| 2579 | 2703 | struct hci_ev_num_comp_blocks *ev = (void *) skb->data; |
| @@ -2595,13 +2719,13 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) · 15 unmodified lines | ||
| 2595 | 2719 | |
| 2596 | 2720 | for (i = 0; i < ev->num_hndl; i++) { |
| 2597 | 2721 | struct hci_comp_blocks_info *info = &ev->handles[i]; |
| 2598 | − struct hci_conn *conn; | |
| 2722 | + struct hci_conn *conn = NULL; | |
| 2599 | 2723 | __u16 handle, block_count; |
| 2600 | 2724 | |
| 2601 | 2725 | handle = __le16_to_cpu(info->handle); |
| 2602 | 2726 | block_count = __le16_to_cpu(info->blocks); |
| 2603 | 2727 | |
| 2604 | − conn = hci_conn_hash_lookup_handle(hdev, handle); | |
| 2728 | + conn = __hci_conn_lookup_handle(hdev, handle); | |
| 2605 | 2729 | if (!conn) |
| 2606 | 2730 | continue; |
| 2607 | 2731 | |
| @@ -2609,6 +2733,7 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) · 1 unmodified line | ||
| 2609 | 2733 | |
| 2610 | 2734 | switch (conn->type) { |
| 2611 | 2735 | case ACL_LINK: |
| 2736 | + case AMP_LINK: | |
| 2612 | 2737 | hdev->block_cnt += block_count; |
| 2613 | 2738 | if (hdev->block_cnt > hdev->num_blocks) |
| 2614 | 2739 | hdev->block_cnt = hdev->num_blocks; |
| @@ -2705,13 +2830,13 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) · 90 unmodified lines | ||
| 2705 | 2830 | |
| 2706 | 2831 | key = hci_find_link_key(hdev, &ev->bdaddr); |
| 2707 | 2832 | if (!key) { |
| 2708 | − BT_DBG("%s link key not found for %s", hdev->name, | |
| 2709 | − batostr(&ev->bdaddr)); | |
| 2833 | + BT_DBG("%s link key not found for %pMR", hdev->name, | |
| 2834 | + &ev->bdaddr); | |
| 2710 | 2835 | goto not_found; |
| 2711 | 2836 | } |
| 2712 | 2837 | |
| 2713 | − BT_DBG("%s found key type %u for %s", hdev->name, key->type, | |
| 2714 | − batostr(&ev->bdaddr)); | |
| 2838 | + BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, | |
| 2839 | + &ev->bdaddr); | |
| 2715 | 2840 | |
| 2716 | 2841 | if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && |
| 2717 | 2842 | key->type == HCI_LK_DEBUG_COMBINATION) { |
| @@ -3558,6 +3683,22 @@ static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) · 840 unmodified lines | ||
| 3558 | 3683 | } |
| 3559 | 3684 | } |
| 3560 | 3685 | |
| 3686 | +static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) | |
| 3687 | +{ | |
| 3688 | + struct hci_ev_channel_selected *ev = (void *) skb->data; | |
| 3689 | + struct hci_conn *hcon; | |
| 3690 | + | |
| 3691 | + BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); | |
| 3692 | + | |
| 3693 | + skb_pull(skb, sizeof(*ev)); | |
| 3694 | + | |
| 3695 | + hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); | |
| 3696 | + if (!hcon) | |
| 3697 | + return; | |
| 3698 | + | |
| 3699 | + amp_read_loc_assoc_final_data(hdev, hcon); | |
| 3700 | +} | |
| 3701 | + | |
| 3561 | 3702 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) |
| 3562 | 3703 | { |
| 3563 | 3704 | struct hci_event_hdr *hdr = (void *) skb->data; |
| @@ -3722,6 +3863,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) · 158 unmodified lines | ||
| 3722 | 3863 | hci_le_meta_evt(hdev, skb); |
| 3723 | 3864 | break; |
| 3724 | 3865 | |
| 3866 | + case HCI_EV_CHANNEL_SELECTED: | |
| 3867 | + hci_chan_selected_evt(hdev, skb); | |
| 3868 | + break; | |
| 3869 | + | |
| 3725 | 3870 | case HCI_EV_REMOTE_OOB_DATA_REQUEST: |
| 3726 | 3871 | hci_remote_oob_data_request_evt(hdev, skb); |
| 3727 | 3872 | break; |
| @@ -38,7 +38,7 @@ static ssize_t show_link_address(struct device *dev, · 37 unmodified lines | ||
| 38 | 38 | struct device_attribute *attr, char *buf) |
| 39 | 39 | { |
| 40 | 40 | struct hci_conn *conn = to_hci_conn(dev); |
| 41 | − return sprintf(buf, "%s\n", batostr(&conn->dst)); | |
| 41 | + return sprintf(buf, "%pMR\n", &conn->dst); | |
| 42 | 42 | } |
| 43 | 43 | |
| 44 | 44 | static ssize_t show_link_features(struct device *dev, |
| @@ -224,7 +224,7 @@ static ssize_t show_address(struct device *dev, · 179 unmodified lines | ||
| 224 | 224 | struct device_attribute *attr, char *buf) |
| 225 | 225 | { |
| 226 | 226 | struct hci_dev *hdev = to_hci_dev(dev); |
| 227 | − return sprintf(buf, "%s\n", batostr(&hdev->bdaddr)); | |
| 227 | + return sprintf(buf, "%pMR\n", &hdev->bdaddr); | |
| 228 | 228 | } |
| 229 | 229 | |
| 230 | 230 | static ssize_t show_features(struct device *dev, |
| @@ -406,8 +406,8 @@ static int inquiry_cache_show(struct seq_file *f, void *p) · 175 unmodified lines | ||
| 406 | 406 | |
| 407 | 407 | list_for_each_entry(e, &cache->all, all) { |
| 408 | 408 | struct inquiry_data *data = &e->data; |
| 409 | − seq_printf(f, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", | |
| 410 | − batostr(&data->bdaddr), | |
| 409 | + seq_printf(f, "%pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", | |
| 410 | + &data->bdaddr, | |
| 411 | 411 | data->pscan_rep_mode, data->pscan_period_mode, |
| 412 | 412 | data->pscan_mode, data->dev_class[2], |
| 413 | 413 | data->dev_class[1], data->dev_class[0], |
| @@ -440,7 +440,7 @@ static int blacklist_show(struct seq_file *f, void *p) · 26 unmodified lines | ||
| 440 | 440 | hci_dev_lock(hdev); |
| 441 | 441 | |
| 442 | 442 | list_for_each_entry(b, &hdev->blacklist, list) |
| 443 | − seq_printf(f, "%s\n", batostr(&b->bdaddr)); | |
| 443 | + seq_printf(f, "%pMR\n", &b->bdaddr); | |
| 444 | 444 | |
| 445 | 445 | hci_dev_unlock(hdev); |
| 446 | 446 | |
| @@ -932,8 +932,12 @@ static int hidp_setup_hid(struct hidp_session *session, · 931 unmodified lines | ||
| 932 | 932 | hid->country = req->country; |
| 933 | 933 | |
| 934 | 934 | strncpy(hid->name, req->name, 128); |
| 935 | − strncpy(hid->phys, batostr(&bt_sk(session->ctrl_sock->sk)->src), 64); | |
| 936 | − strncpy(hid->uniq, batostr(&bt_sk(session->ctrl_sock->sk)->dst), 64); | |
| 935 | + | |
| 936 | + snprintf(hid->phys, sizeof(hid->phys), "%pMR", | |
| 937 | + &bt_sk(session->ctrl_sock->sk)->src); | |
| 938 | + | |
| 939 | + snprintf(hid->uniq, sizeof(hid->uniq), "%pMR", | |
| 940 | + &bt_sk(session->ctrl_sock->sk)->dst); | |
| 937 | 941 | |
| 938 | 942 | hid->dev.parent = &session->conn->dev; |
| 939 | 943 | hid->ll_driver = &hidp_hid_driver; |
| @@ -48,19 +48,20 @@ static LIST_HEAD(chan_list); · 47 unmodified lines | ||
| 48 | 48 | static DEFINE_RWLOCK(chan_list_lock); |
| 49 | 49 | |
| 50 | 50 | static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, |
| 51 | − u8 code, u8 ident, u16 dlen, void *data); | |
| 51 | + u8 code, u8 ident, u16 dlen, void *data); | |
| 52 | 52 | static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, |
| 53 | − void *data); | |
| 53 | + void *data); | |
| 54 | 54 | static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); |
| 55 | 55 | static void l2cap_send_disconn_req(struct l2cap_conn *conn, |
| 56 | 56 | struct l2cap_chan *chan, int err); |
| 57 | 57 | |
| 58 | 58 | static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, |
| 59 | − struct sk_buff_head *skbs, u8 event); | |
| 59 | + struct sk_buff_head *skbs, u8 event); | |
| 60 | 60 | |
| 61 | 61 | /* ---- L2CAP channels ---- */ |
| 62 | 62 | |
| 63 | −static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid) | |
| 63 | +static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, | |
| 64 | + u16 cid) | |
| 64 | 65 | { |
| 65 | 66 | struct l2cap_chan *c; |
| 66 | 67 | |
| @@ -71,7 +72,8 @@ static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 · 4 unmodified lines | ||
| 71 | 72 | return NULL; |
| 72 | 73 | } |
| 73 | 74 | |
| 74 | −static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) | |
| 75 | +static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, | |
| 76 | + u16 cid) | |
| 75 | 77 | { |
| 76 | 78 | struct l2cap_chan *c; |
| 77 | 79 | |
| @@ -84,7 +86,8 @@ static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 · 6 unmodified lines | ||
| 84 | 86 | |
| 85 | 87 | /* Find channel with given SCID. |
| 86 | 88 | * Returns locked channel. */ |
| 87 | −static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) | |
| 89 | +static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, | |
| 90 | + u16 cid) | |
| 88 | 91 | { |
| 89 | 92 | struct l2cap_chan *c; |
| 90 | 93 | |
| @@ -97,7 +100,8 @@ static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 ci · 6 unmodified lines | ||
| 97 | 100 | return c; |
| 98 | 101 | } |
| 99 | 102 | |
| 100 | −static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) | |
| 103 | +static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, | |
| 104 | + u8 ident) | |
| 101 | 105 | { |
| 102 | 106 | struct l2cap_chan *c; |
| 103 | 107 | |
| @@ -178,7 +182,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn) · 74 unmodified lines | ||
| 178 | 182 | static void __l2cap_state_change(struct l2cap_chan *chan, int state) |
| 179 | 183 | { |
| 180 | 184 | BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), |
| 181 | − state_to_string(state)); | |
| 185 | + state_to_string(state)); | |
| 182 | 186 | |
| 183 | 187 | chan->state = state; |
| 184 | 188 | chan->ops->state_change(chan, state); |
| @@ -361,7 +365,7 @@ static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq) · 176 unmodified lines | ||
| 361 | 365 | static void l2cap_chan_timeout(struct work_struct *work) |
| 362 | 366 | { |
| 363 | 367 | struct l2cap_chan *chan = container_of(work, struct l2cap_chan, |
| 364 | − chan_timer.work); | |
| 368 | + chan_timer.work); | |
| 365 | 369 | struct l2cap_conn *conn = chan->conn; |
| 366 | 370 | int reason; |
| 367 | 371 | |
| @@ -373,7 +377,7 @@ static void l2cap_chan_timeout(struct work_struct *work) · 5 unmodified lines | ||
| 373 | 377 | if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) |
| 374 | 378 | reason = ECONNREFUSED; |
| 375 | 379 | else if (chan->state == BT_CONNECT && |
| 376 | − chan->sec_level != BT_SECURITY_SDP) | |
| 380 | + chan->sec_level != BT_SECURITY_SDP) | |
| 377 | 381 | reason = ECONNREFUSED; |
| 378 | 382 | else |
| 379 | 383 | reason = ETIMEDOUT; |
| @@ -455,7 +459,7 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan) · 75 unmodified lines | ||
| 455 | 459 | set_bit(FLAG_FORCE_ACTIVE, &chan->flags); |
| 456 | 460 | } |
| 457 | 461 | |
| 458 | −static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | |
| 462 | +void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | |
| 459 | 463 | { |
| 460 | 464 | BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, |
| 461 | 465 | __le16_to_cpu(chan->psm), chan->dcid); |
| @@ -504,7 +508,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) · 42 unmodified lines | ||
| 504 | 508 | chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; |
| 505 | 509 | chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; |
| 506 | 510 | chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; |
| 507 | − chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO; | |
| 511 | + chan->local_flush_to = L2CAP_EFS_DEFAULT_FLUSH_TO; | |
| 508 | 512 | |
| 509 | 513 | l2cap_chan_hold(chan); |
| 510 | 514 | |
| @@ -527,6 +531,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) · 16 unmodified lines | ||
| 527 | 531 | BT_DBG("chan %p, conn %p, err %d", chan, conn, err); |
| 528 | 532 | |
| 529 | 533 | if (conn) { |
| 534 | + struct amp_mgr *mgr = conn->hcon->amp_mgr; | |
| 530 | 535 | /* Delete from channel list */ |
| 531 | 536 | list_del(&chan->list); |
| 532 | 537 | |
| @@ -536,10 +541,12 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) · 3 unmodified lines | ||
| 536 | 541 | |
| 537 | 542 | if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP) |
| 538 | 543 | hci_conn_put(conn->hcon); |
| 544 | + | |
| 545 | + if (mgr && mgr->bredr_chan == chan) | |
| 546 | + mgr->bredr_chan = NULL; | |
| 539 | 547 | } |
| 540 | 548 | |
| 541 | − if (chan->ops->teardown) | |
| 542 | − chan->ops->teardown(chan, err); | |
| 549 | + chan->ops->teardown(chan, err); | |
| 543 | 550 | |
| 544 | 551 | if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) |
| 545 | 552 | return; |
| @@ -573,19 +580,18 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) · 27 unmodified lines | ||
| 573 | 580 | struct l2cap_conn *conn = chan->conn; |
| 574 | 581 | struct sock *sk = chan->sk; |
| 575 | 582 | |
| 576 | − BT_DBG("chan %p state %s sk %p", chan, | |
| 577 | − state_to_string(chan->state), sk); | |
| 583 | + BT_DBG("chan %p state %s sk %p", chan, state_to_string(chan->state), | |
| 584 | + sk); | |
| 578 | 585 | |
| 579 | 586 | switch (chan->state) { |
| 580 | 587 | case BT_LISTEN: |
| 581 | − if (chan->ops->teardown) | |
| 582 | − chan->ops->teardown(chan, 0); | |
| 588 | + chan->ops->teardown(chan, 0); | |
| 583 | 589 | break; |
| 584 | 590 | |
| 585 | 591 | case BT_CONNECTED: |
| 586 | 592 | case BT_CONFIG: |
| 587 | 593 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && |
| 588 | − conn->hcon->type == ACL_LINK) { | |
| 594 | + conn->hcon->type == ACL_LINK) { | |
| 589 | 595 | __set_chan_timer(chan, sk->sk_sndtimeo); |
| 590 | 596 | l2cap_send_disconn_req(conn, chan, reason); |
| 591 | 597 | } else |
| @@ -594,7 +600,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) · 2 unmodified lines | ||
| 594 | 600 | |
| 595 | 601 | case BT_CONNECT2: |
| 596 | 602 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && |
| 597 | − conn->hcon->type == ACL_LINK) { | |
| 603 | + conn->hcon->type == ACL_LINK) { | |
| 598 | 604 | struct l2cap_conn_rsp rsp; |
| 599 | 605 | __u16 result; |
| 600 | 606 | |
| @@ -609,7 +615,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) · 8 unmodified lines | ||
| 609 | 615 | rsp.result = cpu_to_le16(result); |
| 610 | 616 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); |
| 611 | 617 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, |
| 612 | − sizeof(rsp), &rsp); | |
| 618 | + sizeof(rsp), &rsp); | |
| 613 | 619 | } |
| 614 | 620 | |
| 615 | 621 | l2cap_chan_del(chan, reason); |
| @@ -621,8 +627,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) · 5 unmodified lines | ||
| 621 | 627 | break; |
| 622 | 628 | |
| 623 | 629 | default: |
| 624 | − if (chan->ops->teardown) | |
| 625 | − chan->ops->teardown(chan, 0); | |
| 630 | + chan->ops->teardown(chan, 0); | |
| 626 | 631 | break; |
| 627 | 632 | } |
| 628 | 633 | } |
| @@ -691,7 +696,8 @@ static u8 l2cap_get_ident(struct l2cap_conn *conn) · 62 unmodified lines | ||
| 691 | 696 | return id; |
| 692 | 697 | } |
| 693 | 698 | |
| 694 | −static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) | |
| 699 | +static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, | |
| 700 | + void *data) | |
| 695 | 701 | { |
| 696 | 702 | struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); |
| 697 | 703 | u8 flags; |
| @@ -718,10 +724,10 @@ static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) · 20 unmodified lines | ||
| 718 | 724 | u16 flags; |
| 719 | 725 | |
| 720 | 726 | BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, |
| 721 | − skb->priority); | |
| 727 | + skb->priority); | |
| 722 | 728 | |
| 723 | 729 | if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && |
| 724 | − lmp_no_flush_capable(hcon->hdev)) | |
| 730 | + lmp_no_flush_capable(hcon->hdev)) | |
| 725 | 731 | flags = ACL_START_NO_FLUSH; |
| 726 | 732 | else |
| 727 | 733 | flags = ACL_START; |
| @@ -946,7 +952,19 @@ static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) · 218 unmodified lines | ||
| 946 | 952 | return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); |
| 947 | 953 | } |
| 948 | 954 | |
| 949 | −static void l2cap_send_conn_req(struct l2cap_chan *chan) | |
| 955 | +static bool __amp_capable(struct l2cap_chan *chan) | |
| 956 | +{ | |
| 957 | + struct l2cap_conn *conn = chan->conn; | |
| 958 | + | |
| 959 | + if (enable_hs && | |
| 960 | + chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED && | |
| 961 | + conn->fixed_chan_mask & L2CAP_FC_A2MP) | |
| 962 | + return true; | |
| 963 | + else | |
| 964 | + return false; | |
| 965 | +} | |
| 966 | + | |
| 967 | +void l2cap_send_conn_req(struct l2cap_chan *chan) | |
| 950 | 968 | { |
| 951 | 969 | struct l2cap_conn *conn = chan->conn; |
| 952 | 970 | struct l2cap_conn_req req; |
| @@ -972,6 +990,16 @@ static void l2cap_chan_ready(struct l2cap_chan *chan) · 19 unmodified lines | ||
| 972 | 990 | chan->ops->ready(chan); |
| 973 | 991 | } |
| 974 | 992 | |
| 993 | +static void l2cap_start_connection(struct l2cap_chan *chan) | |
| 994 | +{ | |
| 995 | + if (__amp_capable(chan)) { | |
| 996 | + BT_DBG("chan %p AMP capable: discover AMPs", chan); | |
| 997 | + a2mp_discover_amp(chan); | |
| 998 | + } else { | |
| 999 | + l2cap_send_conn_req(chan); | |
| 1000 | + } | |
| 1001 | +} | |
| 1002 | + | |
| 975 | 1003 | static void l2cap_do_start(struct l2cap_chan *chan) |
| 976 | 1004 | { |
| 977 | 1005 | struct l2cap_conn *conn = chan->conn; |
| @@ -986,8 +1014,9 @@ static void l2cap_do_start(struct l2cap_chan *chan) · 8 unmodified lines | ||
| 986 | 1014 | return; |
| 987 | 1015 | |
| 988 | 1016 | if (l2cap_chan_check_security(chan) && |
| 989 | − __l2cap_no_conn_pending(chan)) | |
| 990 | − l2cap_send_conn_req(chan); | |
| 1017 | + __l2cap_no_conn_pending(chan)) { | |
| 1018 | + l2cap_start_connection(chan); | |
| 1019 | + } | |
| 991 | 1020 | } else { |
| 992 | 1021 | struct l2cap_info_req req; |
| 993 | 1022 | req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); |
| @@ -997,8 +1026,8 @@ static void l2cap_do_start(struct l2cap_chan *chan) · 3 unmodified lines | ||
| 997 | 1026 | |
| 998 | 1027 | schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); |
| 999 | 1028 | |
| 1000 | − l2cap_send_cmd(conn, conn->info_ident, | |
| 1001 | − L2CAP_INFO_REQ, sizeof(req), &req); | |
| 1029 | + l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, | |
| 1030 | + sizeof(req), &req); | |
| 1002 | 1031 | } |
| 1003 | 1032 | } |
| 1004 | 1033 | |
| @@ -1018,7 +1047,8 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) · 13 unmodified lines | ||
| 1018 | 1047 | } |
| 1019 | 1048 | } |
| 1020 | 1049 | |
| 1021 | −static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err) | |
| 1050 | +static void l2cap_send_disconn_req(struct l2cap_conn *conn, | |
| 1051 | + struct l2cap_chan *chan, int err) | |
| 1022 | 1052 | { |
| 1023 | 1053 | struct sock *sk = chan->sk; |
| 1024 | 1054 | struct l2cap_disconn_req req; |
| @@ -1033,14 +1063,14 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c · 8 unmodified lines | ||
| 1033 | 1063 | } |
| 1034 | 1064 | |
| 1035 | 1065 | if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { |
| 1036 | − __l2cap_state_change(chan, BT_DISCONN); | |
| 1066 | + l2cap_state_change(chan, BT_DISCONN); | |
| 1037 | 1067 | return; |
| 1038 | 1068 | } |
| 1039 | 1069 | |
| 1040 | 1070 | req.dcid = cpu_to_le16(chan->dcid); |
| 1041 | 1071 | req.scid = cpu_to_le16(chan->scid); |
| 1042 | − l2cap_send_cmd(conn, l2cap_get_ident(conn), | |
| 1043 | − L2CAP_DISCONN_REQ, sizeof(req), &req); | |
| 1072 | + l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, | |
| 1073 | + sizeof(req), &req); | |
| 1044 | 1074 | |
| 1045 | 1075 | lock_sock(sk); |
| 1046 | 1076 | __l2cap_state_change(chan, BT_DISCONN); |
| @@ -1069,20 +1099,20 @@ static void l2cap_conn_start(struct l2cap_conn *conn) · 22 unmodified lines | ||
| 1069 | 1099 | |
| 1070 | 1100 | if (chan->state == BT_CONNECT) { |
| 1071 | 1101 | if (!l2cap_chan_check_security(chan) || |
| 1072 | − !__l2cap_no_conn_pending(chan)) { | |
| 1102 | + !__l2cap_no_conn_pending(chan)) { | |
| 1073 | 1103 | l2cap_chan_unlock(chan); |
| 1074 | 1104 | continue; |
| 1075 | 1105 | } |
| 1076 | 1106 | |
| 1077 | 1107 | if (!l2cap_mode_supported(chan->mode, conn->feat_mask) |
| 1078 | − && test_bit(CONF_STATE2_DEVICE, | |
| 1108 | + && test_bit(CONF_STATE2_DEVICE, | |
| 1079 | 1109 | &chan->conf_state)) { |
| 1080 | 1110 | l2cap_chan_close(chan, ECONNRESET); |
| 1081 | 1111 | l2cap_chan_unlock(chan); |
| 1082 | 1112 | continue; |
| 1083 | 1113 | } |
| 1084 | 1114 | |
| 1085 | − l2cap_send_conn_req(chan); | |
| 1115 | + l2cap_start_connection(chan); | |
| 1086 | 1116 | |
| 1087 | 1117 | } else if (chan->state == BT_CONNECT2) { |
| 1088 | 1118 | struct l2cap_conn_rsp rsp; |
| @@ -1094,11 +1124,9 @@ static void l2cap_conn_start(struct l2cap_conn *conn) · 5 unmodified lines | ||
| 1094 | 1124 | lock_sock(sk); |
| 1095 | 1125 | if (test_bit(BT_SK_DEFER_SETUP, |
| 1096 | 1126 | &bt_sk(sk)->flags)) { |
| 1097 | − struct sock *parent = bt_sk(sk)->parent; | |
| 1098 | 1127 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); |
| 1099 | 1128 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); |
| 1100 | − if (parent) | |
| 1101 | − parent->sk_data_ready(parent, 0); | |
| 1129 | + chan->ops->defer(chan); | |
| 1102 | 1130 | |
| 1103 | 1131 | } else { |
| 1104 | 1132 | __l2cap_state_change(chan, BT_CONFIG); |
| @@ -1112,17 +1140,17 @@ static void l2cap_conn_start(struct l2cap_conn *conn) · 7 unmodified lines | ||
| 1112 | 1140 | } |
| 1113 | 1141 | |
| 1114 | 1142 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, |
| 1115 | − sizeof(rsp), &rsp); | |
| 1143 | + sizeof(rsp), &rsp); | |
| 1116 | 1144 | |
| 1117 | 1145 | if (test_bit(CONF_REQ_SENT, &chan->conf_state) || |
| 1118 | − rsp.result != L2CAP_CR_SUCCESS) { | |
| 1146 | + rsp.result != L2CAP_CR_SUCCESS) { | |
| 1119 | 1147 | l2cap_chan_unlock(chan); |
| 1120 | 1148 | continue; |
| 1121 | 1149 | } |
| 1122 | 1150 | |
| 1123 | 1151 | set_bit(CONF_REQ_SENT, &chan->conf_state); |
| 1124 | 1152 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, |
| 1125 | − l2cap_build_conf_req(chan, buf), buf); | |
| 1153 | + l2cap_build_conf_req(chan, buf), buf); | |
| 1126 | 1154 | chan->num_conf_req++; |
| 1127 | 1155 | } |
| 1128 | 1156 | |
| @@ -1204,8 +1232,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) · 75 unmodified lines | ||
| 1204 | 1232 | bacpy(&bt_sk(sk)->src, conn->src); |
| 1205 | 1233 | bacpy(&bt_sk(sk)->dst, conn->dst); |
| 1206 | 1234 | |
| 1207 | − bt_accept_enqueue(parent, sk); | |
| 1208 | − | |
| 1209 | 1235 | l2cap_chan_add(conn, chan); |
| 1210 | 1236 | |
| 1211 | 1237 | l2cap_chan_ready(chan); |
| @@ -1270,7 +1296,7 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) · 58 unmodified lines | ||
| 1270 | 1296 | |
| 1271 | 1297 | list_for_each_entry(chan, &conn->chan_l, list) { |
| 1272 | 1298 | if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) |
| 1273 | − __l2cap_chan_set_err(chan, err); | |
| 1299 | + l2cap_chan_set_err(chan, err); | |
| 1274 | 1300 | } |
| 1275 | 1301 | |
| 1276 | 1302 | mutex_unlock(&conn->chan_lock); |
| @@ -1279,7 +1305,7 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) · 2 unmodified lines | ||
| 1279 | 1305 | static void l2cap_info_timeout(struct work_struct *work) |
| 1280 | 1306 | { |
| 1281 | 1307 | struct l2cap_conn *conn = container_of(work, struct l2cap_conn, |
| 1282 | − info_timer.work); | |
| 1308 | + info_timer.work); | |
| 1283 | 1309 | |
| 1284 | 1310 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; |
| 1285 | 1311 | conn->info_ident = 0; |
| @@ -1333,7 +1359,7 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) · 47 unmodified lines | ||
| 1333 | 1359 | static void security_timeout(struct work_struct *work) |
| 1334 | 1360 | { |
| 1335 | 1361 | struct l2cap_conn *conn = container_of(work, struct l2cap_conn, |
| 1336 | − security_timer.work); | |
| 1362 | + security_timer.work); | |
| 1337 | 1363 | |
| 1338 | 1364 | BT_DBG("conn %p", conn); |
| 1339 | 1365 | |
| @@ -1355,7 +1381,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) · 15 unmodified lines | ||
| 1355 | 1381 | if (!hchan) |
| 1356 | 1382 | return NULL; |
| 1357 | 1383 | |
| 1358 | − conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC); | |
| 1384 | + conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL); | |
| 1359 | 1385 | if (!conn) { |
| 1360 | 1386 | hci_chan_del(hchan); |
| 1361 | 1387 | return NULL; |
| @@ -1367,10 +1393,22 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) · 5 unmodified lines | ||
| 1367 | 1393 | |
| 1368 | 1394 | BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); |
| 1369 | 1395 | |
| 1370 | − if (hcon->hdev->le_mtu && hcon->type == LE_LINK) | |
| 1371 | − conn->mtu = hcon->hdev->le_mtu; | |
| 1372 | − else | |
| 1396 | + switch (hcon->type) { | |
| 1397 | + case AMP_LINK: | |
| 1398 | + conn->mtu = hcon->hdev->block_mtu; | |
| 1399 | + break; | |
| 1400 | + | |
| 1401 | + case LE_LINK: | |
| 1402 | + if (hcon->hdev->le_mtu) { | |
| 1403 | + conn->mtu = hcon->hdev->le_mtu; | |
| 1404 | + break; | |
| 1405 | + } | |
| 1406 | + /* fall through */ | |
| 1407 | + | |
| 1408 | + default: | |
| 1373 | 1409 | conn->mtu = hcon->hdev->acl_mtu; |
| 1410 | + break; | |
| 1411 | + } | |
| 1374 | 1412 | |
| 1375 | 1413 | conn->src = &hcon->hdev->bdaddr; |
| 1376 | 1414 | conn->dst = &hcon->dst; |
| @@ -1448,7 +1486,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, · 71 unmodified lines | ||
| 1448 | 1486 | __u8 auth_type; |
| 1449 | 1487 | int err; |
| 1450 | 1488 | |
| 1451 | − BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst), | |
| 1489 | + BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", src, dst, | |
| 1452 | 1490 | dst_type, __le16_to_cpu(psm)); |
| 1453 | 1491 | |
| 1454 | 1492 | hdev = hci_get_route(dst, src); |
| @@ -1461,7 +1499,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, · 6 unmodified lines | ||
| 1461 | 1499 | |
| 1462 | 1500 | /* PSM must be odd and lsb of upper byte must be 0 */ |
| 1463 | 1501 | if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid && |
| 1464 | − chan->chan_type != L2CAP_CHAN_RAW) { | |
| 1502 | + chan->chan_type != L2CAP_CHAN_RAW) { | |
| 1465 | 1503 | err = -EINVAL; |
| 1466 | 1504 | goto done; |
| 1467 | 1505 | } |
| @@ -1770,7 +1808,7 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan) · 302 unmodified lines | ||
| 1770 | 1808 | skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); |
| 1771 | 1809 | if (!skb) { |
| 1772 | 1810 | BT_DBG("Error: Can't retransmit seq %d, frame missing", |
| 1773 | − seq); | |
| 1811 | + seq); | |
| 1774 | 1812 | continue; |
| 1775 | 1813 | } |
| 1776 | 1814 | |
| @@ -1795,9 +1833,9 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan) · 18 unmodified lines | ||
| 1795 | 1833 | /* Cloned sk_buffs are read-only, so we need a |
| 1796 | 1834 | * writeable copy |
| 1797 | 1835 | */ |
| 1798 | − tx_skb = skb_copy(skb, GFP_ATOMIC); | |
| 1836 | + tx_skb = skb_copy(skb, GFP_KERNEL); | |
| 1799 | 1837 | } else { |
| 1800 | − tx_skb = skb_clone(skb, GFP_ATOMIC); | |
| 1838 | + tx_skb = skb_clone(skb, GFP_KERNEL); | |
| 1801 | 1839 | } |
| 1802 | 1840 | |
| 1803 | 1841 | if (!tx_skb) { |
| @@ -1855,7 +1893,7 @@ static void l2cap_retransmit_all(struct l2cap_chan *chan, · 51 unmodified lines | ||
| 1855 | 1893 | if (chan->unacked_frames) { |
| 1856 | 1894 | skb_queue_walk(&chan->tx_q, skb) { |
| 1857 | 1895 | if (bt_cb(skb)->control.txseq == control->reqseq || |
| 1858 | − skb == chan->tx_send_head) | |
| 1896 | + skb == chan->tx_send_head) | |
| 1859 | 1897 | break; |
| 1860 | 1898 | } |
| 1861 | 1899 | |
| @@ -2156,7 +2194,7 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan, · 294 unmodified lines | ||
| 2156 | 2194 | } |
| 2157 | 2195 | |
| 2158 | 2196 | int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, |
| 2159 | − u32 priority) | |
| 2197 | + u32 priority) | |
| 2160 | 2198 | { |
| 2161 | 2199 | struct sk_buff *skb; |
| 2162 | 2200 | int err; |
| @@ -2543,7 +2581,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) · 380 unmodified lines | ||
| 2543 | 2581 | /* Don't send frame to the socket it came from */ |
| 2544 | 2582 | if (skb->sk == sk) |
| 2545 | 2583 | continue; |
| 2546 | − nskb = skb_clone(skb, GFP_ATOMIC); | |
| 2584 | + nskb = skb_clone(skb, GFP_KERNEL); | |
| 2547 | 2585 | if (!nskb) |
| 2548 | 2586 | continue; |
| 2549 | 2587 | |
| @@ -2569,7 +2607,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, · 19 unmodified lines | ||
| 2569 | 2607 | len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; |
| 2570 | 2608 | count = min_t(unsigned int, conn->mtu, len); |
| 2571 | 2609 | |
| 2572 | − skb = bt_skb_alloc(count, GFP_ATOMIC); | |
| 2610 | + skb = bt_skb_alloc(count, GFP_KERNEL); | |
| 2573 | 2611 | if (!skb) |
| 2574 | 2612 | return NULL; |
| 2575 | 2613 | |
| @@ -2599,7 +2637,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, · 23 unmodified lines | ||
| 2599 | 2637 | while (len) { |
| 2600 | 2638 | count = min_t(unsigned int, conn->mtu, len); |
| 2601 | 2639 | |
| 2602 | − *frag = bt_skb_alloc(count, GFP_ATOMIC); | |
| 2640 | + *frag = bt_skb_alloc(count, GFP_KERNEL); | |
| 2603 | 2641 | if (!*frag) |
| 2604 | 2642 | goto fail; |
| 2605 | 2643 | |
| @@ -2618,7 +2656,8 @@ fail: · 12 unmodified lines | ||
| 2618 | 2656 | return NULL; |
| 2619 | 2657 | } |
| 2620 | 2658 | |
| 2621 | −static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val) | |
| 2659 | +static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, | |
| 2660 | + unsigned long *val) | |
| 2622 | 2661 | { |
| 2623 | 2662 | struct l2cap_conf_opt *opt = *ptr; |
| 2624 | 2663 | int len; |
| @@ -2692,7 +2731,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) · 67 unmodified lines | ||
| 2692 | 2731 | efs.msdu = cpu_to_le16(chan->local_msdu); |
| 2693 | 2732 | efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); |
| 2694 | 2733 | efs.acc_lat = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); |
| 2695 | − efs.flush_to = __constant_cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO); | |
| 2734 | + efs.flush_to = __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO); | |
| 2696 | 2735 | break; |
| 2697 | 2736 | |
| 2698 | 2737 | case L2CAP_MODE_STREAMING: |
| @@ -2709,7 +2748,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) · 10 unmodified lines | ||
| 2709 | 2748 | } |
| 2710 | 2749 | |
| 2711 | 2750 | l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), |
| 2712 | − (unsigned long) &efs); | |
| 2751 | + (unsigned long) &efs); | |
| 2713 | 2752 | } |
| 2714 | 2753 | |
| 2715 | 2754 | static void l2cap_ack_timeout(struct work_struct *work) |
| @@ -2798,13 +2837,13 @@ static inline bool __l2cap_efs_supported(struct l2cap_chan *chan) · 82 unmodified lines | ||
| 2798 | 2837 | static inline void l2cap_txwin_setup(struct l2cap_chan *chan) |
| 2799 | 2838 | { |
| 2800 | 2839 | if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && |
| 2801 | − __l2cap_ews_supported(chan)) { | |
| 2840 | + __l2cap_ews_supported(chan)) { | |
| 2802 | 2841 | /* use extended control field */ |
| 2803 | 2842 | set_bit(FLAG_EXT_CTRL, &chan->flags); |
| 2804 | 2843 | chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; |
| 2805 | 2844 | } else { |
| 2806 | 2845 | chan->tx_win = min_t(u16, chan->tx_win, |
| 2807 | − L2CAP_DEFAULT_TX_WINDOW); | |
| 2846 | + L2CAP_DEFAULT_TX_WINDOW); | |
| 2808 | 2847 | chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; |
| 2809 | 2848 | } |
| 2810 | 2849 | chan->ack_win = chan->tx_win; |
| @@ -2844,7 +2883,7 @@ done: · 33 unmodified lines | ||
| 2844 | 2883 | switch (chan->mode) { |
| 2845 | 2884 | case L2CAP_MODE_BASIC: |
| 2846 | 2885 | if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && |
| 2847 | − !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) | |
| 2886 | + !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) | |
| 2848 | 2887 | break; |
| 2849 | 2888 | |
| 2850 | 2889 | rfc.mode = L2CAP_MODE_BASIC; |
| @@ -2855,7 +2894,7 @@ done: · 4 unmodified lines | ||
| 2855 | 2894 | rfc.max_pdu_size = 0; |
| 2856 | 2895 | |
| 2857 | 2896 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), |
| 2858 | − (unsigned long) &rfc); | |
| 2897 | + (unsigned long) &rfc); | |
| 2859 | 2898 | break; |
| 2860 | 2899 | |
| 2861 | 2900 | case L2CAP_MODE_ERTM: |
| @@ -2865,18 +2904,17 @@ done: · 3 unmodified lines | ||
| 2865 | 2904 | rfc.monitor_timeout = 0; |
| 2866 | 2905 | |
| 2867 | 2906 | size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - |
| 2868 | − L2CAP_EXT_HDR_SIZE - | |
| 2869 | − L2CAP_SDULEN_SIZE - | |
| 2870 | − L2CAP_FCS_SIZE); | |
| 2907 | + L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - | |
| 2908 | + L2CAP_FCS_SIZE); | |
| 2871 | 2909 | rfc.max_pdu_size = cpu_to_le16(size); |
| 2872 | 2910 | |
| 2873 | 2911 | l2cap_txwin_setup(chan); |
| 2874 | 2912 | |
| 2875 | 2913 | rfc.txwin_size = min_t(u16, chan->tx_win, |
| 2876 | − L2CAP_DEFAULT_TX_WINDOW); | |
| 2914 | + L2CAP_DEFAULT_TX_WINDOW); | |
| 2877 | 2915 | |
| 2878 | 2916 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), |
| 2879 | − (unsigned long) &rfc); | |
| 2917 | + (unsigned long) &rfc); | |
| 2880 | 2918 | |
| 2881 | 2919 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) |
| 2882 | 2920 | l2cap_add_opt_efs(&ptr, chan); |
| @@ -2885,14 +2923,14 @@ done: · 2 unmodified lines | ||
| 2885 | 2923 | break; |
| 2886 | 2924 | |
| 2887 | 2925 | if (chan->fcs == L2CAP_FCS_NONE || |
| 2888 | − test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { | |
| 2926 | + test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { | |
| 2889 | 2927 | chan->fcs = L2CAP_FCS_NONE; |
| 2890 | 2928 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); |
| 2891 | 2929 | } |
| 2892 | 2930 | |
| 2893 | 2931 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) |
| 2894 | 2932 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, |
| 2895 | − chan->tx_win); | |
| 2933 | + chan->tx_win); | |
| 2896 | 2934 | break; |
| 2897 | 2935 | |
| 2898 | 2936 | case L2CAP_MODE_STREAMING: |
| @@ -2904,13 +2942,12 @@ done: · 5 unmodified lines | ||
| 2904 | 2942 | rfc.monitor_timeout = 0; |
| 2905 | 2943 | |
| 2906 | 2944 | size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - |
| 2907 | − L2CAP_EXT_HDR_SIZE - | |
| 2908 | − L2CAP_SDULEN_SIZE - | |
| 2909 | − L2CAP_FCS_SIZE); | |
| 2945 | + L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - | |
| 2946 | + L2CAP_FCS_SIZE); | |
| 2910 | 2947 | rfc.max_pdu_size = cpu_to_le16(size); |
| 2911 | 2948 | |
| 2912 | 2949 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), |
| 2913 | − (unsigned long) &rfc); | |
| 2950 | + (unsigned long) &rfc); | |
| 2914 | 2951 | |
| 2915 | 2952 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) |
| 2916 | 2953 | l2cap_add_opt_efs(&ptr, chan); |
| @@ -2919,7 +2956,7 @@ done: · 2 unmodified lines | ||
| 2919 | 2956 | break; |
| 2920 | 2957 | |
| 2921 | 2958 | if (chan->fcs == L2CAP_FCS_NONE || |
| 2922 | − test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { | |
| 2959 | + test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { | |
| 2923 | 2960 | chan->fcs = L2CAP_FCS_NONE; |
| 2924 | 2961 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); |
| 2925 | 2962 | } |
| @@ -3011,7 +3048,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) · 85 unmodified lines | ||
| 3011 | 3048 | case L2CAP_MODE_ERTM: |
| 3012 | 3049 | if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { |
| 3013 | 3050 | chan->mode = l2cap_select_mode(rfc.mode, |
| 3014 | − chan->conn->feat_mask); | |
| 3051 | + chan->conn->feat_mask); | |
| 3015 | 3052 | break; |
| 3016 | 3053 | } |
| 3017 | 3054 | |
| @@ -3036,8 +3073,8 @@ done: · 18 unmodified lines | ||
| 3036 | 3073 | if (chan->num_conf_rsp == 1) |
| 3037 | 3074 | return -ECONNREFUSED; |
| 3038 | 3075 | |
| 3039 | − l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, | |
| 3040 | − sizeof(rfc), (unsigned long) &rfc); | |
| 3076 | + l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), | |
| 3077 | + (unsigned long) &rfc); | |
| 3041 | 3078 | } |
| 3042 | 3079 | |
| 3043 | 3080 | if (result == L2CAP_CONF_SUCCESS) { |
| @@ -3054,8 +3091,8 @@ done: · 10 unmodified lines | ||
| 3054 | 3091 | |
| 3055 | 3092 | if (remote_efs) { |
| 3056 | 3093 | if (chan->local_stype != L2CAP_SERV_NOTRAFIC && |
| 3057 | − efs.stype != L2CAP_SERV_NOTRAFIC && | |
| 3058 | − efs.stype != chan->local_stype) { | |
| 3094 | + efs.stype != L2CAP_SERV_NOTRAFIC && | |
| 3095 | + efs.stype != chan->local_stype) { | |
| 3059 | 3096 | |
| 3060 | 3097 | result = L2CAP_CONF_UNACCEPT; |
| 3061 | 3098 | |
| @@ -3063,8 +3100,8 @@ done: · 1 unmodified line | ||
| 3063 | 3100 | return -ECONNREFUSED; |
| 3064 | 3101 | |
| 3065 | 3102 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, |
| 3066 | − sizeof(efs), | |
| 3067 | − (unsigned long) &efs); | |
| 3103 | + sizeof(efs), | |
| 3104 | + (unsigned long) &efs); | |
| 3068 | 3105 | } else { |
| 3069 | 3106 | /* Send PENDING Conf Rsp */ |
| 3070 | 3107 | result = L2CAP_CONF_PENDING; |
| @@ -3087,10 +3124,8 @@ done: · 16 unmodified lines | ||
| 3087 | 3124 | chan->remote_max_tx = rfc.max_transmit; |
| 3088 | 3125 | |
| 3089 | 3126 | size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), |
| 3090 | − chan->conn->mtu - | |
| 3091 | − L2CAP_EXT_HDR_SIZE - | |
| 3092 | − L2CAP_SDULEN_SIZE - | |
| 3093 | − L2CAP_FCS_SIZE); | |
| 3127 | + chan->conn->mtu - L2CAP_EXT_HDR_SIZE - | |
| 3128 | + L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); | |
| 3094 | 3129 | rfc.max_pdu_size = cpu_to_le16(size); |
| 3095 | 3130 | chan->remote_mps = size; |
| 3096 | 3131 | |
| @@ -3102,36 +3137,35 @@ done: · 5 unmodified lines | ||
| 3102 | 3137 | set_bit(CONF_MODE_DONE, &chan->conf_state); |
| 3103 | 3138 | |
| 3104 | 3139 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, |
| 3105 | − sizeof(rfc), (unsigned long) &rfc); | |
| 3140 | + sizeof(rfc), (unsigned long) &rfc); | |
| 3106 | 3141 | |
| 3107 | 3142 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { |
| 3108 | 3143 | chan->remote_id = efs.id; |
| 3109 | 3144 | chan->remote_stype = efs.stype; |
| 3110 | 3145 | chan->remote_msdu = le16_to_cpu(efs.msdu); |
| 3111 | 3146 | chan->remote_flush_to = |
| 3112 | − le32_to_cpu(efs.flush_to); | |
| 3147 | + le32_to_cpu(efs.flush_to); | |
| 3113 | 3148 | chan->remote_acc_lat = |
| 3114 | − le32_to_cpu(efs.acc_lat); | |
| 3149 | + le32_to_cpu(efs.acc_lat); | |
| 3115 | 3150 | chan->remote_sdu_itime = |
| 3116 | 3151 | le32_to_cpu(efs.sdu_itime); |
| 3117 | 3152 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, |
| 3118 | − sizeof(efs), (unsigned long) &efs); | |
| 3153 | + sizeof(efs), | |
| 3154 | + (unsigned long) &efs); | |
| 3119 | 3155 | } |
| 3120 | 3156 | break; |
| 3121 | 3157 | |
| 3122 | 3158 | case L2CAP_MODE_STREAMING: |
| 3123 | 3159 | size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), |
| 3124 | − chan->conn->mtu - | |
| 3125 | − L2CAP_EXT_HDR_SIZE - | |
| 3126 | − L2CAP_SDULEN_SIZE - | |
| 3127 | − L2CAP_FCS_SIZE); | |
| 3160 | + chan->conn->mtu - L2CAP_EXT_HDR_SIZE - | |
| 3161 | + L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); | |
| 3128 | 3162 | rfc.max_pdu_size = cpu_to_le16(size); |
| 3129 | 3163 | chan->remote_mps = size; |
| 3130 | 3164 | |
| 3131 | 3165 | set_bit(CONF_MODE_DONE, &chan->conf_state); |
| 3132 | 3166 | |
| 3133 | − l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, | |
| 3134 | − sizeof(rfc), (unsigned long) &rfc); | |
| 3167 | + l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), | |
| 3168 | + (unsigned long) &rfc); | |
| 3135 | 3169 | |
| 3136 | 3170 | break; |
| 3137 | 3171 | |
| @@ -3152,7 +3186,8 @@ done: · 14 unmodified lines | ||
| 3152 | 3186 | return ptr - data; |
| 3153 | 3187 | } |
| 3154 | 3188 | |
| 3155 | −static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result) | |
| 3189 | +static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, | |
| 3190 | + void *data, u16 *result) | |
| 3156 | 3191 | { |
| 3157 | 3192 | struct l2cap_conf_req *req = data; |
| 3158 | 3193 | void *ptr = req->data; |
| @@ -3179,7 +3214,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi · 20 unmodified lines | ||
| 3179 | 3214 | case L2CAP_CONF_FLUSH_TO: |
| 3180 | 3215 | chan->flush_to = val; |
| 3181 | 3216 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, |
| 3182 | − 2, chan->flush_to); | |
| 3217 | + 2, chan->flush_to); | |
| 3183 | 3218 | break; |
| 3184 | 3219 | |
| 3185 | 3220 | case L2CAP_CONF_RFC: |
| @@ -3187,13 +3222,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi · 1 unmodified line | ||
| 3187 | 3222 | memcpy(&rfc, (void *)val, olen); |
| 3188 | 3223 | |
| 3189 | 3224 | if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && |
| 3190 | − rfc.mode != chan->mode) | |
| 3225 | + rfc.mode != chan->mode) | |
| 3191 | 3226 | return -ECONNREFUSED; |
| 3192 | 3227 | |
| 3193 | 3228 | chan->fcs = 0; |
| 3194 | 3229 | |
| 3195 | 3230 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, |
| 3196 | − sizeof(rfc), (unsigned long) &rfc); | |
| 3231 | + sizeof(rfc), (unsigned long) &rfc); | |
| 3197 | 3232 | break; |
| 3198 | 3233 | |
| 3199 | 3234 | case L2CAP_CONF_EWS: |
| @@ -3207,12 +3242,12 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi · 7 unmodified lines | ||
| 3207 | 3242 | memcpy(&efs, (void *)val, olen); |
| 3208 | 3243 | |
| 3209 | 3244 | if (chan->local_stype != L2CAP_SERV_NOTRAFIC && |
| 3210 | − efs.stype != L2CAP_SERV_NOTRAFIC && | |
| 3211 | − efs.stype != chan->local_stype) | |
| 3245 | + efs.stype != L2CAP_SERV_NOTRAFIC && | |
| 3246 | + efs.stype != chan->local_stype) | |
| 3212 | 3247 | return -ECONNREFUSED; |
| 3213 | 3248 | |
| 3214 | − l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, | |
| 3215 | − sizeof(efs), (unsigned long) &efs); | |
| 3249 | + l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), | |
| 3250 | + (unsigned long) &efs); | |
| 3216 | 3251 | break; |
| 3217 | 3252 | } |
| 3218 | 3253 | } |
| @@ -3235,10 +3270,10 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi · 16 unmodified lines | ||
| 3235 | 3270 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { |
| 3236 | 3271 | chan->local_msdu = le16_to_cpu(efs.msdu); |
| 3237 | 3272 | chan->local_sdu_itime = |
| 3238 | − le32_to_cpu(efs.sdu_itime); | |
| 3273 | + le32_to_cpu(efs.sdu_itime); | |
| 3239 | 3274 | chan->local_acc_lat = le32_to_cpu(efs.acc_lat); |
| 3240 | 3275 | chan->local_flush_to = |
| 3241 | − le32_to_cpu(efs.flush_to); | |
| 3276 | + le32_to_cpu(efs.flush_to); | |
| 3242 | 3277 | } |
| 3243 | 3278 | break; |
| 3244 | 3279 | |
| @@ -3253,7 +3288,8 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi · 8 unmodified lines | ||
| 3253 | 3288 | return ptr - data; |
| 3254 | 3289 | } |
| 3255 | 3290 | |
| 3256 | −static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags) | |
| 3291 | +static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, | |
| 3292 | + u16 result, u16 flags) | |
| 3257 | 3293 | { |
| 3258 | 3294 | struct l2cap_conf_rsp *rsp = data; |
| 3259 | 3295 | void *ptr = rsp->data; |
| @@ -3277,14 +3313,13 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) · 17 unmodified lines | ||
| 3277 | 3313 | rsp.dcid = cpu_to_le16(chan->scid); |
| 3278 | 3314 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); |
| 3279 | 3315 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); |
| 3280 | − l2cap_send_cmd(conn, chan->ident, | |
| 3281 | − L2CAP_CONN_RSP, sizeof(rsp), &rsp); | |
| 3316 | + l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); | |
| 3282 | 3317 | |
| 3283 | 3318 | if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) |
| 3284 | 3319 | return; |
| 3285 | 3320 | |
| 3286 | 3321 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, |
| 3287 | − l2cap_build_conf_req(chan, buf), buf); | |
| 3322 | + l2cap_build_conf_req(chan, buf), buf); | |
| 3288 | 3323 | chan->num_conf_req++; |
| 3289 | 3324 | } |
| 3290 | 3325 | |
| @@ -3339,7 +3374,8 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) · 48 unmodified lines | ||
| 3339 | 3374 | } |
| 3340 | 3375 | } |
| 3341 | 3376 | |
| 3342 | −static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 3377 | +static inline int l2cap_command_rej(struct l2cap_conn *conn, | |
| 3378 | + struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 3343 | 3379 | { |
| 3344 | 3380 | struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; |
| 3345 | 3381 | |
| @@ -3347,7 +3383,7 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd · 1 unmodified line | ||
| 3347 | 3383 | return 0; |
| 3348 | 3384 | |
| 3349 | 3385 | if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && |
| 3350 | − cmd->ident == conn->info_ident) { | |
| 3386 | + cmd->ident == conn->info_ident) { | |
| 3351 | 3387 | cancel_delayed_work(&conn->info_timer); |
| 3352 | 3388 | |
| 3353 | 3389 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; |
| @@ -3359,7 +3395,8 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd · 5 unmodified lines | ||
| 3359 | 3395 | return 0; |
| 3360 | 3396 | } |
| 3361 | 3397 | |
| 3362 | −static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 3398 | +static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, | |
| 3399 | + u8 *data, u8 rsp_code, u8 amp_id) | |
| 3363 | 3400 | { |
| 3364 | 3401 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; |
| 3365 | 3402 | struct l2cap_conn_rsp rsp; |
| @@ -3386,7 +3423,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd · 20 unmodified lines | ||
| 3386 | 3423 | |
| 3387 | 3424 | /* Check if the ACL is secure enough (if not SDP) */ |
| 3388 | 3425 | if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && |
| 3389 | − !hci_conn_check_link_mode(conn->hcon)) { | |
| 3426 | + !hci_conn_check_link_mode(conn->hcon)) { | |
| 3390 | 3427 | conn->disc_reason = HCI_ERROR_AUTH_FAILURE; |
| 3391 | 3428 | result = L2CAP_CR_SEC_BLOCK; |
| 3392 | 3429 | goto response; |
| @@ -3411,8 +3448,6 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd · 18 unmodified lines | ||
| 3411 | 3448 | chan->psm = psm; |
| 3412 | 3449 | chan->dcid = scid; |
| 3413 | 3450 | |
| 3414 | − bt_accept_enqueue(parent, sk); | |
| 3415 | − | |
| 3416 | 3451 | __l2cap_chan_add(conn, chan); |
| 3417 | 3452 | |
| 3418 | 3453 | dcid = chan->scid; |
| @@ -3427,7 +3462,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd · 8 unmodified lines | ||
| 3427 | 3462 | __l2cap_state_change(chan, BT_CONNECT2); |
| 3428 | 3463 | result = L2CAP_CR_PEND; |
| 3429 | 3464 | status = L2CAP_CS_AUTHOR_PEND; |
| 3430 | − parent->sk_data_ready(parent, 0); | |
| 3465 | + chan->ops->defer(chan); | |
| 3431 | 3466 | } else { |
| 3432 | 3467 | __l2cap_state_change(chan, BT_CONFIG); |
| 3433 | 3468 | result = L2CAP_CR_SUCCESS; |
| @@ -3453,7 +3488,7 @@ sendresp: · 19 unmodified lines | ||
| 3453 | 3488 | rsp.dcid = cpu_to_le16(dcid); |
| 3454 | 3489 | rsp.result = cpu_to_le16(result); |
| 3455 | 3490 | rsp.status = cpu_to_le16(status); |
| 3456 | − l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); | |
| 3491 | + l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp); | |
| 3457 | 3492 | |
| 3458 | 3493 | if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { |
| 3459 | 3494 | struct l2cap_info_req info; |
| @@ -3464,23 +3499,29 @@ sendresp: · 4 unmodified lines | ||
| 3464 | 3499 | |
| 3465 | 3500 | schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); |
| 3466 | 3501 | |
| 3467 | − l2cap_send_cmd(conn, conn->info_ident, | |
| 3468 | − L2CAP_INFO_REQ, sizeof(info), &info); | |
| 3502 | + l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, | |
| 3503 | + sizeof(info), &info); | |
| 3469 | 3504 | } |
| 3470 | 3505 | |
| 3471 | 3506 | if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && |
| 3472 | − result == L2CAP_CR_SUCCESS) { | |
| 3507 | + result == L2CAP_CR_SUCCESS) { | |
| 3473 | 3508 | u8 buf[128]; |
| 3474 | 3509 | set_bit(CONF_REQ_SENT, &chan->conf_state); |
| 3475 | 3510 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, |
| 3476 | − l2cap_build_conf_req(chan, buf), buf); | |
| 3511 | + l2cap_build_conf_req(chan, buf), buf); | |
| 3477 | 3512 | chan->num_conf_req++; |
| 3478 | 3513 | } |
| 3514 | +} | |
| 3479 | 3515 | |
| 3516 | +static int l2cap_connect_req(struct l2cap_conn *conn, | |
| 3517 | + struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 3518 | +{ | |
| 3519 | + l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); | |
| 3480 | 3520 | return 0; |
| 3481 | 3521 | } |
| 3482 | 3522 | |
| 3483 | −static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 3523 | +static inline int l2cap_connect_rsp(struct l2cap_conn *conn, | |
| 3524 | + struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 3484 | 3525 | { |
| 3485 | 3526 | struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; |
| 3486 | 3527 | u16 scid, dcid, result, status; |
| @@ -3494,7 +3535,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd · 7 unmodified lines | ||
| 3494 | 3535 | status = __le16_to_cpu(rsp->status); |
| 3495 | 3536 | |
| 3496 | 3537 | BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", |
| 3497 | − dcid, scid, result, status); | |
| 3538 | + dcid, scid, result, status); | |
| 3498 | 3539 | |
| 3499 | 3540 | mutex_lock(&conn->chan_lock); |
| 3500 | 3541 | |
| @@ -3527,7 +3568,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd · 26 unmodified lines | ||
| 3527 | 3568 | break; |
| 3528 | 3569 | |
| 3529 | 3570 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, |
| 3530 | − l2cap_build_conf_req(chan, req), req); | |
| 3571 | + l2cap_build_conf_req(chan, req), req); | |
| 3531 | 3572 | chan->num_conf_req++; |
| 3532 | 3573 | break; |
| 3533 | 3574 | |
| @@ -3559,7 +3600,25 @@ static inline void set_default_fcs(struct l2cap_chan *chan) · 25 unmodified lines | ||
| 3559 | 3600 | chan->fcs = L2CAP_FCS_CRC16; |
| 3560 | 3601 | } |
| 3561 | 3602 | |
| 3562 | −static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) | |
| 3603 | +static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data, | |
| 3604 | + u8 ident, u16 flags) | |
| 3605 | +{ | |
| 3606 | + struct l2cap_conn *conn = chan->conn; | |
| 3607 | + | |
| 3608 | + BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident, | |
| 3609 | + flags); | |
| 3610 | + | |
| 3611 | + clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); | |
| 3612 | + set_bit(CONF_OUTPUT_DONE, &chan->conf_state); | |
| 3613 | + | |
| 3614 | + l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP, | |
| 3615 | + l2cap_build_conf_rsp(chan, data, | |
| 3616 | + L2CAP_CONF_SUCCESS, flags), data); | |
| 3617 | +} | |
| 3618 | + | |
| 3619 | +static inline int l2cap_config_req(struct l2cap_conn *conn, | |
| 3620 | + struct l2cap_cmd_hdr *cmd, u16 cmd_len, | |
| 3621 | + u8 *data) | |
| 3563 | 3622 | { |
| 3564 | 3623 | struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; |
| 3565 | 3624 | u16 dcid, flags; |
| @@ -3584,7 +3643,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr · 18 unmodified lines | ||
| 3584 | 3643 | rej.dcid = cpu_to_le16(chan->dcid); |
| 3585 | 3644 | |
| 3586 | 3645 | l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, |
| 3587 | − sizeof(rej), &rej); | |
| 3646 | + sizeof(rej), &rej); | |
| 3588 | 3647 | goto unlock; |
| 3589 | 3648 | } |
| 3590 | 3649 | |
| @@ -3592,8 +3651,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr · 1 unmodified line | ||
| 3592 | 3651 | len = cmd_len - sizeof(*req); |
| 3593 | 3652 | if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) { |
| 3594 | 3653 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, |
| 3595 | − l2cap_build_conf_rsp(chan, rsp, | |
| 3596 | − L2CAP_CONF_REJECT, flags), rsp); | |
| 3654 | + l2cap_build_conf_rsp(chan, rsp, | |
| 3655 | + L2CAP_CONF_REJECT, flags), rsp); | |
| 3597 | 3656 | goto unlock; |
| 3598 | 3657 | } |
| 3599 | 3658 | |
| @@ -3604,8 +3663,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr · 4 unmodified lines | ||
| 3604 | 3663 | if (flags & L2CAP_CONF_FLAG_CONTINUATION) { |
| 3605 | 3664 | /* Incomplete config. Send empty response. */ |
| 3606 | 3665 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, |
| 3607 | − l2cap_build_conf_rsp(chan, rsp, | |
| 3608 | − L2CAP_CONF_SUCCESS, flags), rsp); | |
| 3666 | + l2cap_build_conf_rsp(chan, rsp, | |
| 3667 | + L2CAP_CONF_SUCCESS, flags), rsp); | |
| 3609 | 3668 | goto unlock; |
| 3610 | 3669 | } |
| 3611 | 3670 | |
| @@ -3643,23 +3702,22 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr · 31 unmodified lines | ||
| 3643 | 3702 | if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { |
| 3644 | 3703 | u8 buf[64]; |
| 3645 | 3704 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, |
| 3646 | − l2cap_build_conf_req(chan, buf), buf); | |
| 3705 | + l2cap_build_conf_req(chan, buf), buf); | |
| 3647 | 3706 | chan->num_conf_req++; |
| 3648 | 3707 | } |
| 3649 | 3708 | |
| 3650 | 3709 | /* Got Conf Rsp PENDING from remote side and asume we sent |
| 3651 | 3710 | Conf Rsp PENDING in the code above */ |
| 3652 | 3711 | if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && |
| 3653 | − test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { | |
| 3712 | + test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { | |
| 3654 | 3713 | |
| 3655 | 3714 | /* check compatibility */ |
| 3656 | 3715 | |
| 3657 | − clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); | |
| 3658 | − set_bit(CONF_OUTPUT_DONE, &chan->conf_state); | |
| 3659 | − | |
| 3660 | − l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, | |
| 3661 | − l2cap_build_conf_rsp(chan, rsp, | |
| 3662 | − L2CAP_CONF_SUCCESS, flags), rsp); | |
| 3716 | + /* Send rsp for BR/EDR channel */ | |
| 3717 | + if (!chan->ctrl_id) | |
| 3718 | + l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags); | |
| 3719 | + else | |
| 3720 | + chan->ident = cmd->ident; | |
| 3663 | 3721 | } |
| 3664 | 3722 | |
| 3665 | 3723 | unlock: |
| @@ -3667,7 +3725,8 @@ unlock: · 1 unmodified line | ||
| 3667 | 3725 | return err; |
| 3668 | 3726 | } |
| 3669 | 3727 | |
| 3670 | −static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 3728 | +static inline int l2cap_config_rsp(struct l2cap_conn *conn, | |
| 3729 | + struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 3671 | 3730 | { |
| 3672 | 3731 | struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; |
| 3673 | 3732 | u16 scid, flags, result; |
| @@ -3699,7 +3758,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr · 25 unmodified lines | ||
| 3699 | 3758 | char buf[64]; |
| 3700 | 3759 | |
| 3701 | 3760 | len = l2cap_parse_conf_rsp(chan, rsp->data, len, |
| 3702 | − buf, &result); | |
| 3761 | + buf, &result); | |
| 3703 | 3762 | if (len < 0) { |
| 3704 | 3763 | l2cap_send_disconn_req(conn, chan, ECONNRESET); |
| 3705 | 3764 | goto done; |
| @@ -3707,12 +3766,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr · 1 unmodified line | ||
| 3707 | 3766 | |
| 3708 | 3767 | /* check compatibility */ |
| 3709 | 3768 | |
| 3710 | − clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); | |
| 3711 | − set_bit(CONF_OUTPUT_DONE, &chan->conf_state); | |
| 3712 | − | |
| 3713 | − l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, | |
| 3714 | − l2cap_build_conf_rsp(chan, buf, | |
| 3715 | − L2CAP_CONF_SUCCESS, 0x0000), buf); | |
| 3769 | + if (!chan->ctrl_id) | |
| 3770 | + l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, | |
| 3771 | + 0); | |
| 3772 | + else | |
| 3773 | + chan->ident = cmd->ident; | |
| 3716 | 3774 | } |
| 3717 | 3775 | goto done; |
| 3718 | 3776 | |
| @@ -3728,14 +3786,14 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr · 9 unmodified lines | ||
| 3728 | 3786 | /* throw out any old stored conf requests */ |
| 3729 | 3787 | result = L2CAP_CONF_SUCCESS; |
| 3730 | 3788 | len = l2cap_parse_conf_rsp(chan, rsp->data, len, |
| 3731 | − req, &result); | |
| 3789 | + req, &result); | |
| 3732 | 3790 | if (len < 0) { |
| 3733 | 3791 | l2cap_send_disconn_req(conn, chan, ECONNRESET); |
| 3734 | 3792 | goto done; |
| 3735 | 3793 | } |
| 3736 | 3794 | |
| 3737 | 3795 | l2cap_send_cmd(conn, l2cap_get_ident(conn), |
| 3738 | − L2CAP_CONF_REQ, len, req); | |
| 3796 | + L2CAP_CONF_REQ, len, req); | |
| 3739 | 3797 | chan->num_conf_req++; |
| 3740 | 3798 | if (result != L2CAP_CONF_SUCCESS) |
| 3741 | 3799 | goto done; |
| @@ -3773,7 +3831,8 @@ done: · 31 unmodified lines | ||
| 3773 | 3831 | return err; |
| 3774 | 3832 | } |
| 3775 | 3833 | |
| 3776 | −static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 3834 | +static inline int l2cap_disconnect_req(struct l2cap_conn *conn, | |
| 3835 | + struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 3777 | 3836 | { |
| 3778 | 3837 | struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; |
| 3779 | 3838 | struct l2cap_disconn_rsp rsp; |
| @@ -3819,7 +3878,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd · 39 unmodified lines | ||
| 3819 | 3878 | return 0; |
| 3820 | 3879 | } |
| 3821 | 3880 | |
| 3822 | −static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 3881 | +static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, | |
| 3882 | + struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 3823 | 3883 | { |
| 3824 | 3884 | struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; |
| 3825 | 3885 | u16 dcid, scid; |
| @@ -3853,7 +3913,8 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd · 27 unmodified lines | ||
| 3853 | 3913 | return 0; |
| 3854 | 3914 | } |
| 3855 | 3915 | |
| 3856 | −static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 3916 | +static inline int l2cap_information_req(struct l2cap_conn *conn, | |
| 3917 | + struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 3857 | 3918 | { |
| 3858 | 3919 | struct l2cap_info_req *req = (struct l2cap_info_req *) data; |
| 3859 | 3920 | u16 type; |
| @@ -3870,14 +3931,14 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm · 10 unmodified lines | ||
| 3870 | 3931 | rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); |
| 3871 | 3932 | if (!disable_ertm) |
| 3872 | 3933 | feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING |
| 3873 | − | L2CAP_FEAT_FCS; | |
| 3934 | + | L2CAP_FEAT_FCS; | |
| 3874 | 3935 | if (enable_hs) |
| 3875 | 3936 | feat_mask |= L2CAP_FEAT_EXT_FLOW |
| 3876 | − | L2CAP_FEAT_EXT_WINDOW; | |
| 3937 | + | L2CAP_FEAT_EXT_WINDOW; | |
| 3877 | 3938 | |
| 3878 | 3939 | put_unaligned_le32(feat_mask, rsp->data); |
| 3879 | − l2cap_send_cmd(conn, cmd->ident, | |
| 3880 | − L2CAP_INFO_RSP, sizeof(buf), buf); | |
| 3940 | + l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), | |
| 3941 | + buf); | |
| 3881 | 3942 | } else if (type == L2CAP_IT_FIXED_CHAN) { |
| 3882 | 3943 | u8 buf[12]; |
| 3883 | 3944 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; |
| @@ -3890,20 +3951,21 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm · 6 unmodified lines | ||
| 3890 | 3951 | rsp->type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); |
| 3891 | 3952 | rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); |
| 3892 | 3953 | memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); |
| 3893 | − l2cap_send_cmd(conn, cmd->ident, | |
| 3894 | − L2CAP_INFO_RSP, sizeof(buf), buf); | |
| 3954 | + l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), | |
| 3955 | + buf); | |
| 3895 | 3956 | } else { |
| 3896 | 3957 | struct l2cap_info_rsp rsp; |
| 3897 | 3958 | rsp.type = cpu_to_le16(type); |
| 3898 | 3959 | rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP); |
| 3899 | − l2cap_send_cmd(conn, cmd->ident, | |
| 3900 | − L2CAP_INFO_RSP, sizeof(rsp), &rsp); | |
| 3960 | + l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), | |
| 3961 | + &rsp); | |
| 3901 | 3962 | } |
| 3902 | 3963 | |
| 3903 | 3964 | return 0; |
| 3904 | 3965 | } |
| 3905 | 3966 | |
| 3906 | −static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 3967 | +static inline int l2cap_information_rsp(struct l2cap_conn *conn, | |
| 3968 | + struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 3907 | 3969 | { |
| 3908 | 3970 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; |
| 3909 | 3971 | u16 type, result; |
| @@ -3915,7 +3977,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm · 5 unmodified lines | ||
| 3915 | 3977 | |
| 3916 | 3978 | /* L2CAP Info req/rsp are unbound to channels, add extra checks */ |
| 3917 | 3979 | if (cmd->ident != conn->info_ident || |
| 3918 | − conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) | |
| 3980 | + conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) | |
| 3919 | 3981 | return 0; |
| 3920 | 3982 | |
| 3921 | 3983 | cancel_delayed_work(&conn->info_timer); |
| @@ -3940,7 +4002,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm · 18 unmodified lines | ||
| 3940 | 4002 | conn->info_ident = l2cap_get_ident(conn); |
| 3941 | 4003 | |
| 3942 | 4004 | l2cap_send_cmd(conn, conn->info_ident, |
| 3943 | − L2CAP_INFO_REQ, sizeof(req), &req); | |
| 4005 | + L2CAP_INFO_REQ, sizeof(req), &req); | |
| 3944 | 4006 | } else { |
| 3945 | 4007 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; |
| 3946 | 4008 | conn->info_ident = 0; |
| @@ -3962,8 +4024,8 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm · 15 unmodified lines | ||
| 3962 | 4024 | } |
| 3963 | 4025 | |
| 3964 | 4026 | static inline int l2cap_create_channel_req(struct l2cap_conn *conn, |
| 3965 | − struct l2cap_cmd_hdr *cmd, u16 cmd_len, | |
| 3966 | − void *data) | |
| 4027 | + struct l2cap_cmd_hdr *cmd, | |
| 4028 | + u16 cmd_len, void *data) | |
| 3967 | 4029 | { |
| 3968 | 4030 | struct l2cap_create_chan_req *req = data; |
| 3969 | 4031 | struct l2cap_create_chan_rsp rsp; |
| @@ -3993,7 +4055,8 @@ static inline int l2cap_create_channel_req(struct l2cap_conn *conn, · 23 unmodified lines | ||
| 3993 | 4055 | } |
| 3994 | 4056 | |
| 3995 | 4057 | static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn, |
| 3996 | − struct l2cap_cmd_hdr *cmd, void *data) | |
| 4058 | + struct l2cap_cmd_hdr *cmd, | |
| 4059 | + void *data) | |
| 3997 | 4060 | { |
| 3998 | 4061 | BT_DBG("conn %p", conn); |
| 3999 | 4062 | |
| @@ -4126,7 +4189,7 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, · 126 unmodified lines | ||
| 4126 | 4189 | } |
| 4127 | 4190 | |
| 4128 | 4191 | static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, |
| 4129 | − u16 to_multiplier) | |
| 4192 | + u16 to_multiplier) | |
| 4130 | 4193 | { |
| 4131 | 4194 | u16 max_latency; |
| 4132 | 4195 | |
| @@ -4147,7 +4210,8 @@ static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, · 14 unmodified lines | ||
| 4147 | 4210 | } |
| 4148 | 4211 | |
| 4149 | 4212 | static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, |
| 4150 | − struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 4213 | + struct l2cap_cmd_hdr *cmd, | |
| 4214 | + u8 *data) | |
| 4151 | 4215 | { |
| 4152 | 4216 | struct hci_conn *hcon = conn->hcon; |
| 4153 | 4217 | struct l2cap_conn_param_update_req *req; |
| @@ -4169,7 +4233,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, · 15 unmodified lines | ||
| 4169 | 4233 | to_multiplier = __le16_to_cpu(req->to_multiplier); |
| 4170 | 4234 | |
| 4171 | 4235 | BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", |
| 4172 | − min, max, latency, to_multiplier); | |
| 4236 | + min, max, latency, to_multiplier); | |
| 4173 | 4237 | |
| 4174 | 4238 | memset(&rsp, 0, sizeof(rsp)); |
| 4175 | 4239 | |
| @@ -4180,7 +4244,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, · 4 unmodified lines | ||
| 4180 | 4244 | rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); |
| 4181 | 4245 | |
| 4182 | 4246 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, |
| 4183 | − sizeof(rsp), &rsp); | |
| 4247 | + sizeof(rsp), &rsp); | |
| 4184 | 4248 | |
| 4185 | 4249 | if (!err) |
| 4186 | 4250 | hci_le_conn_update(hcon, min, max, latency, to_multiplier); |
| @@ -4189,7 +4253,8 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, · 2 unmodified lines | ||
| 4189 | 4253 | } |
| 4190 | 4254 | |
| 4191 | 4255 | static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, |
| 4192 | − struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) | |
| 4256 | + struct l2cap_cmd_hdr *cmd, u16 cmd_len, | |
| 4257 | + u8 *data) | |
| 4193 | 4258 | { |
| 4194 | 4259 | int err = 0; |
| 4195 | 4260 | |
| @@ -4203,6 +4268,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, · 7 unmodified lines | ||
| 4203 | 4268 | break; |
| 4204 | 4269 | |
| 4205 | 4270 | case L2CAP_CONN_RSP: |
| 4271 | + case L2CAP_CREATE_CHAN_RSP: | |
| 4206 | 4272 | err = l2cap_connect_rsp(conn, cmd, data); |
| 4207 | 4273 | break; |
| 4208 | 4274 | |
| @@ -4241,10 +4307,6 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, · 32 unmodified lines | ||
| 4241 | 4307 | err = l2cap_create_channel_req(conn, cmd, cmd_len, data); |
| 4242 | 4308 | break; |
| 4243 | 4309 | |
| 4244 | − case L2CAP_CREATE_CHAN_RSP: | |
| 4245 | − err = l2cap_create_channel_rsp(conn, cmd, data); | |
| 4246 | − break; | |
| 4247 | − | |
| 4248 | 4310 | case L2CAP_MOVE_CHAN_REQ: |
| 4249 | 4311 | err = l2cap_move_channel_req(conn, cmd, cmd_len, data); |
| 4250 | 4312 | break; |
| @@ -4271,7 +4333,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, · 20 unmodified lines | ||
| 4271 | 4333 | } |
| 4272 | 4334 | |
| 4273 | 4335 | static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, |
| 4274 | − struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 4336 | + struct l2cap_cmd_hdr *cmd, u8 *data) | |
| 4275 | 4337 | { |
| 4276 | 4338 | switch (cmd->code) { |
| 4277 | 4339 | case L2CAP_COMMAND_REJ: |
| @@ -4290,7 +4352,7 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, · 12 unmodified lines | ||
| 4290 | 4352 | } |
| 4291 | 4353 | |
| 4292 | 4354 | static inline void l2cap_sig_channel(struct l2cap_conn *conn, |
| 4293 | − struct sk_buff *skb) | |
| 4355 | + struct sk_buff *skb) | |
| 4294 | 4356 | { |
| 4295 | 4357 | u8 *data = skb->data; |
| 4296 | 4358 | int len = skb->len; |
| @@ -4307,7 +4369,8 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, · 10 unmodified lines | ||
| 4307 | 4369 | |
| 4308 | 4370 | cmd_len = le16_to_cpu(cmd.len); |
| 4309 | 4371 | |
| 4310 | − BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident); | |
| 4372 | + BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, | |
| 4373 | + cmd.ident); | |
| 4311 | 4374 | |
| 4312 | 4375 | if (cmd_len > len || !cmd.ident) { |
| 4313 | 4376 | BT_DBG("corrupted command"); |
| @@ -4326,7 +4389,8 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, · 12 unmodified lines | ||
| 4326 | 4389 | |
| 4327 | 4390 | /* FIXME: Map err to a valid reason */ |
| 4328 | 4391 | rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); |
| 4329 | − l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); | |
| 4392 | + l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, | |
| 4393 | + sizeof(rej), &rej); | |
| 4330 | 4394 | } |
| 4331 | 4395 | |
| 4332 | 4396 | data += cmd_len; |
| @@ -4391,8 +4455,8 @@ static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) · 58 unmodified lines | ||
| 4391 | 4455 | } |
| 4392 | 4456 | } |
| 4393 | 4457 | |
| 4394 | −static void append_skb_frag(struct sk_buff *skb, | |
| 4395 | − struct sk_buff *new_frag, struct sk_buff **last_frag) | |
| 4458 | +static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag, | |
| 4459 | + struct sk_buff **last_frag) | |
| 4396 | 4460 | { |
| 4397 | 4461 | /* skb->len reflects data in skb as well as all fragments |
| 4398 | 4462 | * skb->data_len reflects only data in fragments |
| @@ -4641,7 +4705,7 @@ static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) · 242 unmodified lines | ||
| 4641 | 4705 | |
| 4642 | 4706 | if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { |
| 4643 | 4707 | if (__seq_offset(chan, txseq, chan->last_acked_seq) >= |
| 4644 | − chan->tx_win) { | |
| 4708 | + chan->tx_win) { | |
| 4645 | 4709 | /* See notes below regarding "double poll" and |
| 4646 | 4710 | * invalid packets. |
| 4647 | 4711 | */ |
| @@ -4682,8 +4746,7 @@ static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) · 34 unmodified lines | ||
| 4682 | 4746 | } |
| 4683 | 4747 | |
| 4684 | 4748 | if (__seq_offset(chan, txseq, chan->last_acked_seq) < |
| 4685 | − __seq_offset(chan, chan->expected_tx_seq, | |
| 4686 | − chan->last_acked_seq)){ | |
| 4749 | + __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) { | |
| 4687 | 4750 | BT_DBG("Duplicate - expected_tx_seq later than txseq"); |
| 4688 | 4751 | return L2CAP_TXSEQ_DUPLICATE; |
| 4689 | 4752 | } |
| @@ -5323,7 +5386,7 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) · 633 unmodified lines | ||
| 5323 | 5386 | int exact = 0, lm1 = 0, lm2 = 0; |
| 5324 | 5387 | struct l2cap_chan *c; |
| 5325 | 5388 | |
| 5326 | − BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); | |
| 5389 | + BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr); | |
| 5327 | 5390 | |
| 5328 | 5391 | /* Find listening sockets and check their link_mode */ |
| 5329 | 5392 | read_lock(&chan_list_lock); |
| @@ -5353,7 +5416,7 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) · 23 unmodified lines | ||
| 5353 | 5416 | { |
| 5354 | 5417 | struct l2cap_conn *conn; |
| 5355 | 5418 | |
| 5356 | − BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); | |
| 5419 | + BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); | |
| 5357 | 5420 | |
| 5358 | 5421 | if (!status) { |
| 5359 | 5422 | conn = l2cap_conn_add(hcon, status); |
| @@ -5443,7 +5506,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) · 83 unmodified lines | ||
| 5443 | 5506 | } |
| 5444 | 5507 | |
| 5445 | 5508 | if (!status && (chan->state == BT_CONNECTED || |
| 5446 | − chan->state == BT_CONFIG)) { | |
| 5509 | + chan->state == BT_CONFIG)) { | |
| 5447 | 5510 | struct sock *sk = chan->sk; |
| 5448 | 5511 | |
| 5449 | 5512 | clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); |
| @@ -5456,7 +5519,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) · 6 unmodified lines | ||
| 5456 | 5519 | |
| 5457 | 5520 | if (chan->state == BT_CONNECT) { |
| 5458 | 5521 | if (!status) { |
| 5459 | − l2cap_send_conn_req(chan); | |
| 5522 | + l2cap_start_connection(chan); | |
| 5460 | 5523 | } else { |
| 5461 | 5524 | __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); |
| 5462 | 5525 | } |
| @@ -5470,11 +5533,9 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) · 7 unmodified lines | ||
| 5470 | 5533 | if (!status) { |
| 5471 | 5534 | if (test_bit(BT_SK_DEFER_SETUP, |
| 5472 | 5535 | &bt_sk(sk)->flags)) { |
| 5473 | − struct sock *parent = bt_sk(sk)->parent; | |
| 5474 | 5536 | res = L2CAP_CR_PEND; |
| 5475 | 5537 | stat = L2CAP_CS_AUTHOR_PEND; |
| 5476 | − if (parent) | |
| 5477 | − parent->sk_data_ready(parent, 0); | |
| 5538 | + chan->ops->defer(chan); | |
| 5478 | 5539 | } else { |
| 5479 | 5540 | __l2cap_state_change(chan, BT_CONFIG); |
| 5480 | 5541 | res = L2CAP_CR_SUCCESS; |
| @@ -5494,7 +5555,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) · 13 unmodified lines | ||
| 5494 | 5555 | rsp.result = cpu_to_le16(res); |
| 5495 | 5556 | rsp.status = cpu_to_le16(stat); |
| 5496 | 5557 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, |
| 5497 | − sizeof(rsp), &rsp); | |
| 5558 | + sizeof(rsp), &rsp); | |
| 5498 | 5559 | |
| 5499 | 5560 | if (!test_bit(CONF_REQ_SENT, &chan->conf_state) && |
| 5500 | 5561 | res == L2CAP_CR_SUCCESS) { |
| @@ -5519,6 +5580,12 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) · 18 unmodified lines | ||
| 5519 | 5580 | int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) |
| 5520 | 5581 | { |
| 5521 | 5582 | struct l2cap_conn *conn = hcon->l2cap_data; |
| 5583 | + struct l2cap_hdr *hdr; | |
| 5584 | + int len; | |
| 5585 | + | |
| 5586 | + /* For AMP controller do not create l2cap conn */ | |
| 5587 | + if (!conn && hcon->hdev->dev_type != HCI_BREDR) | |
| 5588 | + goto drop; | |
| 5522 | 5589 | |
| 5523 | 5590 | if (!conn) |
| 5524 | 5591 | conn = l2cap_conn_add(hcon, 0); |
| @@ -5528,10 +5595,10 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) · 3 unmodified lines | ||
| 5528 | 5595 | |
| 5529 | 5596 | BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); |
| 5530 | 5597 | |
| 5531 | − if (!(flags & ACL_CONT)) { | |
| 5532 | − struct l2cap_hdr *hdr; | |
| 5533 | − int len; | |
| 5534 | − | |
| 5598 | + switch (flags) { | |
| 5599 | + case ACL_START: | |
| 5600 | + case ACL_START_NO_FLUSH: | |
| 5601 | + case ACL_COMPLETE: | |
| 5535 | 5602 | if (conn->rx_len) { |
| 5536 | 5603 | BT_ERR("Unexpected start frame (len %d)", skb->len); |
| 5537 | 5604 | kfree_skb(conn->rx_skb); |
| @@ -5560,20 +5627,22 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) · 22 unmodified lines | ||
| 5560 | 5627 | |
| 5561 | 5628 | if (skb->len > len) { |
| 5562 | 5629 | BT_ERR("Frame is too long (len %d, expected len %d)", |
| 5563 | − skb->len, len); | |
| 5630 | + skb->len, len); | |
| 5564 | 5631 | l2cap_conn_unreliable(conn, ECOMM); |
| 5565 | 5632 | goto drop; |
| 5566 | 5633 | } |
| 5567 | 5634 | |
| 5568 | 5635 | /* Allocate skb for the complete frame (with header) */ |
| 5569 | − conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); | |
| 5636 | + conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL); | |
| 5570 | 5637 | if (!conn->rx_skb) |
| 5571 | 5638 | goto drop; |
| 5572 | 5639 | |
| 5573 | 5640 | skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), |
| 5574 | − skb->len); | |
| 5641 | + skb->len); | |
| 5575 | 5642 | conn->rx_len = len - skb->len; |
| 5576 | − } else { | |
| 5643 | + break; | |
| 5644 | + | |
| 5645 | + case ACL_CONT: | |
| 5577 | 5646 | BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); |
| 5578 | 5647 | |
| 5579 | 5648 | if (!conn->rx_len) { |
| @@ -5584,7 +5653,7 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) · 4 unmodified lines | ||
| 5584 | 5653 | |
| 5585 | 5654 | if (skb->len > conn->rx_len) { |
| 5586 | 5655 | BT_ERR("Fragment is too long (len %d, expected %d)", |
| 5587 | − skb->len, conn->rx_len); | |
| 5656 | + skb->len, conn->rx_len); | |
| 5588 | 5657 | kfree_skb(conn->rx_skb); |
| 5589 | 5658 | conn->rx_skb = NULL; |
| 5590 | 5659 | conn->rx_len = 0; |
| @@ -5593,7 +5662,7 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) · 2 unmodified lines | ||
| 5593 | 5662 | } |
| 5594 | 5663 | |
| 5595 | 5664 | skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), |
| 5596 | − skb->len); | |
| 5665 | + skb->len); | |
| 5597 | 5666 | conn->rx_len -= skb->len; |
| 5598 | 5667 | |
| 5599 | 5668 | if (!conn->rx_len) { |
| @@ -5601,6 +5670,7 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) · 1 unmodified line | ||
| 5601 | 5670 | l2cap_recv_frame(conn, conn->rx_skb); |
| 5602 | 5671 | conn->rx_skb = NULL; |
| 5603 | 5672 | } |
| 5673 | + break; | |
| 5604 | 5674 | } |
| 5605 | 5675 | |
| 5606 | 5676 | drop: |
| @@ -5617,12 +5687,11 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p) · 10 unmodified lines | ||
| 5617 | 5687 | list_for_each_entry(c, &chan_list, global_l) { |
| 5618 | 5688 | struct sock *sk = c->sk; |
| 5619 | 5689 | |
| 5620 | − seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", | |
| 5621 | − batostr(&bt_sk(sk)->src), | |
| 5622 | − batostr(&bt_sk(sk)->dst), | |
| 5623 | − c->state, __le16_to_cpu(c->psm), | |
| 5624 | − c->scid, c->dcid, c->imtu, c->omtu, | |
| 5625 | − c->sec_level, c->mode); | |
| 5690 | + seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", | |
| 5691 | + &bt_sk(sk)->src, &bt_sk(sk)->dst, | |
| 5692 | + c->state, __le16_to_cpu(c->psm), | |
| 5693 | + c->scid, c->dcid, c->imtu, c->omtu, | |
| 5694 | + c->sec_level, c->mode); | |
| 5626 | 5695 | } |
| 5627 | 5696 | |
| 5628 | 5697 | read_unlock(&chan_list_lock); |
| @@ -5653,8 +5722,8 @@ int __init l2cap_init(void) · 24 unmodified lines | ||
| 5653 | 5722 | return err; |
| 5654 | 5723 | |
| 5655 | 5724 | if (bt_debugfs) { |
| 5656 | − l2cap_debugfs = debugfs_create_file("l2cap", 0444, | |
| 5657 | − bt_debugfs, NULL, &l2cap_debugfs_fops); | |
| 5725 | + l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, | |
| 5726 | + NULL, &l2cap_debugfs_fops); | |
| 5658 | 5727 | if (!l2cap_debugfs) |
| 5659 | 5728 | BT_ERR("Failed to create L2CAP debug file"); |
| 5660 | 5729 | } |
| @@ -40,7 +40,8 @@ static struct bt_sock_list l2cap_sk_list = { · 39 unmodified lines | ||
| 40 | 40 | |
| 41 | 41 | static const struct proto_ops l2cap_sock_ops; |
| 42 | 42 | static void l2cap_sock_init(struct sock *sk, struct sock *parent); |
| 43 | −static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); | |
| 43 | +static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, | |
| 44 | + int proto, gfp_t prio); | |
| 44 | 45 | |
| 45 | 46 | static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) |
| 46 | 47 | { |
| @@ -106,7 +107,8 @@ done: · 59 unmodified lines | ||
| 106 | 107 | return err; |
| 107 | 108 | } |
| 108 | 109 | |
| 109 | −static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags) | |
| 110 | +static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, | |
| 111 | + int alen, int flags) | |
| 110 | 112 | { |
| 111 | 113 | struct sock *sk = sock->sk; |
| 112 | 114 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
| @@ -134,7 +136,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al · 21 unmodified lines | ||
| 134 | 136 | lock_sock(sk); |
| 135 | 137 | |
| 136 | 138 | err = bt_sock_wait_state(sk, BT_CONNECTED, |
| 137 | − sock_sndtimeo(sk, flags & O_NONBLOCK)); | |
| 139 | + sock_sndtimeo(sk, flags & O_NONBLOCK)); | |
| 138 | 140 | |
| 139 | 141 | release_sock(sk); |
| 140 | 142 | |
| @@ -185,7 +187,8 @@ done: · 44 unmodified lines | ||
| 185 | 187 | return err; |
| 186 | 188 | } |
| 187 | 189 | |
| 188 | −static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags) | |
| 190 | +static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, | |
| 191 | + int flags) | |
| 189 | 192 | { |
| 190 | 193 | DECLARE_WAITQUEUE(wait, current); |
| 191 | 194 | struct sock *sk = sock->sk, *nsk; |
| @@ -241,7 +244,8 @@ done: · 49 unmodified lines | ||
| 241 | 244 | return err; |
| 242 | 245 | } |
| 243 | 246 | |
| 244 | −static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer) | |
| 247 | +static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, | |
| 248 | + int *len, int peer) | |
| 245 | 249 | { |
| 246 | 250 | struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr; |
| 247 | 251 | struct sock *sk = sock->sk; |
| @@ -266,7 +270,8 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l · 18 unmodified lines | ||
| 266 | 270 | return 0; |
| 267 | 271 | } |
| 268 | 272 | |
| 269 | −static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen) | |
| 273 | +static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, | |
| 274 | + char __user *optval, int __user *optlen) | |
| 270 | 275 | { |
| 271 | 276 | struct sock *sk = sock->sk; |
| 272 | 277 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
| @@ -309,7 +314,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us · 36 unmodified lines | ||
| 309 | 314 | break; |
| 310 | 315 | case BT_SECURITY_HIGH: |
| 311 | 316 | opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT | |
| 312 | − L2CAP_LM_SECURE; | |
| 317 | + L2CAP_LM_SECURE; | |
| 313 | 318 | break; |
| 314 | 319 | default: |
| 315 | 320 | opt = 0; |
| @@ -353,7 +358,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us · 37 unmodified lines | ||
| 353 | 358 | return err; |
| 354 | 359 | } |
| 355 | 360 | |
| 356 | −static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) | |
| 361 | +static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, | |
| 362 | + char __user *optval, int __user *optlen) | |
| 357 | 363 | { |
| 358 | 364 | struct sock *sk = sock->sk; |
| 359 | 365 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
| @@ -377,19 +383,20 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch · 17 unmodified lines | ||
| 377 | 383 | switch (optname) { |
| 378 | 384 | case BT_SECURITY: |
| 379 | 385 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && |
| 380 | − chan->chan_type != L2CAP_CHAN_RAW) { | |
| 386 | + chan->chan_type != L2CAP_CHAN_RAW) { | |
| 381 | 387 | err = -EINVAL; |
| 382 | 388 | break; |
| 383 | 389 | } |
| 384 | 390 | |
| 385 | 391 | memset(&sec, 0, sizeof(sec)); |
| 386 | − if (chan->conn) | |
| 392 | + if (chan->conn) { | |
| 387 | 393 | sec.level = chan->conn->hcon->sec_level; |
| 388 | − else | |
| 389 | − sec.level = chan->sec_level; | |
| 390 | 394 | |
| 391 | − if (sk->sk_state == BT_CONNECTED) | |
| 392 | − sec.key_size = chan->conn->hcon->enc_key_size; | |
| 395 | + if (sk->sk_state == BT_CONNECTED) | |
| 396 | + sec.key_size = chan->conn->hcon->enc_key_size; | |
| 397 | + } else { | |
| 398 | + sec.level = chan->sec_level; | |
| 399 | + } | |
| 393 | 400 | |
| 394 | 401 | len = min_t(unsigned int, len, sizeof(sec)); |
| 395 | 402 | if (copy_to_user(optval, (char *) &sec, len)) |
| @@ -411,14 +418,14 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch · 15 unmodified lines | ||
| 411 | 418 | |
| 412 | 419 | case BT_FLUSHABLE: |
| 413 | 420 | if (put_user(test_bit(FLAG_FLUSHABLE, &chan->flags), |
| 414 | − (u32 __user *) optval)) | |
| 421 | + (u32 __user *) optval)) | |
| 415 | 422 | err = -EFAULT; |
| 416 | 423 | |
| 417 | 424 | break; |
| 418 | 425 | |
| 419 | 426 | case BT_POWER: |
| 420 | 427 | if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM |
| 421 | − && sk->sk_type != SOCK_RAW) { | |
| 428 | + && sk->sk_type != SOCK_RAW) { | |
| 422 | 429 | err = -EINVAL; |
| 423 | 430 | break; |
| 424 | 431 | } |
| @@ -466,7 +473,8 @@ static bool l2cap_valid_mtu(struct l2cap_chan *chan, u16 mtu) · 41 unmodified lines | ||
| 466 | 473 | return true; |
| 467 | 474 | } |
| 468 | 475 | |
| 469 | −static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen) | |
| 476 | +static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, | |
| 477 | + char __user *optval, unsigned int optlen) | |
| 470 | 478 | { |
| 471 | 479 | struct sock *sk = sock->sk; |
| 472 | 480 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
| @@ -529,6 +537,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us · 56 unmodified lines | ||
| 529 | 537 | chan->fcs = opts.fcs; |
| 530 | 538 | chan->max_tx = opts.max_tx; |
| 531 | 539 | chan->tx_win = opts.txwin_size; |
| 540 | + chan->flush_to = opts.flush_to; | |
| 532 | 541 | break; |
| 533 | 542 | |
| 534 | 543 | case L2CAP_LM: |
| @@ -564,7 +573,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us · 29 unmodified lines | ||
| 564 | 573 | return err; |
| 565 | 574 | } |
| 566 | 575 | |
| 567 | −static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) | |
| 576 | +static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |
| 577 | + char __user *optval, unsigned int optlen) | |
| 568 | 578 | { |
| 569 | 579 | struct sock *sk = sock->sk; |
| 570 | 580 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
| @@ -587,7 +597,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch · 16 unmodified lines | ||
| 587 | 597 | switch (optname) { |
| 588 | 598 | case BT_SECURITY: |
| 589 | 599 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && |
| 590 | − chan->chan_type != L2CAP_CHAN_RAW) { | |
| 600 | + chan->chan_type != L2CAP_CHAN_RAW) { | |
| 591 | 601 | err = -EINVAL; |
| 592 | 602 | break; |
| 593 | 603 | } |
| @@ -601,7 +611,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch · 7 unmodified lines | ||
| 601 | 611 | } |
| 602 | 612 | |
| 603 | 613 | if (sec.level < BT_SECURITY_LOW || |
| 604 | − sec.level > BT_SECURITY_HIGH) { | |
| 614 | + sec.level > BT_SECURITY_HIGH) { | |
| 605 | 615 | err = -EINVAL; |
| 606 | 616 | break; |
| 607 | 617 | } |
| @@ -627,7 +637,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch · 19 unmodified lines | ||
| 627 | 637 | |
| 628 | 638 | /* or for ACL link */ |
| 629 | 639 | } else if ((sk->sk_state == BT_CONNECT2 && |
| 630 | − test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) || | |
| 640 | + test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) || | |
| 631 | 641 | sk->sk_state == BT_CONNECTED) { |
| 632 | 642 | if (!l2cap_chan_check_security(chan)) |
| 633 | 643 | set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); |
| @@ -684,7 +694,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch · 50 unmodified lines | ||
| 684 | 694 | |
| 685 | 695 | case BT_POWER: |
| 686 | 696 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && |
| 687 | − chan->chan_type != L2CAP_CHAN_RAW) { | |
| 697 | + chan->chan_type != L2CAP_CHAN_RAW) { | |
| 688 | 698 | err = -EINVAL; |
| 689 | 699 | break; |
| 690 | 700 | } |
| @@ -720,7 +730,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch · 29 unmodified lines | ||
| 720 | 730 | } |
| 721 | 731 | |
| 722 | 732 | if (chan->mode != L2CAP_MODE_ERTM && |
| 723 | − chan->mode != L2CAP_MODE_STREAMING) { | |
| 733 | + chan->mode != L2CAP_MODE_STREAMING) { | |
| 724 | 734 | err = -EOPNOTSUPP; |
| 725 | 735 | break; |
| 726 | 736 | } |
| @@ -737,7 +747,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch · 10 unmodified lines | ||
| 737 | 747 | return err; |
| 738 | 748 | } |
| 739 | 749 | |
| 740 | −static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) | |
| 750 | +static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |
| 751 | + struct msghdr *msg, size_t len) | |
| 741 | 752 | { |
| 742 | 753 | struct sock *sk = sock->sk; |
| 743 | 754 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
| @@ -762,7 +773,8 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms · 18 unmodified lines | ||
| 762 | 773 | return err; |
| 763 | 774 | } |
| 764 | 775 | |
| 765 | −static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags) | |
| 776 | +static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | |
| 777 | + struct msghdr *msg, size_t len, int flags) | |
| 766 | 778 | { |
| 767 | 779 | struct sock *sk = sock->sk; |
| 768 | 780 | struct l2cap_pinfo *pi = l2cap_pi(sk); |
| @@ -866,7 +878,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) · 97 unmodified lines | ||
| 866 | 878 | |
| 867 | 879 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) |
| 868 | 880 | err = bt_sock_wait_state(sk, BT_CLOSED, |
| 869 | − sk->sk_lingertime); | |
| 881 | + sk->sk_lingertime); | |
| 870 | 882 | } |
| 871 | 883 | |
| 872 | 884 | if (!err && sk->sk_err) |
| @@ -930,7 +942,7 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) · 57 unmodified lines | ||
| 930 | 942 | } |
| 931 | 943 | |
| 932 | 944 | sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, |
| 933 | − GFP_ATOMIC); | |
| 945 | + GFP_ATOMIC); | |
| 934 | 946 | if (!sk) |
| 935 | 947 | return NULL; |
| 936 | 948 | |
| @@ -938,6 +950,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) · 1 unmodified line | ||
| 938 | 950 | |
| 939 | 951 | l2cap_sock_init(sk, parent); |
| 940 | 952 | |
| 953 | + bt_accept_enqueue(parent, sk); | |
| 954 | + | |
| 941 | 955 | return l2cap_pi(sk)->chan; |
| 942 | 956 | } |
| 943 | 957 | |
| @@ -1068,6 +1082,15 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan) · 124 unmodified lines | ||
| 1068 | 1082 | release_sock(sk); |
| 1069 | 1083 | } |
| 1070 | 1084 | |
| 1085 | +static void l2cap_sock_defer_cb(struct l2cap_chan *chan) | |
| 1086 | +{ | |
| 1087 | + struct sock *sk = chan->data; | |
| 1088 | + struct sock *parent = bt_sk(sk)->parent; | |
| 1089 | + | |
| 1090 | + if (parent) | |
| 1091 | + parent->sk_data_ready(parent, 0); | |
| 1092 | +} | |
| 1093 | + | |
| 1071 | 1094 | static struct l2cap_ops l2cap_chan_ops = { |
| 1072 | 1095 | .name = "L2CAP Socket Interface", |
| 1073 | 1096 | .new_connection = l2cap_sock_new_connection_cb, |
| @@ -1076,6 +1099,7 @@ static struct l2cap_ops l2cap_chan_ops = { · 2 unmodified lines | ||
| 1076 | 1099 | .teardown = l2cap_sock_teardown_cb, |
| 1077 | 1100 | .state_change = l2cap_sock_state_change_cb, |
| 1078 | 1101 | .ready = l2cap_sock_ready_cb, |
| 1102 | + .defer = l2cap_sock_defer_cb, | |
| 1079 | 1103 | .alloc_skb = l2cap_sock_alloc_skb_cb, |
| 1080 | 1104 | }; |
| 1081 | 1105 | |
| @@ -1083,7 +1107,8 @@ static void l2cap_sock_destruct(struct sock *sk) · 1 unmodified line | ||
| 1083 | 1107 | { |
| 1084 | 1108 | BT_DBG("sk %p", sk); |
| 1085 | 1109 | |
| 1086 | − l2cap_chan_put(l2cap_pi(sk)->chan); | |
| 1110 | + if (l2cap_pi(sk)->chan) | |
| 1111 | + l2cap_chan_put(l2cap_pi(sk)->chan); | |
| 1087 | 1112 | if (l2cap_pi(sk)->rx_busy_skb) { |
| 1088 | 1113 | kfree_skb(l2cap_pi(sk)->rx_busy_skb); |
| 1089 | 1114 | l2cap_pi(sk)->rx_busy_skb = NULL; |
| @@ -1159,7 +1184,8 @@ static struct proto l2cap_proto = { · 69 unmodified lines | ||
| 1159 | 1184 | .obj_size = sizeof(struct l2cap_pinfo) |
| 1160 | 1185 | }; |
| 1161 | 1186 | |
| 1162 | −static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio) | |
| 1187 | +static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, | |
| 1188 | + int proto, gfp_t prio) | |
| 1163 | 1189 | { |
| 1164 | 1190 | struct sock *sk; |
| 1165 | 1191 | struct l2cap_chan *chan; |
| @@ -1204,7 +1230,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, · 38 unmodified lines | ||
| 1204 | 1230 | sock->state = SS_UNCONNECTED; |
| 1205 | 1231 | |
| 1206 | 1232 | if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM && |
| 1207 | − sock->type != SOCK_DGRAM && sock->type != SOCK_RAW) | |
| 1233 | + sock->type != SOCK_DGRAM && sock->type != SOCK_RAW) | |
| 1208 | 1234 | return -ESOCKTNOSUPPORT; |
| 1209 | 1235 | |
| 1210 | 1236 | if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) |
| @@ -1261,7 +1287,8 @@ int __init l2cap_init_sockets(void) · 50 unmodified lines | ||
| 1261 | 1287 | goto error; |
| 1262 | 1288 | } |
| 1263 | 1289 | |
| 1264 | − err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list, NULL); | |
| 1290 | + err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list, | |
| 1291 | + NULL); | |
| 1265 | 1292 | if (err < 0) { |
| 1266 | 1293 | BT_ERR("Failed to create L2CAP proc file"); |
| 1267 | 1294 | bt_sock_unregister(BTPROTO_L2CAP); |
| @@ -41,20 +41,6 @@ void baswap(bdaddr_t *dst, bdaddr_t *src) · 40 unmodified lines | ||
| 41 | 41 | } |
| 42 | 42 | EXPORT_SYMBOL(baswap); |
| 43 | 43 | |
| 44 | −char *batostr(bdaddr_t *ba) | |
| 45 | −{ | |
| 46 | − static char str[2][18]; | |
| 47 | − static int i = 1; | |
| 48 | − | |
| 49 | − i ^= 1; | |
| 50 | − sprintf(str[i], "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", | |
| 51 | − ba->b[5], ba->b[4], ba->b[3], | |
| 52 | − ba->b[2], ba->b[1], ba->b[0]); | |
| 53 | − | |
| 54 | − return str[i]; | |
| 55 | −} | |
| 56 | −EXPORT_SYMBOL(batostr); | |
| 57 | − | |
| 58 | 44 | /* Bluetooth error codes to Unix errno mapping */ |
| 59 | 45 | int bt_to_errno(__u16 code) |
| 60 | 46 | { |
| @@ -3125,6 +3125,9 @@ int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, · 3124 unmodified lines | ||
| 3125 | 3125 | struct pending_cmd *cmd; |
| 3126 | 3126 | int err; |
| 3127 | 3127 | |
| 3128 | + mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp, | |
| 3129 | + hdev); | |
| 3130 | + | |
| 3128 | 3131 | cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev); |
| 3129 | 3132 | if (!cmd) |
| 3130 | 3133 | return -ENOENT; |
| @@ -3137,8 +3140,6 @@ int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, · 6 unmodified lines | ||
| 3137 | 3140 | |
| 3138 | 3141 | mgmt_pending_remove(cmd); |
| 3139 | 3142 | |
| 3140 | − mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp, | |
| 3141 | − hdev); | |
| 3142 | 3143 | return err; |
| 3143 | 3144 | } |
| 3144 | 3145 | |
| @@ -377,8 +377,8 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, · 376 unmodified lines | ||
| 377 | 377 | int err = 0; |
| 378 | 378 | u8 dlci; |
| 379 | 379 | |
| 380 | − BT_DBG("dlc %p state %ld %s %s channel %d", | |
| 381 | − d, d->state, batostr(src), batostr(dst), channel); | |
| 380 | + BT_DBG("dlc %p state %ld %pMR -> %pMR channel %d", | |
| 381 | + d, d->state, src, dst, channel); | |
| 382 | 382 | |
| 383 | 383 | if (channel < 1 || channel > 30) |
| 384 | 384 | return -EINVAL; |
| @@ -676,7 +676,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, · 291 unmodified lines | ||
| 676 | 676 | struct socket *sock; |
| 677 | 677 | struct sock *sk; |
| 678 | 678 | |
| 679 | − BT_DBG("%s %s", batostr(src), batostr(dst)); | |
| 679 | + BT_DBG("%pMR -> %pMR", src, dst); | |
| 680 | 680 | |
| 681 | 681 | *err = rfcomm_l2sock_create(&sock); |
| 682 | 682 | if (*err < 0) |
| @@ -709,7 +709,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, · 26 unmodified lines | ||
| 709 | 709 | |
| 710 | 710 | bacpy(&addr.l2_bdaddr, dst); |
| 711 | 711 | addr.l2_family = AF_BLUETOOTH; |
| 712 | − addr.l2_psm = cpu_to_le16(RFCOMM_PSM); | |
| 712 | + addr.l2_psm = __constant_cpu_to_le16(RFCOMM_PSM); | |
| 713 | 713 | addr.l2_cid = 0; |
| 714 | 714 | *err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK); |
| 715 | 715 | if (*err == 0 || *err == -EINPROGRESS) |
| @@ -1987,7 +1987,7 @@ static int rfcomm_add_listener(bdaddr_t *ba) · 1271 unmodified lines | ||
| 1987 | 1987 | /* Bind socket */ |
| 1988 | 1988 | bacpy(&addr.l2_bdaddr, ba); |
| 1989 | 1989 | addr.l2_family = AF_BLUETOOTH; |
| 1990 | − addr.l2_psm = cpu_to_le16(RFCOMM_PSM); | |
| 1990 | + addr.l2_psm = __constant_cpu_to_le16(RFCOMM_PSM); | |
| 1991 | 1991 | addr.l2_cid = 0; |
| 1992 | 1992 | err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr)); |
| 1993 | 1993 | if (err < 0) { |
| @@ -2125,11 +2125,10 @@ static int rfcomm_dlc_debugfs_show(struct seq_file *f, void *x) · 131 unmodified lines | ||
| 2125 | 2125 | list_for_each_entry(d, &s->dlcs, list) { |
| 2126 | 2126 | struct sock *sk = s->sock->sk; |
| 2127 | 2127 | |
| 2128 | − seq_printf(f, "%s %s %ld %d %d %d %d\n", | |
| 2129 | − batostr(&bt_sk(sk)->src), | |
| 2130 | − batostr(&bt_sk(sk)->dst), | |
| 2131 | − d->state, d->dlci, d->mtu, | |
| 2132 | − d->rx_credits, d->tx_credits); | |
| 2128 | + seq_printf(f, "%pMR %pMR %ld %d %d %d %d\n", | |
| 2129 | + &bt_sk(sk)->src, &bt_sk(sk)->dst, | |
| 2130 | + d->state, d->dlci, d->mtu, | |
| 2131 | + d->rx_credits, d->tx_credits); | |
| 2133 | 2132 | } |
| 2134 | 2133 | } |
| 2135 | 2134 | |
| @@ -334,7 +334,7 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr · 333 unmodified lines | ||
| 334 | 334 | struct sock *sk = sock->sk; |
| 335 | 335 | int err = 0; |
| 336 | 336 | |
| 337 | − BT_DBG("sk %p %s", sk, batostr(&sa->rc_bdaddr)); | |
| 337 | + BT_DBG("sk %p %pMR", sk, &sa->rc_bdaddr); | |
| 338 | 338 | |
| 339 | 339 | if (!addr || addr->sa_family != AF_BLUETOOTH) |
| 340 | 340 | return -EINVAL; |
| @@ -975,10 +975,9 @@ static int rfcomm_sock_debugfs_show(struct seq_file *f, void *p) · 634 unmodified lines | ||
| 975 | 975 | read_lock(&rfcomm_sk_list.lock); |
| 976 | 976 | |
| 977 | 977 | sk_for_each(sk, node, &rfcomm_sk_list.head) { |
| 978 | − seq_printf(f, "%s %s %d %d\n", | |
| 979 | − batostr(&bt_sk(sk)->src), | |
| 980 | − batostr(&bt_sk(sk)->dst), | |
| 981 | − sk->sk_state, rfcomm_pi(sk)->channel); | |
| 978 | + seq_printf(f, "%pMR %pMR %d %d\n", | |
| 979 | + &bt_sk(sk)->src, &bt_sk(sk)->dst, | |
| 980 | + sk->sk_state, rfcomm_pi(sk)->channel); | |
| 982 | 981 | } |
| 983 | 982 | |
| 984 | 983 | read_unlock(&rfcomm_sk_list.lock); |
| @@ -166,7 +166,7 @@ static struct device *rfcomm_get_device(struct rfcomm_dev *dev) · 165 unmodified lines | ||
| 166 | 166 | static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf) |
| 167 | 167 | { |
| 168 | 168 | struct rfcomm_dev *dev = dev_get_drvdata(tty_dev); |
| 169 | − return sprintf(buf, "%s\n", batostr(&dev->dst)); | |
| 169 | + return sprintf(buf, "%pMR\n", &dev->dst); | |
| 170 | 170 | } |
| 171 | 171 | |
| 172 | 172 | static ssize_t show_channel(struct device *tty_dev, struct device_attribute *attr, char *buf) |
| @@ -663,8 +663,8 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) · 490 unmodified lines | ||
| 663 | 663 | if (!dev) |
| 664 | 664 | return -ENODEV; |
| 665 | 665 | |
| 666 | − BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst), | |
| 667 | − dev->channel, dev->port.count); | |
| 666 | + BT_DBG("dev %p dst %pMR channel %d opened %d", dev, &dev->dst, | |
| 667 | + dev->channel, dev->port.count); | |
| 668 | 668 | |
| 669 | 669 | spin_lock_irqsave(&dev->port.lock, flags); |
| 670 | 670 | if (++dev->port.count > 1) { |
| @@ -172,7 +172,7 @@ static int sco_connect(struct sock *sk) · 171 unmodified lines | ||
| 172 | 172 | struct hci_dev *hdev; |
| 173 | 173 | int err, type; |
| 174 | 174 | |
| 175 | − BT_DBG("%s -> %s", batostr(src), batostr(dst)); | |
| 175 | + BT_DBG("%pMR -> %pMR", src, dst); | |
| 176 | 176 | |
| 177 | 177 | hdev = hci_get_route(dst, src); |
| 178 | 178 | if (!hdev) |
| @@ -460,7 +460,7 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le · 281 unmodified lines | ||
| 460 | 460 | struct sock *sk = sock->sk; |
| 461 | 461 | int err = 0; |
| 462 | 462 | |
| 463 | − BT_DBG("sk %p %s", sk, batostr(&sa->sco_bdaddr)); | |
| 463 | + BT_DBG("sk %p %pMR", sk, &sa->sco_bdaddr); | |
| 464 | 464 | |
| 465 | 465 | if (!addr || addr->sa_family != AF_BLUETOOTH) |
| 466 | 466 | return -EINVAL; |
| @@ -893,7 +893,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) · 426 unmodified lines | ||
| 893 | 893 | struct hlist_node *node; |
| 894 | 894 | int lm = 0; |
| 895 | 895 | |
| 896 | − BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); | |
| 896 | + BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr); | |
| 897 | 897 | |
| 898 | 898 | /* Find listening sockets */ |
| 899 | 899 | read_lock(&sco_sk_list.lock); |
| @@ -914,7 +914,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) · 14 unmodified lines | ||
| 914 | 914 | |
| 915 | 915 | void sco_connect_cfm(struct hci_conn *hcon, __u8 status) |
| 916 | 916 | { |
| 917 | − BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); | |
| 917 | + BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); | |
| 918 | 918 | if (!status) { |
| 919 | 919 | struct sco_conn *conn; |
| 920 | 920 | |
| @@ -959,8 +959,8 @@ static int sco_debugfs_show(struct seq_file *f, void *p) · 38 unmodified lines | ||
| 959 | 959 | read_lock(&sco_sk_list.lock); |
| 960 | 960 | |
| 961 | 961 | sk_for_each(sk, node, &sco_sk_list.head) { |
| 962 | − seq_printf(f, "%s %s %d\n", batostr(&bt_sk(sk)->src), | |
| 963 | − batostr(&bt_sk(sk)->dst), sk->sk_state); | |
| 962 | + seq_printf(f, "%pMR %pMR %d\n", &bt_sk(sk)->src, | |
| 963 | + &bt_sk(sk)->dst, sk->sk_state); | |
| 964 | 964 | } |
| 965 | 965 | |
| 966 | 966 | read_unlock(&sco_sk_list.lock); |
| @@ -167,7 +167,7 @@ static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code, · 166 unmodified lines | ||
| 167 | 167 | |
| 168 | 168 | lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); |
| 169 | 169 | lh->len = cpu_to_le16(sizeof(code) + dlen); |
| 170 | − lh->cid = cpu_to_le16(L2CAP_CID_SMP); | |
| 170 | + lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP); | |
| 171 | 171 | |
| 172 | 172 | memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code)); |
| 173 | 173 | |
| @@ -248,7 +248,7 @@ config MAC80211_MHWMP_DEBUG · 247 unmodified lines | ||
| 248 | 248 | Do not select this option. |
| 249 | 249 | |
| 250 | 250 | config MAC80211_MESH_SYNC_DEBUG |
| 251 | − bool "Verbose mesh mesh synchronization debugging" | |
| 251 | + bool "Verbose mesh synchronization debugging" | |
| 252 | 252 | depends on MAC80211_DEBUG_MENU |
| 253 | 253 | depends on MAC80211_MESH |
| 254 | 254 | ---help--- |
| @@ -8,6 +8,7 @@ mac80211-y := \ · 7 unmodified lines | ||
| 8 | 8 | wpa.o \ |
| 9 | 9 | scan.o offchannel.o \ |
| 10 | 10 | ht.o agg-tx.o agg-rx.o \ |
| 11 | + vht.o \ | |
| 11 | 12 | ibss.o \ |
| 12 | 13 | iface.o \ |
| 13 | 14 | rate.o \ |
| @@ -126,3 +126,20 @@ void ieee80211_aes_cmac_key_free(struct crypto_cipher *tfm) · 125 unmodified lines | ||
| 126 | 126 | { |
| 127 | 127 | crypto_free_cipher(tfm); |
| 128 | 128 | } |
| 129 | + | |
| 130 | +void ieee80211_aes_cmac_calculate_k1_k2(struct ieee80211_key_conf *keyconf, | |
| 131 | + u8 *k1, u8 *k2) | |
| 132 | +{ | |
| 133 | + u8 l[AES_BLOCK_SIZE] = {}; | |
| 134 | + struct ieee80211_key *key = | |
| 135 | + container_of(keyconf, struct ieee80211_key, conf); | |
| 136 | + | |
| 137 | + crypto_cipher_encrypt_one(key->u.aes_cmac.tfm, l, l); | |
| 138 | + | |
| 139 | + memcpy(k1, l, AES_BLOCK_SIZE); | |
| 140 | + gf_mulx(k1); | |
| 141 | + | |
| 142 | + memcpy(k2, k1, AES_BLOCK_SIZE); | |
| 143 | + gf_mulx(k2); | |
| 144 | +} | |
| 145 | +EXPORT_SYMBOL(ieee80211_aes_cmac_calculate_k1_k2); | |
| @@ -372,10 +372,11 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy, · 371 unmodified lines | ||
| 372 | 372 | |
| 373 | 373 | static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, int idx) |
| 374 | 374 | { |
| 375 | + enum ieee80211_band band = ieee80211_get_sdata_band(sta->sdata); | |
| 376 | + | |
| 375 | 377 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) { |
| 376 | 378 | struct ieee80211_supported_band *sband; |
| 377 | − sband = sta->local->hw.wiphy->bands[ | |
| 378 | − sta->local->oper_channel->band]; | |
| 379 | + sband = sta->local->hw.wiphy->bands[band]; | |
| 379 | 380 | rate->legacy = sband->bitrates[idx].bitrate; |
| 380 | 381 | } else |
| 381 | 382 | rate->mcs = idx; |
| @@ -532,6 +533,8 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, · 150 unmodified lines | ||
| 532 | 533 | u64 *data) |
| 533 | 534 | { |
| 534 | 535 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 536 | + struct ieee80211_chanctx_conf *chanctx_conf; | |
| 537 | + struct ieee80211_channel *channel; | |
| 535 | 538 | struct sta_info *sta; |
| 536 | 539 | struct ieee80211_local *local = sdata->local; |
| 537 | 540 | struct station_info sinfo; |
| @@ -607,19 +610,26 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy, · 69 unmodified lines | ||
| 607 | 610 | do_survey: |
| 608 | 611 | i = STA_STATS_LEN - STA_STATS_SURVEY_LEN; |
| 609 | 612 | /* Get survey stats for current channel */ |
| 610 | − q = 0; | |
| 611 | − while (true) { | |
| 612 | − survey.filled = 0; | |
| 613 | − if (drv_get_survey(local, q, &survey) != 0) { | |
| 614 | − survey.filled = 0; | |
| 615 | − break; | |
| 616 | − } | |
| 613 | + survey.filled = 0; | |
| 617 | 614 | |
| 618 | − if (survey.channel && | |
| 619 | − (local->oper_channel->center_freq == | |
| 620 | − survey.channel->center_freq)) | |
| 621 | − break; | |
| 622 | − q++; | |
| 615 | + rcu_read_lock(); | |
| 616 | + chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | |
| 617 | + if (chanctx_conf) | |
| 618 | + channel = chanctx_conf->channel; | |
| 619 | + else | |
| 620 | + channel = NULL; | |
| 621 | + rcu_read_unlock(); | |
| 622 | + | |
| 623 | + if (channel) { | |
| 624 | + q = 0; | |
| 625 | + do { | |
| 626 | + survey.filled = 0; | |
| 627 | + if (drv_get_survey(local, q, &survey) != 0) { | |
| 628 | + survey.filled = 0; | |
| 629 | + break; | |
| 630 | + } | |
| 631 | + q++; | |
| 632 | + } while (channel != survey.channel); | |
| 623 | 633 | } |
| 624 | 634 | |
| 625 | 635 | if (survey.filled) |
| @@ -724,47 +734,42 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, · 98 unmodified lines | ||
| 724 | 734 | return ret; |
| 725 | 735 | } |
| 726 | 736 | |
| 727 | −static int ieee80211_set_channel(struct wiphy *wiphy, | |
| 728 | − struct net_device *netdev, | |
| 729 | − struct ieee80211_channel *chan, | |
| 730 | − enum nl80211_channel_type channel_type) | |
| 737 | +static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | |
| 738 | + struct ieee80211_channel *chan, | |
| 739 | + enum nl80211_channel_type channel_type) | |
| 731 | 740 | { |
| 732 | 741 | struct ieee80211_local *local = wiphy_priv(wiphy); |
| 733 | − struct ieee80211_sub_if_data *sdata = NULL; | |
| 734 | − | |
| 735 | − if (netdev) | |
| 736 | − sdata = IEEE80211_DEV_TO_SUB_IF(netdev); | |
| 737 | − | |
| 738 | − switch (ieee80211_get_channel_mode(local, NULL)) { | |
| 739 | − case CHAN_MODE_HOPPING: | |
| 740 | − return -EBUSY; | |
| 741 | − case CHAN_MODE_FIXED: | |
| 742 | − if (local->oper_channel != chan || | |
| 743 | − (!sdata && local->_oper_channel_type != channel_type)) | |
| 744 | − return -EBUSY; | |
| 745 | − if (!sdata && local->_oper_channel_type == channel_type) | |
| 746 | − return 0; | |
| 747 | − break; | |
| 748 | − case CHAN_MODE_UNDEFINED: | |
| 749 | − break; | |
| 750 | − } | |
| 751 | − | |
| 752 | − if (!ieee80211_set_channel_type(local, sdata, channel_type)) | |
| 753 | − return -EBUSY; | |
| 742 | + struct ieee80211_sub_if_data *sdata; | |
| 743 | + int ret = 0; | |
| 754 | 744 | |
| 755 | − local->oper_channel = chan; | |
| 745 | + if (local->monitor_channel == chan && | |
| 746 | + local->monitor_channel_type == channel_type) | |
| 747 | + return 0; | |
| 756 | 748 | |
| 757 | − /* auto-detects changes */ | |
| 758 | − ieee80211_hw_config(local, 0); | |
| 749 | + mutex_lock(&local->iflist_mtx); | |
| 750 | + if (local->use_chanctx) { | |
| 751 | + sdata = rcu_dereference_protected( | |
| 752 | + local->monitor_sdata, | |
| 753 | + lockdep_is_held(&local->iflist_mtx)); | |
| 754 | + if (sdata) { | |
| 755 | + ieee80211_vif_release_channel(sdata); | |
| 756 | + ret = ieee80211_vif_use_channel( | |
| 757 | + sdata, chan, channel_type, | |
| 758 | + IEEE80211_CHANCTX_EXCLUSIVE); | |
| 759 | + } | |
| 760 | + } else if (local->open_count == local->monitors) { | |
| 761 | + local->_oper_channel = chan; | |
| 762 | + local->_oper_channel_type = channel_type; | |
| 763 | + ieee80211_hw_config(local, 0); | |
| 764 | + } | |
| 759 | 765 | |
| 760 | − return 0; | |
| 761 | −} | |
| 766 | + if (ret == 0) { | |
| 767 | + local->monitor_channel = chan; | |
| 768 | + local->monitor_channel_type = channel_type; | |
| 769 | + } | |
| 770 | + mutex_unlock(&local->iflist_mtx); | |
| 762 | 771 | |
| 763 | −static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | |
| 764 | − struct ieee80211_channel *chan, | |
| 765 | − enum nl80211_channel_type channel_type) | |
| 766 | −{ | |
| 767 | − return ieee80211_set_channel(wiphy, NULL, chan, channel_type); | |
| 772 | + return ret; | |
| 768 | 773 | } |
| 769 | 774 | |
| 770 | 775 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, |
| @@ -879,8 +884,13 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, · 108 unmodified lines | ||
| 879 | 884 | if (old) |
| 880 | 885 | return -EALREADY; |
| 881 | 886 | |
| 882 | − err = ieee80211_set_channel(wiphy, dev, params->channel, | |
| 883 | − params->channel_type); | |
| 887 | + /* TODO: make hostapd tell us what it wants */ | |
| 888 | + sdata->smps_mode = IEEE80211_SMPS_OFF; | |
| 889 | + sdata->needed_rx_chains = sdata->local->rx_chains; | |
| 890 | + | |
| 891 | + err = ieee80211_vif_use_channel(sdata, params->channel, | |
| 892 | + params->channel_type, | |
| 893 | + IEEE80211_CHANCTX_SHARED); | |
| 884 | 894 | if (err) |
| 885 | 895 | return err; |
| 886 | 896 | |
| @@ -963,6 +973,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) · 76 unmodified lines | ||
| 963 | 973 | sta_info_flush(sdata->local, sdata); |
| 964 | 974 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
| 965 | 975 | |
| 976 | + ieee80211_vif_release_channel(sdata); | |
| 977 | + | |
| 966 | 978 | return 0; |
| 967 | 979 | } |
| 968 | 980 | |
| @@ -1019,9 +1031,10 @@ static int sta_apply_parameters(struct ieee80211_local *local, · 50 unmodified lines | ||
| 1019 | 1031 | int i, j; |
| 1020 | 1032 | struct ieee80211_supported_band *sband; |
| 1021 | 1033 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
| 1034 | + enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | |
| 1022 | 1035 | u32 mask, set; |
| 1023 | 1036 | |
| 1024 | − sband = local->hw.wiphy->bands[local->oper_channel->band]; | |
| 1037 | + sband = local->hw.wiphy->bands[band]; | |
| 1025 | 1038 | |
| 1026 | 1039 | mask = params->sta_flags_mask; |
| 1027 | 1040 | set = params->sta_flags_set; |
| @@ -1136,7 +1149,7 @@ static int sta_apply_parameters(struct ieee80211_local *local, · 108 unmodified lines | ||
| 1136 | 1149 | rates |= BIT(j); |
| 1137 | 1150 | } |
| 1138 | 1151 | } |
| 1139 | − sta->sta.supp_rates[local->oper_channel->band] = rates; | |
| 1152 | + sta->sta.supp_rates[band] = rates; | |
| 1140 | 1153 | } |
| 1141 | 1154 | |
| 1142 | 1155 | if (params->ht_capa) |
| @@ -1144,6 +1157,11 @@ static int sta_apply_parameters(struct ieee80211_local *local, · 1 unmodified line | ||
| 1144 | 1157 | params->ht_capa, |
| 1145 | 1158 | &sta->sta.ht_cap); |
| 1146 | 1159 | |
| 1160 | + if (params->vht_capa) | |
| 1161 | + ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, | |
| 1162 | + params->vht_capa, | |
| 1163 | + &sta->sta.vht_cap); | |
| 1164 | + | |
| 1147 | 1165 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
| 1148 | 1166 | #ifdef CONFIG_MAC80211_MESH |
| 1149 | 1167 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) |
| @@ -1664,8 +1682,13 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, · 514 unmodified lines | ||
| 1664 | 1682 | if (err) |
| 1665 | 1683 | return err; |
| 1666 | 1684 | |
| 1667 | − err = ieee80211_set_channel(wiphy, dev, setup->channel, | |
| 1668 | − setup->channel_type); | |
| 1685 | + /* can mesh use other SMPS modes? */ | |
| 1686 | + sdata->smps_mode = IEEE80211_SMPS_OFF; | |
| 1687 | + sdata->needed_rx_chains = sdata->local->rx_chains; | |
| 1688 | + | |
| 1689 | + err = ieee80211_vif_use_channel(sdata, setup->channel, | |
| 1690 | + setup->channel_type, | |
| 1691 | + IEEE80211_CHANCTX_SHARED); | |
| 1669 | 1692 | if (err) |
| 1670 | 1693 | return err; |
| 1671 | 1694 | |
| @@ -1679,6 +1702,7 @@ static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev) · 7 unmodified lines | ||
| 1679 | 1702 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 1680 | 1703 | |
| 1681 | 1704 | ieee80211_stop_mesh(sdata); |
| 1705 | + ieee80211_vif_release_channel(sdata); | |
| 1682 | 1706 | |
| 1683 | 1707 | return 0; |
| 1684 | 1708 | } |
| @@ -1688,10 +1712,14 @@ static int ieee80211_change_bss(struct wiphy *wiphy, · 3 unmodified lines | ||
| 1688 | 1712 | struct net_device *dev, |
| 1689 | 1713 | struct bss_parameters *params) |
| 1690 | 1714 | { |
| 1691 | − struct ieee80211_sub_if_data *sdata; | |
| 1715 | + struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | |
| 1716 | + enum ieee80211_band band; | |
| 1692 | 1717 | u32 changed = 0; |
| 1693 | 1718 | |
| 1694 | − sdata = IEEE80211_DEV_TO_SUB_IF(dev); | |
| 1719 | + if (!rtnl_dereference(sdata->u.ap.beacon)) | |
| 1720 | + return -ENOENT; | |
| 1721 | + | |
| 1722 | + band = ieee80211_get_sdata_band(sdata); | |
| 1695 | 1723 | |
| 1696 | 1724 | if (params->use_cts_prot >= 0) { |
| 1697 | 1725 | sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot; |
| @@ -1704,7 +1732,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, · 6 unmodified lines | ||
| 1704 | 1732 | } |
| 1705 | 1733 | |
| 1706 | 1734 | if (!sdata->vif.bss_conf.use_short_slot && |
| 1707 | − sdata->local->oper_channel->band == IEEE80211_BAND_5GHZ) { | |
| 1735 | + band == IEEE80211_BAND_5GHZ) { | |
| 1708 | 1736 | sdata->vif.bss_conf.use_short_slot = true; |
| 1709 | 1737 | changed |= BSS_CHANGED_ERP_SLOT; |
| 1710 | 1738 | } |
| @@ -1718,9 +1746,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, · 7 unmodified lines | ||
| 1718 | 1746 | if (params->basic_rates) { |
| 1719 | 1747 | int i, j; |
| 1720 | 1748 | u32 rates = 0; |
| 1721 | − struct ieee80211_local *local = wiphy_priv(wiphy); | |
| 1722 | − struct ieee80211_supported_band *sband = | |
| 1723 | − wiphy->bands[local->oper_channel->band]; | |
| 1749 | + struct ieee80211_supported_band *sband = wiphy->bands[band]; | |
| 1724 | 1750 | |
| 1725 | 1751 | for (i = 0; i < params->basic_rates_len; i++) { |
| 1726 | 1752 | int rate = (params->basic_rates[i] & 0x7f) * 5; |
| @@ -1829,7 +1855,16 @@ static int ieee80211_scan(struct wiphy *wiphy, · 102 unmodified lines | ||
| 1829 | 1855 | * beaconing hasn't been configured yet |
| 1830 | 1856 | */ |
| 1831 | 1857 | case NL80211_IFTYPE_AP: |
| 1832 | − if (sdata->u.ap.beacon) | |
| 1858 | + /* | |
| 1859 | + * If the scan has been forced (and the driver supports | |
| 1860 | + * forcing), don't care about being beaconing already. | |
| 1861 | + * This will create problems to the attached stations (e.g. all | |
| 1862 | + * the frames sent while scanning on other channel will be | |
| 1863 | + * lost) | |
| 1864 | + */ | |
| 1865 | + if (sdata->u.ap.beacon && | |
| 1866 | + (!(wiphy->features & NL80211_FEATURE_AP_SCAN) || | |
| 1867 | + !(req->flags & NL80211_SCAN_FLAG_AP))) | |
| 1833 | 1868 | return -EOPNOTSUPP; |
| 1834 | 1869 | break; |
| 1835 | 1870 | default: |
| @@ -1872,20 +1907,6 @@ static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, · 36 unmodified lines | ||
| 1872 | 1907 | static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev, |
| 1873 | 1908 | struct cfg80211_assoc_request *req) |
| 1874 | 1909 | { |
| 1875 | − struct ieee80211_local *local = wiphy_priv(wiphy); | |
| 1876 | − struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | |
| 1877 | − | |
| 1878 | − switch (ieee80211_get_channel_mode(local, sdata)) { | |
| 1879 | − case CHAN_MODE_HOPPING: | |
| 1880 | − return -EBUSY; | |
| 1881 | − case CHAN_MODE_FIXED: | |
| 1882 | − if (local->oper_channel == req->bss->channel) | |
| 1883 | − break; | |
| 1884 | − return -EBUSY; | |
| 1885 | − case CHAN_MODE_UNDEFINED: | |
| 1886 | − break; | |
| 1887 | − } | |
| 1888 | − | |
| 1889 | 1910 | return ieee80211_mgd_assoc(IEEE80211_DEV_TO_SUB_IF(dev), req); |
| 1890 | 1911 | } |
| 1891 | 1912 | |
| @@ -1904,30 +1925,12 @@ static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev, · 12 unmodified lines | ||
| 1904 | 1925 | static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, |
| 1905 | 1926 | struct cfg80211_ibss_params *params) |
| 1906 | 1927 | { |
| 1907 | − struct ieee80211_local *local = wiphy_priv(wiphy); | |
| 1908 | − struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | |
| 1909 | − | |
| 1910 | − switch (ieee80211_get_channel_mode(local, sdata)) { | |
| 1911 | − case CHAN_MODE_HOPPING: | |
| 1912 | − return -EBUSY; | |
| 1913 | − case CHAN_MODE_FIXED: | |
| 1914 | − if (!params->channel_fixed) | |
| 1915 | − return -EBUSY; | |
| 1916 | − if (local->oper_channel == params->channel) | |
| 1917 | − break; | |
| 1918 | − return -EBUSY; | |
| 1919 | − case CHAN_MODE_UNDEFINED: | |
| 1920 | − break; | |
| 1921 | − } | |
| 1922 | − | |
| 1923 | − return ieee80211_ibss_join(sdata, params); | |
| 1928 | + return ieee80211_ibss_join(IEEE80211_DEV_TO_SUB_IF(dev), params); | |
| 1924 | 1929 | } |
| 1925 | 1930 | |
| 1926 | 1931 | static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) |
| 1927 | 1932 | { |
| 1928 | − struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | |
| 1929 | − | |
| 1930 | − return ieee80211_ibss_leave(sdata); | |
| 1933 | + return ieee80211_ibss_leave(IEEE80211_DEV_TO_SUB_IF(dev)); | |
| 1931 | 1934 | } |
| 1932 | 1935 | |
| 1933 | 1936 | static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) |
| @@ -1971,9 +1974,13 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, · 37 unmodified lines | ||
| 1971 | 1974 | enum nl80211_tx_power_setting type, int mbm) |
| 1972 | 1975 | { |
| 1973 | 1976 | struct ieee80211_local *local = wiphy_priv(wiphy); |
| 1974 | − struct ieee80211_channel *chan = local->oper_channel; | |
| 1977 | + struct ieee80211_channel *chan = local->_oper_channel; | |
| 1975 | 1978 | u32 changes = 0; |
| 1976 | 1979 | |
| 1980 | + /* FIXME */ | |
| 1981 | + if (local->use_chanctx) | |
| 1982 | + return -EOPNOTSUPP; | |
| 1983 | + | |
| 1977 | 1984 | switch (type) { |
| 1978 | 1985 | case NL80211_TX_POWER_AUTOMATIC: |
| 1979 | 1986 | local->user_power_level = -1; |
| @@ -2067,13 +2074,12 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, · 87 unmodified lines | ||
| 2067 | 2074 | |
| 2068 | 2075 | /* |
| 2069 | 2076 | * If not associated, or current association is not an HT |
| 2070 | − * association, there's no need to send an action frame. | |
| 2077 | + * association, there's no need to do anything, just store | |
| 2078 | + * the new value until we associate. | |
| 2071 | 2079 | */ |
| 2072 | 2080 | if (!sdata->u.mgd.associated || |
| 2073 | − sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) { | |
| 2074 | − ieee80211_recalc_smps(sdata->local); | |
| 2081 | + sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) | |
| 2075 | 2082 | return 0; |
| 2076 | − } | |
| 2077 | 2083 | |
| 2078 | 2084 | ap = sdata->u.mgd.associated->bssid; |
| 2079 | 2085 | |
| @@ -2189,6 +2195,9 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, · 109 unmodified lines | ||
| 2189 | 2195 | |
| 2190 | 2196 | lockdep_assert_held(&local->mtx); |
| 2191 | 2197 | |
| 2198 | + if (local->use_chanctx && !local->ops->remain_on_channel) | |
| 2199 | + return -EOPNOTSUPP; | |
| 2200 | + | |
| 2192 | 2201 | roc = kzalloc(sizeof(*roc), GFP_KERNEL); |
| 2193 | 2202 | if (!roc) |
| 2194 | 2203 | return -ENOMEM; |
| @@ -2515,10 +2524,20 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, · 320 unmodified lines | ||
| 2515 | 2524 | |
| 2516 | 2525 | /* Check if the operating channel is the requested channel */ |
| 2517 | 2526 | if (!need_offchan) { |
| 2518 | − need_offchan = chan != local->oper_channel; | |
| 2519 | − if (channel_type_valid && | |
| 2520 | − channel_type != local->_oper_channel_type) | |
| 2527 | + struct ieee80211_chanctx_conf *chanctx_conf; | |
| 2528 | + | |
| 2529 | + rcu_read_lock(); | |
| 2530 | + chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | |
| 2531 | + | |
| 2532 | + if (chanctx_conf) { | |
| 2533 | + need_offchan = chan != chanctx_conf->channel; | |
| 2534 | + if (channel_type_valid && | |
| 2535 | + channel_type != chanctx_conf->channel_type) | |
| 2536 | + need_offchan = true; | |
| 2537 | + } else { | |
| 2521 | 2538 | need_offchan = true; |
| 2539 | + } | |
| 2540 | + rcu_read_unlock(); | |
| 2522 | 2541 | } |
| 2523 | 2542 | |
| 2524 | 2543 | if (need_offchan && !offchan) { |
| @@ -2667,7 +2686,7 @@ static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata) · 142 unmodified lines | ||
| 2667 | 2686 | u16 capab; |
| 2668 | 2687 | |
| 2669 | 2688 | capab = 0; |
| 2670 | − if (local->oper_channel->band != IEEE80211_BAND_2GHZ) | |
| 2689 | + if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ) | |
| 2671 | 2690 | return capab; |
| 2672 | 2691 | |
| 2673 | 2692 | if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)) |
| @@ -2699,7 +2718,7 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, · 25 unmodified lines | ||
| 2699 | 2718 | u16 status_code, struct sk_buff *skb) |
| 2700 | 2719 | { |
| 2701 | 2720 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 2702 | − struct ieee80211_local *local = sdata->local; | |
| 2721 | + enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | |
| 2703 | 2722 | struct ieee80211_tdls_data *tf; |
| 2704 | 2723 | |
| 2705 | 2724 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); |
| @@ -2719,10 +2738,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, · 13 unmodified lines | ||
| 2719 | 2738 | tf->u.setup_req.capability = |
| 2720 | 2739 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
| 2721 | 2740 | |
| 2722 | − ieee80211_add_srates_ie(sdata, skb, false, | |
| 2723 | − local->oper_channel->band); | |
| 2724 | − ieee80211_add_ext_srates_ie(sdata, skb, false, | |
| 2725 | − local->oper_channel->band); | |
| 2741 | + ieee80211_add_srates_ie(sdata, skb, false, band); | |
| 2742 | + ieee80211_add_ext_srates_ie(sdata, skb, false, band); | |
| 2726 | 2743 | ieee80211_tdls_add_ext_capab(skb); |
| 2727 | 2744 | break; |
| 2728 | 2745 | case WLAN_TDLS_SETUP_RESPONSE: |
| @@ -2735,10 +2752,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, · 6 unmodified lines | ||
| 2735 | 2752 | tf->u.setup_resp.capability = |
| 2736 | 2753 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
| 2737 | 2754 | |
| 2738 | − ieee80211_add_srates_ie(sdata, skb, false, | |
| 2739 | − local->oper_channel->band); | |
| 2740 | − ieee80211_add_ext_srates_ie(sdata, skb, false, | |
| 2741 | − local->oper_channel->band); | |
| 2755 | + ieee80211_add_srates_ie(sdata, skb, false, band); | |
| 2756 | + ieee80211_add_ext_srates_ie(sdata, skb, false, band); | |
| 2742 | 2757 | ieee80211_tdls_add_ext_capab(skb); |
| 2743 | 2758 | break; |
| 2744 | 2759 | case WLAN_TDLS_SETUP_CONFIRM: |
| @@ -2776,7 +2791,7 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, · 31 unmodified lines | ||
| 2776 | 2791 | u16 status_code, struct sk_buff *skb) |
| 2777 | 2792 | { |
| 2778 | 2793 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 2779 | − struct ieee80211_local *local = sdata->local; | |
| 2794 | + enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | |
| 2780 | 2795 | struct ieee80211_mgmt *mgmt; |
| 2781 | 2796 | |
| 2782 | 2797 | mgmt = (void *)skb_put(skb, 24); |
| @@ -2799,10 +2814,8 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, · 16 unmodified lines | ||
| 2799 | 2814 | mgmt->u.action.u.tdls_discover_resp.capability = |
| 2800 | 2815 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
| 2801 | 2816 | |
| 2802 | − ieee80211_add_srates_ie(sdata, skb, false, | |
| 2803 | − local->oper_channel->band); | |
| 2804 | − ieee80211_add_ext_srates_ie(sdata, skb, false, | |
| 2805 | − local->oper_channel->band); | |
| 2817 | + ieee80211_add_srates_ie(sdata, skb, false, band); | |
| 2818 | + ieee80211_add_ext_srates_ie(sdata, skb, false, band); | |
| 2806 | 2819 | ieee80211_tdls_add_ext_capab(skb); |
| 2807 | 2820 | break; |
| 2808 | 2821 | default: |
| @@ -2819,7 +2832,6 @@ static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, · 10 unmodified lines | ||
| 2819 | 2832 | { |
| 2820 | 2833 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 2821 | 2834 | struct ieee80211_local *local = sdata->local; |
| 2822 | − struct ieee80211_tx_info *info; | |
| 2823 | 2835 | struct sk_buff *skb = NULL; |
| 2824 | 2836 | bool send_direct; |
| 2825 | 2837 | int ret; |
| @@ -2845,7 +2857,6 @@ static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, · 19 unmodified lines | ||
| 2845 | 2857 | if (!skb) |
| 2846 | 2858 | return -ENOMEM; |
| 2847 | 2859 | |
| 2848 | − info = IEEE80211_SKB_CB(skb); | |
| 2849 | 2860 | skb_reserve(skb, local->hw.extra_tx_headroom); |
| 2850 | 2861 | |
| 2851 | 2862 | switch (action_code) { |
| @@ -2982,12 +2993,19 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, · 130 unmodified lines | ||
| 2982 | 2993 | bool qos; |
| 2983 | 2994 | struct ieee80211_tx_info *info; |
| 2984 | 2995 | struct sta_info *sta; |
| 2996 | + struct ieee80211_chanctx_conf *chanctx_conf; | |
| 2997 | + enum ieee80211_band band; | |
| 2985 | 2998 | |
| 2986 | 2999 | rcu_read_lock(); |
| 3000 | + chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | |
| 3001 | + if (WARN_ON(!chanctx_conf)) { | |
| 3002 | + rcu_read_unlock(); | |
| 3003 | + return -EINVAL; | |
| 3004 | + } | |
| 3005 | + band = chanctx_conf->channel->band; | |
| 2987 | 3006 | sta = sta_info_get(sdata, peer); |
| 2988 | 3007 | if (sta) { |
| 2989 | 3008 | qos = test_sta_flag(sta, WLAN_STA_WME); |
| 2990 | − rcu_read_unlock(); | |
| 2991 | 3009 | } else { |
| 2992 | 3010 | rcu_read_unlock(); |
| 2993 | 3011 | return -ENOLINK; |
| @@ -3005,8 +3023,10 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, · 11 unmodified lines | ||
| 3005 | 3023 | } |
| 3006 | 3024 | |
| 3007 | 3025 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + size); |
| 3008 | − if (!skb) | |
| 3026 | + if (!skb) { | |
| 3027 | + rcu_read_unlock(); | |
| 3009 | 3028 | return -ENOMEM; |
| 3029 | + } | |
| 3010 | 3030 | |
| 3011 | 3031 | skb->dev = dev; |
| 3012 | 3032 | |
| @@ -3031,8 +3051,9 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, · 18 unmodified lines | ||
| 3031 | 3051 | nullfunc->qos_ctrl = cpu_to_le16(7); |
| 3032 | 3052 | |
| 3033 | 3053 | local_bh_disable(); |
| 3034 | − ieee80211_xmit(sdata, skb); | |
| 3054 | + ieee80211_xmit(sdata, skb, band); | |
| 3035 | 3055 | local_bh_enable(); |
| 3056 | + rcu_read_unlock(); | |
| 3036 | 3057 | |
| 3037 | 3058 | *cookie = (unsigned long) skb; |
| 3038 | 3059 | return 0; |
| @@ -3042,10 +3063,19 @@ static struct ieee80211_channel * · 3 unmodified lines | ||
| 3042 | 3063 | ieee80211_cfg_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev, |
21 more lines aren’t shown here.
This diff is large: its 475 lines aren’t shown here.
This diff is large: its 13 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 70 lines aren’t shown here.
This diff is large: its 217 lines aren’t shown here.
This diff is large: its 355 lines aren’t shown here.
This diff is large: its 122 lines aren’t shown here.
This diff is large: its 241 lines aren’t shown here.
This diff is large: its 119 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 48 lines aren’t shown here.
This diff is large: its 72 lines aren’t shown here.
This diff is large: its 523 lines aren’t shown here.
This diff is large: its 30 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 96 lines aren’t shown here.
This diff is large: its 78 lines aren’t shown here.
This diff is large: its 147 lines aren’t shown here.
This diff is large: its 39 lines aren’t shown here.
This diff is large: its 196 lines aren’t shown here.
This diff is large: its 724 lines aren’t shown here.
This diff is large: its 271 lines aren’t shown here.
This diff is large: its 36 lines aren’t shown here.
This diff is large: its 11 lines aren’t shown here.
This diff is large: its 133 lines aren’t shown here.
This diff is large: its 47 lines aren’t shown here.
This diff is large: its 163 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 23 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 185 lines aren’t shown here.
This diff is large: its 391 lines aren’t shown here.
This diff is large: its 38 lines aren’t shown here.
This diff is large: its 67 lines aren’t shown here.
This diff is large: its 9 lines aren’t shown here.
This diff is large: its 75 lines aren’t shown here.
This diff is large: its 192 lines aren’t shown here.
This diff is large: its 20 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 15 lines aren’t shown here.
This diff is large: its 17 lines aren’t shown here.
This diff is large: its 55 lines aren’t shown here.
This diff is large: its 65 lines aren’t shown here.
This diff is large: its 18 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 44 lines aren’t shown here.
This diff is large: its 46 lines aren’t shown here.
This diff is large: its 353 lines aren’t shown here.
This diff is large: its 746 lines aren’t shown here.
This diff is large: its 880 lines aren’t shown here.
This diff is large: its 267 lines aren’t shown here.
This diff is large: its 57 lines aren’t shown here.
This diff is large: its 26 lines aren’t shown here.
This diff is large: its 8 lines aren’t shown here.
This diff is large: its 2297 lines aren’t shown here.
This diff is large: its 43 lines aren’t shown here.
This diff is large: its 184 lines aren’t shown here.