diff options
Diffstat (limited to 'drivers')
112 files changed, 4938 insertions, 4577 deletions
diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c index 893f6e0c759f..bc6e89212ad3 100644 --- a/drivers/bcma/core.c +++ b/drivers/bcma/core.c | |||
@@ -30,6 +30,7 @@ void bcma_core_disable(struct bcma_device *core, u32 flags) | |||
30 | udelay(10); | 30 | udelay(10); |
31 | 31 | ||
32 | bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); | 32 | bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); |
33 | bcma_aread32(core, BCMA_RESET_CTL); | ||
33 | udelay(1); | 34 | udelay(1); |
34 | } | 35 | } |
35 | EXPORT_SYMBOL_GPL(bcma_core_disable); | 36 | EXPORT_SYMBOL_GPL(bcma_core_disable); |
@@ -77,7 +78,7 @@ void bcma_core_set_clockmode(struct bcma_device *core, | |||
77 | pr_err("HT force timeout\n"); | 78 | pr_err("HT force timeout\n"); |
78 | break; | 79 | break; |
79 | case BCMA_CLKMODE_DYNAMIC: | 80 | case BCMA_CLKMODE_DYNAMIC: |
80 | pr_warn("Dynamic clockmode not supported yet!\n"); | 81 | bcma_set32(core, BCMA_CLKCTLST, ~BCMA_CLKCTLST_FORCEHT); |
81 | break; | 82 | break; |
82 | } | 83 | } |
83 | } | 84 | } |
diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c index 4d38ae179b48..9a96f14c8f47 100644 --- a/drivers/bcma/driver_pci.c +++ b/drivers/bcma/driver_pci.c | |||
@@ -24,14 +24,12 @@ u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address) | |||
24 | return pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_DATA); | 24 | return pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_DATA); |
25 | } | 25 | } |
26 | 26 | ||
27 | #if 0 | ||
28 | static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data) | 27 | static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data) |
29 | { | 28 | { |
30 | pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address); | 29 | pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_ADDR, address); |
31 | pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR); | 30 | pcicore_read32(pc, BCMA_CORE_PCI_PCIEIND_ADDR); |
32 | pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_DATA, data); | 31 | pcicore_write32(pc, BCMA_CORE_PCI_PCIEIND_DATA, data); |
33 | } | 32 | } |
34 | #endif | ||
35 | 33 | ||
36 | static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy) | 34 | static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy) |
37 | { | 35 | { |
@@ -170,13 +168,50 @@ static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc) | |||
170 | tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN); | 168 | tmp & ~BCMA_CORE_PCI_PLL_CTRL_FREQDET_EN); |
171 | } | 169 | } |
172 | 170 | ||
171 | static void bcma_core_pci_fixcfg(struct bcma_drv_pci *pc) | ||
172 | { | ||
173 | struct bcma_device *core = pc->core; | ||
174 | u16 val16, core_index; | ||
175 | uint regoff; | ||
176 | |||
177 | regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_PI_OFFSET); | ||
178 | core_index = (u16)core->core_index; | ||
179 | |||
180 | val16 = pcicore_read16(pc, regoff); | ||
181 | if (((val16 & BCMA_CORE_PCI_SPROM_PI_MASK) >> BCMA_CORE_PCI_SPROM_PI_SHIFT) | ||
182 | != core_index) { | ||
183 | val16 = (core_index << BCMA_CORE_PCI_SPROM_PI_SHIFT) | | ||
184 | (val16 & ~BCMA_CORE_PCI_SPROM_PI_MASK); | ||
185 | pcicore_write16(pc, regoff, val16); | ||
186 | } | ||
187 | } | ||
188 | |||
189 | /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */ | ||
190 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | ||
191 | static void bcma_core_pci_config_fixup(struct bcma_drv_pci *pc) | ||
192 | { | ||
193 | u16 val16; | ||
194 | uint regoff; | ||
195 | |||
196 | regoff = BCMA_CORE_PCI_SPROM(BCMA_CORE_PCI_SPROM_MISC_CONFIG); | ||
197 | |||
198 | val16 = pcicore_read16(pc, regoff); | ||
199 | |||
200 | if (!(val16 & BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST)) { | ||
201 | val16 |= BCMA_CORE_PCI_SPROM_L23READY_EXIT_NOPERST; | ||
202 | pcicore_write16(pc, regoff, val16); | ||
203 | } | ||
204 | } | ||
205 | |||
173 | /************************************************** | 206 | /************************************************** |
174 | * Init. | 207 | * Init. |
175 | **************************************************/ | 208 | **************************************************/ |
176 | 209 | ||
177 | static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc) | 210 | static void __devinit bcma_core_pci_clientmode_init(struct bcma_drv_pci *pc) |
178 | { | 211 | { |
212 | bcma_core_pci_fixcfg(pc); | ||
179 | bcma_pcicore_serdes_workaround(pc); | 213 | bcma_pcicore_serdes_workaround(pc); |
214 | bcma_core_pci_config_fixup(pc); | ||
180 | } | 215 | } |
181 | 216 | ||
182 | void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc) | 217 | void __devinit bcma_core_pci_init(struct bcma_drv_pci *pc) |
@@ -224,3 +259,17 @@ out: | |||
224 | return err; | 259 | return err; |
225 | } | 260 | } |
226 | EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl); | 261 | EXPORT_SYMBOL_GPL(bcma_core_pci_irq_ctl); |
262 | |||
263 | void bcma_core_pci_extend_L1timer(struct bcma_drv_pci *pc, bool extend) | ||
264 | { | ||
265 | u32 w; | ||
266 | |||
267 | w = bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG); | ||
268 | if (extend) | ||
269 | w |= BCMA_CORE_PCI_ASPMTIMER_EXTEND; | ||
270 | else | ||
271 | w &= ~BCMA_CORE_PCI_ASPMTIMER_EXTEND; | ||
272 | bcma_pcie_write(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG, w); | ||
273 | bcma_pcie_read(pc, BCMA_CORE_PCI_DLLP_PMTHRESHREG); | ||
274 | } | ||
275 | EXPORT_SYMBOL_GPL(bcma_core_pci_extend_L1timer); | ||
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c index d2097a11c3c7..b9a86edfec39 100644 --- a/drivers/bcma/driver_pci_host.c +++ b/drivers/bcma/driver_pci_host.c | |||
@@ -119,7 +119,7 @@ static int bcma_extpci_read_config(struct bcma_drv_pci *pc, unsigned int dev, | |||
119 | if (unlikely(!addr)) | 119 | if (unlikely(!addr)) |
120 | goto out; | 120 | goto out; |
121 | err = -ENOMEM; | 121 | err = -ENOMEM; |
122 | mmio = ioremap_nocache(addr, len); | 122 | mmio = ioremap_nocache(addr, sizeof(val)); |
123 | if (!mmio) | 123 | if (!mmio) |
124 | goto out; | 124 | goto out; |
125 | 125 | ||
@@ -171,7 +171,7 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, | |||
171 | addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0; | 171 | addr = pc->core->addr + BCMA_CORE_PCI_PCICFG0; |
172 | addr |= (func << 8); | 172 | addr |= (func << 8); |
173 | addr |= (off & 0xfc); | 173 | addr |= (off & 0xfc); |
174 | mmio = ioremap_nocache(addr, len); | 174 | mmio = ioremap_nocache(addr, sizeof(val)); |
175 | if (!mmio) | 175 | if (!mmio) |
176 | goto out; | 176 | goto out; |
177 | } | 177 | } |
@@ -180,7 +180,7 @@ static int bcma_extpci_write_config(struct bcma_drv_pci *pc, unsigned int dev, | |||
180 | if (unlikely(!addr)) | 180 | if (unlikely(!addr)) |
181 | goto out; | 181 | goto out; |
182 | err = -ENOMEM; | 182 | err = -ENOMEM; |
183 | mmio = ioremap_nocache(addr, len); | 183 | mmio = ioremap_nocache(addr, sizeof(val)); |
184 | if (!mmio) | 184 | if (!mmio) |
185 | goto out; | 185 | goto out; |
186 | 186 | ||
@@ -491,8 +491,8 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) | |||
491 | /* Ok, ready to run, register it to the system. | 491 | /* Ok, ready to run, register it to the system. |
492 | * The following needs change, if we want to port hostmode | 492 | * The following needs change, if we want to port hostmode |
493 | * to non-MIPS platform. */ | 493 | * to non-MIPS platform. */ |
494 | io_map_base = (unsigned long)ioremap_nocache(BCMA_SOC_PCI_MEM, | 494 | io_map_base = (unsigned long)ioremap_nocache(pc_host->mem_resource.start, |
495 | 0x04000000); | 495 | resource_size(&pc_host->mem_resource)); |
496 | pc_host->pci_controller.io_map_base = io_map_base; | 496 | pc_host->pci_controller.io_map_base = io_map_base; |
497 | set_io_port_base(pc_host->pci_controller.io_map_base); | 497 | set_io_port_base(pc_host->pci_controller.io_map_base); |
498 | /* Give some time to the PCI controller to configure itself with the new | 498 | /* Give some time to the PCI controller to configure itself with the new |
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index e3928d68802b..6c05cf470f96 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c | |||
@@ -201,6 +201,9 @@ static int __devinit bcma_host_pci_probe(struct pci_dev *dev, | |||
201 | bus->hosttype = BCMA_HOSTTYPE_PCI; | 201 | bus->hosttype = BCMA_HOSTTYPE_PCI; |
202 | bus->ops = &bcma_host_pci_ops; | 202 | bus->ops = &bcma_host_pci_ops; |
203 | 203 | ||
204 | bus->boardinfo.vendor = bus->host_pci->subsystem_vendor; | ||
205 | bus->boardinfo.type = bus->host_pci->subsystem_device; | ||
206 | |||
204 | /* Register */ | 207 | /* Register */ |
205 | err = bcma_bus_register(bus); | 208 | err = bcma_bus_register(bus); |
206 | if (err) | 209 | if (err) |
@@ -222,7 +225,7 @@ err_kfree_bus: | |||
222 | return err; | 225 | return err; |
223 | } | 226 | } |
224 | 227 | ||
225 | static void bcma_host_pci_remove(struct pci_dev *dev) | 228 | static void __devexit bcma_host_pci_remove(struct pci_dev *dev) |
226 | { | 229 | { |
227 | struct bcma_bus *bus = pci_get_drvdata(dev); | 230 | struct bcma_bus *bus = pci_get_drvdata(dev); |
228 | 231 | ||
@@ -277,7 +280,7 @@ static struct pci_driver bcma_pci_bridge_driver = { | |||
277 | .name = "bcma-pci-bridge", | 280 | .name = "bcma-pci-bridge", |
278 | .id_table = bcma_pci_bridge_tbl, | 281 | .id_table = bcma_pci_bridge_tbl, |
279 | .probe = bcma_host_pci_probe, | 282 | .probe = bcma_host_pci_probe, |
280 | .remove = bcma_host_pci_remove, | 283 | .remove = __devexit_p(bcma_host_pci_remove), |
281 | .driver.pm = BCMA_PM_OPS, | 284 | .driver.pm = BCMA_PM_OPS, |
282 | }; | 285 | }; |
283 | 286 | ||
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index 3bea7fe25b20..5ed0718fc660 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c | |||
@@ -19,7 +19,14 @@ struct bcma_device_id_name { | |||
19 | u16 id; | 19 | u16 id; |
20 | const char *name; | 20 | const char *name; |
21 | }; | 21 | }; |
22 | struct bcma_device_id_name bcma_device_names[] = { | 22 | |
23 | static const struct bcma_device_id_name bcma_arm_device_names[] = { | ||
24 | { BCMA_CORE_ARM_1176, "ARM 1176" }, | ||
25 | { BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" }, | ||
26 | { BCMA_CORE_ARM_CM3, "ARM CM3" }, | ||
27 | }; | ||
28 | |||
29 | static const struct bcma_device_id_name bcma_bcm_device_names[] = { | ||
23 | { BCMA_CORE_OOB_ROUTER, "OOB Router" }, | 30 | { BCMA_CORE_OOB_ROUTER, "OOB Router" }, |
24 | { BCMA_CORE_INVALID, "Invalid" }, | 31 | { BCMA_CORE_INVALID, "Invalid" }, |
25 | { BCMA_CORE_CHIPCOMMON, "ChipCommon" }, | 32 | { BCMA_CORE_CHIPCOMMON, "ChipCommon" }, |
@@ -27,7 +34,6 @@ struct bcma_device_id_name bcma_device_names[] = { | |||
27 | { BCMA_CORE_SRAM, "SRAM" }, | 34 | { BCMA_CORE_SRAM, "SRAM" }, |
28 | { BCMA_CORE_SDRAM, "SDRAM" }, | 35 | { BCMA_CORE_SDRAM, "SDRAM" }, |
29 | { BCMA_CORE_PCI, "PCI" }, | 36 | { BCMA_CORE_PCI, "PCI" }, |
30 | { BCMA_CORE_MIPS, "MIPS" }, | ||
31 | { BCMA_CORE_ETHERNET, "Fast Ethernet" }, | 37 | { BCMA_CORE_ETHERNET, "Fast Ethernet" }, |
32 | { BCMA_CORE_V90, "V90" }, | 38 | { BCMA_CORE_V90, "V90" }, |
33 | { BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" }, | 39 | { BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" }, |
@@ -44,7 +50,6 @@ struct bcma_device_id_name bcma_device_names[] = { | |||
44 | { BCMA_CORE_PHY_A, "PHY A" }, | 50 | { BCMA_CORE_PHY_A, "PHY A" }, |
45 | { BCMA_CORE_PHY_B, "PHY B" }, | 51 | { BCMA_CORE_PHY_B, "PHY B" }, |
46 | { BCMA_CORE_PHY_G, "PHY G" }, | 52 | { BCMA_CORE_PHY_G, "PHY G" }, |
47 | { BCMA_CORE_MIPS_3302, "MIPS 3302" }, | ||
48 | { BCMA_CORE_USB11_HOST, "USB 1.1 Host" }, | 53 | { BCMA_CORE_USB11_HOST, "USB 1.1 Host" }, |
49 | { BCMA_CORE_USB11_DEV, "USB 1.1 Device" }, | 54 | { BCMA_CORE_USB11_DEV, "USB 1.1 Device" }, |
50 | { BCMA_CORE_USB20_HOST, "USB 2.0 Host" }, | 55 | { BCMA_CORE_USB20_HOST, "USB 2.0 Host" }, |
@@ -58,15 +63,11 @@ struct bcma_device_id_name bcma_device_names[] = { | |||
58 | { BCMA_CORE_PHY_N, "PHY N" }, | 63 | { BCMA_CORE_PHY_N, "PHY N" }, |
59 | { BCMA_CORE_SRAM_CTL, "SRAM Controller" }, | 64 | { BCMA_CORE_SRAM_CTL, "SRAM Controller" }, |
60 | { BCMA_CORE_MINI_MACPHY, "Mini MACPHY" }, | 65 | { BCMA_CORE_MINI_MACPHY, "Mini MACPHY" }, |
61 | { BCMA_CORE_ARM_1176, "ARM 1176" }, | ||
62 | { BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" }, | ||
63 | { BCMA_CORE_PHY_LP, "PHY LP" }, | 66 | { BCMA_CORE_PHY_LP, "PHY LP" }, |
64 | { BCMA_CORE_PMU, "PMU" }, | 67 | { BCMA_CORE_PMU, "PMU" }, |
65 | { BCMA_CORE_PHY_SSN, "PHY SSN" }, | 68 | { BCMA_CORE_PHY_SSN, "PHY SSN" }, |
66 | { BCMA_CORE_SDIO_DEV, "SDIO Device" }, | 69 | { BCMA_CORE_SDIO_DEV, "SDIO Device" }, |
67 | { BCMA_CORE_ARM_CM3, "ARM CM3" }, | ||
68 | { BCMA_CORE_PHY_HT, "PHY HT" }, | 70 | { BCMA_CORE_PHY_HT, "PHY HT" }, |
69 | { BCMA_CORE_MIPS_74K, "MIPS 74K" }, | ||
70 | { BCMA_CORE_MAC_GBIT, "GBit MAC" }, | 71 | { BCMA_CORE_MAC_GBIT, "GBit MAC" }, |
71 | { BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" }, | 72 | { BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" }, |
72 | { BCMA_CORE_PCIE_RC, "PCIe Root Complex" }, | 73 | { BCMA_CORE_PCIE_RC, "PCIe Root Complex" }, |
@@ -79,16 +80,41 @@ struct bcma_device_id_name bcma_device_names[] = { | |||
79 | { BCMA_CORE_SHIM, "SHIM" }, | 80 | { BCMA_CORE_SHIM, "SHIM" }, |
80 | { BCMA_CORE_DEFAULT, "Default" }, | 81 | { BCMA_CORE_DEFAULT, "Default" }, |
81 | }; | 82 | }; |
82 | const char *bcma_device_name(struct bcma_device_id *id) | 83 | |
84 | static const struct bcma_device_id_name bcma_mips_device_names[] = { | ||
85 | { BCMA_CORE_MIPS, "MIPS" }, | ||
86 | { BCMA_CORE_MIPS_3302, "MIPS 3302" }, | ||
87 | { BCMA_CORE_MIPS_74K, "MIPS 74K" }, | ||
88 | }; | ||
89 | |||
90 | static const char *bcma_device_name(const struct bcma_device_id *id) | ||
83 | { | 91 | { |
84 | int i; | 92 | const struct bcma_device_id_name *names; |
93 | int size, i; | ||
94 | |||
95 | /* search manufacturer specific names */ | ||
96 | switch (id->manuf) { | ||
97 | case BCMA_MANUF_ARM: | ||
98 | names = bcma_arm_device_names; | ||
99 | size = ARRAY_SIZE(bcma_arm_device_names); | ||
100 | break; | ||
101 | case BCMA_MANUF_BCM: | ||
102 | names = bcma_bcm_device_names; | ||
103 | size = ARRAY_SIZE(bcma_bcm_device_names); | ||
104 | break; | ||
105 | case BCMA_MANUF_MIPS: | ||
106 | names = bcma_mips_device_names; | ||
107 | size = ARRAY_SIZE(bcma_mips_device_names); | ||
108 | break; | ||
109 | default: | ||
110 | return "UNKNOWN"; | ||
111 | } | ||
85 | 112 | ||
86 | if (id->manuf == BCMA_MANUF_BCM) { | 113 | for (i = 0; i < size; i++) { |
87 | for (i = 0; i < ARRAY_SIZE(bcma_device_names); i++) { | 114 | if (names[i].id == id->id) |
88 | if (bcma_device_names[i].id == id->id) | 115 | return names[i].name; |
89 | return bcma_device_names[i].name; | ||
90 | } | ||
91 | } | 116 | } |
117 | |||
92 | return "UNKNOWN"; | 118 | return "UNKNOWN"; |
93 | } | 119 | } |
94 | 120 | ||
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index 3e2a6002aae6..c7f93359acb0 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c | |||
@@ -181,6 +181,22 @@ static int bcma_sprom_valid(const u16 *sprom) | |||
181 | #define SPEX(_field, _offset, _mask, _shift) \ | 181 | #define SPEX(_field, _offset, _mask, _shift) \ |
182 | bus->sprom._field = ((sprom[SPOFF(_offset)] & (_mask)) >> (_shift)) | 182 | bus->sprom._field = ((sprom[SPOFF(_offset)] & (_mask)) >> (_shift)) |
183 | 183 | ||
184 | #define SPEX32(_field, _offset, _mask, _shift) \ | ||
185 | bus->sprom._field = ((((u32)sprom[SPOFF((_offset)+2)] << 16 | \ | ||
186 | sprom[SPOFF(_offset)]) & (_mask)) >> (_shift)) | ||
187 | |||
188 | #define SPEX_ARRAY8(_field, _offset, _mask, _shift) \ | ||
189 | do { \ | ||
190 | SPEX(_field[0], _offset + 0, _mask, _shift); \ | ||
191 | SPEX(_field[1], _offset + 2, _mask, _shift); \ | ||
192 | SPEX(_field[2], _offset + 4, _mask, _shift); \ | ||
193 | SPEX(_field[3], _offset + 6, _mask, _shift); \ | ||
194 | SPEX(_field[4], _offset + 8, _mask, _shift); \ | ||
195 | SPEX(_field[5], _offset + 10, _mask, _shift); \ | ||
196 | SPEX(_field[6], _offset + 12, _mask, _shift); \ | ||
197 | SPEX(_field[7], _offset + 14, _mask, _shift); \ | ||
198 | } while (0) | ||
199 | |||
184 | static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) | 200 | static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) |
185 | { | 201 | { |
186 | u16 v, o; | 202 | u16 v, o; |
@@ -243,7 +259,8 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) | |||
243 | SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, ~0, 0); | 259 | SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, ~0, 0); |
244 | SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, ~0, 0); | 260 | SPEX(boardflags2_hi, SSB_SPROM8_BFL2HI, ~0, 0); |
245 | 261 | ||
246 | SPEX(country_code, SSB_SPROM8_CCODE, ~0, 0); | 262 | SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); |
263 | SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); | ||
247 | 264 | ||
248 | /* Extract cores power info info */ | 265 | /* Extract cores power info info */ |
249 | for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { | 266 | for (i = 0; i < ARRAY_SIZE(pwr_info_offset); i++) { |
@@ -298,6 +315,136 @@ static void bcma_sprom_extract_r8(struct bcma_bus *bus, const u16 *sprom) | |||
298 | SSB_SROM8_FEM_TR_ISO_SHIFT); | 315 | SSB_SROM8_FEM_TR_ISO_SHIFT); |
299 | SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT, | 316 | SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, SSB_SROM8_FEM_ANTSWLUT, |
300 | SSB_SROM8_FEM_ANTSWLUT_SHIFT); | 317 | SSB_SROM8_FEM_ANTSWLUT_SHIFT); |
318 | |||
319 | SPEX(ant_available_a, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_A, | ||
320 | SSB_SPROM8_ANTAVAIL_A_SHIFT); | ||
321 | SPEX(ant_available_bg, SSB_SPROM8_ANTAVAIL, SSB_SPROM8_ANTAVAIL_BG, | ||
322 | SSB_SPROM8_ANTAVAIL_BG_SHIFT); | ||
323 | SPEX(maxpwr_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_MAXP_BG_MASK, 0); | ||
324 | SPEX(itssi_bg, SSB_SPROM8_MAXP_BG, SSB_SPROM8_ITSSI_BG, | ||
325 | SSB_SPROM8_ITSSI_BG_SHIFT); | ||
326 | SPEX(maxpwr_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_MAXP_A_MASK, 0); | ||
327 | SPEX(itssi_a, SSB_SPROM8_MAXP_A, SSB_SPROM8_ITSSI_A, | ||
328 | SSB_SPROM8_ITSSI_A_SHIFT); | ||
329 | SPEX(maxpwr_ah, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AH_MASK, 0); | ||
330 | SPEX(maxpwr_al, SSB_SPROM8_MAXP_AHL, SSB_SPROM8_MAXP_AL_MASK, | ||
331 | SSB_SPROM8_MAXP_AL_SHIFT); | ||
332 | SPEX(gpio0, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P0, 0); | ||
333 | SPEX(gpio1, SSB_SPROM8_GPIOA, SSB_SPROM8_GPIOA_P1, | ||
334 | SSB_SPROM8_GPIOA_P1_SHIFT); | ||
335 | SPEX(gpio2, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P2, 0); | ||
336 | SPEX(gpio3, SSB_SPROM8_GPIOB, SSB_SPROM8_GPIOB_P3, | ||
337 | SSB_SPROM8_GPIOB_P3_SHIFT); | ||
338 | SPEX(tri2g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI2G, 0); | ||
339 | SPEX(tri5g, SSB_SPROM8_TRI25G, SSB_SPROM8_TRI5G, | ||
340 | SSB_SPROM8_TRI5G_SHIFT); | ||
341 | SPEX(tri5gl, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GL, 0); | ||
342 | SPEX(tri5gh, SSB_SPROM8_TRI5GHL, SSB_SPROM8_TRI5GH, | ||
343 | SSB_SPROM8_TRI5GH_SHIFT); | ||
344 | SPEX(rxpo2g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO2G, | ||
345 | SSB_SPROM8_RXPO2G_SHIFT); | ||
346 | SPEX(rxpo5g, SSB_SPROM8_RXPO, SSB_SPROM8_RXPO5G, | ||
347 | SSB_SPROM8_RXPO5G_SHIFT); | ||
348 | SPEX(rssismf2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMF2G, 0); | ||
349 | SPEX(rssismc2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISMC2G, | ||
350 | SSB_SPROM8_RSSISMC2G_SHIFT); | ||
351 | SPEX(rssisav2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_RSSISAV2G, | ||
352 | SSB_SPROM8_RSSISAV2G_SHIFT); | ||
353 | SPEX(bxa2g, SSB_SPROM8_RSSIPARM2G, SSB_SPROM8_BXA2G, | ||
354 | SSB_SPROM8_BXA2G_SHIFT); | ||
355 | SPEX(rssismf5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMF5G, 0); | ||
356 | SPEX(rssismc5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISMC5G, | ||
357 | SSB_SPROM8_RSSISMC5G_SHIFT); | ||
358 | SPEX(rssisav5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_RSSISAV5G, | ||
359 | SSB_SPROM8_RSSISAV5G_SHIFT); | ||
360 | SPEX(bxa5g, SSB_SPROM8_RSSIPARM5G, SSB_SPROM8_BXA5G, | ||
361 | SSB_SPROM8_BXA5G_SHIFT); | ||
362 | |||
363 | SPEX(pa0b0, SSB_SPROM8_PA0B0, ~0, 0); | ||
364 | SPEX(pa0b1, SSB_SPROM8_PA0B1, ~0, 0); | ||
365 | SPEX(pa0b2, SSB_SPROM8_PA0B2, ~0, 0); | ||
366 | SPEX(pa1b0, SSB_SPROM8_PA1B0, ~0, 0); | ||
367 | SPEX(pa1b1, SSB_SPROM8_PA1B1, ~0, 0); | ||
368 | SPEX(pa1b2, SSB_SPROM8_PA1B2, ~0, 0); | ||
369 | SPEX(pa1lob0, SSB_SPROM8_PA1LOB0, ~0, 0); | ||
370 | SPEX(pa1lob1, SSB_SPROM8_PA1LOB1, ~0, 0); | ||
371 | SPEX(pa1lob2, SSB_SPROM8_PA1LOB2, ~0, 0); | ||
372 | SPEX(pa1hib0, SSB_SPROM8_PA1HIB0, ~0, 0); | ||
373 | SPEX(pa1hib1, SSB_SPROM8_PA1HIB1, ~0, 0); | ||
374 | SPEX(pa1hib2, SSB_SPROM8_PA1HIB2, ~0, 0); | ||
375 | SPEX(cck2gpo, SSB_SPROM8_CCK2GPO, ~0, 0); | ||
376 | SPEX32(ofdm2gpo, SSB_SPROM8_OFDM2GPO, ~0, 0); | ||
377 | SPEX32(ofdm5glpo, SSB_SPROM8_OFDM5GLPO, ~0, 0); | ||
378 | SPEX32(ofdm5gpo, SSB_SPROM8_OFDM5GPO, ~0, 0); | ||
379 | SPEX32(ofdm5ghpo, SSB_SPROM8_OFDM5GHPO, ~0, 0); | ||
380 | |||
381 | /* Extract the antenna gain values. */ | ||
382 | SPEX(antenna_gain.a0, SSB_SPROM8_AGAIN01, | ||
383 | SSB_SPROM8_AGAIN0, SSB_SPROM8_AGAIN0_SHIFT); | ||
384 | SPEX(antenna_gain.a1, SSB_SPROM8_AGAIN01, | ||
385 | SSB_SPROM8_AGAIN1, SSB_SPROM8_AGAIN1_SHIFT); | ||
386 | SPEX(antenna_gain.a2, SSB_SPROM8_AGAIN23, | ||
387 | SSB_SPROM8_AGAIN2, SSB_SPROM8_AGAIN2_SHIFT); | ||
388 | SPEX(antenna_gain.a3, SSB_SPROM8_AGAIN23, | ||
389 | SSB_SPROM8_AGAIN3, SSB_SPROM8_AGAIN3_SHIFT); | ||
390 | |||
391 | SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON, | ||
392 | SSB_SPROM8_LEDDC_ON_SHIFT); | ||
393 | SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF, | ||
394 | SSB_SPROM8_LEDDC_OFF_SHIFT); | ||
395 | |||
396 | SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN, | ||
397 | SSB_SPROM8_TXRXC_TXCHAIN_SHIFT); | ||
398 | SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN, | ||
399 | SSB_SPROM8_TXRXC_RXCHAIN_SHIFT); | ||
400 | SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH, | ||
401 | SSB_SPROM8_TXRXC_SWITCH_SHIFT); | ||
402 | |||
403 | SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0); | ||
404 | |||
405 | SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0); | ||
406 | SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0); | ||
407 | SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0); | ||
408 | SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0); | ||
409 | |||
410 | SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP, | ||
411 | SSB_SPROM8_RAWTS_RAWTEMP_SHIFT); | ||
412 | SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER, | ||
413 | SSB_SPROM8_RAWTS_MEASPOWER_SHIFT); | ||
414 | SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX, | ||
415 | SSB_SPROM8_OPT_CORRX_TEMP_SLOPE, | ||
416 | SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT); | ||
417 | SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX, | ||
418 | SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT); | ||
419 | SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX, | ||
420 | SSB_SPROM8_OPT_CORRX_TEMP_OPTION, | ||
421 | SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT); | ||
422 | SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP, | ||
423 | SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR, | ||
424 | SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT); | ||
425 | SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP, | ||
426 | SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP, | ||
427 | SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT); | ||
428 | SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL, | ||
429 | SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT); | ||
430 | |||
431 | SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0); | ||
432 | SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0); | ||
433 | SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0); | ||
434 | SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0); | ||
435 | |||
436 | SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH, | ||
437 | SSB_SPROM8_THERMAL_TRESH_SHIFT); | ||
438 | SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET, | ||
439 | SSB_SPROM8_THERMAL_OFFSET_SHIFT); | ||
440 | SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA, | ||
441 | SSB_SPROM8_TEMPDELTA_PHYCAL, | ||
442 | SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT); | ||
443 | SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD, | ||
444 | SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT); | ||
445 | SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA, | ||
446 | SSB_SPROM8_TEMPDELTA_HYSTERESIS, | ||
447 | SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT); | ||
301 | } | 448 | } |
302 | 449 | ||
303 | /* | 450 | /* |
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 2812b152d6e9..ad591bd240ec 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c | |||
@@ -81,6 +81,9 @@ static struct usb_device_id ath3k_table[] = { | |||
81 | /* Atheros AR5BBU12 with sflash firmware */ | 81 | /* Atheros AR5BBU12 with sflash firmware */ |
82 | { USB_DEVICE(0x0489, 0xE02C) }, | 82 | { USB_DEVICE(0x0489, 0xE02C) }, |
83 | 83 | ||
84 | /* Atheros AR5BBU22 with sflash firmware */ | ||
85 | { USB_DEVICE(0x0489, 0xE03C) }, | ||
86 | |||
84 | { } /* Terminating entry */ | 87 | { } /* Terminating entry */ |
85 | }; | 88 | }; |
86 | 89 | ||
@@ -99,6 +102,9 @@ static struct usb_device_id ath3k_blist_tbl[] = { | |||
99 | { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, | 102 | { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, |
100 | { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, | 103 | { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, |
101 | 104 | ||
105 | /* Atheros AR5BBU22 with sflash firmware */ | ||
106 | { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, | ||
107 | |||
102 | { } /* Terminating entry */ | 108 | { } /* Terminating entry */ |
103 | }; | 109 | }; |
104 | 110 | ||
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h index 90bda50dc446..94f2d65131c4 100644 --- a/drivers/bluetooth/btmrvl_drv.h +++ b/drivers/bluetooth/btmrvl_drv.h | |||
@@ -67,6 +67,7 @@ struct btmrvl_adapter { | |||
67 | u8 wakeup_tries; | 67 | u8 wakeup_tries; |
68 | wait_queue_head_t cmd_wait_q; | 68 | wait_queue_head_t cmd_wait_q; |
69 | u8 cmd_complete; | 69 | u8 cmd_complete; |
70 | bool is_suspended; | ||
70 | }; | 71 | }; |
71 | 72 | ||
72 | struct btmrvl_private { | 73 | struct btmrvl_private { |
@@ -139,8 +140,10 @@ void btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb); | |||
139 | int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb); | 140 | int btmrvl_process_event(struct btmrvl_private *priv, struct sk_buff *skb); |
140 | 141 | ||
141 | int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd); | 142 | int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd); |
143 | int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv); | ||
142 | int btmrvl_enable_ps(struct btmrvl_private *priv); | 144 | int btmrvl_enable_ps(struct btmrvl_private *priv); |
143 | int btmrvl_prepare_command(struct btmrvl_private *priv); | 145 | int btmrvl_prepare_command(struct btmrvl_private *priv); |
146 | int btmrvl_enable_hs(struct btmrvl_private *priv); | ||
144 | 147 | ||
145 | #ifdef CONFIG_DEBUG_FS | 148 | #ifdef CONFIG_DEBUG_FS |
146 | void btmrvl_debugfs_init(struct hci_dev *hdev); | 149 | void btmrvl_debugfs_init(struct hci_dev *hdev); |
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index d1209adc882d..681ca9d18e12 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c | |||
@@ -200,6 +200,36 @@ int btmrvl_send_module_cfg_cmd(struct btmrvl_private *priv, int subcmd) | |||
200 | } | 200 | } |
201 | EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd); | 201 | EXPORT_SYMBOL_GPL(btmrvl_send_module_cfg_cmd); |
202 | 202 | ||
203 | int btmrvl_send_hscfg_cmd(struct btmrvl_private *priv) | ||
204 | { | ||
205 | struct sk_buff *skb; | ||
206 | struct btmrvl_cmd *cmd; | ||
207 | |||
208 | skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); | ||
209 | if (!skb) { | ||
210 | BT_ERR("No free skb"); | ||
211 | return -ENOMEM; | ||
212 | } | ||
213 | |||
214 | cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); | ||
215 | cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, | ||
216 | BT_CMD_HOST_SLEEP_CONFIG)); | ||
217 | cmd->length = 2; | ||
218 | cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; | ||
219 | cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff); | ||
220 | |||
221 | bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; | ||
222 | |||
223 | skb->dev = (void *) priv->btmrvl_dev.hcidev; | ||
224 | skb_queue_head(&priv->adapter->tx_queue, skb); | ||
225 | |||
226 | BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x", cmd->data[0], | ||
227 | cmd->data[1]); | ||
228 | |||
229 | return 0; | ||
230 | } | ||
231 | EXPORT_SYMBOL_GPL(btmrvl_send_hscfg_cmd); | ||
232 | |||
203 | int btmrvl_enable_ps(struct btmrvl_private *priv) | 233 | int btmrvl_enable_ps(struct btmrvl_private *priv) |
204 | { | 234 | { |
205 | struct sk_buff *skb; | 235 | struct sk_buff *skb; |
@@ -232,7 +262,7 @@ int btmrvl_enable_ps(struct btmrvl_private *priv) | |||
232 | } | 262 | } |
233 | EXPORT_SYMBOL_GPL(btmrvl_enable_ps); | 263 | EXPORT_SYMBOL_GPL(btmrvl_enable_ps); |
234 | 264 | ||
235 | static int btmrvl_enable_hs(struct btmrvl_private *priv) | 265 | int btmrvl_enable_hs(struct btmrvl_private *priv) |
236 | { | 266 | { |
237 | struct sk_buff *skb; | 267 | struct sk_buff *skb; |
238 | struct btmrvl_cmd *cmd; | 268 | struct btmrvl_cmd *cmd; |
@@ -268,35 +298,15 @@ static int btmrvl_enable_hs(struct btmrvl_private *priv) | |||
268 | 298 | ||
269 | return ret; | 299 | return ret; |
270 | } | 300 | } |
301 | EXPORT_SYMBOL_GPL(btmrvl_enable_hs); | ||
271 | 302 | ||
272 | int btmrvl_prepare_command(struct btmrvl_private *priv) | 303 | int btmrvl_prepare_command(struct btmrvl_private *priv) |
273 | { | 304 | { |
274 | struct sk_buff *skb = NULL; | ||
275 | struct btmrvl_cmd *cmd; | ||
276 | int ret = 0; | 305 | int ret = 0; |
277 | 306 | ||
278 | if (priv->btmrvl_dev.hscfgcmd) { | 307 | if (priv->btmrvl_dev.hscfgcmd) { |
279 | priv->btmrvl_dev.hscfgcmd = 0; | 308 | priv->btmrvl_dev.hscfgcmd = 0; |
280 | 309 | btmrvl_send_hscfg_cmd(priv); | |
281 | skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC); | ||
282 | if (skb == NULL) { | ||
283 | BT_ERR("No free skb"); | ||
284 | return -ENOMEM; | ||
285 | } | ||
286 | |||
287 | cmd = (struct btmrvl_cmd *) skb_put(skb, sizeof(*cmd)); | ||
288 | cmd->ocf_ogf = cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_HOST_SLEEP_CONFIG)); | ||
289 | cmd->length = 2; | ||
290 | cmd->data[0] = (priv->btmrvl_dev.gpio_gap & 0xff00) >> 8; | ||
291 | cmd->data[1] = (u8) (priv->btmrvl_dev.gpio_gap & 0x00ff); | ||
292 | |||
293 | bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; | ||
294 | |||
295 | skb->dev = (void *) priv->btmrvl_dev.hcidev; | ||
296 | skb_queue_head(&priv->adapter->tx_queue, skb); | ||
297 | |||
298 | BT_DBG("Queue HSCFG Command, gpio=0x%x, gap=0x%x", | ||
299 | cmd->data[0], cmd->data[1]); | ||
300 | } | 310 | } |
301 | 311 | ||
302 | if (priv->btmrvl_dev.pscmd) { | 312 | if (priv->btmrvl_dev.pscmd) { |
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 27b74b0d547b..a853244e7fd7 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c | |||
@@ -339,9 +339,7 @@ static int btmrvl_sdio_download_helper(struct btmrvl_sdio_card *card) | |||
339 | 339 | ||
340 | done: | 340 | done: |
341 | kfree(tmphlprbuf); | 341 | kfree(tmphlprbuf); |
342 | if (fw_helper) | 342 | release_firmware(fw_helper); |
343 | release_firmware(fw_helper); | ||
344 | |||
345 | return ret; | 343 | return ret; |
346 | } | 344 | } |
347 | 345 | ||
@@ -484,10 +482,7 @@ static int btmrvl_sdio_download_fw_w_helper(struct btmrvl_sdio_card *card) | |||
484 | 482 | ||
485 | done: | 483 | done: |
486 | kfree(tmpfwbuf); | 484 | kfree(tmpfwbuf); |
487 | 485 | release_firmware(fw_firmware); | |
488 | if (fw_firmware) | ||
489 | release_firmware(fw_firmware); | ||
490 | |||
491 | return ret; | 486 | return ret; |
492 | } | 487 | } |
493 | 488 | ||
@@ -1013,6 +1008,9 @@ static int btmrvl_sdio_probe(struct sdio_func *func, | |||
1013 | priv->btmrvl_dev.psmode = 1; | 1008 | priv->btmrvl_dev.psmode = 1; |
1014 | btmrvl_enable_ps(priv); | 1009 | btmrvl_enable_ps(priv); |
1015 | 1010 | ||
1011 | priv->btmrvl_dev.gpio_gap = 0xffff; | ||
1012 | btmrvl_send_hscfg_cmd(priv); | ||
1013 | |||
1016 | return 0; | 1014 | return 0; |
1017 | 1015 | ||
1018 | disable_host_int: | 1016 | disable_host_int: |
@@ -1048,11 +1046,111 @@ static void btmrvl_sdio_remove(struct sdio_func *func) | |||
1048 | } | 1046 | } |
1049 | } | 1047 | } |
1050 | 1048 | ||
1049 | static int btmrvl_sdio_suspend(struct device *dev) | ||
1050 | { | ||
1051 | struct sdio_func *func = dev_to_sdio_func(dev); | ||
1052 | struct btmrvl_sdio_card *card; | ||
1053 | struct btmrvl_private *priv; | ||
1054 | mmc_pm_flag_t pm_flags; | ||
1055 | struct hci_dev *hcidev; | ||
1056 | |||
1057 | if (func) { | ||
1058 | pm_flags = sdio_get_host_pm_caps(func); | ||
1059 | BT_DBG("%s: suspend: PM flags = 0x%x", sdio_func_id(func), | ||
1060 | pm_flags); | ||
1061 | if (!(pm_flags & MMC_PM_KEEP_POWER)) { | ||
1062 | BT_ERR("%s: cannot remain alive while suspended", | ||
1063 | sdio_func_id(func)); | ||
1064 | return -ENOSYS; | ||
1065 | } | ||
1066 | card = sdio_get_drvdata(func); | ||
1067 | if (!card || !card->priv) { | ||
1068 | BT_ERR("card or priv structure is not valid"); | ||
1069 | return 0; | ||
1070 | } | ||
1071 | } else { | ||
1072 | BT_ERR("sdio_func is not specified"); | ||
1073 | return 0; | ||
1074 | } | ||
1075 | |||
1076 | priv = card->priv; | ||
1077 | |||
1078 | if (priv->adapter->hs_state != HS_ACTIVATED) { | ||
1079 | if (btmrvl_enable_hs(priv)) { | ||
1080 | BT_ERR("HS not actived, suspend failed!"); | ||
1081 | return -EBUSY; | ||
1082 | } | ||
1083 | } | ||
1084 | hcidev = priv->btmrvl_dev.hcidev; | ||
1085 | BT_DBG("%s: SDIO suspend", hcidev->name); | ||
1086 | hci_suspend_dev(hcidev); | ||
1087 | skb_queue_purge(&priv->adapter->tx_queue); | ||
1088 | |||
1089 | priv->adapter->is_suspended = true; | ||
1090 | |||
1091 | /* We will keep the power when hs enabled successfully */ | ||
1092 | if (priv->adapter->hs_state == HS_ACTIVATED) { | ||
1093 | BT_DBG("suspend with MMC_PM_KEEP_POWER"); | ||
1094 | return sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); | ||
1095 | } else { | ||
1096 | BT_DBG("suspend without MMC_PM_KEEP_POWER"); | ||
1097 | return 0; | ||
1098 | } | ||
1099 | } | ||
1100 | |||
1101 | static int btmrvl_sdio_resume(struct device *dev) | ||
1102 | { | ||
1103 | struct sdio_func *func = dev_to_sdio_func(dev); | ||
1104 | struct btmrvl_sdio_card *card; | ||
1105 | struct btmrvl_private *priv; | ||
1106 | mmc_pm_flag_t pm_flags; | ||
1107 | struct hci_dev *hcidev; | ||
1108 | |||
1109 | if (func) { | ||
1110 | pm_flags = sdio_get_host_pm_caps(func); | ||
1111 | BT_DBG("%s: resume: PM flags = 0x%x", sdio_func_id(func), | ||
1112 | pm_flags); | ||
1113 | card = sdio_get_drvdata(func); | ||
1114 | if (!card || !card->priv) { | ||
1115 | BT_ERR("card or priv structure is not valid"); | ||
1116 | return 0; | ||
1117 | } | ||
1118 | } else { | ||
1119 | BT_ERR("sdio_func is not specified"); | ||
1120 | return 0; | ||
1121 | } | ||
1122 | priv = card->priv; | ||
1123 | |||
1124 | if (!priv->adapter->is_suspended) { | ||
1125 | BT_DBG("device already resumed"); | ||
1126 | return 0; | ||
1127 | } | ||
1128 | |||
1129 | priv->adapter->is_suspended = false; | ||
1130 | hcidev = priv->btmrvl_dev.hcidev; | ||
1131 | BT_DBG("%s: SDIO resume", hcidev->name); | ||
1132 | hci_resume_dev(hcidev); | ||
1133 | priv->hw_wakeup_firmware(priv); | ||
1134 | priv->adapter->hs_state = HS_DEACTIVATED; | ||
1135 | BT_DBG("%s: HS DEACTIVATED in resume!", hcidev->name); | ||
1136 | |||
1137 | return 0; | ||
1138 | } | ||
1139 | |||
1140 | static const struct dev_pm_ops btmrvl_sdio_pm_ops = { | ||
1141 | .suspend = btmrvl_sdio_suspend, | ||
1142 | .resume = btmrvl_sdio_resume, | ||
1143 | }; | ||
1144 | |||
1051 | static struct sdio_driver bt_mrvl_sdio = { | 1145 | static struct sdio_driver bt_mrvl_sdio = { |
1052 | .name = "btmrvl_sdio", | 1146 | .name = "btmrvl_sdio", |
1053 | .id_table = btmrvl_sdio_ids, | 1147 | .id_table = btmrvl_sdio_ids, |
1054 | .probe = btmrvl_sdio_probe, | 1148 | .probe = btmrvl_sdio_probe, |
1055 | .remove = btmrvl_sdio_remove, | 1149 | .remove = btmrvl_sdio_remove, |
1150 | .drv = { | ||
1151 | .owner = THIS_MODULE, | ||
1152 | .pm = &btmrvl_sdio_pm_ops, | ||
1153 | } | ||
1056 | }; | 1154 | }; |
1057 | 1155 | ||
1058 | static int __init btmrvl_sdio_init_module(void) | 1156 | static int __init btmrvl_sdio_init_module(void) |
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 461c68bc4dd7..c9463af8e564 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -143,6 +143,9 @@ static struct usb_device_id blacklist_table[] = { | |||
143 | /* Atheros AR5BBU12 with sflash firmware */ | 143 | /* Atheros AR5BBU12 with sflash firmware */ |
144 | { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, | 144 | { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, |
145 | 145 | ||
146 | /* Atheros AR5BBU12 with sflash firmware */ | ||
147 | { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 }, | ||
148 | |||
146 | /* Broadcom BCM2035 */ | 149 | /* Broadcom BCM2035 */ |
147 | { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, | 150 | { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU }, |
148 | { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU }, | 151 | { USB_DEVICE(0x0a5c, 0x200a), .driver_info = BTUSB_WRONG_SCO_MTU }, |
@@ -855,6 +858,7 @@ static void btusb_work(struct work_struct *work) | |||
855 | { | 858 | { |
856 | struct btusb_data *data = container_of(work, struct btusb_data, work); | 859 | struct btusb_data *data = container_of(work, struct btusb_data, work); |
857 | struct hci_dev *hdev = data->hdev; | 860 | struct hci_dev *hdev = data->hdev; |
861 | int new_alts; | ||
858 | int err; | 862 | int err; |
859 | 863 | ||
860 | if (hdev->conn_hash.sco_num > 0) { | 864 | if (hdev->conn_hash.sco_num > 0) { |
@@ -868,11 +872,19 @@ static void btusb_work(struct work_struct *work) | |||
868 | 872 | ||
869 | set_bit(BTUSB_DID_ISO_RESUME, &data->flags); | 873 | set_bit(BTUSB_DID_ISO_RESUME, &data->flags); |
870 | } | 874 | } |
871 | if (data->isoc_altsetting != 2) { | 875 | |
876 | if (hdev->voice_setting & 0x0020) { | ||
877 | static const int alts[3] = { 2, 4, 5 }; | ||
878 | new_alts = alts[hdev->conn_hash.sco_num - 1]; | ||
879 | } else { | ||
880 | new_alts = hdev->conn_hash.sco_num; | ||
881 | } | ||
882 | |||
883 | if (data->isoc_altsetting != new_alts) { | ||
872 | clear_bit(BTUSB_ISOC_RUNNING, &data->flags); | 884 | clear_bit(BTUSB_ISOC_RUNNING, &data->flags); |
873 | usb_kill_anchored_urbs(&data->isoc_anchor); | 885 | usb_kill_anchored_urbs(&data->isoc_anchor); |
874 | 886 | ||
875 | if (__set_isoc_interface(hdev, 2) < 0) | 887 | if (__set_isoc_interface(hdev, new_alts) < 0) |
876 | return; | 888 | return; |
877 | } | 889 | } |
878 | 890 | ||
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 98a8c05d4f23..e564579a6115 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c | |||
@@ -388,7 +388,7 @@ static int hci_uart_register_dev(struct hci_uart *hu) | |||
388 | hdev->close = hci_uart_close; | 388 | hdev->close = hci_uart_close; |
389 | hdev->flush = hci_uart_flush; | 389 | hdev->flush = hci_uart_flush; |
390 | hdev->send = hci_uart_send_frame; | 390 | hdev->send = hci_uart_send_frame; |
391 | hdev->parent = hu->tty->dev; | 391 | SET_HCIDEV_DEV(hdev, hu->tty->dev); |
392 | 392 | ||
393 | if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags)) | 393 | if (test_bit(HCI_UART_RAW_DEVICE, &hu->hdev_flags)) |
394 | set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); | 394 | set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); |
diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 158bfe507da7..3f72595a6017 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c | |||
@@ -252,8 +252,9 @@ static int vhci_open(struct inode *inode, struct file *file) | |||
252 | } | 252 | } |
253 | 253 | ||
254 | file->private_data = data; | 254 | file->private_data = data; |
255 | nonseekable_open(inode, file); | ||
255 | 256 | ||
256 | return nonseekable_open(inode, file); | 257 | return 0; |
257 | } | 258 | } |
258 | 259 | ||
259 | static int vhci_release(struct inode *inode, struct file *file) | 260 | static int vhci_release(struct inode *inode, struct file *file) |
diff --git a/drivers/isdn/hardware/mISDN/hfcsusb.h b/drivers/isdn/hardware/mISDN/hfcsusb.h index cb1231b08f78..4157311d569d 100644 --- a/drivers/isdn/hardware/mISDN/hfcsusb.h +++ b/drivers/isdn/hardware/mISDN/hfcsusb.h | |||
@@ -410,6 +410,12 @@ static struct usb_device_id hfcsusb_idtab[] = { | |||
410 | {LED_SCHEME1, {0x88, -64, -32, -16}, | 410 | {LED_SCHEME1, {0x88, -64, -32, -16}, |
411 | "ZyXEL OMNI.NET USB II"}), | 411 | "ZyXEL OMNI.NET USB II"}), |
412 | }, | 412 | }, |
413 | { | ||
414 | USB_DEVICE(0x1ae7, 0x0525), | ||
415 | .driver_info = (unsigned long) &((struct hfcsusb_vdata) | ||
416 | {LED_SCHEME1, {0x88, -64, -32, -16}, | ||
417 | "X-Tensions USB ISDN TA XC-525"}), | ||
418 | }, | ||
413 | { } | 419 | { } |
414 | }; | 420 | }; |
415 | 421 | ||
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 1adb0245b9dd..0741aded9eb0 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c | |||
@@ -1082,7 +1082,7 @@ static int gfar_probe(struct platform_device *ofdev) | |||
1082 | 1082 | ||
1083 | if (dev->features & NETIF_F_IP_CSUM || | 1083 | if (dev->features & NETIF_F_IP_CSUM || |
1084 | priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) | 1084 | priv->device_flags & FSL_GIANFAR_DEV_HAS_TIMER) |
1085 | dev->hard_header_len += GMAC_FCB_LEN; | 1085 | dev->needed_headroom = GMAC_FCB_LEN; |
1086 | 1086 | ||
1087 | /* Program the isrg regs only if number of grps > 1 */ | 1087 | /* Program the isrg regs only if number of grps > 1 */ |
1088 | if (priv->num_grps > 1) { | 1088 | if (priv->num_grps > 1) { |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 28a65d3a03d0..b869a358ce43 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -693,8 +693,8 @@ ath6kl_add_bss_if_needed(struct ath6kl_vif *vif, | |||
693 | ie, 2 + vif->ssid_len + beacon_ie_len, | 693 | ie, 2 + vif->ssid_len + beacon_ie_len, |
694 | 0, GFP_KERNEL); | 694 | 0, GFP_KERNEL); |
695 | if (bss) | 695 | if (bss) |
696 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "added bss %pM to " | 696 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
697 | "cfg80211\n", bssid); | 697 | "added bss %pM to cfg80211\n", bssid); |
698 | kfree(ie); | 698 | kfree(ie); |
699 | } else | 699 | } else |
700 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss\n"); | 700 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss\n"); |
@@ -882,6 +882,32 @@ void ath6kl_cfg80211_disconnect_event(struct ath6kl_vif *vif, u8 reason, | |||
882 | vif->sme_state = SME_DISCONNECTED; | 882 | vif->sme_state = SME_DISCONNECTED; |
883 | } | 883 | } |
884 | 884 | ||
885 | static int ath6kl_set_probed_ssids(struct ath6kl *ar, | ||
886 | struct ath6kl_vif *vif, | ||
887 | struct cfg80211_ssid *ssids, int n_ssids) | ||
888 | { | ||
889 | u8 i; | ||
890 | |||
891 | if (n_ssids > MAX_PROBED_SSID_INDEX) | ||
892 | return -EINVAL; | ||
893 | |||
894 | for (i = 0; i < n_ssids; i++) { | ||
895 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, | ||
896 | ssids[i].ssid_len ? | ||
897 | SPECIFIC_SSID_FLAG : ANY_SSID_FLAG, | ||
898 | ssids[i].ssid_len, | ||
899 | ssids[i].ssid); | ||
900 | } | ||
901 | |||
902 | /* Make sure no old entries are left behind */ | ||
903 | for (i = n_ssids; i < MAX_PROBED_SSID_INDEX; i++) { | ||
904 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, i, | ||
905 | DISABLE_SSID_FLAG, 0, NULL); | ||
906 | } | ||
907 | |||
908 | return 0; | ||
909 | } | ||
910 | |||
885 | static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | 911 | static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, |
886 | struct cfg80211_scan_request *request) | 912 | struct cfg80211_scan_request *request) |
887 | { | 913 | { |
@@ -899,36 +925,25 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | |||
899 | 925 | ||
900 | if (!ar->usr_bss_filter) { | 926 | if (!ar->usr_bss_filter) { |
901 | clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags); | 927 | clear_bit(CLEAR_BSSFILTER_ON_BEACON, &vif->flags); |
902 | ret = ath6kl_wmi_bssfilter_cmd( | 928 | ret = ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, |
903 | ar->wmi, vif->fw_vif_idx, | 929 | ALL_BSS_FILTER, 0); |
904 | (test_bit(CONNECTED, &vif->flags) ? | ||
905 | ALL_BUT_BSS_FILTER : ALL_BSS_FILTER), 0); | ||
906 | if (ret) { | 930 | if (ret) { |
907 | ath6kl_err("couldn't set bss filtering\n"); | 931 | ath6kl_err("couldn't set bss filtering\n"); |
908 | return ret; | 932 | return ret; |
909 | } | 933 | } |
910 | } | 934 | } |
911 | 935 | ||
912 | if (request->n_ssids && request->ssids[0].ssid_len) { | 936 | ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, |
913 | u8 i; | 937 | request->n_ssids); |
914 | 938 | if (ret < 0) | |
915 | if (request->n_ssids > (MAX_PROBED_SSID_INDEX - 1)) | 939 | return ret; |
916 | request->n_ssids = MAX_PROBED_SSID_INDEX - 1; | ||
917 | |||
918 | for (i = 0; i < request->n_ssids; i++) | ||
919 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, | ||
920 | i + 1, SPECIFIC_SSID_FLAG, | ||
921 | request->ssids[i].ssid_len, | ||
922 | request->ssids[i].ssid); | ||
923 | } | ||
924 | 940 | ||
925 | /* this also clears IE in fw if it's not set */ | 941 | /* this also clears IE in fw if it's not set */ |
926 | ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, | 942 | ret = ath6kl_wmi_set_appie_cmd(ar->wmi, vif->fw_vif_idx, |
927 | WMI_FRAME_PROBE_REQ, | 943 | WMI_FRAME_PROBE_REQ, |
928 | request->ie, request->ie_len); | 944 | request->ie, request->ie_len); |
929 | if (ret) { | 945 | if (ret) { |
930 | ath6kl_err("failed to set Probe Request appie for " | 946 | ath6kl_err("failed to set Probe Request appie for scan"); |
931 | "scan"); | ||
932 | return ret; | 947 | return ret; |
933 | } | 948 | } |
934 | 949 | ||
@@ -945,8 +960,7 @@ static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, | |||
945 | 960 | ||
946 | channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL); | 961 | channels = kzalloc(n_channels * sizeof(u16), GFP_KERNEL); |
947 | if (channels == NULL) { | 962 | if (channels == NULL) { |
948 | ath6kl_warn("failed to set scan channels, " | 963 | ath6kl_warn("failed to set scan channels, scan all channels"); |
949 | "scan all channels"); | ||
950 | n_channels = 0; | 964 | n_channels = 0; |
951 | } | 965 | } |
952 | 966 | ||
@@ -1018,6 +1032,20 @@ out: | |||
1018 | vif->scan_req = NULL; | 1032 | vif->scan_req = NULL; |
1019 | } | 1033 | } |
1020 | 1034 | ||
1035 | void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq, | ||
1036 | enum wmi_phy_mode mode) | ||
1037 | { | ||
1038 | enum nl80211_channel_type type; | ||
1039 | |||
1040 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, | ||
1041 | "channel switch notify nw_type %d freq %d mode %d\n", | ||
1042 | vif->nw_type, freq, mode); | ||
1043 | |||
1044 | type = (mode == WMI_11G_HT20) ? NL80211_CHAN_HT20 : NL80211_CHAN_NO_HT; | ||
1045 | |||
1046 | cfg80211_ch_switch_notify(vif->ndev, freq, type); | ||
1047 | } | ||
1048 | |||
1021 | static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | 1049 | static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, |
1022 | u8 key_index, bool pairwise, | 1050 | u8 key_index, bool pairwise, |
1023 | const u8 *mac_addr, | 1051 | const u8 *mac_addr, |
@@ -1111,9 +1139,8 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
1111 | ar->ap_mode_bkey.key_len = key->key_len; | 1139 | ar->ap_mode_bkey.key_len = key->key_len; |
1112 | memcpy(ar->ap_mode_bkey.key, key->key, key->key_len); | 1140 | memcpy(ar->ap_mode_bkey.key, key->key, key->key_len); |
1113 | if (!test_bit(CONNECTED, &vif->flags)) { | 1141 | if (!test_bit(CONNECTED, &vif->flags)) { |
1114 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay initial group " | 1142 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
1115 | "key configuration until AP mode has been " | 1143 | "Delay initial group key configuration until AP mode has been started\n"); |
1116 | "started\n"); | ||
1117 | /* | 1144 | /* |
1118 | * The key will be set in ath6kl_connect_ap_mode() once | 1145 | * The key will be set in ath6kl_connect_ap_mode() once |
1119 | * the connected event is received from the target. | 1146 | * the connected event is received from the target. |
@@ -1129,8 +1156,8 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
1129 | * the AP mode has properly started | 1156 | * the AP mode has properly started |
1130 | * (ath6kl_install_statioc_wep_keys). | 1157 | * (ath6kl_install_statioc_wep_keys). |
1131 | */ | 1158 | */ |
1132 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delay WEP key configuration " | 1159 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
1133 | "until AP mode has been started\n"); | 1160 | "Delay WEP key configuration until AP mode has been started\n"); |
1134 | vif->wep_key_list[key_index].key_len = key->key_len; | 1161 | vif->wep_key_list[key_index].key_len = key->key_len; |
1135 | memcpy(vif->wep_key_list[key_index].key, key->key, | 1162 | memcpy(vif->wep_key_list[key_index].key, key->key, |
1136 | key->key_len); | 1163 | key->key_len); |
@@ -1962,8 +1989,7 @@ static int ath6kl_wow_sta(struct ath6kl *ar, struct ath6kl_vif *vif) | |||
1962 | sizeof(discvr_pattern), discvr_offset, | 1989 | sizeof(discvr_pattern), discvr_offset, |
1963 | discvr_pattern, discvr_mask); | 1990 | discvr_pattern, discvr_mask); |
1964 | if (ret) { | 1991 | if (ret) { |
1965 | ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR " | 1992 | ath6kl_err("failed to add WOW mDNS/SSDP/LLMNR pattern\n"); |
1966 | "pattern\n"); | ||
1967 | return ret; | 1993 | return ret; |
1968 | } | 1994 | } |
1969 | } | 1995 | } |
@@ -2031,6 +2057,10 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | |||
2031 | u8 index = 0; | 2057 | u8 index = 0; |
2032 | __be32 ips[MAX_IP_ADDRS]; | 2058 | __be32 ips[MAX_IP_ADDRS]; |
2033 | 2059 | ||
2060 | /* The FW currently can't support multi-vif WoW properly. */ | ||
2061 | if (ar->num_vif > 1) | ||
2062 | return -EIO; | ||
2063 | |||
2034 | vif = ath6kl_vif_first(ar); | 2064 | vif = ath6kl_vif_first(ar); |
2035 | if (!vif) | 2065 | if (!vif) |
2036 | return -EIO; | 2066 | return -EIO; |
@@ -2044,6 +2074,13 @@ static int ath6kl_wow_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | |||
2044 | if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) | 2074 | if (wow && (wow->n_patterns > WOW_MAX_FILTERS_PER_LIST)) |
2045 | return -EINVAL; | 2075 | return -EINVAL; |
2046 | 2076 | ||
2077 | if (!test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) { | ||
2078 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, | ||
2079 | vif->fw_vif_idx, false); | ||
2080 | if (ret) | ||
2081 | return ret; | ||
2082 | } | ||
2083 | |||
2047 | /* Clear existing WOW patterns */ | 2084 | /* Clear existing WOW patterns */ |
2048 | for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++) | 2085 | for (i = 0; i < WOW_MAX_FILTERS_PER_LIST; i++) |
2049 | ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx, | 2086 | ath6kl_wmi_del_wow_pattern_cmd(ar->wmi, vif->fw_vif_idx, |
@@ -2147,8 +2184,8 @@ static int ath6kl_wow_resume(struct ath6kl *ar) | |||
2147 | ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, | 2184 | ret = ath6kl_wmi_set_host_sleep_mode_cmd(ar->wmi, vif->fw_vif_idx, |
2148 | ATH6KL_HOST_MODE_AWAKE); | 2185 | ATH6KL_HOST_MODE_AWAKE); |
2149 | if (ret) { | 2186 | if (ret) { |
2150 | ath6kl_warn("Failed to configure host sleep mode for " | 2187 | ath6kl_warn("Failed to configure host sleep mode for wow resume: %d\n", |
2151 | "wow resume: %d\n", ret); | 2188 | ret); |
2152 | ar->state = ATH6KL_STATE_WOW; | 2189 | ar->state = ATH6KL_STATE_WOW; |
2153 | return ret; | 2190 | return ret; |
2154 | } | 2191 | } |
@@ -2172,6 +2209,13 @@ static int ath6kl_wow_resume(struct ath6kl *ar) | |||
2172 | 2209 | ||
2173 | ar->state = ATH6KL_STATE_ON; | 2210 | ar->state = ATH6KL_STATE_ON; |
2174 | 2211 | ||
2212 | if (!test_bit(NETDEV_MCAST_ALL_OFF, &vif->flags)) { | ||
2213 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, | ||
2214 | vif->fw_vif_idx, true); | ||
2215 | if (ret) | ||
2216 | return ret; | ||
2217 | } | ||
2218 | |||
2175 | netif_wake_queue(vif->ndev); | 2219 | netif_wake_queue(vif->ndev); |
2176 | 2220 | ||
2177 | return 0; | 2221 | return 0; |
@@ -2186,8 +2230,10 @@ static int ath6kl_cfg80211_deepsleep_suspend(struct ath6kl *ar) | |||
2186 | if (!vif) | 2230 | if (!vif) |
2187 | return -EIO; | 2231 | return -EIO; |
2188 | 2232 | ||
2189 | if (!ath6kl_cfg80211_ready(vif)) | 2233 | if (!test_bit(WMI_READY, &ar->flag)) { |
2234 | ath6kl_err("deepsleep failed as wmi is not ready\n"); | ||
2190 | return -EIO; | 2235 | return -EIO; |
2236 | } | ||
2191 | 2237 | ||
2192 | ath6kl_cfg80211_stop_all(ar); | 2238 | ath6kl_cfg80211_stop_all(ar); |
2193 | 2239 | ||
@@ -2447,6 +2493,24 @@ static int ath6kl_set_htcap(struct ath6kl_vif *vif, enum ieee80211_band band, | |||
2447 | band, htcap); | 2493 | band, htcap); |
2448 | } | 2494 | } |
2449 | 2495 | ||
2496 | static int ath6kl_restore_htcap(struct ath6kl_vif *vif) | ||
2497 | { | ||
2498 | struct wiphy *wiphy = vif->ar->wiphy; | ||
2499 | int band, ret = 0; | ||
2500 | |||
2501 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
2502 | if (!wiphy->bands[band]) | ||
2503 | continue; | ||
2504 | |||
2505 | ret = ath6kl_set_htcap(vif, band, | ||
2506 | wiphy->bands[band]->ht_cap.ht_supported); | ||
2507 | if (ret) | ||
2508 | return ret; | ||
2509 | } | ||
2510 | |||
2511 | return ret; | ||
2512 | } | ||
2513 | |||
2450 | static bool ath6kl_is_p2p_ie(const u8 *pos) | 2514 | static bool ath6kl_is_p2p_ie(const u8 *pos) |
2451 | { | 2515 | { |
2452 | return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && | 2516 | return pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && |
@@ -2568,28 +2632,34 @@ static int ath6kl_get_rsn_capab(struct cfg80211_beacon_data *beacon, | |||
2568 | /* skip element id and length */ | 2632 | /* skip element id and length */ |
2569 | rsn_ie += 2; | 2633 | rsn_ie += 2; |
2570 | 2634 | ||
2571 | /* skip version, group cipher */ | 2635 | /* skip version */ |
2572 | if (rsn_ie_len < 6) | 2636 | if (rsn_ie_len < 2) |
2573 | return -EINVAL; | 2637 | return -EINVAL; |
2574 | rsn_ie += 6; | 2638 | rsn_ie += 2; |
2575 | rsn_ie_len -= 6; | 2639 | rsn_ie_len -= 2; |
2640 | |||
2641 | /* skip group cipher suite */ | ||
2642 | if (rsn_ie_len < 4) | ||
2643 | return 0; | ||
2644 | rsn_ie += 4; | ||
2645 | rsn_ie_len -= 4; | ||
2576 | 2646 | ||
2577 | /* skip pairwise cipher suite */ | 2647 | /* skip pairwise cipher suite */ |
2578 | if (rsn_ie_len < 2) | 2648 | if (rsn_ie_len < 2) |
2579 | return -EINVAL; | 2649 | return 0; |
2580 | cnt = *((u16 *) rsn_ie); | 2650 | cnt = get_unaligned_le16(rsn_ie); |
2581 | rsn_ie += (2 + cnt * 4); | 2651 | rsn_ie += (2 + cnt * 4); |
2582 | rsn_ie_len -= (2 + cnt * 4); | 2652 | rsn_ie_len -= (2 + cnt * 4); |
2583 | 2653 | ||
2584 | /* skip akm suite */ | 2654 | /* skip akm suite */ |
2585 | if (rsn_ie_len < 2) | 2655 | if (rsn_ie_len < 2) |
2586 | return -EINVAL; | 2656 | return 0; |
2587 | cnt = *((u16 *) rsn_ie); | 2657 | cnt = get_unaligned_le16(rsn_ie); |
2588 | rsn_ie += (2 + cnt * 4); | 2658 | rsn_ie += (2 + cnt * 4); |
2589 | rsn_ie_len -= (2 + cnt * 4); | 2659 | rsn_ie_len -= (2 + cnt * 4); |
2590 | 2660 | ||
2591 | if (rsn_ie_len < 2) | 2661 | if (rsn_ie_len < 2) |
2592 | return -EINVAL; | 2662 | return 0; |
2593 | 2663 | ||
2594 | memcpy(rsn_capab, rsn_ie, 2); | 2664 | memcpy(rsn_capab, rsn_ie, 2); |
2595 | 2665 | ||
@@ -2766,6 +2836,7 @@ static int ath6kl_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
2766 | return res; | 2836 | return res; |
2767 | } | 2837 | } |
2768 | 2838 | ||
2839 | memcpy(&vif->profile, &p, sizeof(p)); | ||
2769 | res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p); | 2840 | res = ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, &p); |
2770 | if (res < 0) | 2841 | if (res < 0) |
2771 | return res; | 2842 | return res; |
@@ -2801,13 +2872,7 @@ static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
2801 | clear_bit(CONNECTED, &vif->flags); | 2872 | clear_bit(CONNECTED, &vif->flags); |
2802 | 2873 | ||
2803 | /* Restore ht setting in firmware */ | 2874 | /* Restore ht setting in firmware */ |
2804 | if (ath6kl_set_htcap(vif, IEEE80211_BAND_2GHZ, true)) | 2875 | return ath6kl_restore_htcap(vif); |
2805 | return -EIO; | ||
2806 | |||
2807 | if (ath6kl_set_htcap(vif, IEEE80211_BAND_5GHZ, true)) | ||
2808 | return -EIO; | ||
2809 | |||
2810 | return 0; | ||
2811 | } | 2876 | } |
2812 | 2877 | ||
2813 | static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | 2878 | static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
@@ -3081,7 +3146,6 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, | |||
3081 | struct ath6kl_vif *vif = netdev_priv(dev); | 3146 | struct ath6kl_vif *vif = netdev_priv(dev); |
3082 | u16 interval; | 3147 | u16 interval; |
3083 | int ret; | 3148 | int ret; |
3084 | u8 i; | ||
3085 | 3149 | ||
3086 | if (ar->state != ATH6KL_STATE_ON) | 3150 | if (ar->state != ATH6KL_STATE_ON) |
3087 | return -EIO; | 3151 | return -EIO; |
@@ -3089,29 +3153,23 @@ static int ath6kl_cfg80211_sscan_start(struct wiphy *wiphy, | |||
3089 | if (vif->sme_state != SME_DISCONNECTED) | 3153 | if (vif->sme_state != SME_DISCONNECTED) |
3090 | return -EBUSY; | 3154 | return -EBUSY; |
3091 | 3155 | ||
3156 | /* The FW currently can't support multi-vif WoW properly. */ | ||
3157 | if (ar->num_vif > 1) | ||
3158 | return -EIO; | ||
3159 | |||
3092 | ath6kl_cfg80211_scan_complete_event(vif, true); | 3160 | ath6kl_cfg80211_scan_complete_event(vif, true); |
3093 | 3161 | ||
3094 | for (i = 0; i < ar->wiphy->max_sched_scan_ssids; i++) { | 3162 | ret = ath6kl_set_probed_ssids(ar, vif, request->ssids, |
3095 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, | 3163 | request->n_ssids); |
3096 | i, DISABLE_SSID_FLAG, | 3164 | if (ret < 0) |
3097 | 0, NULL); | 3165 | return ret; |
3098 | } | ||
3099 | 3166 | ||
3100 | /* fw uses seconds, also make sure that it's >0 */ | 3167 | /* fw uses seconds, also make sure that it's >0 */ |
3101 | interval = max_t(u16, 1, request->interval / 1000); | 3168 | interval = max_t(u16, 1, request->interval / 1000); |
3102 | 3169 | ||
3103 | ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, | 3170 | ath6kl_wmi_scanparams_cmd(ar->wmi, vif->fw_vif_idx, |
3104 | interval, interval, | 3171 | interval, interval, |
3105 | 10, 0, 0, 0, 3, 0, 0, 0); | 3172 | vif->bg_scan_period, 0, 0, 0, 3, 0, 0, 0); |
3106 | |||
3107 | if (request->n_ssids && request->ssids[0].ssid_len) { | ||
3108 | for (i = 0; i < request->n_ssids; i++) { | ||
3109 | ath6kl_wmi_probedssid_cmd(ar->wmi, vif->fw_vif_idx, | ||
3110 | i, SPECIFIC_SSID_FLAG, | ||
3111 | request->ssids[i].ssid_len, | ||
3112 | request->ssids[i].ssid); | ||
3113 | } | ||
3114 | } | ||
3115 | 3173 | ||
3116 | ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx, | 3174 | ret = ath6kl_wmi_set_wow_mode_cmd(ar->wmi, vif->fw_vif_idx, |
3117 | ATH6KL_WOW_MODE_ENABLE, | 3175 | ATH6KL_WOW_MODE_ENABLE, |
@@ -3271,8 +3329,7 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar) | |||
3271 | ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode; | 3329 | ar->wmi->saved_pwr_mode = ar->wmi->pwr_mode; |
3272 | 3330 | ||
3273 | if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0) | 3331 | if (ath6kl_wmi_powermode_cmd(ar->wmi, 0, REC_POWER) != 0) |
3274 | ath6kl_warn("ath6kl_deep_sleep_enable: " | 3332 | ath6kl_warn("ath6kl_deep_sleep_enable: wmi_powermode_cmd failed\n"); |
3275 | "wmi_powermode_cmd failed\n"); | ||
3276 | return; | 3333 | return; |
3277 | } | 3334 | } |
3278 | 3335 | ||
@@ -3352,6 +3409,7 @@ struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, | |||
3352 | vif->next_mode = nw_type; | 3409 | vif->next_mode = nw_type; |
3353 | vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; | 3410 | vif->listen_intvl_t = ATH6KL_DEFAULT_LISTEN_INTVAL; |
3354 | vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; | 3411 | vif->bmiss_time_t = ATH6KL_DEFAULT_BMISS_TIME; |
3412 | vif->bg_scan_period = 0; | ||
3355 | vif->htcap.ht_enable = true; | 3413 | vif->htcap.ht_enable = true; |
3356 | 3414 | ||
3357 | memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); | 3415 | memcpy(ndev->dev_addr, ar->mac_addr, ETH_ALEN); |
@@ -3393,6 +3451,7 @@ err: | |||
3393 | int ath6kl_cfg80211_init(struct ath6kl *ar) | 3451 | int ath6kl_cfg80211_init(struct ath6kl *ar) |
3394 | { | 3452 | { |
3395 | struct wiphy *wiphy = ar->wiphy; | 3453 | struct wiphy *wiphy = ar->wiphy; |
3454 | bool band_2gig = false, band_5gig = false, ht = false; | ||
3396 | int ret; | 3455 | int ret; |
3397 | 3456 | ||
3398 | wiphy->mgmt_stypes = ath6kl_mgmt_stypes; | 3457 | wiphy->mgmt_stypes = ath6kl_mgmt_stypes; |
@@ -3413,8 +3472,46 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
3413 | /* max num of ssids that can be probed during scanning */ | 3472 | /* max num of ssids that can be probed during scanning */ |
3414 | wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; | 3473 | wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX; |
3415 | wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ | 3474 | wiphy->max_scan_ie_len = 1000; /* FIX: what is correct limit? */ |
3416 | wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; | 3475 | switch (ar->hw.cap) { |
3417 | wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; | 3476 | case WMI_11AN_CAP: |
3477 | ht = true; | ||
3478 | case WMI_11A_CAP: | ||
3479 | band_5gig = true; | ||
3480 | break; | ||
3481 | case WMI_11GN_CAP: | ||
3482 | ht = true; | ||
3483 | case WMI_11G_CAP: | ||
3484 | band_2gig = true; | ||
3485 | break; | ||
3486 | case WMI_11AGN_CAP: | ||
3487 | ht = true; | ||
3488 | case WMI_11AG_CAP: | ||
3489 | band_2gig = true; | ||
3490 | band_5gig = true; | ||
3491 | break; | ||
3492 | default: | ||
3493 | ath6kl_err("invalid phy capability!\n"); | ||
3494 | return -EINVAL; | ||
3495 | } | ||
3496 | |||
3497 | /* | ||
3498 | * Even if the fw has HT support, advertise HT cap only when | ||
3499 | * the firmware has support to override RSN capability, otherwise | ||
3500 | * 4-way handshake would fail. | ||
3501 | */ | ||
3502 | if (!(ht && | ||
3503 | test_bit(ATH6KL_FW_CAPABILITY_RSN_CAP_OVERRIDE, | ||
3504 | ar->fw_capabilities))) { | ||
3505 | ath6kl_band_2ghz.ht_cap.cap = 0; | ||
3506 | ath6kl_band_2ghz.ht_cap.ht_supported = false; | ||
3507 | ath6kl_band_5ghz.ht_cap.cap = 0; | ||
3508 | ath6kl_band_5ghz.ht_cap.ht_supported = false; | ||
3509 | } | ||
3510 | if (band_2gig) | ||
3511 | wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz; | ||
3512 | if (band_5gig) | ||
3513 | wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz; | ||
3514 | |||
3418 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 3515 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
3419 | 3516 | ||
3420 | wiphy->cipher_suites = cipher_suites; | 3517 | wiphy->cipher_suites = cipher_suites; |
@@ -3430,7 +3527,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
3430 | wiphy->wowlan.pattern_min_len = 1; | 3527 | wiphy->wowlan.pattern_min_len = 1; |
3431 | wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; | 3528 | wiphy->wowlan.pattern_max_len = WOW_PATTERN_SIZE; |
3432 | 3529 | ||
3433 | wiphy->max_sched_scan_ssids = 10; | 3530 | wiphy->max_sched_scan_ssids = MAX_PROBED_SSID_INDEX; |
3434 | 3531 | ||
3435 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | | 3532 | ar->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM | |
3436 | WIPHY_FLAG_HAVE_AP_SME | | 3533 | WIPHY_FLAG_HAVE_AP_SME | |
@@ -3447,8 +3544,7 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
3447 | ar->wiphy->probe_resp_offload = | 3544 | ar->wiphy->probe_resp_offload = |
3448 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | | 3545 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | |
3449 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | 3546 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | |
3450 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P | | 3547 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; |
3451 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U; | ||
3452 | 3548 | ||
3453 | ret = wiphy_register(wiphy); | 3549 | ret = wiphy_register(wiphy); |
3454 | if (ret < 0) { | 3550 | if (ret < 0) { |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h index c5def436417f..5ea8cbb79f43 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.h +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h | |||
@@ -28,6 +28,8 @@ enum ath6kl_cfg_suspend_mode { | |||
28 | struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, | 28 | struct net_device *ath6kl_interface_add(struct ath6kl *ar, char *name, |
29 | enum nl80211_iftype type, | 29 | enum nl80211_iftype type, |
30 | u8 fw_vif_idx, u8 nw_type); | 30 | u8 fw_vif_idx, u8 nw_type); |
31 | void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq, | ||
32 | enum wmi_phy_mode mode); | ||
31 | void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted); | 33 | void ath6kl_cfg80211_scan_complete_event(struct ath6kl_vif *vif, bool aborted); |
32 | 34 | ||
33 | void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, | 35 | void ath6kl_cfg80211_connect_event(struct ath6kl_vif *vif, u16 channel, |
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h index 9d67964a51dd..4d9c6f142698 100644 --- a/drivers/net/wireless/ath/ath6kl/core.h +++ b/drivers/net/wireless/ath/ath6kl/core.h | |||
@@ -126,9 +126,9 @@ struct ath6kl_fw_ie { | |||
126 | #define AR6003_HW_2_0_FIRMWARE_FILE "athwlan.bin.z77" | 126 | #define AR6003_HW_2_0_FIRMWARE_FILE "athwlan.bin.z77" |
127 | #define AR6003_HW_2_0_TCMD_FIRMWARE_FILE "athtcmd_ram.bin" | 127 | #define AR6003_HW_2_0_TCMD_FIRMWARE_FILE "athtcmd_ram.bin" |
128 | #define AR6003_HW_2_0_PATCH_FILE "data.patch.bin" | 128 | #define AR6003_HW_2_0_PATCH_FILE "data.patch.bin" |
129 | #define AR6003_HW_2_0_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin" | 129 | #define AR6003_HW_2_0_BOARD_DATA_FILE AR6003_HW_2_0_FW_DIR "/bdata.bin" |
130 | #define AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE \ | 130 | #define AR6003_HW_2_0_DEFAULT_BOARD_DATA_FILE \ |
131 | "ath6k/AR6003/hw2.0/bdata.SD31.bin" | 131 | AR6003_HW_2_0_FW_DIR "/bdata.SD31.bin" |
132 | 132 | ||
133 | /* AR6003 3.0 definitions */ | 133 | /* AR6003 3.0 definitions */ |
134 | #define AR6003_HW_2_1_1_VERSION 0x30000582 | 134 | #define AR6003_HW_2_1_1_VERSION 0x30000582 |
@@ -139,25 +139,33 @@ struct ath6kl_fw_ie { | |||
139 | #define AR6003_HW_2_1_1_UTF_FIRMWARE_FILE "utf.bin" | 139 | #define AR6003_HW_2_1_1_UTF_FIRMWARE_FILE "utf.bin" |
140 | #define AR6003_HW_2_1_1_TESTSCRIPT_FILE "nullTestFlow.bin" | 140 | #define AR6003_HW_2_1_1_TESTSCRIPT_FILE "nullTestFlow.bin" |
141 | #define AR6003_HW_2_1_1_PATCH_FILE "data.patch.bin" | 141 | #define AR6003_HW_2_1_1_PATCH_FILE "data.patch.bin" |
142 | #define AR6003_HW_2_1_1_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin" | 142 | #define AR6003_HW_2_1_1_BOARD_DATA_FILE AR6003_HW_2_1_1_FW_DIR "/bdata.bin" |
143 | #define AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE \ | 143 | #define AR6003_HW_2_1_1_DEFAULT_BOARD_DATA_FILE \ |
144 | "ath6k/AR6003/hw2.1.1/bdata.SD31.bin" | 144 | AR6003_HW_2_1_1_FW_DIR "/bdata.SD31.bin" |
145 | 145 | ||
146 | /* AR6004 1.0 definitions */ | 146 | /* AR6004 1.0 definitions */ |
147 | #define AR6004_HW_1_0_VERSION 0x30000623 | 147 | #define AR6004_HW_1_0_VERSION 0x30000623 |
148 | #define AR6004_HW_1_0_FW_DIR "ath6k/AR6004/hw1.0" | 148 | #define AR6004_HW_1_0_FW_DIR "ath6k/AR6004/hw1.0" |
149 | #define AR6004_HW_1_0_FIRMWARE_FILE "fw.ram.bin" | 149 | #define AR6004_HW_1_0_FIRMWARE_FILE "fw.ram.bin" |
150 | #define AR6004_HW_1_0_BOARD_DATA_FILE "ath6k/AR6004/hw1.0/bdata.bin" | 150 | #define AR6004_HW_1_0_BOARD_DATA_FILE AR6004_HW_1_0_FW_DIR "/bdata.bin" |
151 | #define AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE \ | 151 | #define AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE \ |
152 | "ath6k/AR6004/hw1.0/bdata.DB132.bin" | 152 | AR6004_HW_1_0_FW_DIR "/bdata.DB132.bin" |
153 | 153 | ||
154 | /* AR6004 1.1 definitions */ | 154 | /* AR6004 1.1 definitions */ |
155 | #define AR6004_HW_1_1_VERSION 0x30000001 | 155 | #define AR6004_HW_1_1_VERSION 0x30000001 |
156 | #define AR6004_HW_1_1_FW_DIR "ath6k/AR6004/hw1.1" | 156 | #define AR6004_HW_1_1_FW_DIR "ath6k/AR6004/hw1.1" |
157 | #define AR6004_HW_1_1_FIRMWARE_FILE "fw.ram.bin" | 157 | #define AR6004_HW_1_1_FIRMWARE_FILE "fw.ram.bin" |
158 | #define AR6004_HW_1_1_BOARD_DATA_FILE "ath6k/AR6004/hw1.1/bdata.bin" | 158 | #define AR6004_HW_1_1_BOARD_DATA_FILE AR6004_HW_1_1_FW_DIR "/bdata.bin" |
159 | #define AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE \ | 159 | #define AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE \ |
160 | "ath6k/AR6004/hw1.1/bdata.DB132.bin" | 160 | AR6004_HW_1_1_FW_DIR "/bdata.DB132.bin" |
161 | |||
162 | /* AR6004 1.2 definitions */ | ||
163 | #define AR6004_HW_1_2_VERSION 0x300007e8 | ||
164 | #define AR6004_HW_1_2_FW_DIR "ath6k/AR6004/hw1.2" | ||
165 | #define AR6004_HW_1_2_FIRMWARE_FILE "fw.ram.bin" | ||
166 | #define AR6004_HW_1_2_BOARD_DATA_FILE AR6004_HW_1_2_FW_DIR "/bdata.bin" | ||
167 | #define AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE \ | ||
168 | AR6004_HW_1_2_FW_DIR "/bdata.bin" | ||
161 | 169 | ||
162 | /* Per STA data, used in AP mode */ | 170 | /* Per STA data, used in AP mode */ |
163 | #define STA_PS_AWAKE BIT(0) | 171 | #define STA_PS_AWAKE BIT(0) |
@@ -502,6 +510,8 @@ enum ath6kl_vif_state { | |||
502 | WLAN_ENABLED, | 510 | WLAN_ENABLED, |
503 | STATS_UPDATE_PEND, | 511 | STATS_UPDATE_PEND, |
504 | HOST_SLEEP_MODE_CMD_PROCESSED, | 512 | HOST_SLEEP_MODE_CMD_PROCESSED, |
513 | NETDEV_MCAST_ALL_ON, | ||
514 | NETDEV_MCAST_ALL_OFF, | ||
505 | }; | 515 | }; |
506 | 516 | ||
507 | struct ath6kl_vif { | 517 | struct ath6kl_vif { |
@@ -549,9 +559,11 @@ struct ath6kl_vif { | |||
549 | u16 assoc_bss_beacon_int; | 559 | u16 assoc_bss_beacon_int; |
550 | u16 listen_intvl_t; | 560 | u16 listen_intvl_t; |
551 | u16 bmiss_time_t; | 561 | u16 bmiss_time_t; |
562 | u16 bg_scan_period; | ||
552 | u8 assoc_bss_dtim_period; | 563 | u8 assoc_bss_dtim_period; |
553 | struct net_device_stats net_stats; | 564 | struct net_device_stats net_stats; |
554 | struct target_stats target_stats; | 565 | struct target_stats target_stats; |
566 | struct wmi_connect_cmd profile; | ||
555 | 567 | ||
556 | struct list_head mc_filter; | 568 | struct list_head mc_filter; |
557 | }; | 569 | }; |
@@ -640,6 +652,7 @@ struct ath6kl { | |||
640 | u8 sta_list_index; | 652 | u8 sta_list_index; |
641 | struct ath6kl_req_key ap_mode_bkey; | 653 | struct ath6kl_req_key ap_mode_bkey; |
642 | struct sk_buff_head mcastpsq; | 654 | struct sk_buff_head mcastpsq; |
655 | u32 want_ch_switch; | ||
643 | 656 | ||
644 | /* | 657 | /* |
645 | * FIXME: protects access to mcastpsq but is actually useless as | 658 | * FIXME: protects access to mcastpsq but is actually useless as |
@@ -672,6 +685,7 @@ struct ath6kl { | |||
672 | u32 refclk_hz; | 685 | u32 refclk_hz; |
673 | u32 uarttx_pin; | 686 | u32 uarttx_pin; |
674 | u32 testscript_addr; | 687 | u32 testscript_addr; |
688 | enum wmi_phy_cap cap; | ||
675 | 689 | ||
676 | struct ath6kl_hw_fw { | 690 | struct ath6kl_hw_fw { |
677 | const char *dir; | 691 | const char *dir; |
@@ -805,7 +819,8 @@ void aggr_reset_state(struct aggr_info_conn *aggr_conn); | |||
805 | struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 *node_addr); | 819 | struct ath6kl_sta *ath6kl_find_sta(struct ath6kl_vif *vif, u8 *node_addr); |
806 | struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid); | 820 | struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid); |
807 | 821 | ||
808 | void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver); | 822 | void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver, |
823 | enum wmi_phy_cap cap); | ||
809 | int ath6kl_control_tx(void *devt, struct sk_buff *skb, | 824 | int ath6kl_control_tx(void *devt, struct sk_buff *skb, |
810 | enum htc_endpoint_id eid); | 825 | enum htc_endpoint_id eid); |
811 | void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, | 826 | void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 1b76aff78508..15cfe30e54fd 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c | |||
@@ -401,8 +401,10 @@ static ssize_t ath6kl_fwlog_block_read(struct file *file, | |||
401 | 401 | ||
402 | ret = wait_for_completion_interruptible( | 402 | ret = wait_for_completion_interruptible( |
403 | &ar->debug.fwlog_completion); | 403 | &ar->debug.fwlog_completion); |
404 | if (ret == -ERESTARTSYS) | 404 | if (ret == -ERESTARTSYS) { |
405 | vfree(buf); | ||
405 | return ret; | 406 | return ret; |
407 | } | ||
406 | 408 | ||
407 | spin_lock(&ar->debug.fwlog_queue.lock); | 409 | spin_lock(&ar->debug.fwlog_queue.lock); |
408 | } | 410 | } |
@@ -1570,10 +1572,15 @@ static ssize_t ath6kl_bgscan_int_write(struct file *file, | |||
1570 | size_t count, loff_t *ppos) | 1572 | size_t count, loff_t *ppos) |
1571 | { | 1573 | { |
1572 | struct ath6kl *ar = file->private_data; | 1574 | struct ath6kl *ar = file->private_data; |
1575 | struct ath6kl_vif *vif; | ||
1573 | u16 bgscan_int; | 1576 | u16 bgscan_int; |
1574 | char buf[32]; | 1577 | char buf[32]; |
1575 | ssize_t len; | 1578 | ssize_t len; |
1576 | 1579 | ||
1580 | vif = ath6kl_vif_first(ar); | ||
1581 | if (!vif) | ||
1582 | return -EIO; | ||
1583 | |||
1577 | len = min(count, sizeof(buf) - 1); | 1584 | len = min(count, sizeof(buf) - 1); |
1578 | if (copy_from_user(buf, user_buf, len)) | 1585 | if (copy_from_user(buf, user_buf, len)) |
1579 | return -EFAULT; | 1586 | return -EFAULT; |
@@ -1585,6 +1592,8 @@ static ssize_t ath6kl_bgscan_int_write(struct file *file, | |||
1585 | if (bgscan_int == 0) | 1592 | if (bgscan_int == 0) |
1586 | bgscan_int = 0xffff; | 1593 | bgscan_int = 0xffff; |
1587 | 1594 | ||
1595 | vif->bg_scan_period = bgscan_int; | ||
1596 | |||
1588 | ath6kl_wmi_scanparams_cmd(ar->wmi, 0, 0, 0, bgscan_int, 0, 0, 0, 3, | 1597 | ath6kl_wmi_scanparams_cmd(ar->wmi, 0, 0, 0, bgscan_int, 0, 0, 0, 3, |
1589 | 0, 0, 0); | 1598 | 0, 0, 0); |
1590 | 1599 | ||
@@ -1809,6 +1818,7 @@ int ath6kl_debug_init_fs(struct ath6kl *ar) | |||
1809 | void ath6kl_debug_cleanup(struct ath6kl *ar) | 1818 | void ath6kl_debug_cleanup(struct ath6kl *ar) |
1810 | { | 1819 | { |
1811 | skb_queue_purge(&ar->debug.fwlog_queue); | 1820 | skb_queue_purge(&ar->debug.fwlog_queue); |
1821 | complete(&ar->debug.fwlog_completion); | ||
1812 | kfree(ar->debug.roam_tbl); | 1822 | kfree(ar->debug.roam_tbl); |
1813 | } | 1823 | } |
1814 | 1824 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c index 065e61516d7a..2798624d3a9d 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c +++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c | |||
@@ -83,10 +83,7 @@ static void ath6kl_credit_init(struct ath6kl_htc_credit_info *cred_info, | |||
83 | * never goes inactive EVER. | 83 | * never goes inactive EVER. |
84 | */ | 84 | */ |
85 | cur_ep_dist->dist_flags |= HTC_EP_ACTIVE; | 85 | cur_ep_dist->dist_flags |= HTC_EP_ACTIVE; |
86 | } else if (cur_ep_dist->svc_id == WMI_DATA_BK_SVC) | 86 | } |
87 | /* this is the lowest priority data endpoint */ | ||
88 | /* FIXME: this looks fishy, check */ | ||
89 | cred_info->lowestpri_ep_dist = cur_ep_dist->list; | ||
90 | 87 | ||
91 | /* | 88 | /* |
92 | * Streams have to be created (explicit | implicit) for all | 89 | * Streams have to be created (explicit | implicit) for all |
@@ -100,6 +97,13 @@ static void ath6kl_credit_init(struct ath6kl_htc_credit_info *cred_info, | |||
100 | */ | 97 | */ |
101 | } | 98 | } |
102 | 99 | ||
100 | /* | ||
101 | * For ath6kl_credit_seek function, | ||
102 | * it use list_for_each_entry_reverse to walk around the whole ep list. | ||
103 | * Therefore assign this lowestpri_ep_dist after walk around the ep_list | ||
104 | */ | ||
105 | cred_info->lowestpri_ep_dist = cur_ep_dist->list; | ||
106 | |||
103 | WARN_ON(cred_info->cur_free_credits <= 0); | 107 | WARN_ON(cred_info->cur_free_credits <= 0); |
104 | 108 | ||
105 | list_for_each_entry(cur_ep_dist, ep_list, list) { | 109 | list_for_each_entry(cur_ep_dist, ep_list, list) { |
@@ -758,7 +762,7 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint, | |||
758 | u32 txb_mask; | 762 | u32 txb_mask; |
759 | u8 ac = WMM_NUM_AC; | 763 | u8 ac = WMM_NUM_AC; |
760 | 764 | ||
761 | if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) || | 765 | if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) && |
762 | (WMI_CONTROL_SVC != endpoint->svc_id)) | 766 | (WMI_CONTROL_SVC != endpoint->svc_id)) |
763 | ac = target->dev->ar->ep2ac_map[endpoint->eid]; | 767 | ac = target->dev->ar->ep2ac_map[endpoint->eid]; |
764 | 768 | ||
@@ -793,16 +797,17 @@ static void ath6kl_htc_tx_bundle(struct htc_endpoint *endpoint, | |||
793 | * itself | 797 | * itself |
794 | */ | 798 | */ |
795 | txb_mask = ((1 << ac) - 1); | 799 | txb_mask = ((1 << ac) - 1); |
796 | /* | 800 | |
797 | * when the scatter request resources drop below a | 801 | /* |
798 | * certain threshold, disable Tx bundling for all | 802 | * when the scatter request resources drop below a |
799 | * AC's with priority lower than the current requesting | 803 | * certain threshold, disable Tx bundling for all |
800 | * AC. Otherwise re-enable Tx bundling for them | 804 | * AC's with priority lower than the current requesting |
801 | */ | 805 | * AC. Otherwise re-enable Tx bundling for them |
802 | if (scat_req->scat_q_depth < ATH6KL_SCATTER_REQS) | 806 | */ |
803 | target->tx_bndl_mask &= ~txb_mask; | 807 | if (scat_req->scat_q_depth < ATH6KL_SCATTER_REQS) |
804 | else | 808 | target->tx_bndl_mask &= ~txb_mask; |
805 | target->tx_bndl_mask |= txb_mask; | 809 | else |
810 | target->tx_bndl_mask |= txb_mask; | ||
806 | } | 811 | } |
807 | 812 | ||
808 | ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx pkts to scatter: %d\n", | 813 | ath6kl_dbg(ATH6KL_DBG_HTC, "htc tx pkts to scatter: %d\n", |
@@ -849,6 +854,7 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target, | |||
849 | int bundle_sent; | 854 | int bundle_sent; |
850 | int n_pkts_bundle; | 855 | int n_pkts_bundle; |
851 | u8 ac = WMM_NUM_AC; | 856 | u8 ac = WMM_NUM_AC; |
857 | int status; | ||
852 | 858 | ||
853 | spin_lock_bh(&target->tx_lock); | 859 | spin_lock_bh(&target->tx_lock); |
854 | 860 | ||
@@ -866,7 +872,7 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target, | |||
866 | */ | 872 | */ |
867 | INIT_LIST_HEAD(&txq); | 873 | INIT_LIST_HEAD(&txq); |
868 | 874 | ||
869 | if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) || | 875 | if ((HTC_CTRL_RSVD_SVC != endpoint->svc_id) && |
870 | (WMI_CONTROL_SVC != endpoint->svc_id)) | 876 | (WMI_CONTROL_SVC != endpoint->svc_id)) |
871 | ac = target->dev->ar->ep2ac_map[endpoint->eid]; | 877 | ac = target->dev->ar->ep2ac_map[endpoint->eid]; |
872 | 878 | ||
@@ -910,7 +916,12 @@ static void ath6kl_htc_tx_from_queue(struct htc_target *target, | |||
910 | 916 | ||
911 | ath6kl_htc_tx_prep_pkt(packet, packet->info.tx.flags, | 917 | ath6kl_htc_tx_prep_pkt(packet, packet->info.tx.flags, |
912 | 0, packet->info.tx.seqno); | 918 | 0, packet->info.tx.seqno); |
913 | ath6kl_htc_tx_issue(target, packet); | 919 | status = ath6kl_htc_tx_issue(target, packet); |
920 | |||
921 | if (status) { | ||
922 | packet->status = status; | ||
923 | packet->completion(packet->context, packet); | ||
924 | } | ||
914 | } | 925 | } |
915 | 926 | ||
916 | spin_lock_bh(&target->tx_lock); | 927 | spin_lock_bh(&target->tx_lock); |
diff --git a/drivers/net/wireless/ath/ath6kl/htc_pipe.c b/drivers/net/wireless/ath/ath6kl/htc_pipe.c index b277b3446882..f9626c723693 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_pipe.c +++ b/drivers/net/wireless/ath/ath6kl/htc_pipe.c | |||
@@ -108,8 +108,6 @@ static void get_htc_packet_credit_based(struct htc_target *target, | |||
108 | 108 | ||
109 | /* get packet at head, but don't remove it */ | 109 | /* get packet at head, but don't remove it */ |
110 | packet = list_first_entry(&ep->txq, struct htc_packet, list); | 110 | packet = list_first_entry(&ep->txq, struct htc_packet, list); |
111 | if (packet == NULL) | ||
112 | break; | ||
113 | 111 | ||
114 | ath6kl_dbg(ATH6KL_DBG_HTC, | 112 | ath6kl_dbg(ATH6KL_DBG_HTC, |
115 | "%s: got head packet:0x%p , queue depth: %d\n", | 113 | "%s: got head packet:0x%p , queue depth: %d\n", |
@@ -803,8 +801,6 @@ static int htc_send_packets_multiple(struct htc_target *target, | |||
803 | 801 | ||
804 | /* get first packet to find out which ep the packets will go into */ | 802 | /* get first packet to find out which ep the packets will go into */ |
805 | packet = list_first_entry(pkt_queue, struct htc_packet, list); | 803 | packet = list_first_entry(pkt_queue, struct htc_packet, list); |
806 | if (packet == NULL) | ||
807 | return -EINVAL; | ||
808 | 804 | ||
809 | if (packet->endpoint >= ENDPOINT_MAX) { | 805 | if (packet->endpoint >= ENDPOINT_MAX) { |
810 | WARN_ON_ONCE(1); | 806 | WARN_ON_ONCE(1); |
@@ -1382,6 +1378,9 @@ static int ath6kl_htc_pipe_conn_service(struct htc_target *target, | |||
1382 | /* copy all the callbacks */ | 1378 | /* copy all the callbacks */ |
1383 | ep->ep_cb = conn_req->ep_cb; | 1379 | ep->ep_cb = conn_req->ep_cb; |
1384 | 1380 | ||
1381 | /* initialize tx_drop_packet_threshold */ | ||
1382 | ep->tx_drop_packet_threshold = MAX_HI_COOKIE_NUM; | ||
1383 | |||
1385 | status = ath6kl_hif_pipe_map_service(ar, ep->svc_id, | 1384 | status = ath6kl_hif_pipe_map_service(ar, ep->svc_id, |
1386 | &ep->pipe.pipeid_ul, | 1385 | &ep->pipe.pipeid_ul, |
1387 | &ep->pipe.pipeid_dl); | 1386 | &ep->pipe.pipeid_dl); |
@@ -1636,10 +1635,6 @@ static int ath6kl_htc_pipe_add_rxbuf_multiple(struct htc_target *target, | |||
1636 | return -EINVAL; | 1635 | return -EINVAL; |
1637 | 1636 | ||
1638 | first = list_first_entry(pkt_queue, struct htc_packet, list); | 1637 | first = list_first_entry(pkt_queue, struct htc_packet, list); |
1639 | if (first == NULL) { | ||
1640 | WARN_ON_ONCE(1); | ||
1641 | return -EINVAL; | ||
1642 | } | ||
1643 | 1638 | ||
1644 | if (first->endpoint >= ENDPOINT_MAX) { | 1639 | if (first->endpoint >= ENDPOINT_MAX) { |
1645 | WARN_ON_ONCE(1); | 1640 | WARN_ON_ONCE(1); |
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 29ef50ea07d5..7eb0515f458a 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
@@ -119,6 +119,24 @@ static const struct ath6kl_hw hw_list[] = { | |||
119 | .fw_board = AR6004_HW_1_1_BOARD_DATA_FILE, | 119 | .fw_board = AR6004_HW_1_1_BOARD_DATA_FILE, |
120 | .fw_default_board = AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE, | 120 | .fw_default_board = AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE, |
121 | }, | 121 | }, |
122 | { | ||
123 | .id = AR6004_HW_1_2_VERSION, | ||
124 | .name = "ar6004 hw 1.2", | ||
125 | .dataset_patch_addr = 0x436ecc, | ||
126 | .app_load_addr = 0x1234, | ||
127 | .board_ext_data_addr = 0x437000, | ||
128 | .reserved_ram_size = 9216, | ||
129 | .board_addr = 0x435c00, | ||
130 | .refclk_hz = 40000000, | ||
131 | .uarttx_pin = 11, | ||
132 | |||
133 | .fw = { | ||
134 | .dir = AR6004_HW_1_2_FW_DIR, | ||
135 | .fw = AR6004_HW_1_2_FIRMWARE_FILE, | ||
136 | }, | ||
137 | .fw_board = AR6004_HW_1_2_BOARD_DATA_FILE, | ||
138 | .fw_default_board = AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE, | ||
139 | }, | ||
122 | }; | 140 | }; |
123 | 141 | ||
124 | /* | 142 | /* |
@@ -445,9 +463,9 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx) | |||
445 | P2P_FLAG_MACADDR_REQ | | 463 | P2P_FLAG_MACADDR_REQ | |
446 | P2P_FLAG_HMODEL_REQ); | 464 | P2P_FLAG_HMODEL_REQ); |
447 | if (ret) { | 465 | if (ret) { |
448 | ath6kl_dbg(ATH6KL_DBG_TRC, "failed to request P2P " | 466 | ath6kl_dbg(ATH6KL_DBG_TRC, |
449 | "capabilities (%d) - assuming P2P not " | 467 | "failed to request P2P capabilities (%d) - assuming P2P not supported\n", |
450 | "supported\n", ret); | 468 | ret); |
451 | ar->p2p = false; | 469 | ar->p2p = false; |
452 | } | 470 | } |
453 | } | 471 | } |
@@ -456,8 +474,9 @@ static int ath6kl_target_config_wlan_params(struct ath6kl *ar, int idx) | |||
456 | /* Enable Probe Request reporting for P2P */ | 474 | /* Enable Probe Request reporting for P2P */ |
457 | ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, idx, true); | 475 | ret = ath6kl_wmi_probe_report_req_cmd(ar->wmi, idx, true); |
458 | if (ret) { | 476 | if (ret) { |
459 | ath6kl_dbg(ATH6KL_DBG_TRC, "failed to enable Probe " | 477 | ath6kl_dbg(ATH6KL_DBG_TRC, |
460 | "Request reporting (%d)\n", ret); | 478 | "failed to enable Probe Request reporting (%d)\n", |
479 | ret); | ||
461 | } | 480 | } |
462 | } | 481 | } |
463 | 482 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c index 4d818f96c415..e5524470529c 100644 --- a/drivers/net/wireless/ath/ath6kl/main.c +++ b/drivers/net/wireless/ath/ath6kl/main.c | |||
@@ -421,8 +421,8 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel) | |||
421 | if (!ik->valid) | 421 | if (!ik->valid) |
422 | break; | 422 | break; |
423 | 423 | ||
424 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed addkey for " | 424 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
425 | "the initial group key for AP mode\n"); | 425 | "Delayed addkey for the initial group key for AP mode\n"); |
426 | memset(key_rsc, 0, sizeof(key_rsc)); | 426 | memset(key_rsc, 0, sizeof(key_rsc)); |
427 | res = ath6kl_wmi_addkey_cmd( | 427 | res = ath6kl_wmi_addkey_cmd( |
428 | ar->wmi, vif->fw_vif_idx, ik->key_index, ik->key_type, | 428 | ar->wmi, vif->fw_vif_idx, ik->key_index, ik->key_type, |
@@ -430,12 +430,19 @@ void ath6kl_connect_ap_mode_bss(struct ath6kl_vif *vif, u16 channel) | |||
430 | ik->key, | 430 | ik->key, |
431 | KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG); | 431 | KEY_OP_INIT_VAL, NULL, SYNC_BOTH_WMIFLAG); |
432 | if (res) { | 432 | if (res) { |
433 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "Delayed " | 433 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, |
434 | "addkey failed: %d\n", res); | 434 | "Delayed addkey failed: %d\n", res); |
435 | } | 435 | } |
436 | break; | 436 | break; |
437 | } | 437 | } |
438 | 438 | ||
439 | if (ar->want_ch_switch & (1 << vif->fw_vif_idx)) { | ||
440 | ar->want_ch_switch &= ~(1 << vif->fw_vif_idx); | ||
441 | /* we actually don't know the phymode, default to HT20 */ | ||
442 | ath6kl_cfg80211_ch_switch_notify(vif, channel, | ||
443 | WMI_11G_HT20); | ||
444 | } | ||
445 | |||
439 | ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, NONE_BSS_FILTER, 0); | 446 | ath6kl_wmi_bssfilter_cmd(ar->wmi, vif->fw_vif_idx, NONE_BSS_FILTER, 0); |
440 | set_bit(CONNECTED, &vif->flags); | 447 | set_bit(CONNECTED, &vif->flags); |
441 | netif_carrier_on(vif->ndev); | 448 | netif_carrier_on(vif->ndev); |
@@ -541,7 +548,8 @@ void ath6kl_disconnect(struct ath6kl_vif *vif) | |||
541 | 548 | ||
542 | /* WMI Event handlers */ | 549 | /* WMI Event handlers */ |
543 | 550 | ||
544 | void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver) | 551 | void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver, |
552 | enum wmi_phy_cap cap) | ||
545 | { | 553 | { |
546 | struct ath6kl *ar = devt; | 554 | struct ath6kl *ar = devt; |
547 | 555 | ||
@@ -551,6 +559,7 @@ void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver) | |||
551 | 559 | ||
552 | ar->version.wlan_ver = sw_ver; | 560 | ar->version.wlan_ver = sw_ver; |
553 | ar->version.abi_ver = abi_ver; | 561 | ar->version.abi_ver = abi_ver; |
562 | ar->hw.cap = cap; | ||
554 | 563 | ||
555 | snprintf(ar->wiphy->fw_version, | 564 | snprintf(ar->wiphy->fw_version, |
556 | sizeof(ar->wiphy->fw_version), | 565 | sizeof(ar->wiphy->fw_version), |
@@ -584,6 +593,45 @@ void ath6kl_scan_complete_evt(struct ath6kl_vif *vif, int status) | |||
584 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "scan complete: %d\n", status); | 593 | ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "scan complete: %d\n", status); |
585 | } | 594 | } |
586 | 595 | ||
596 | static int ath6kl_commit_ch_switch(struct ath6kl_vif *vif, u16 channel) | ||
597 | { | ||
598 | |||
599 | struct ath6kl *ar = vif->ar; | ||
600 | |||
601 | vif->next_chan = channel; | ||
602 | vif->profile.ch = cpu_to_le16(channel); | ||
603 | |||
604 | switch (vif->nw_type) { | ||
605 | case AP_NETWORK: | ||
606 | return ath6kl_wmi_ap_profile_commit(ar->wmi, vif->fw_vif_idx, | ||
607 | &vif->profile); | ||
608 | default: | ||
609 | ath6kl_err("won't switch channels nw_type=%d\n", vif->nw_type); | ||
610 | return -ENOTSUPP; | ||
611 | } | ||
612 | } | ||
613 | |||
614 | static void ath6kl_check_ch_switch(struct ath6kl *ar, u16 channel) | ||
615 | { | ||
616 | |||
617 | struct ath6kl_vif *vif; | ||
618 | int res = 0; | ||
619 | |||
620 | if (!ar->want_ch_switch) | ||
621 | return; | ||
622 | |||
623 | spin_lock_bh(&ar->list_lock); | ||
624 | list_for_each_entry(vif, &ar->vif_list, list) { | ||
625 | if (ar->want_ch_switch & (1 << vif->fw_vif_idx)) | ||
626 | res = ath6kl_commit_ch_switch(vif, channel); | ||
627 | |||
628 | if (res) | ||
629 | ath6kl_err("channel switch failed nw_type %d res %d\n", | ||
630 | vif->nw_type, res); | ||
631 | } | ||
632 | spin_unlock_bh(&ar->list_lock); | ||
633 | } | ||
634 | |||
587 | void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid, | 635 | void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid, |
588 | u16 listen_int, u16 beacon_int, | 636 | u16 listen_int, u16 beacon_int, |
589 | enum network_type net_type, u8 beacon_ie_len, | 637 | enum network_type net_type, u8 beacon_ie_len, |
@@ -601,9 +649,11 @@ void ath6kl_connect_event(struct ath6kl_vif *vif, u16 channel, u8 *bssid, | |||
601 | memcpy(vif->bssid, bssid, sizeof(vif->bssid)); | 649 | memcpy(vif->bssid, bssid, sizeof(vif->bssid)); |
602 | vif->bss_ch = channel; | 650 | vif->bss_ch = channel; |
603 | 651 | ||
604 | if ((vif->nw_type == INFRA_NETWORK)) | 652 | if ((vif->nw_type == INFRA_NETWORK)) { |
605 | ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, | 653 | ath6kl_wmi_listeninterval_cmd(ar->wmi, vif->fw_vif_idx, |
606 | vif->listen_intvl_t, 0); | 654 | vif->listen_intvl_t, 0); |
655 | ath6kl_check_ch_switch(ar, channel); | ||
656 | } | ||
607 | 657 | ||
608 | netif_wake_queue(vif->ndev); | 658 | netif_wake_queue(vif->ndev); |
609 | 659 | ||
@@ -926,6 +976,11 @@ void ath6kl_disconnect_event(struct ath6kl_vif *vif, u8 reason, u8 *bssid, | |||
926 | struct ath6kl *ar = vif->ar; | 976 | struct ath6kl *ar = vif->ar; |
927 | 977 | ||
928 | if (vif->nw_type == AP_NETWORK) { | 978 | if (vif->nw_type == AP_NETWORK) { |
979 | /* disconnect due to other STA vif switching channels */ | ||
980 | if (reason == BSS_DISCONNECTED && | ||
981 | prot_reason_status == WMI_AP_REASON_STA_ROAM) | ||
982 | ar->want_ch_switch |= 1 << vif->fw_vif_idx; | ||
983 | |||
929 | if (!ath6kl_remove_sta(ar, bssid, prot_reason_status)) | 984 | if (!ath6kl_remove_sta(ar, bssid, prot_reason_status)) |
930 | return; | 985 | return; |
931 | 986 | ||
@@ -1090,7 +1145,7 @@ static int ath6kl_set_features(struct net_device *dev, | |||
1090 | static void ath6kl_set_multicast_list(struct net_device *ndev) | 1145 | static void ath6kl_set_multicast_list(struct net_device *ndev) |
1091 | { | 1146 | { |
1092 | struct ath6kl_vif *vif = netdev_priv(ndev); | 1147 | struct ath6kl_vif *vif = netdev_priv(ndev); |
1093 | bool mc_all_on = false, mc_all_off = false; | 1148 | bool mc_all_on = false; |
1094 | int mc_count = netdev_mc_count(ndev); | 1149 | int mc_count = netdev_mc_count(ndev); |
1095 | struct netdev_hw_addr *ha; | 1150 | struct netdev_hw_addr *ha; |
1096 | bool found; | 1151 | bool found; |
@@ -1102,24 +1157,41 @@ static void ath6kl_set_multicast_list(struct net_device *ndev) | |||
1102 | !test_bit(WLAN_ENABLED, &vif->flags)) | 1157 | !test_bit(WLAN_ENABLED, &vif->flags)) |
1103 | return; | 1158 | return; |
1104 | 1159 | ||
1160 | /* Enable multicast-all filter. */ | ||
1105 | mc_all_on = !!(ndev->flags & IFF_PROMISC) || | 1161 | mc_all_on = !!(ndev->flags & IFF_PROMISC) || |
1106 | !!(ndev->flags & IFF_ALLMULTI) || | 1162 | !!(ndev->flags & IFF_ALLMULTI) || |
1107 | !!(mc_count > ATH6K_MAX_MC_FILTERS_PER_LIST); | 1163 | !!(mc_count > ATH6K_MAX_MC_FILTERS_PER_LIST); |
1108 | 1164 | ||
1109 | mc_all_off = !(ndev->flags & IFF_MULTICAST) || mc_count == 0; | 1165 | if (mc_all_on) |
1166 | set_bit(NETDEV_MCAST_ALL_ON, &vif->flags); | ||
1167 | else | ||
1168 | clear_bit(NETDEV_MCAST_ALL_ON, &vif->flags); | ||
1169 | |||
1170 | mc_all_on = mc_all_on || (vif->ar->state == ATH6KL_STATE_ON); | ||
1110 | 1171 | ||
1111 | if (mc_all_on || mc_all_off) { | 1172 | if (!(ndev->flags & IFF_MULTICAST)) { |
1112 | /* Enable/disable all multicast */ | 1173 | mc_all_on = false; |
1113 | ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast filter\n", | 1174 | set_bit(NETDEV_MCAST_ALL_OFF, &vif->flags); |
1114 | mc_all_on ? "enabling" : "disabling"); | 1175 | } else { |
1115 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx, | 1176 | clear_bit(NETDEV_MCAST_ALL_OFF, &vif->flags); |
1177 | } | ||
1178 | |||
1179 | /* Enable/disable "multicast-all" filter*/ | ||
1180 | ath6kl_dbg(ATH6KL_DBG_TRC, "%s multicast-all filter\n", | ||
1181 | mc_all_on ? "enabling" : "disabling"); | ||
1182 | |||
1183 | ret = ath6kl_wmi_mcast_filter_cmd(vif->ar->wmi, vif->fw_vif_idx, | ||
1116 | mc_all_on); | 1184 | mc_all_on); |
1117 | if (ret) | 1185 | if (ret) { |
1118 | ath6kl_warn("Failed to %s multicast receive\n", | 1186 | ath6kl_warn("Failed to %s multicast-all receive\n", |
1119 | mc_all_on ? "enable" : "disable"); | 1187 | mc_all_on ? "enable" : "disable"); |
1120 | return; | 1188 | return; |
1121 | } | 1189 | } |
1122 | 1190 | ||
1191 | if (test_bit(NETDEV_MCAST_ALL_ON, &vif->flags)) | ||
1192 | return; | ||
1193 | |||
1194 | /* Keep the driver and firmware mcast list in sync. */ | ||
1123 | list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) { | 1195 | list_for_each_entry_safe(mc_filter, tmp, &vif->mc_filter, list) { |
1124 | found = false; | 1196 | found = false; |
1125 | netdev_for_each_mc_addr(ha, ndev) { | 1197 | netdev_for_each_mc_addr(ha, ndev) { |
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c index 44ea7a742101..05b95405f7b5 100644 --- a/drivers/net/wireless/ath/ath6kl/sdio.c +++ b/drivers/net/wireless/ath/ath6kl/sdio.c | |||
@@ -552,7 +552,7 @@ static int ath6kl_sdio_write_async(struct ath6kl *ar, u32 address, u8 *buffer, | |||
552 | 552 | ||
553 | bus_req = ath6kl_sdio_alloc_busreq(ar_sdio); | 553 | bus_req = ath6kl_sdio_alloc_busreq(ar_sdio); |
554 | 554 | ||
555 | if (!bus_req) | 555 | if (WARN_ON_ONCE(!bus_req)) |
556 | return -ENOMEM; | 556 | return -ENOMEM; |
557 | 557 | ||
558 | bus_req->address = address; | 558 | bus_req->address = address; |
@@ -915,6 +915,9 @@ static int ath6kl_sdio_suspend(struct ath6kl *ar, struct cfg80211_wowlan *wow) | |||
915 | } | 915 | } |
916 | 916 | ||
917 | cut_pwr: | 917 | cut_pwr: |
918 | if (func->card && func->card->host) | ||
919 | func->card->host->pm_flags &= ~MMC_PM_KEEP_POWER; | ||
920 | |||
918 | return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_CUTPOWER, NULL); | 921 | return ath6kl_cfg80211_suspend(ar, ATH6KL_CFG_SUSPEND_CUTPOWER, NULL); |
919 | } | 922 | } |
920 | 923 | ||
@@ -985,9 +988,8 @@ static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr) | |||
985 | } | 988 | } |
986 | 989 | ||
987 | if (status) { | 990 | if (status) { |
988 | ath6kl_err("%s: failed to write initial bytes of 0x%x " | 991 | ath6kl_err("%s: failed to write initial bytes of 0x%x to window reg: 0x%X\n", |
989 | "to window reg: 0x%X\n", __func__, | 992 | __func__, addr, reg_addr); |
990 | addr, reg_addr); | ||
991 | return status; | 993 | return status; |
992 | } | 994 | } |
993 | 995 | ||
@@ -1076,8 +1078,8 @@ static int ath6kl_sdio_bmi_credits(struct ath6kl *ar) | |||
1076 | (u8 *)&ar->bmi.cmd_credits, 4, | 1078 | (u8 *)&ar->bmi.cmd_credits, 4, |
1077 | HIF_RD_SYNC_BYTE_INC); | 1079 | HIF_RD_SYNC_BYTE_INC); |
1078 | if (ret) { | 1080 | if (ret) { |
1079 | ath6kl_err("Unable to decrement the command credit " | 1081 | ath6kl_err("Unable to decrement the command credit count register: %d\n", |
1080 | "count register: %d\n", ret); | 1082 | ret); |
1081 | return ret; | 1083 | return ret; |
1082 | } | 1084 | } |
1083 | 1085 | ||
@@ -1457,3 +1459,6 @@ MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE); | |||
1457 | MODULE_FIRMWARE(AR6004_HW_1_1_FW_DIR "/" AR6004_HW_1_1_FIRMWARE_FILE); | 1459 | MODULE_FIRMWARE(AR6004_HW_1_1_FW_DIR "/" AR6004_HW_1_1_FIRMWARE_FILE); |
1458 | MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); | 1460 | MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); |
1459 | MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); | 1461 | MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); |
1462 | MODULE_FIRMWARE(AR6004_HW_1_2_FW_DIR "/" AR6004_HW_1_2_FIRMWARE_FILE); | ||
1463 | MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE); | ||
1464 | MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE); | ||
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c index 82f2f5cb475b..67206aedea6c 100644 --- a/drivers/net/wireless/ath/ath6kl/txrx.c +++ b/drivers/net/wireless/ath/ath6kl/txrx.c | |||
@@ -362,15 +362,11 @@ int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev) | |||
362 | skb, skb->data, skb->len); | 362 | skb, skb->data, skb->len); |
363 | 363 | ||
364 | /* If target is not associated */ | 364 | /* If target is not associated */ |
365 | if (!test_bit(CONNECTED, &vif->flags)) { | 365 | if (!test_bit(CONNECTED, &vif->flags)) |
366 | dev_kfree_skb(skb); | 366 | goto fail_tx; |
367 | return 0; | ||
368 | } | ||
369 | 367 | ||
370 | if (WARN_ON_ONCE(ar->state != ATH6KL_STATE_ON)) { | 368 | if (WARN_ON_ONCE(ar->state != ATH6KL_STATE_ON)) |
371 | dev_kfree_skb(skb); | 369 | goto fail_tx; |
372 | return 0; | ||
373 | } | ||
374 | 370 | ||
375 | if (!test_bit(WMI_READY, &ar->flag)) | 371 | if (!test_bit(WMI_READY, &ar->flag)) |
376 | goto fail_tx; | 372 | goto fail_tx; |
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c index 44a795f14da9..3740c3d6ab88 100644 --- a/drivers/net/wireless/ath/ath6kl/usb.c +++ b/drivers/net/wireless/ath/ath6kl/usb.c | |||
@@ -1037,6 +1037,14 @@ static void ath6kl_usb_stop(struct ath6kl *ar) | |||
1037 | hif_stop(ar); | 1037 | hif_stop(ar); |
1038 | } | 1038 | } |
1039 | 1039 | ||
1040 | static void ath6kl_usb_cleanup_scatter(struct ath6kl *ar) | ||
1041 | { | ||
1042 | /* | ||
1043 | * USB doesn't support it. Just return. | ||
1044 | */ | ||
1045 | return; | ||
1046 | } | ||
1047 | |||
1040 | static const struct ath6kl_hif_ops ath6kl_usb_ops = { | 1048 | static const struct ath6kl_hif_ops ath6kl_usb_ops = { |
1041 | .diag_read32 = ath6kl_usb_diag_read32, | 1049 | .diag_read32 = ath6kl_usb_diag_read32, |
1042 | .diag_write32 = ath6kl_usb_diag_write32, | 1050 | .diag_write32 = ath6kl_usb_diag_write32, |
@@ -1049,6 +1057,7 @@ static const struct ath6kl_hif_ops ath6kl_usb_ops = { | |||
1049 | .pipe_get_default = ath6kl_usb_get_default_pipe, | 1057 | .pipe_get_default = ath6kl_usb_get_default_pipe, |
1050 | .pipe_map_service = ath6kl_usb_map_service_pipe, | 1058 | .pipe_map_service = ath6kl_usb_map_service_pipe, |
1051 | .pipe_get_free_queue_number = ath6kl_usb_get_free_queue_number, | 1059 | .pipe_get_free_queue_number = ath6kl_usb_get_free_queue_number, |
1060 | .cleanup_scatter = ath6kl_usb_cleanup_scatter, | ||
1052 | }; | 1061 | }; |
1053 | 1062 | ||
1054 | /* ath6kl usb driver registered functions */ | 1063 | /* ath6kl usb driver registered functions */ |
@@ -1208,3 +1217,6 @@ MODULE_FIRMWARE(AR6004_HW_1_0_DEFAULT_BOARD_DATA_FILE); | |||
1208 | MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE); | 1217 | MODULE_FIRMWARE(AR6004_HW_1_1_FIRMWARE_FILE); |
1209 | MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); | 1218 | MODULE_FIRMWARE(AR6004_HW_1_1_BOARD_DATA_FILE); |
1210 | MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); | 1219 | MODULE_FIRMWARE(AR6004_HW_1_1_DEFAULT_BOARD_DATA_FILE); |
1220 | MODULE_FIRMWARE(AR6004_HW_1_2_FIRMWARE_FILE); | ||
1221 | MODULE_FIRMWARE(AR6004_HW_1_2_BOARD_DATA_FILE); | ||
1222 | MODULE_FIRMWARE(AR6004_HW_1_2_DEFAULT_BOARD_DATA_FILE); | ||
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c index 7c8a9977faf5..ee8ec2394c2c 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.c +++ b/drivers/net/wireless/ath/ath6kl/wmi.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/ip.h> | 18 | #include <linux/ip.h> |
19 | #include <linux/in.h> | ||
19 | #include "core.h" | 20 | #include "core.h" |
20 | #include "debug.h" | 21 | #include "debug.h" |
21 | #include "testmode.h" | 22 | #include "testmode.h" |
@@ -289,6 +290,13 @@ int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, u8 if_idx, | |||
289 | layer2_priority); | 290 | layer2_priority); |
290 | } else | 291 | } else |
291 | usr_pri = layer2_priority & 0x7; | 292 | usr_pri = layer2_priority & 0x7; |
293 | |||
294 | /* | ||
295 | * Queue the EAPOL frames in the same WMM_AC_VO queue | ||
296 | * as that of management frames. | ||
297 | */ | ||
298 | if (skb->protocol == cpu_to_be16(ETH_P_PAE)) | ||
299 | usr_pri = WMI_VOICE_USER_PRIORITY; | ||
292 | } | 300 | } |
293 | 301 | ||
294 | /* | 302 | /* |
@@ -460,8 +468,9 @@ static int ath6kl_wmi_remain_on_chnl_event_rx(struct wmi *wmi, u8 *datap, | |||
460 | freq, dur); | 468 | freq, dur); |
461 | chan = ieee80211_get_channel(ar->wiphy, freq); | 469 | chan = ieee80211_get_channel(ar->wiphy, freq); |
462 | if (!chan) { | 470 | if (!chan) { |
463 | ath6kl_dbg(ATH6KL_DBG_WMI, "remain_on_chnl: Unknown channel " | 471 | ath6kl_dbg(ATH6KL_DBG_WMI, |
464 | "(freq=%u)\n", freq); | 472 | "remain_on_chnl: Unknown channel (freq=%u)\n", |
473 | freq); | ||
465 | return -EINVAL; | 474 | return -EINVAL; |
466 | } | 475 | } |
467 | id = vif->last_roc_id; | 476 | id = vif->last_roc_id; |
@@ -488,12 +497,14 @@ static int ath6kl_wmi_cancel_remain_on_chnl_event_rx(struct wmi *wmi, | |||
488 | ev = (struct wmi_cancel_remain_on_chnl_event *) datap; | 497 | ev = (struct wmi_cancel_remain_on_chnl_event *) datap; |
489 | freq = le32_to_cpu(ev->freq); | 498 | freq = le32_to_cpu(ev->freq); |
490 | dur = le32_to_cpu(ev->duration); | 499 | dur = le32_to_cpu(ev->duration); |
491 | ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: freq=%u dur=%u " | 500 | ath6kl_dbg(ATH6KL_DBG_WMI, |
492 | "status=%u\n", freq, dur, ev->status); | 501 | "cancel_remain_on_chnl: freq=%u dur=%u status=%u\n", |
502 | freq, dur, ev->status); | ||
493 | chan = ieee80211_get_channel(ar->wiphy, freq); | 503 | chan = ieee80211_get_channel(ar->wiphy, freq); |
494 | if (!chan) { | 504 | if (!chan) { |
495 | ath6kl_dbg(ATH6KL_DBG_WMI, "cancel_remain_on_chnl: Unknown " | 505 | ath6kl_dbg(ATH6KL_DBG_WMI, |
496 | "channel (freq=%u)\n", freq); | 506 | "cancel_remain_on_chnl: Unknown channel (freq=%u)\n", |
507 | freq); | ||
497 | return -EINVAL; | 508 | return -EINVAL; |
498 | } | 509 | } |
499 | if (vif->last_cancel_roc_id && | 510 | if (vif->last_cancel_roc_id && |
@@ -548,12 +559,12 @@ static int ath6kl_wmi_rx_probe_req_event_rx(struct wmi *wmi, u8 *datap, int len, | |||
548 | freq = le32_to_cpu(ev->freq); | 559 | freq = le32_to_cpu(ev->freq); |
549 | dlen = le16_to_cpu(ev->len); | 560 | dlen = le16_to_cpu(ev->len); |
550 | if (datap + len < ev->data + dlen) { | 561 | if (datap + len < ev->data + dlen) { |
551 | ath6kl_err("invalid wmi_p2p_rx_probe_req_event: " | 562 | ath6kl_err("invalid wmi_p2p_rx_probe_req_event: len=%d dlen=%u\n", |
552 | "len=%d dlen=%u\n", len, dlen); | 563 | len, dlen); |
553 | return -EINVAL; | 564 | return -EINVAL; |
554 | } | 565 | } |
555 | ath6kl_dbg(ATH6KL_DBG_WMI, "rx_probe_req: len=%u freq=%u " | 566 | ath6kl_dbg(ATH6KL_DBG_WMI, |
556 | "probe_req_report=%d\n", | 567 | "rx_probe_req: len=%u freq=%u probe_req_report=%d\n", |
557 | dlen, freq, vif->probe_req_report); | 568 | dlen, freq, vif->probe_req_report); |
558 | 569 | ||
559 | if (vif->probe_req_report || vif->nw_type == AP_NETWORK) | 570 | if (vif->probe_req_report || vif->nw_type == AP_NETWORK) |
@@ -592,8 +603,8 @@ static int ath6kl_wmi_rx_action_event_rx(struct wmi *wmi, u8 *datap, int len, | |||
592 | freq = le32_to_cpu(ev->freq); | 603 | freq = le32_to_cpu(ev->freq); |
593 | dlen = le16_to_cpu(ev->len); | 604 | dlen = le16_to_cpu(ev->len); |
594 | if (datap + len < ev->data + dlen) { | 605 | if (datap + len < ev->data + dlen) { |
595 | ath6kl_err("invalid wmi_rx_action_event: " | 606 | ath6kl_err("invalid wmi_rx_action_event: len=%d dlen=%u\n", |
596 | "len=%d dlen=%u\n", len, dlen); | 607 | len, dlen); |
597 | return -EINVAL; | 608 | return -EINVAL; |
598 | } | 609 | } |
599 | ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq); | 610 | ath6kl_dbg(ATH6KL_DBG_WMI, "rx_action: len=%u freq=%u\n", dlen, freq); |
@@ -687,7 +698,7 @@ static int ath6kl_wmi_ready_event_rx(struct wmi *wmi, u8 *datap, int len) | |||
687 | 698 | ||
688 | ath6kl_ready_event(wmi->parent_dev, ev->mac_addr, | 699 | ath6kl_ready_event(wmi->parent_dev, ev->mac_addr, |
689 | le32_to_cpu(ev->sw_version), | 700 | le32_to_cpu(ev->sw_version), |
690 | le32_to_cpu(ev->abi_version)); | 701 | le32_to_cpu(ev->abi_version), ev->phy_cap); |
691 | 702 | ||
692 | return 0; | 703 | return 0; |
693 | } | 704 | } |
@@ -777,16 +788,15 @@ static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len, | |||
777 | /* AP mode start/STA connected event */ | 788 | /* AP mode start/STA connected event */ |
778 | struct net_device *dev = vif->ndev; | 789 | struct net_device *dev = vif->ndev; |
779 | if (memcmp(dev->dev_addr, ev->u.ap_bss.bssid, ETH_ALEN) == 0) { | 790 | if (memcmp(dev->dev_addr, ev->u.ap_bss.bssid, ETH_ALEN) == 0) { |
780 | ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM " | 791 | ath6kl_dbg(ATH6KL_DBG_WMI, |
781 | "(AP started)\n", | 792 | "%s: freq %d bssid %pM (AP started)\n", |
782 | __func__, le16_to_cpu(ev->u.ap_bss.ch), | 793 | __func__, le16_to_cpu(ev->u.ap_bss.ch), |
783 | ev->u.ap_bss.bssid); | 794 | ev->u.ap_bss.bssid); |
784 | ath6kl_connect_ap_mode_bss( | 795 | ath6kl_connect_ap_mode_bss( |
785 | vif, le16_to_cpu(ev->u.ap_bss.ch)); | 796 | vif, le16_to_cpu(ev->u.ap_bss.ch)); |
786 | } else { | 797 | } else { |
787 | ath6kl_dbg(ATH6KL_DBG_WMI, "%s: aid %u mac_addr %pM " | 798 | ath6kl_dbg(ATH6KL_DBG_WMI, |
788 | "auth=%u keymgmt=%u cipher=%u apsd_info=%u " | 799 | "%s: aid %u mac_addr %pM auth=%u keymgmt=%u cipher=%u apsd_info=%u (STA connected)\n", |
789 | "(STA connected)\n", | ||
790 | __func__, ev->u.ap_sta.aid, | 800 | __func__, ev->u.ap_sta.aid, |
791 | ev->u.ap_sta.mac_addr, | 801 | ev->u.ap_sta.mac_addr, |
792 | ev->u.ap_sta.auth, | 802 | ev->u.ap_sta.auth, |
@@ -1229,8 +1239,9 @@ static int ath6kl_wmi_neighbor_report_event_rx(struct wmi *wmi, u8 *datap, | |||
1229 | ev = (struct wmi_neighbor_report_event *) datap; | 1239 | ev = (struct wmi_neighbor_report_event *) datap; |
1230 | if (sizeof(*ev) + ev->num_neighbors * sizeof(struct wmi_neighbor_info) | 1240 | if (sizeof(*ev) + ev->num_neighbors * sizeof(struct wmi_neighbor_info) |
1231 | > len) { | 1241 | > len) { |
1232 | ath6kl_dbg(ATH6KL_DBG_WMI, "truncated neighbor event " | 1242 | ath6kl_dbg(ATH6KL_DBG_WMI, |
1233 | "(num=%d len=%d)\n", ev->num_neighbors, len); | 1243 | "truncated neighbor event (num=%d len=%d)\n", |
1244 | ev->num_neighbors, len); | ||
1234 | return -EINVAL; | 1245 | return -EINVAL; |
1235 | } | 1246 | } |
1236 | for (i = 0; i < ev->num_neighbors; i++) { | 1247 | for (i = 0; i < ev->num_neighbors; i++) { |
@@ -1814,12 +1825,14 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx, | |||
1814 | u32 home_dwell_time, u32 force_scan_interval, | 1825 | u32 home_dwell_time, u32 force_scan_interval, |
1815 | s8 num_chan, u16 *ch_list, u32 no_cck, u32 *rates) | 1826 | s8 num_chan, u16 *ch_list, u32 no_cck, u32 *rates) |
1816 | { | 1827 | { |
1828 | struct ieee80211_supported_band *sband; | ||
1817 | struct sk_buff *skb; | 1829 | struct sk_buff *skb; |
1818 | struct wmi_begin_scan_cmd *sc; | 1830 | struct wmi_begin_scan_cmd *sc; |
1819 | s8 size; | 1831 | s8 size, *supp_rates; |
1820 | int i, band, ret; | 1832 | int i, band, ret; |
1821 | struct ath6kl *ar = wmi->parent_dev; | 1833 | struct ath6kl *ar = wmi->parent_dev; |
1822 | int num_rates; | 1834 | int num_rates; |
1835 | u32 ratemask; | ||
1823 | 1836 | ||
1824 | size = sizeof(struct wmi_begin_scan_cmd); | 1837 | size = sizeof(struct wmi_begin_scan_cmd); |
1825 | 1838 | ||
@@ -1846,10 +1859,13 @@ int ath6kl_wmi_beginscan_cmd(struct wmi *wmi, u8 if_idx, | |||
1846 | sc->num_ch = num_chan; | 1859 | sc->num_ch = num_chan; |
1847 | 1860 | ||
1848 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 1861 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
1849 | struct ieee80211_supported_band *sband = | 1862 | sband = ar->wiphy->bands[band]; |
1850 | ar->wiphy->bands[band]; | 1863 | |
1851 | u32 ratemask = rates[band]; | 1864 | if (!sband) |
1852 | u8 *supp_rates = sc->supp_rates[band].rates; | 1865 | continue; |
1866 | |||
1867 | ratemask = rates[band]; | ||
1868 | supp_rates = sc->supp_rates[band].rates; | ||
1853 | num_rates = 0; | 1869 | num_rates = 0; |
1854 | 1870 | ||
1855 | for (i = 0; i < sband->n_bitrates; i++) { | 1871 | for (i = 0; i < sband->n_bitrates; i++) { |
@@ -2129,8 +2145,8 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index, | |||
2129 | struct wmi_add_cipher_key_cmd *cmd; | 2145 | struct wmi_add_cipher_key_cmd *cmd; |
2130 | int ret; | 2146 | int ret; |
2131 | 2147 | ||
2132 | ath6kl_dbg(ATH6KL_DBG_WMI, "addkey cmd: key_index=%u key_type=%d " | 2148 | ath6kl_dbg(ATH6KL_DBG_WMI, |
2133 | "key_usage=%d key_len=%d key_op_ctrl=%d\n", | 2149 | "addkey cmd: key_index=%u key_type=%d key_usage=%d key_len=%d key_op_ctrl=%d\n", |
2134 | key_index, key_type, key_usage, key_len, key_op_ctrl); | 2150 | key_index, key_type, key_usage, key_len, key_op_ctrl); |
2135 | 2151 | ||
2136 | if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) || | 2152 | if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) || |
@@ -3047,8 +3063,8 @@ int ath6kl_wmi_ap_profile_commit(struct wmi *wmip, u8 if_idx, | |||
3047 | 3063 | ||
3048 | res = ath6kl_wmi_cmd_send(wmip, if_idx, skb, WMI_AP_CONFIG_COMMIT_CMDID, | 3064 | res = ath6kl_wmi_cmd_send(wmip, if_idx, skb, WMI_AP_CONFIG_COMMIT_CMDID, |
3049 | NO_SYNC_WMIFLAG); | 3065 | NO_SYNC_WMIFLAG); |
3050 | ath6kl_dbg(ATH6KL_DBG_WMI, "%s: nw_type=%u auth_mode=%u ch=%u " | 3066 | ath6kl_dbg(ATH6KL_DBG_WMI, |
3051 | "ctrl_flags=0x%x-> res=%d\n", | 3067 | "%s: nw_type=%u auth_mode=%u ch=%u ctrl_flags=0x%x-> res=%d\n", |
3052 | __func__, p->nw_type, p->auth_mode, le16_to_cpu(p->ch), | 3068 | __func__, p->nw_type, p->auth_mode, le16_to_cpu(p->ch), |
3053 | le32_to_cpu(p->ctrl_flags), res); | 3069 | le32_to_cpu(p->ctrl_flags), res); |
3054 | return res; | 3070 | return res; |
@@ -3208,8 +3224,9 @@ int ath6kl_wmi_set_appie_cmd(struct wmi *wmi, u8 if_idx, u8 mgmt_frm_type, | |||
3208 | if (!skb) | 3224 | if (!skb) |
3209 | return -ENOMEM; | 3225 | return -ENOMEM; |
3210 | 3226 | ||
3211 | ath6kl_dbg(ATH6KL_DBG_WMI, "set_appie_cmd: mgmt_frm_type=%u " | 3227 | ath6kl_dbg(ATH6KL_DBG_WMI, |
3212 | "ie_len=%u\n", mgmt_frm_type, ie_len); | 3228 | "set_appie_cmd: mgmt_frm_type=%u ie_len=%u\n", |
3229 | mgmt_frm_type, ie_len); | ||
3213 | p = (struct wmi_set_appie_cmd *) skb->data; | 3230 | p = (struct wmi_set_appie_cmd *) skb->data; |
3214 | p->mgmt_frm_type = mgmt_frm_type; | 3231 | p->mgmt_frm_type = mgmt_frm_type; |
3215 | p->ie_len = ie_len; | 3232 | p->ie_len = ie_len; |
@@ -3310,8 +3327,9 @@ static int ath6kl_wmi_send_action_cmd(struct wmi *wmi, u8 if_idx, u32 id, | |||
3310 | wmi->last_mgmt_tx_frame = buf; | 3327 | wmi->last_mgmt_tx_frame = buf; |
3311 | wmi->last_mgmt_tx_frame_len = data_len; | 3328 | wmi->last_mgmt_tx_frame_len = data_len; |
3312 | 3329 | ||
3313 | ath6kl_dbg(ATH6KL_DBG_WMI, "send_action_cmd: id=%u freq=%u wait=%u " | 3330 | ath6kl_dbg(ATH6KL_DBG_WMI, |
3314 | "len=%u\n", id, freq, wait, data_len); | 3331 | "send_action_cmd: id=%u freq=%u wait=%u len=%u\n", |
3332 | id, freq, wait, data_len); | ||
3315 | p = (struct wmi_send_action_cmd *) skb->data; | 3333 | p = (struct wmi_send_action_cmd *) skb->data; |
3316 | p->id = cpu_to_le32(id); | 3334 | p->id = cpu_to_le32(id); |
3317 | p->freq = cpu_to_le32(freq); | 3335 | p->freq = cpu_to_le32(freq); |
@@ -3348,8 +3366,9 @@ static int __ath6kl_wmi_send_mgmt_cmd(struct wmi *wmi, u8 if_idx, u32 id, | |||
3348 | wmi->last_mgmt_tx_frame = buf; | 3366 | wmi->last_mgmt_tx_frame = buf; |
3349 | wmi->last_mgmt_tx_frame_len = data_len; | 3367 | wmi->last_mgmt_tx_frame_len = data_len; |
3350 | 3368 | ||
3351 | ath6kl_dbg(ATH6KL_DBG_WMI, "send_action_cmd: id=%u freq=%u wait=%u " | 3369 | ath6kl_dbg(ATH6KL_DBG_WMI, |
3352 | "len=%u\n", id, freq, wait, data_len); | 3370 | "send_action_cmd: id=%u freq=%u wait=%u len=%u\n", |
3371 | id, freq, wait, data_len); | ||
3353 | p = (struct wmi_send_mgmt_cmd *) skb->data; | 3372 | p = (struct wmi_send_mgmt_cmd *) skb->data; |
3354 | p->id = cpu_to_le32(id); | 3373 | p->id = cpu_to_le32(id); |
3355 | p->freq = cpu_to_le32(freq); | 3374 | p->freq = cpu_to_le32(freq); |
@@ -3402,8 +3421,9 @@ int ath6kl_wmi_send_probe_response_cmd(struct wmi *wmi, u8 if_idx, u32 freq, | |||
3402 | if (!skb) | 3421 | if (!skb) |
3403 | return -ENOMEM; | 3422 | return -ENOMEM; |
3404 | 3423 | ||
3405 | ath6kl_dbg(ATH6KL_DBG_WMI, "send_probe_response_cmd: freq=%u dst=%pM " | 3424 | ath6kl_dbg(ATH6KL_DBG_WMI, |
3406 | "len=%u\n", freq, dst, data_len); | 3425 | "send_probe_response_cmd: freq=%u dst=%pM len=%u\n", |
3426 | freq, dst, data_len); | ||
3407 | p = (struct wmi_p2p_probe_response_cmd *) skb->data; | 3427 | p = (struct wmi_p2p_probe_response_cmd *) skb->data; |
3408 | p->freq = cpu_to_le32(freq); | 3428 | p->freq = cpu_to_le32(freq); |
3409 | memcpy(p->destination_addr, dst, ETH_ALEN); | 3429 | memcpy(p->destination_addr, dst, ETH_ALEN); |
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h index d3d2ab5c1689..9076bec3a2ba 100644 --- a/drivers/net/wireless/ath/ath6kl/wmi.h +++ b/drivers/net/wireless/ath/ath6kl/wmi.h | |||
@@ -106,6 +106,8 @@ struct wmi_data_sync_bufs { | |||
106 | #define WMM_AC_VI 2 /* video */ | 106 | #define WMM_AC_VI 2 /* video */ |
107 | #define WMM_AC_VO 3 /* voice */ | 107 | #define WMM_AC_VO 3 /* voice */ |
108 | 108 | ||
109 | #define WMI_VOICE_USER_PRIORITY 0x7 | ||
110 | |||
109 | struct wmi { | 111 | struct wmi { |
110 | u16 stream_exist_for_ac[WMM_NUM_AC]; | 112 | u16 stream_exist_for_ac[WMM_NUM_AC]; |
111 | u8 fat_pipe_exist; | 113 | u8 fat_pipe_exist; |
@@ -1151,6 +1153,7 @@ enum wmi_phy_mode { | |||
1151 | WMI_11AG_MODE = 0x3, | 1153 | WMI_11AG_MODE = 0x3, |
1152 | WMI_11B_MODE = 0x4, | 1154 | WMI_11B_MODE = 0x4, |
1153 | WMI_11GONLY_MODE = 0x5, | 1155 | WMI_11GONLY_MODE = 0x5, |
1156 | WMI_11G_HT20 = 0x6, | ||
1154 | }; | 1157 | }; |
1155 | 1158 | ||
1156 | #define WMI_MAX_CHANNELS 32 | 1159 | #define WMI_MAX_CHANNELS 32 |
@@ -1416,6 +1419,16 @@ struct wmi_ready_event_2 { | |||
1416 | u8 phy_cap; | 1419 | u8 phy_cap; |
1417 | } __packed; | 1420 | } __packed; |
1418 | 1421 | ||
1422 | /* WMI_PHY_CAPABILITY */ | ||
1423 | enum wmi_phy_cap { | ||
1424 | WMI_11A_CAP = 0x01, | ||
1425 | WMI_11G_CAP = 0x02, | ||
1426 | WMI_11AG_CAP = 0x03, | ||
1427 | WMI_11AN_CAP = 0x04, | ||
1428 | WMI_11GN_CAP = 0x05, | ||
1429 | WMI_11AGN_CAP = 0x06, | ||
1430 | }; | ||
1431 | |||
1419 | /* Connect Event */ | 1432 | /* Connect Event */ |
1420 | struct wmi_connect_event { | 1433 | struct wmi_connect_event { |
1421 | union { | 1434 | union { |
@@ -1468,6 +1481,17 @@ enum wmi_disconnect_reason { | |||
1468 | IBSS_MERGE = 0xe, | 1481 | IBSS_MERGE = 0xe, |
1469 | }; | 1482 | }; |
1470 | 1483 | ||
1484 | /* AP mode disconnect proto_reasons */ | ||
1485 | enum ap_disconnect_reason { | ||
1486 | WMI_AP_REASON_STA_LEFT = 101, | ||
1487 | WMI_AP_REASON_FROM_HOST = 102, | ||
1488 | WMI_AP_REASON_COMM_TIMEOUT = 103, | ||
1489 | WMI_AP_REASON_MAX_STA = 104, | ||
1490 | WMI_AP_REASON_ACL = 105, | ||
1491 | WMI_AP_REASON_STA_ROAM = 106, | ||
1492 | WMI_AP_REASON_DFS_CHANNEL = 107, | ||
1493 | }; | ||
1494 | |||
1471 | #define ATH6KL_COUNTRY_RD_SHIFT 16 | 1495 | #define ATH6KL_COUNTRY_RD_SHIFT 16 |
1472 | 1496 | ||
1473 | struct ath6kl_wmi_regdomain { | 1497 | struct ath6kl_wmi_regdomain { |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index a0387a027db0..9fdd70fcaf5b 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -892,34 +892,6 @@ static void ar9003_hw_tx_iq_cal_reload(struct ath_hw *ah) | |||
892 | AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1); | 892 | AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x1); |
893 | } | 893 | } |
894 | 894 | ||
895 | static bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan) | ||
896 | { | ||
897 | struct ath9k_rtt_hist *hist; | ||
898 | u32 *table; | ||
899 | int i; | ||
900 | bool restore; | ||
901 | |||
902 | if (!ah->caldata) | ||
903 | return false; | ||
904 | |||
905 | hist = &ah->caldata->rtt_hist; | ||
906 | if (!hist->num_readings) | ||
907 | return false; | ||
908 | |||
909 | ar9003_hw_rtt_enable(ah); | ||
910 | ar9003_hw_rtt_set_mask(ah, 0x00); | ||
911 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | ||
912 | if (!(ah->rxchainmask & (1 << i))) | ||
913 | continue; | ||
914 | table = &hist->table[i][hist->num_readings][0]; | ||
915 | ar9003_hw_rtt_load_hist(ah, i, table); | ||
916 | } | ||
917 | restore = ar9003_hw_rtt_force_restore(ah); | ||
918 | ar9003_hw_rtt_disable(ah); | ||
919 | |||
920 | return restore; | ||
921 | } | ||
922 | |||
923 | static bool ar9003_hw_init_cal(struct ath_hw *ah, | 895 | static bool ar9003_hw_init_cal(struct ath_hw *ah, |
924 | struct ath9k_channel *chan) | 896 | struct ath9k_channel *chan) |
925 | { | 897 | { |
@@ -942,9 +914,10 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
942 | if (!ar9003_hw_rtt_restore(ah, chan)) | 914 | if (!ar9003_hw_rtt_restore(ah, chan)) |
943 | run_rtt_cal = true; | 915 | run_rtt_cal = true; |
944 | 916 | ||
945 | ath_dbg(common, CALIBRATE, "RTT restore %s\n", | 917 | if (run_rtt_cal) |
946 | run_rtt_cal ? "failed" : "succeed"); | 918 | ath_dbg(common, CALIBRATE, "RTT calibration to be done\n"); |
947 | } | 919 | } |
920 | |||
948 | run_agc_cal = run_rtt_cal; | 921 | run_agc_cal = run_rtt_cal; |
949 | 922 | ||
950 | if (run_rtt_cal) { | 923 | if (run_rtt_cal) { |
@@ -1069,17 +1042,14 @@ skip_tx_iqcal: | |||
1069 | #undef CL_TAB_ENTRY | 1042 | #undef CL_TAB_ENTRY |
1070 | 1043 | ||
1071 | if (run_rtt_cal && caldata) { | 1044 | if (run_rtt_cal && caldata) { |
1072 | struct ath9k_rtt_hist *hist = &caldata->rtt_hist; | 1045 | if (is_reusable) { |
1073 | if (is_reusable && (hist->num_readings < RTT_HIST_MAX)) { | 1046 | if (!ath9k_hw_rfbus_req(ah)) |
1074 | u32 *table; | 1047 | ath_err(ath9k_hw_common(ah), |
1048 | "Could not stop baseband\n"); | ||
1049 | else | ||
1050 | ar9003_hw_rtt_fill_hist(ah); | ||
1075 | 1051 | ||
1076 | hist->num_readings++; | 1052 | ath9k_hw_rfbus_done(ah); |
1077 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | ||
1078 | if (!(ah->rxchainmask & (1 << i))) | ||
1079 | continue; | ||
1080 | table = &hist->table[i][hist->num_readings][0]; | ||
1081 | ar9003_hw_rtt_fill_hist(ah, i, table); | ||
1082 | } | ||
1083 | } | 1053 | } |
1084 | 1054 | ||
1085 | ar9003_hw_rtt_disable(ah); | 1055 | ar9003_hw_rtt_disable(ah); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c index 3cac293a2849..ffbb180f91e1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c | |||
@@ -756,7 +756,7 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
756 | if (caldata) { | 756 | if (caldata) { |
757 | caldata->done_txiqcal_once = false; | 757 | caldata->done_txiqcal_once = false; |
758 | caldata->done_txclcal_once = false; | 758 | caldata->done_txclcal_once = false; |
759 | caldata->rtt_hist.num_readings = 0; | 759 | caldata->rtt_done = false; |
760 | } | 760 | } |
761 | 761 | ||
762 | if (!ath9k_hw_init_cal(ah, chan)) | 762 | if (!ath9k_hw_init_cal(ah, chan)) |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_rtt.c b/drivers/net/wireless/ath/ath9k/ar9003_rtt.c index 458bedf0b0ae..74de3539c2c8 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_rtt.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_rtt.c | |||
@@ -15,6 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include "hw.h" | 17 | #include "hw.h" |
18 | #include "hw-ops.h" | ||
18 | #include "ar9003_phy.h" | 19 | #include "ar9003_phy.h" |
19 | #include "ar9003_rtt.h" | 20 | #include "ar9003_rtt.h" |
20 | 21 | ||
@@ -69,7 +70,7 @@ bool ar9003_hw_rtt_force_restore(struct ath_hw *ah) | |||
69 | } | 70 | } |
70 | 71 | ||
71 | static void ar9003_hw_rtt_load_hist_entry(struct ath_hw *ah, u8 chain, | 72 | static void ar9003_hw_rtt_load_hist_entry(struct ath_hw *ah, u8 chain, |
72 | u32 index, u32 data28) | 73 | u32 index, u32 data28) |
73 | { | 74 | { |
74 | u32 val; | 75 | u32 val; |
75 | 76 | ||
@@ -100,12 +101,21 @@ static void ar9003_hw_rtt_load_hist_entry(struct ath_hw *ah, u8 chain, | |||
100 | RTT_ACCESS_TIMEOUT); | 101 | RTT_ACCESS_TIMEOUT); |
101 | } | 102 | } |
102 | 103 | ||
103 | void ar9003_hw_rtt_load_hist(struct ath_hw *ah, u8 chain, u32 *table) | 104 | void ar9003_hw_rtt_load_hist(struct ath_hw *ah) |
104 | { | 105 | { |
105 | int i; | 106 | int chain, i; |
106 | 107 | ||
107 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) | 108 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { |
108 | ar9003_hw_rtt_load_hist_entry(ah, chain, i, table[i]); | 109 | if (!(ah->rxchainmask & (1 << chain))) |
110 | continue; | ||
111 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) { | ||
112 | ar9003_hw_rtt_load_hist_entry(ah, chain, i, | ||
113 | ah->caldata->rtt_table[chain][i]); | ||
114 | ath_dbg(ath9k_hw_common(ah), CALIBRATE, | ||
115 | "Load RTT value at idx %d, chain %d: 0x%x\n", | ||
116 | i, chain, ah->caldata->rtt_table[chain][i]); | ||
117 | } | ||
118 | } | ||
109 | } | 119 | } |
110 | 120 | ||
111 | static int ar9003_hw_rtt_fill_hist_entry(struct ath_hw *ah, u8 chain, u32 index) | 121 | static int ar9003_hw_rtt_fill_hist_entry(struct ath_hw *ah, u8 chain, u32 index) |
@@ -128,27 +138,71 @@ static int ar9003_hw_rtt_fill_hist_entry(struct ath_hw *ah, u8 chain, u32 index) | |||
128 | RTT_ACCESS_TIMEOUT)) | 138 | RTT_ACCESS_TIMEOUT)) |
129 | return RTT_BAD_VALUE; | 139 | return RTT_BAD_VALUE; |
130 | 140 | ||
131 | val = REG_READ(ah, AR_PHY_RTT_TABLE_SW_INTF_1_B(chain)); | 141 | val = MS(REG_READ(ah, AR_PHY_RTT_TABLE_SW_INTF_1_B(chain)), |
142 | AR_PHY_RTT_SW_RTT_TABLE_DATA); | ||
143 | |||
132 | 144 | ||
133 | return val; | 145 | return val; |
134 | } | 146 | } |
135 | 147 | ||
136 | void ar9003_hw_rtt_fill_hist(struct ath_hw *ah, u8 chain, u32 *table) | 148 | void ar9003_hw_rtt_fill_hist(struct ath_hw *ah) |
137 | { | 149 | { |
138 | int i; | 150 | int chain, i; |
151 | |||
152 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { | ||
153 | if (!(ah->rxchainmask & (1 << chain))) | ||
154 | continue; | ||
155 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) { | ||
156 | ah->caldata->rtt_table[chain][i] = | ||
157 | ar9003_hw_rtt_fill_hist_entry(ah, chain, i); | ||
158 | ath_dbg(ath9k_hw_common(ah), CALIBRATE, | ||
159 | "RTT value at idx %d, chain %d is: 0x%x\n", | ||
160 | i, chain, ah->caldata->rtt_table[chain][i]); | ||
161 | } | ||
162 | } | ||
139 | 163 | ||
140 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) | 164 | ah->caldata->rtt_done = true; |
141 | table[i] = ar9003_hw_rtt_fill_hist_entry(ah, chain, i); | ||
142 | } | 165 | } |
143 | 166 | ||
144 | void ar9003_hw_rtt_clear_hist(struct ath_hw *ah) | 167 | void ar9003_hw_rtt_clear_hist(struct ath_hw *ah) |
145 | { | 168 | { |
146 | int i, j; | 169 | int chain, i; |
147 | 170 | ||
148 | for (i = 0; i < AR9300_MAX_CHAINS; i++) { | 171 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { |
149 | if (!(ah->rxchainmask & (1 << i))) | 172 | if (!(ah->rxchainmask & (1 << chain))) |
150 | continue; | 173 | continue; |
151 | for (j = 0; j < MAX_RTT_TABLE_ENTRY; j++) | 174 | for (i = 0; i < MAX_RTT_TABLE_ENTRY; i++) |
152 | ar9003_hw_rtt_load_hist_entry(ah, i, j, 0); | 175 | ar9003_hw_rtt_load_hist_entry(ah, chain, i, 0); |
153 | } | 176 | } |
177 | |||
178 | if (ah->caldata) | ||
179 | ah->caldata->rtt_done = false; | ||
180 | } | ||
181 | |||
182 | bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan) | ||
183 | { | ||
184 | bool restore; | ||
185 | |||
186 | if (!ah->caldata) | ||
187 | return false; | ||
188 | |||
189 | if (!ah->caldata->rtt_done) | ||
190 | return false; | ||
191 | |||
192 | ar9003_hw_rtt_enable(ah); | ||
193 | ar9003_hw_rtt_set_mask(ah, 0x10); | ||
194 | |||
195 | if (!ath9k_hw_rfbus_req(ah)) { | ||
196 | ath_err(ath9k_hw_common(ah), "Could not stop baseband\n"); | ||
197 | restore = false; | ||
198 | goto fail; | ||
199 | } | ||
200 | |||
201 | ar9003_hw_rtt_load_hist(ah); | ||
202 | restore = ar9003_hw_rtt_force_restore(ah); | ||
203 | |||
204 | fail: | ||
205 | ath9k_hw_rfbus_done(ah); | ||
206 | ar9003_hw_rtt_disable(ah); | ||
207 | return restore; | ||
154 | } | 208 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_rtt.h b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h index 030758d087d6..a43b30d723a4 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_rtt.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h | |||
@@ -21,8 +21,9 @@ void ar9003_hw_rtt_enable(struct ath_hw *ah); | |||
21 | void ar9003_hw_rtt_disable(struct ath_hw *ah); | 21 | void ar9003_hw_rtt_disable(struct ath_hw *ah); |
22 | void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask); | 22 | void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask); |
23 | bool ar9003_hw_rtt_force_restore(struct ath_hw *ah); | 23 | bool ar9003_hw_rtt_force_restore(struct ath_hw *ah); |
24 | void ar9003_hw_rtt_load_hist(struct ath_hw *ah, u8 chain, u32 *table); | 24 | void ar9003_hw_rtt_load_hist(struct ath_hw *ah); |
25 | void ar9003_hw_rtt_fill_hist(struct ath_hw *ah, u8 chain, u32 *table); | 25 | void ar9003_hw_rtt_fill_hist(struct ath_hw *ah); |
26 | void ar9003_hw_rtt_clear_hist(struct ath_hw *ah); | 26 | void ar9003_hw_rtt_clear_hist(struct ath_hw *ah); |
27 | bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan); | ||
27 | 28 | ||
28 | #endif | 29 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index f84477c5ebb1..abe05ec85d50 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1702,10 +1702,10 @@ static int ath9k_hw_do_fastcc(struct ath_hw *ah, struct ath9k_channel *chan) | |||
1702 | * For AR9462, make sure that calibration data for | 1702 | * For AR9462, make sure that calibration data for |
1703 | * re-using are present. | 1703 | * re-using are present. |
1704 | */ | 1704 | */ |
1705 | if (AR_SREV_9462(ah) && (!ah->caldata || | 1705 | if (AR_SREV_9462(ah) && (ah->caldata && |
1706 | !ah->caldata->done_txiqcal_once || | 1706 | (!ah->caldata->done_txiqcal_once || |
1707 | !ah->caldata->done_txclcal_once || | 1707 | !ah->caldata->done_txclcal_once || |
1708 | !ah->caldata->rtt_hist.num_readings)) | 1708 | !ah->caldata->rtt_done))) |
1709 | goto fail; | 1709 | goto fail; |
1710 | 1710 | ||
1711 | ath_dbg(common, RESET, "FastChannelChange for %d -> %d\n", | 1711 | ath_dbg(common, RESET, "FastChannelChange for %d -> %d\n", |
@@ -1941,7 +1941,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1941 | if (caldata) { | 1941 | if (caldata) { |
1942 | caldata->done_txiqcal_once = false; | 1942 | caldata->done_txiqcal_once = false; |
1943 | caldata->done_txclcal_once = false; | 1943 | caldata->done_txclcal_once = false; |
1944 | caldata->rtt_hist.num_readings = 0; | ||
1945 | } | 1944 | } |
1946 | if (!ath9k_hw_init_cal(ah, chan)) | 1945 | if (!ath9k_hw_init_cal(ah, chan)) |
1947 | return -EIO; | 1946 | return -EIO; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 828b9bbc456d..b620c557c2a6 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -348,12 +348,6 @@ enum ath9k_int { | |||
348 | CHANNEL_HT40MINUS) | 348 | CHANNEL_HT40MINUS) |
349 | 349 | ||
350 | #define MAX_RTT_TABLE_ENTRY 6 | 350 | #define MAX_RTT_TABLE_ENTRY 6 |
351 | #define RTT_HIST_MAX 3 | ||
352 | struct ath9k_rtt_hist { | ||
353 | u32 table[AR9300_MAX_CHAINS][RTT_HIST_MAX][MAX_RTT_TABLE_ENTRY]; | ||
354 | u8 num_readings; | ||
355 | }; | ||
356 | |||
357 | #define MAX_IQCAL_MEASUREMENT 8 | 351 | #define MAX_IQCAL_MEASUREMENT 8 |
358 | #define MAX_CL_TAB_ENTRY 16 | 352 | #define MAX_CL_TAB_ENTRY 16 |
359 | 353 | ||
@@ -363,6 +357,7 @@ struct ath9k_hw_cal_data { | |||
363 | int32_t CalValid; | 357 | int32_t CalValid; |
364 | int8_t iCoff; | 358 | int8_t iCoff; |
365 | int8_t qCoff; | 359 | int8_t qCoff; |
360 | bool rtt_done; | ||
366 | bool paprd_done; | 361 | bool paprd_done; |
367 | bool nfcal_pending; | 362 | bool nfcal_pending; |
368 | bool nfcal_interference; | 363 | bool nfcal_interference; |
@@ -373,8 +368,8 @@ struct ath9k_hw_cal_data { | |||
373 | u32 num_measures[AR9300_MAX_CHAINS]; | 368 | u32 num_measures[AR9300_MAX_CHAINS]; |
374 | int tx_corr_coeff[MAX_IQCAL_MEASUREMENT][AR9300_MAX_CHAINS]; | 369 | int tx_corr_coeff[MAX_IQCAL_MEASUREMENT][AR9300_MAX_CHAINS]; |
375 | u32 tx_clcal[AR9300_MAX_CHAINS][MAX_CL_TAB_ENTRY]; | 370 | u32 tx_clcal[AR9300_MAX_CHAINS][MAX_CL_TAB_ENTRY]; |
371 | u32 rtt_table[AR9300_MAX_CHAINS][MAX_RTT_TABLE_ENTRY]; | ||
376 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; | 372 | struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; |
377 | struct ath9k_rtt_hist rtt_hist; | ||
378 | }; | 373 | }; |
379 | 374 | ||
380 | struct ath9k_channel { | 375 | struct ath9k_channel { |
diff --git a/drivers/net/wireless/b43/bus.c b/drivers/net/wireless/b43/bus.c index 424692df239d..565fdbdd6915 100644 --- a/drivers/net/wireless/b43/bus.c +++ b/drivers/net/wireless/b43/bus.c | |||
@@ -107,11 +107,9 @@ struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core) | |||
107 | dev->dma_dev = core->dma_dev; | 107 | dev->dma_dev = core->dma_dev; |
108 | dev->irq = core->irq; | 108 | dev->irq = core->irq; |
109 | 109 | ||
110 | /* | ||
111 | dev->board_vendor = core->bus->boardinfo.vendor; | 110 | dev->board_vendor = core->bus->boardinfo.vendor; |
112 | dev->board_type = core->bus->boardinfo.type; | 111 | dev->board_type = core->bus->boardinfo.type; |
113 | dev->board_rev = core->bus->boardinfo.rev; | 112 | dev->board_rev = core->bus->sprom.board_rev; |
114 | */ | ||
115 | 113 | ||
116 | dev->chip_id = core->bus->chipinfo.id; | 114 | dev->chip_id = core->bus->chipinfo.id; |
117 | dev->chip_rev = core->bus->chipinfo.rev; | 115 | dev->chip_rev = core->bus->chipinfo.rev; |
@@ -210,7 +208,7 @@ struct b43_bus_dev *b43_bus_dev_ssb_init(struct ssb_device *sdev) | |||
210 | 208 | ||
211 | dev->board_vendor = sdev->bus->boardinfo.vendor; | 209 | dev->board_vendor = sdev->bus->boardinfo.vendor; |
212 | dev->board_type = sdev->bus->boardinfo.type; | 210 | dev->board_type = sdev->bus->boardinfo.type; |
213 | dev->board_rev = sdev->bus->boardinfo.rev; | 211 | dev->board_rev = sdev->bus->sprom.board_rev; |
214 | 212 | ||
215 | dev->chip_id = sdev->bus->chip_id; | 213 | dev->chip_id = sdev->bus->chip_id; |
216 | dev->chip_rev = sdev->bus->chip_rev; | 214 | dev->chip_rev = sdev->bus->chip_rev; |
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index b5f1b91002bb..777cd74921d7 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c | |||
@@ -1109,7 +1109,7 @@ static bool b43_dma_translation_in_low_word(struct b43_wldev *dev, | |||
1109 | #ifdef CONFIG_B43_SSB | 1109 | #ifdef CONFIG_B43_SSB |
1110 | if (dev->dev->bus_type == B43_BUS_SSB && | 1110 | if (dev->dev->bus_type == B43_BUS_SSB && |
1111 | dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI && | 1111 | dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI && |
1112 | !(dev->dev->sdev->bus->host_pci->is_pcie && | 1112 | !(pci_is_pcie(dev->dev->sdev->bus->host_pci) && |
1113 | ssb_read32(dev->dev->sdev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64)) | 1113 | ssb_read32(dev->dev->sdev, SSB_TMSHIGH) & SSB_TMSHIGH_DMA64)) |
1114 | return 1; | 1114 | return 1; |
1115 | #endif | 1115 | #endif |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 617afc8211b2..5a39b226b2e3 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -5243,10 +5243,10 @@ static void b43_sprom_fixup(struct ssb_bus *bus) | |||
5243 | 5243 | ||
5244 | /* boardflags workarounds */ | 5244 | /* boardflags workarounds */ |
5245 | if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL && | 5245 | if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL && |
5246 | bus->chip_id == 0x4301 && bus->boardinfo.rev == 0x74) | 5246 | bus->chip_id == 0x4301 && bus->sprom.board_rev == 0x74) |
5247 | bus->sprom.boardflags_lo |= B43_BFL_BTCOEXIST; | 5247 | bus->sprom.boardflags_lo |= B43_BFL_BTCOEXIST; |
5248 | if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && | 5248 | if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && |
5249 | bus->boardinfo.type == 0x4E && bus->boardinfo.rev > 0x40) | 5249 | bus->boardinfo.type == 0x4E && bus->sprom.board_rev > 0x40) |
5250 | bus->sprom.boardflags_lo |= B43_BFL_PACTRL; | 5250 | bus->sprom.boardflags_lo |= B43_BFL_PACTRL; |
5251 | if (bus->bustype == SSB_BUSTYPE_PCI) { | 5251 | if (bus->bustype == SSB_BUSTYPE_PCI) { |
5252 | pdev = bus->host_pci; | 5252 | pdev = bus->host_pci; |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 1be214b815fb..cd9c9bc186d9 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -1573,8 +1573,6 @@ static void b43legacy_request_firmware(struct work_struct *work) | |||
1573 | const char *filename; | 1573 | const char *filename; |
1574 | int err; | 1574 | int err; |
1575 | 1575 | ||
1576 | /* do dummy read */ | ||
1577 | ssb_read32(dev->dev, SSB_TMSHIGH); | ||
1578 | if (!fw->ucode) { | 1576 | if (!fw->ucode) { |
1579 | if (rev == 2) | 1577 | if (rev == 2) |
1580 | filename = "ucode2"; | 1578 | filename = "ucode2"; |
@@ -3781,7 +3779,7 @@ static void b43legacy_sprom_fixup(struct ssb_bus *bus) | |||
3781 | /* boardflags workarounds */ | 3779 | /* boardflags workarounds */ |
3782 | if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && | 3780 | if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && |
3783 | bus->boardinfo.type == 0x4E && | 3781 | bus->boardinfo.type == 0x4E && |
3784 | bus->boardinfo.rev > 0x40) | 3782 | bus->sprom.board_rev > 0x40) |
3785 | bus->sprom.boardflags_lo |= B43legacy_BFL_PACTRL; | 3783 | bus->sprom.boardflags_lo |= B43legacy_BFL_PACTRL; |
3786 | } | 3784 | } |
3787 | 3785 | ||
diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c index 950334197f40..995c7d0c212a 100644 --- a/drivers/net/wireless/b43legacy/phy.c +++ b/drivers/net/wireless/b43legacy/phy.c | |||
@@ -408,7 +408,7 @@ static void b43legacy_phy_setupg(struct b43legacy_wldev *dev) | |||
408 | 408 | ||
409 | if (is_bcm_board_vendor(dev) && | 409 | if (is_bcm_board_vendor(dev) && |
410 | (dev->dev->bus->boardinfo.type == 0x0416) && | 410 | (dev->dev->bus->boardinfo.type == 0x0416) && |
411 | (dev->dev->bus->boardinfo.rev == 0x0017)) | 411 | (dev->dev->bus->sprom.board_rev == 0x0017)) |
412 | return; | 412 | return; |
413 | 413 | ||
414 | b43legacy_ilt_write(dev, 0x5001, 0x0002); | 414 | b43legacy_ilt_write(dev, 0x5001, 0x0002); |
@@ -424,7 +424,7 @@ static void b43legacy_phy_setupg(struct b43legacy_wldev *dev) | |||
424 | 424 | ||
425 | if (is_bcm_board_vendor(dev) && | 425 | if (is_bcm_board_vendor(dev) && |
426 | (dev->dev->bus->boardinfo.type == 0x0416) && | 426 | (dev->dev->bus->boardinfo.type == 0x0416) && |
427 | (dev->dev->bus->boardinfo.rev == 0x0017)) | 427 | (dev->dev->bus->sprom.board_rev == 0x0017)) |
428 | return; | 428 | return; |
429 | 429 | ||
430 | b43legacy_ilt_write(dev, 0x0401, 0x0002); | 430 | b43legacy_ilt_write(dev, 0x0401, 0x0002); |
diff --git a/drivers/net/wireless/b43legacy/radio.c b/drivers/net/wireless/b43legacy/radio.c index fcbafcd603cc..896177690394 100644 --- a/drivers/net/wireless/b43legacy/radio.c +++ b/drivers/net/wireless/b43legacy/radio.c | |||
@@ -1998,7 +1998,7 @@ u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev) | |||
1998 | if (phy->type == B43legacy_PHYTYPE_G) { | 1998 | if (phy->type == B43legacy_PHYTYPE_G) { |
1999 | if (is_bcm_board_vendor(dev) && | 1999 | if (is_bcm_board_vendor(dev) && |
2000 | dev->dev->bus->boardinfo.type == 0x421 && | 2000 | dev->dev->bus->boardinfo.type == 0x421 && |
2001 | dev->dev->bus->boardinfo.rev >= 30) | 2001 | dev->dev->bus->sprom.board_rev >= 30) |
2002 | att = 3; | 2002 | att = 3; |
2003 | else if (is_bcm_board_vendor(dev) && | 2003 | else if (is_bcm_board_vendor(dev) && |
2004 | dev->dev->bus->boardinfo.type == 0x416) | 2004 | dev->dev->bus->boardinfo.type == 0x416) |
@@ -2008,7 +2008,7 @@ u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev) | |||
2008 | } else { | 2008 | } else { |
2009 | if (is_bcm_board_vendor(dev) && | 2009 | if (is_bcm_board_vendor(dev) && |
2010 | dev->dev->bus->boardinfo.type == 0x421 && | 2010 | dev->dev->bus->boardinfo.type == 0x421 && |
2011 | dev->dev->bus->boardinfo.rev >= 30) | 2011 | dev->dev->bus->sprom.board_rev >= 30) |
2012 | att = 7; | 2012 | att = 7; |
2013 | else | 2013 | else |
2014 | att = 6; | 2014 | att = 6; |
@@ -2018,7 +2018,7 @@ u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev) | |||
2018 | if (phy->type == B43legacy_PHYTYPE_G) { | 2018 | if (phy->type == B43legacy_PHYTYPE_G) { |
2019 | if (is_bcm_board_vendor(dev) && | 2019 | if (is_bcm_board_vendor(dev) && |
2020 | dev->dev->bus->boardinfo.type == 0x421 && | 2020 | dev->dev->bus->boardinfo.type == 0x421 && |
2021 | dev->dev->bus->boardinfo.rev >= 30) | 2021 | dev->dev->bus->sprom.board_rev >= 30) |
2022 | att = 3; | 2022 | att = 3; |
2023 | else if (is_bcm_board_vendor(dev) && | 2023 | else if (is_bcm_board_vendor(dev) && |
2024 | dev->dev->bus->boardinfo.type == | 2024 | dev->dev->bus->boardinfo.type == |
@@ -2052,9 +2052,9 @@ u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev) | |||
2052 | } | 2052 | } |
2053 | if (is_bcm_board_vendor(dev) && | 2053 | if (is_bcm_board_vendor(dev) && |
2054 | dev->dev->bus->boardinfo.type == 0x421) { | 2054 | dev->dev->bus->boardinfo.type == 0x421) { |
2055 | if (dev->dev->bus->boardinfo.rev < 0x43) | 2055 | if (dev->dev->bus->sprom.board_rev < 0x43) |
2056 | att = 2; | 2056 | att = 2; |
2057 | else if (dev->dev->bus->boardinfo.rev < 0x51) | 2057 | else if (dev->dev->bus->sprom.board_rev < 0x51) |
2058 | att = 3; | 2058 | att = 3; |
2059 | } | 2059 | } |
2060 | if (att == 0xFFFF) | 2060 | if (att == 0xFFFF) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 4add7da24681..e2480d196276 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -85,18 +85,15 @@ int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev) | |||
85 | sdiodev->irq_wake = true; | 85 | sdiodev->irq_wake = true; |
86 | 86 | ||
87 | /* must configure SDIO_CCCR_IENx to enable irq */ | 87 | /* must configure SDIO_CCCR_IENx to enable irq */ |
88 | data = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_0, | 88 | data = brcmf_sdio_regrb(sdiodev, SDIO_CCCR_IENx, &ret); |
89 | SDIO_CCCR_IENx, &ret); | ||
90 | data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; | 89 | data |= 1 << SDIO_FUNC_1 | 1 << SDIO_FUNC_2 | 1; |
91 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx, | 90 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, data, &ret); |
92 | data, &ret); | ||
93 | 91 | ||
94 | /* redirect, configure ane enable io for interrupt signal */ | 92 | /* redirect, configure ane enable io for interrupt signal */ |
95 | data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; | 93 | data = SDIO_SEPINT_MASK | SDIO_SEPINT_OE; |
96 | if (sdiodev->irq_flags | IRQF_TRIGGER_HIGH) | 94 | if (sdiodev->irq_flags | IRQF_TRIGGER_HIGH) |
97 | data |= SDIO_SEPINT_ACT_HI; | 95 | data |= SDIO_SEPINT_ACT_HI; |
98 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_BRCM_SEPINT, | 96 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, data, &ret); |
99 | data, &ret); | ||
100 | 97 | ||
101 | return 0; | 98 | return 0; |
102 | } | 99 | } |
@@ -105,9 +102,8 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) | |||
105 | { | 102 | { |
106 | brcmf_dbg(TRACE, "Entering\n"); | 103 | brcmf_dbg(TRACE, "Entering\n"); |
107 | 104 | ||
108 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_BRCM_SEPINT, | 105 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_BRCM_SEPINT, 0, NULL); |
109 | 0, NULL); | 106 | brcmf_sdio_regwb(sdiodev, SDIO_CCCR_IENx, 0, NULL); |
110 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_0, SDIO_CCCR_IENx, 0, NULL); | ||
111 | 107 | ||
112 | if (sdiodev->irq_wake) { | 108 | if (sdiodev->irq_wake) { |
113 | disable_irq_wake(sdiodev->irq); | 109 | disable_irq_wake(sdiodev->irq); |
@@ -158,153 +154,147 @@ int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev) | |||
158 | } | 154 | } |
159 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ | 155 | #endif /* CONFIG_BRCMFMAC_SDIO_OOB */ |
160 | 156 | ||
161 | u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr, | ||
162 | int *err) | ||
163 | { | ||
164 | int status; | ||
165 | s32 retry = 0; | ||
166 | u8 data = 0; | ||
167 | |||
168 | do { | ||
169 | if (retry) /* wait for 1 ms till bus get settled down */ | ||
170 | udelay(1000); | ||
171 | status = brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, fnc_num, | ||
172 | addr, (u8 *) &data); | ||
173 | } while (status != 0 | ||
174 | && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); | ||
175 | if (err) | ||
176 | *err = status; | ||
177 | |||
178 | brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n", | ||
179 | fnc_num, addr, data); | ||
180 | |||
181 | return data; | ||
182 | } | ||
183 | |||
184 | void | ||
185 | brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint fnc_num, u32 addr, | ||
186 | u8 data, int *err) | ||
187 | { | ||
188 | int status; | ||
189 | s32 retry = 0; | ||
190 | |||
191 | do { | ||
192 | if (retry) /* wait for 1 ms till bus get settled down */ | ||
193 | udelay(1000); | ||
194 | status = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, fnc_num, | ||
195 | addr, (u8 *) &data); | ||
196 | } while (status != 0 | ||
197 | && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); | ||
198 | if (err) | ||
199 | *err = status; | ||
200 | |||
201 | brcmf_dbg(INFO, "fun = %d, addr = 0x%x, u8data = 0x%x\n", | ||
202 | fnc_num, addr, data); | ||
203 | } | ||
204 | |||
205 | int | 157 | int |
206 | brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) | 158 | brcmf_sdcard_set_sbaddr_window(struct brcmf_sdio_dev *sdiodev, u32 address) |
207 | { | 159 | { |
208 | int err = 0; | 160 | int err = 0, i; |
209 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, | 161 | u8 addr[3]; |
210 | (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err); | 162 | s32 retry; |
211 | if (!err) | 163 | |
212 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, | 164 | addr[0] = (address >> 8) & SBSDIO_SBADDRLOW_MASK; |
213 | SBSDIO_FUNC1_SBADDRMID, | 165 | addr[1] = (address >> 16) & SBSDIO_SBADDRMID_MASK; |
214 | (address >> 16) & SBSDIO_SBADDRMID_MASK, | 166 | addr[2] = (address >> 24) & SBSDIO_SBADDRHIGH_MASK; |
215 | &err); | 167 | |
216 | if (!err) | 168 | for (i = 0; i < 3; i++) { |
217 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, | 169 | retry = 0; |
218 | SBSDIO_FUNC1_SBADDRHIGH, | 170 | do { |
219 | (address >> 24) & SBSDIO_SBADDRHIGH_MASK, | 171 | if (retry) |
220 | &err); | 172 | usleep_range(1000, 2000); |
173 | err = brcmf_sdioh_request_byte(sdiodev, SDIOH_WRITE, | ||
174 | SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW + i, | ||
175 | &addr[i]); | ||
176 | } while (err != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); | ||
177 | |||
178 | if (err) { | ||
179 | brcmf_dbg(ERROR, "failed at addr:0x%0x\n", | ||
180 | SBSDIO_FUNC1_SBADDRLOW + i); | ||
181 | break; | ||
182 | } | ||
183 | } | ||
221 | 184 | ||
222 | return err; | 185 | return err; |
223 | } | 186 | } |
224 | 187 | ||
225 | u32 brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size) | 188 | static int |
189 | brcmf_sdio_regrw_helper(struct brcmf_sdio_dev *sdiodev, u32 addr, | ||
190 | void *data, bool write) | ||
226 | { | 191 | { |
227 | int status; | 192 | u8 func_num, reg_size; |
228 | u32 word = 0; | 193 | u32 bar; |
229 | uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; | 194 | s32 retry = 0; |
230 | 195 | int ret; | |
231 | brcmf_dbg(INFO, "fun = 1, addr = 0x%x\n", addr); | ||
232 | |||
233 | if (bar0 != sdiodev->sbwad) { | ||
234 | if (brcmf_sdcard_set_sbaddr_window(sdiodev, bar0)) | ||
235 | return 0xFFFFFFFF; | ||
236 | 196 | ||
237 | sdiodev->sbwad = bar0; | 197 | /* |
198 | * figure out how to read the register based on address range | ||
199 | * 0x00 ~ 0x7FF: function 0 CCCR and FBR | ||
200 | * 0x10000 ~ 0x1FFFF: function 1 miscellaneous registers | ||
201 | * The rest: function 1 silicon backplane core registers | ||
202 | */ | ||
203 | if ((addr & ~REG_F0_REG_MASK) == 0) { | ||
204 | func_num = SDIO_FUNC_0; | ||
205 | reg_size = 1; | ||
206 | } else if ((addr & ~REG_F1_MISC_MASK) == 0) { | ||
207 | func_num = SDIO_FUNC_1; | ||
208 | reg_size = 1; | ||
209 | } else { | ||
210 | func_num = SDIO_FUNC_1; | ||
211 | reg_size = 4; | ||
212 | |||
213 | /* Set the window for SB core register */ | ||
214 | bar = addr & ~SBSDIO_SB_OFT_ADDR_MASK; | ||
215 | if (bar != sdiodev->sbwad) { | ||
216 | ret = brcmf_sdcard_set_sbaddr_window(sdiodev, bar); | ||
217 | if (ret != 0) { | ||
218 | memset(data, 0xFF, reg_size); | ||
219 | return ret; | ||
220 | } | ||
221 | sdiodev->sbwad = bar; | ||
222 | } | ||
223 | addr &= SBSDIO_SB_OFT_ADDR_MASK; | ||
224 | addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; | ||
238 | } | 225 | } |
239 | 226 | ||
240 | addr &= SBSDIO_SB_OFT_ADDR_MASK; | 227 | do { |
241 | if (size == 4) | 228 | if (!write) |
242 | addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; | 229 | memset(data, 0, reg_size); |
230 | if (retry) /* wait for 1 ms till bus get settled down */ | ||
231 | usleep_range(1000, 2000); | ||
232 | if (reg_size == 1) | ||
233 | ret = brcmf_sdioh_request_byte(sdiodev, write, | ||
234 | func_num, addr, data); | ||
235 | else | ||
236 | ret = brcmf_sdioh_request_word(sdiodev, write, | ||
237 | func_num, addr, data, 4); | ||
238 | } while (ret != 0 && retry++ < SDIOH_API_ACCESS_RETRY_LIMIT); | ||
243 | 239 | ||
244 | status = brcmf_sdioh_request_word(sdiodev, SDIOH_READ, SDIO_FUNC_1, | 240 | if (ret != 0) |
245 | addr, &word, size); | 241 | brcmf_dbg(ERROR, "failed with %d\n", ret); |
246 | 242 | ||
247 | sdiodev->regfail = (status != 0); | 243 | return ret; |
244 | } | ||
248 | 245 | ||
249 | brcmf_dbg(INFO, "u32data = 0x%x\n", word); | 246 | u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) |
247 | { | ||
248 | u8 data; | ||
249 | int retval; | ||
250 | 250 | ||
251 | /* if ok, return appropriately masked word */ | 251 | brcmf_dbg(INFO, "addr:0x%08x\n", addr); |
252 | if (status == 0) { | 252 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); |
253 | switch (size) { | 253 | brcmf_dbg(INFO, "data:0x%02x\n", data); |
254 | case sizeof(u8): | ||
255 | return word & 0xff; | ||
256 | case sizeof(u16): | ||
257 | return word & 0xffff; | ||
258 | case sizeof(u32): | ||
259 | return word; | ||
260 | default: | ||
261 | sdiodev->regfail = true; | ||
262 | 254 | ||
263 | } | 255 | if (ret) |
264 | } | 256 | *ret = retval; |
265 | 257 | ||
266 | /* otherwise, bad sdio access or invalid size */ | 258 | return data; |
267 | brcmf_dbg(ERROR, "error reading addr 0x%04x size %d\n", addr, size); | ||
268 | return 0xFFFFFFFF; | ||
269 | } | 259 | } |
270 | 260 | ||
271 | u32 brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size, | 261 | u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret) |
272 | u32 data) | ||
273 | { | 262 | { |
274 | int status; | 263 | u32 data; |
275 | uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; | 264 | int retval; |
276 | int err = 0; | ||
277 | 265 | ||
278 | brcmf_dbg(INFO, "fun = 1, addr = 0x%x, uint%ddata = 0x%x\n", | 266 | brcmf_dbg(INFO, "addr:0x%08x\n", addr); |
279 | addr, size * 8, data); | 267 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, false); |
268 | brcmf_dbg(INFO, "data:0x%08x\n", data); | ||
280 | 269 | ||
281 | if (bar0 != sdiodev->sbwad) { | 270 | if (ret) |
282 | err = brcmf_sdcard_set_sbaddr_window(sdiodev, bar0); | 271 | *ret = retval; |
283 | if (err) | ||
284 | return err; | ||
285 | 272 | ||
286 | sdiodev->sbwad = bar0; | 273 | return data; |
287 | } | 274 | } |
288 | 275 | ||
289 | addr &= SBSDIO_SB_OFT_ADDR_MASK; | 276 | void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, |
290 | if (size == 4) | 277 | u8 data, int *ret) |
291 | addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; | 278 | { |
292 | status = | 279 | int retval; |
293 | brcmf_sdioh_request_word(sdiodev, SDIOH_WRITE, SDIO_FUNC_1, | ||
294 | addr, &data, size); | ||
295 | sdiodev->regfail = (status != 0); | ||
296 | 280 | ||
297 | if (status == 0) | 281 | brcmf_dbg(INFO, "addr:0x%08x, data:0x%02x\n", addr, data); |
298 | return 0; | 282 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); |
299 | 283 | ||
300 | brcmf_dbg(ERROR, "error writing 0x%08x to addr 0x%04x size %d\n", | 284 | if (ret) |
301 | data, addr, size); | 285 | *ret = retval; |
302 | return 0xFFFFFFFF; | ||
303 | } | 286 | } |
304 | 287 | ||
305 | bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev) | 288 | void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, |
289 | u32 data, int *ret) | ||
306 | { | 290 | { |
307 | return sdiodev->regfail; | 291 | int retval; |
292 | |||
293 | brcmf_dbg(INFO, "addr:0x%08x, data:0x%08x\n", addr, data); | ||
294 | retval = brcmf_sdio_regrw_helper(sdiodev, addr, &data, true); | ||
295 | |||
296 | if (ret) | ||
297 | *ret = retval; | ||
308 | } | 298 | } |
309 | 299 | ||
310 | static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn, | 300 | static int brcmf_sdcard_recv_prepare(struct brcmf_sdio_dev *sdiodev, uint fn, |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c index dd07d33a927c..82f51dbd0d66 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c | |||
@@ -346,43 +346,17 @@ int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev, | |||
346 | return status; | 346 | return status; |
347 | } | 347 | } |
348 | 348 | ||
349 | /* Read client card reg */ | ||
350 | static int | ||
351 | brcmf_sdioh_card_regread(struct brcmf_sdio_dev *sdiodev, int func, u32 regaddr, | ||
352 | int regsize, u32 *data) | ||
353 | { | ||
354 | |||
355 | if ((func == 0) || (regsize == 1)) { | ||
356 | u8 temp = 0; | ||
357 | |||
358 | brcmf_sdioh_request_byte(sdiodev, SDIOH_READ, func, regaddr, | ||
359 | &temp); | ||
360 | *data = temp; | ||
361 | *data &= 0xff; | ||
362 | brcmf_dbg(DATA, "byte read data=0x%02x\n", *data); | ||
363 | } else { | ||
364 | brcmf_sdioh_request_word(sdiodev, SDIOH_READ, func, regaddr, | ||
365 | data, regsize); | ||
366 | if (regsize == 2) | ||
367 | *data &= 0xffff; | ||
368 | |||
369 | brcmf_dbg(DATA, "word read data=0x%08x\n", *data); | ||
370 | } | ||
371 | |||
372 | return SUCCESS; | ||
373 | } | ||
374 | |||
375 | static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr) | 349 | static int brcmf_sdioh_get_cisaddr(struct brcmf_sdio_dev *sdiodev, u32 regaddr) |
376 | { | 350 | { |
377 | /* read 24 bits and return valid 17 bit addr */ | 351 | /* read 24 bits and return valid 17 bit addr */ |
378 | int i; | 352 | int i, ret; |
379 | u32 scratch, regdata; | 353 | u32 scratch, regdata; |
380 | __le32 scratch_le; | 354 | __le32 scratch_le; |
381 | u8 *ptr = (u8 *)&scratch_le; | 355 | u8 *ptr = (u8 *)&scratch_le; |
382 | 356 | ||
383 | for (i = 0; i < 3; i++) { | 357 | for (i = 0; i < 3; i++) { |
384 | if ((brcmf_sdioh_card_regread(sdiodev, 0, regaddr, 1, | 358 | regdata = brcmf_sdio_regrl(sdiodev, regaddr, &ret); |
385 | ®data)) != SUCCESS) | 359 | if (ret != 0) |
386 | brcmf_dbg(ERROR, "Can't read!\n"); | 360 | brcmf_dbg(ERROR, "Can't read!\n"); |
387 | 361 | ||
388 | *ptr++ = (u8) regdata; | 362 | *ptr++ = (u8) regdata; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 149ee67beb2e..1dbf2be478c8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -629,43 +629,29 @@ static bool data_ok(struct brcmf_sdio *bus) | |||
629 | * Reads a register in the SDIO hardware block. This block occupies a series of | 629 | * Reads a register in the SDIO hardware block. This block occupies a series of |
630 | * adresses on the 32 bit backplane bus. | 630 | * adresses on the 32 bit backplane bus. |
631 | */ | 631 | */ |
632 | static void | 632 | static int |
633 | r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 reg_offset, u32 *retryvar) | 633 | r_sdreg32(struct brcmf_sdio *bus, u32 *regvar, u32 offset) |
634 | { | 634 | { |
635 | u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); | 635 | u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); |
636 | *retryvar = 0; | 636 | int ret; |
637 | do { | 637 | |
638 | *regvar = brcmf_sdcard_reg_read(bus->sdiodev, | 638 | *regvar = brcmf_sdio_regrl(bus->sdiodev, |
639 | bus->ci->c_inf[idx].base + reg_offset, | 639 | bus->ci->c_inf[idx].base + offset, &ret); |
640 | sizeof(u32)); | 640 | |
641 | } while (brcmf_sdcard_regfail(bus->sdiodev) && | 641 | return ret; |
642 | (++(*retryvar) <= retry_limit)); | ||
643 | if (*retryvar) { | ||
644 | bus->regfails += (*retryvar-1); | ||
645 | if (*retryvar > retry_limit) { | ||
646 | brcmf_dbg(ERROR, "FAILED READ %Xh\n", reg_offset); | ||
647 | *regvar = 0; | ||
648 | } | ||
649 | } | ||
650 | } | 642 | } |
651 | 643 | ||
652 | static void | 644 | static int |
653 | w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset, u32 *retryvar) | 645 | w_sdreg32(struct brcmf_sdio *bus, u32 regval, u32 reg_offset) |
654 | { | 646 | { |
655 | u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); | 647 | u8 idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); |
656 | *retryvar = 0; | 648 | int ret; |
657 | do { | 649 | |
658 | brcmf_sdcard_reg_write(bus->sdiodev, | 650 | brcmf_sdio_regwl(bus->sdiodev, |
659 | bus->ci->c_inf[idx].base + reg_offset, | 651 | bus->ci->c_inf[idx].base + reg_offset, |
660 | sizeof(u32), regval); | 652 | regval, &ret); |
661 | } while (brcmf_sdcard_regfail(bus->sdiodev) && | 653 | |
662 | (++(*retryvar) <= retry_limit)); | 654 | return ret; |
663 | if (*retryvar) { | ||
664 | bus->regfails += (*retryvar-1); | ||
665 | if (*retryvar > retry_limit) | ||
666 | brcmf_dbg(ERROR, "FAILED REGISTER WRITE %Xh\n", | ||
667 | reg_offset); | ||
668 | } | ||
669 | } | 655 | } |
670 | 656 | ||
671 | #define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND) | 657 | #define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND) |
@@ -697,16 +683,16 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
697 | clkreq = | 683 | clkreq = |
698 | bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ; | 684 | bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ; |
699 | 685 | ||
700 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 686 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
701 | SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); | 687 | clkreq, &err); |
702 | if (err) { | 688 | if (err) { |
703 | brcmf_dbg(ERROR, "HT Avail request error: %d\n", err); | 689 | brcmf_dbg(ERROR, "HT Avail request error: %d\n", err); |
704 | return -EBADE; | 690 | return -EBADE; |
705 | } | 691 | } |
706 | 692 | ||
707 | /* Check current status */ | 693 | /* Check current status */ |
708 | clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 694 | clkctl = brcmf_sdio_regrb(bus->sdiodev, |
709 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | 695 | SBSDIO_FUNC1_CHIPCLKCSR, &err); |
710 | if (err) { | 696 | if (err) { |
711 | brcmf_dbg(ERROR, "HT Avail read error: %d\n", err); | 697 | brcmf_dbg(ERROR, "HT Avail read error: %d\n", err); |
712 | return -EBADE; | 698 | return -EBADE; |
@@ -715,9 +701,8 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
715 | /* Go to pending and await interrupt if appropriate */ | 701 | /* Go to pending and await interrupt if appropriate */ |
716 | if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) { | 702 | if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) { |
717 | /* Allow only clock-available interrupt */ | 703 | /* Allow only clock-available interrupt */ |
718 | devctl = brcmf_sdcard_cfg_read(bus->sdiodev, | 704 | devctl = brcmf_sdio_regrb(bus->sdiodev, |
719 | SDIO_FUNC_1, | 705 | SBSDIO_DEVICE_CTL, &err); |
720 | SBSDIO_DEVICE_CTL, &err); | ||
721 | if (err) { | 706 | if (err) { |
722 | brcmf_dbg(ERROR, "Devctl error setting CA: %d\n", | 707 | brcmf_dbg(ERROR, "Devctl error setting CA: %d\n", |
723 | err); | 708 | err); |
@@ -725,30 +710,28 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
725 | } | 710 | } |
726 | 711 | ||
727 | devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; | 712 | devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; |
728 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 713 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, |
729 | SBSDIO_DEVICE_CTL, devctl, &err); | 714 | devctl, &err); |
730 | brcmf_dbg(INFO, "CLKCTL: set PENDING\n"); | 715 | brcmf_dbg(INFO, "CLKCTL: set PENDING\n"); |
731 | bus->clkstate = CLK_PENDING; | 716 | bus->clkstate = CLK_PENDING; |
732 | 717 | ||
733 | return 0; | 718 | return 0; |
734 | } else if (bus->clkstate == CLK_PENDING) { | 719 | } else if (bus->clkstate == CLK_PENDING) { |
735 | /* Cancel CA-only interrupt filter */ | 720 | /* Cancel CA-only interrupt filter */ |
736 | devctl = | 721 | devctl = brcmf_sdio_regrb(bus->sdiodev, |
737 | brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | ||
738 | SBSDIO_DEVICE_CTL, &err); | 722 | SBSDIO_DEVICE_CTL, &err); |
739 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; | 723 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; |
740 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 724 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, |
741 | SBSDIO_DEVICE_CTL, devctl, &err); | 725 | devctl, &err); |
742 | } | 726 | } |
743 | 727 | ||
744 | /* Otherwise, wait here (polling) for HT Avail */ | 728 | /* Otherwise, wait here (polling) for HT Avail */ |
745 | timeout = jiffies + | 729 | timeout = jiffies + |
746 | msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000); | 730 | msecs_to_jiffies(PMU_MAX_TRANSITION_DLY/1000); |
747 | while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { | 731 | while (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { |
748 | clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, | 732 | clkctl = brcmf_sdio_regrb(bus->sdiodev, |
749 | SDIO_FUNC_1, | 733 | SBSDIO_FUNC1_CHIPCLKCSR, |
750 | SBSDIO_FUNC1_CHIPCLKCSR, | 734 | &err); |
751 | &err); | ||
752 | if (time_after(jiffies, timeout)) | 735 | if (time_after(jiffies, timeout)) |
753 | break; | 736 | break; |
754 | else | 737 | else |
@@ -781,17 +764,16 @@ static int brcmf_sdbrcm_htclk(struct brcmf_sdio *bus, bool on, bool pendok) | |||
781 | 764 | ||
782 | if (bus->clkstate == CLK_PENDING) { | 765 | if (bus->clkstate == CLK_PENDING) { |
783 | /* Cancel CA-only interrupt filter */ | 766 | /* Cancel CA-only interrupt filter */ |
784 | devctl = brcmf_sdcard_cfg_read(bus->sdiodev, | 767 | devctl = brcmf_sdio_regrb(bus->sdiodev, |
785 | SDIO_FUNC_1, | 768 | SBSDIO_DEVICE_CTL, &err); |
786 | SBSDIO_DEVICE_CTL, &err); | ||
787 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; | 769 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; |
788 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 770 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, |
789 | SBSDIO_DEVICE_CTL, devctl, &err); | 771 | devctl, &err); |
790 | } | 772 | } |
791 | 773 | ||
792 | bus->clkstate = CLK_SDONLY; | 774 | bus->clkstate = CLK_SDONLY; |
793 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 775 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
794 | SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); | 776 | clkreq, &err); |
795 | brcmf_dbg(INFO, "CLKCTL: turned OFF\n"); | 777 | brcmf_dbg(INFO, "CLKCTL: turned OFF\n"); |
796 | if (err) { | 778 | if (err) { |
797 | brcmf_dbg(ERROR, "Failed access turning clock off: %d\n", | 779 | brcmf_dbg(ERROR, "Failed access turning clock off: %d\n", |
@@ -874,7 +856,7 @@ static int brcmf_sdbrcm_clkctl(struct brcmf_sdio *bus, uint target, bool pendok) | |||
874 | 856 | ||
875 | static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep) | 857 | static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep) |
876 | { | 858 | { |
877 | uint retries = 0; | 859 | int ret; |
878 | 860 | ||
879 | brcmf_dbg(INFO, "request %s (currently %s)\n", | 861 | brcmf_dbg(INFO, "request %s (currently %s)\n", |
880 | sleep ? "SLEEP" : "WAKE", | 862 | sleep ? "SLEEP" : "WAKE", |
@@ -894,22 +876,20 @@ static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep) | |||
894 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 876 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); |
895 | 877 | ||
896 | /* Tell device to start using OOB wakeup */ | 878 | /* Tell device to start using OOB wakeup */ |
897 | w_sdreg32(bus, SMB_USE_OOB, | 879 | ret = w_sdreg32(bus, SMB_USE_OOB, |
898 | offsetof(struct sdpcmd_regs, tosbmailbox), &retries); | 880 | offsetof(struct sdpcmd_regs, tosbmailbox)); |
899 | if (retries > retry_limit) | 881 | if (ret != 0) |
900 | brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"); | 882 | brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"); |
901 | 883 | ||
902 | /* Turn off our contribution to the HT clock request */ | 884 | /* Turn off our contribution to the HT clock request */ |
903 | brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); | 885 | brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); |
904 | 886 | ||
905 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 887 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
906 | SBSDIO_FUNC1_CHIPCLKCSR, | 888 | SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); |
907 | SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); | ||
908 | 889 | ||
909 | /* Isolate the bus */ | 890 | /* Isolate the bus */ |
910 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 891 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, |
911 | SBSDIO_DEVICE_CTL, | 892 | SBSDIO_DEVCTL_PADS_ISO, NULL); |
912 | SBSDIO_DEVCTL_PADS_ISO, NULL); | ||
913 | 893 | ||
914 | /* Change state */ | 894 | /* Change state */ |
915 | bus->sleeping = true; | 895 | bus->sleeping = true; |
@@ -917,21 +897,20 @@ static int brcmf_sdbrcm_bussleep(struct brcmf_sdio *bus, bool sleep) | |||
917 | } else { | 897 | } else { |
918 | /* Waking up: bus power up is ok, set local state */ | 898 | /* Waking up: bus power up is ok, set local state */ |
919 | 899 | ||
920 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 900 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
921 | SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); | 901 | 0, NULL); |
922 | 902 | ||
923 | /* Make sure the controller has the bus up */ | 903 | /* Make sure the controller has the bus up */ |
924 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 904 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); |
925 | 905 | ||
926 | /* Send misc interrupt to indicate OOB not needed */ | 906 | /* Send misc interrupt to indicate OOB not needed */ |
927 | w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, tosbmailboxdata), | 907 | ret = w_sdreg32(bus, 0, |
928 | &retries); | 908 | offsetof(struct sdpcmd_regs, tosbmailboxdata)); |
929 | if (retries <= retry_limit) | 909 | if (ret == 0) |
930 | w_sdreg32(bus, SMB_DEV_INT, | 910 | ret = w_sdreg32(bus, SMB_DEV_INT, |
931 | offsetof(struct sdpcmd_regs, tosbmailbox), | 911 | offsetof(struct sdpcmd_regs, tosbmailbox)); |
932 | &retries); | 912 | |
933 | 913 | if (ret != 0) | |
934 | if (retries > retry_limit) | ||
935 | brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"); | 914 | brcmf_dbg(ERROR, "CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"); |
936 | 915 | ||
937 | /* Make sure we have SD bus access */ | 916 | /* Make sure we have SD bus access */ |
@@ -955,17 +934,17 @@ static u32 brcmf_sdbrcm_hostmail(struct brcmf_sdio *bus) | |||
955 | u32 intstatus = 0; | 934 | u32 intstatus = 0; |
956 | u32 hmb_data; | 935 | u32 hmb_data; |
957 | u8 fcbits; | 936 | u8 fcbits; |
958 | uint retries = 0; | 937 | int ret; |
959 | 938 | ||
960 | brcmf_dbg(TRACE, "Enter\n"); | 939 | brcmf_dbg(TRACE, "Enter\n"); |
961 | 940 | ||
962 | /* Read mailbox data and ack that we did so */ | 941 | /* Read mailbox data and ack that we did so */ |
963 | r_sdreg32(bus, &hmb_data, | 942 | ret = r_sdreg32(bus, &hmb_data, |
964 | offsetof(struct sdpcmd_regs, tohostmailboxdata), &retries); | 943 | offsetof(struct sdpcmd_regs, tohostmailboxdata)); |
965 | 944 | ||
966 | if (retries <= retry_limit) | 945 | if (ret == 0) |
967 | w_sdreg32(bus, SMB_INT_ACK, | 946 | w_sdreg32(bus, SMB_INT_ACK, |
968 | offsetof(struct sdpcmd_regs, tosbmailbox), &retries); | 947 | offsetof(struct sdpcmd_regs, tosbmailbox)); |
969 | bus->f1regdata += 2; | 948 | bus->f1regdata += 2; |
970 | 949 | ||
971 | /* Dongle recomposed rx frames, accept them again */ | 950 | /* Dongle recomposed rx frames, accept them again */ |
@@ -1040,17 +1019,16 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) | |||
1040 | if (abort) | 1019 | if (abort) |
1041 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); | 1020 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); |
1042 | 1021 | ||
1043 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 1022 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, |
1044 | SBSDIO_FUNC1_FRAMECTRL, | 1023 | SFC_RF_TERM, &err); |
1045 | SFC_RF_TERM, &err); | ||
1046 | bus->f1regdata++; | 1024 | bus->f1regdata++; |
1047 | 1025 | ||
1048 | /* Wait until the packet has been flushed (device/FIFO stable) */ | 1026 | /* Wait until the packet has been flushed (device/FIFO stable) */ |
1049 | for (lastrbc = retries = 0xffff; retries > 0; retries--) { | 1027 | for (lastrbc = retries = 0xffff; retries > 0; retries--) { |
1050 | hi = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 1028 | hi = brcmf_sdio_regrb(bus->sdiodev, |
1051 | SBSDIO_FUNC1_RFRAMEBCHI, NULL); | 1029 | SBSDIO_FUNC1_RFRAMEBCHI, &err); |
1052 | lo = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 1030 | lo = brcmf_sdio_regrb(bus->sdiodev, |
1053 | SBSDIO_FUNC1_RFRAMEBCLO, NULL); | 1031 | SBSDIO_FUNC1_RFRAMEBCLO, &err); |
1054 | bus->f1regdata += 2; | 1032 | bus->f1regdata += 2; |
1055 | 1033 | ||
1056 | if ((hi == 0) && (lo == 0)) | 1034 | if ((hi == 0) && (lo == 0)) |
@@ -1070,11 +1048,11 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) | |||
1070 | 1048 | ||
1071 | if (rtx) { | 1049 | if (rtx) { |
1072 | bus->rxrtx++; | 1050 | bus->rxrtx++; |
1073 | w_sdreg32(bus, SMB_NAK, | 1051 | err = w_sdreg32(bus, SMB_NAK, |
1074 | offsetof(struct sdpcmd_regs, tosbmailbox), &retries); | 1052 | offsetof(struct sdpcmd_regs, tosbmailbox)); |
1075 | 1053 | ||
1076 | bus->f1regdata++; | 1054 | bus->f1regdata++; |
1077 | if (retries <= retry_limit) | 1055 | if (err == 0) |
1078 | bus->rxskip = true; | 1056 | bus->rxskip = true; |
1079 | } | 1057 | } |
1080 | 1058 | ||
@@ -1082,7 +1060,7 @@ static void brcmf_sdbrcm_rxfail(struct brcmf_sdio *bus, bool abort, bool rtx) | |||
1082 | bus->nextlen = 0; | 1060 | bus->nextlen = 0; |
1083 | 1061 | ||
1084 | /* If we can't reach the device, signal failure */ | 1062 | /* If we can't reach the device, signal failure */ |
1085 | if (err || brcmf_sdcard_regfail(bus->sdiodev)) | 1063 | if (err) |
1086 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 1064 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
1087 | } | 1065 | } |
1088 | 1066 | ||
@@ -2178,21 +2156,16 @@ static int brcmf_sdbrcm_txpkt(struct brcmf_sdio *bus, struct sk_buff *pkt, | |||
2178 | bus->tx_sderrs++; | 2156 | bus->tx_sderrs++; |
2179 | 2157 | ||
2180 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); | 2158 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); |
2181 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 2159 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, |
2182 | SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, | 2160 | SFC_WF_TERM, NULL); |
2183 | NULL); | ||
2184 | bus->f1regdata++; | 2161 | bus->f1regdata++; |
2185 | 2162 | ||
2186 | for (i = 0; i < 3; i++) { | 2163 | for (i = 0; i < 3; i++) { |
2187 | u8 hi, lo; | 2164 | u8 hi, lo; |
2188 | hi = brcmf_sdcard_cfg_read(bus->sdiodev, | 2165 | hi = brcmf_sdio_regrb(bus->sdiodev, |
2189 | SDIO_FUNC_1, | 2166 | SBSDIO_FUNC1_WFRAMEBCHI, NULL); |
2190 | SBSDIO_FUNC1_WFRAMEBCHI, | 2167 | lo = brcmf_sdio_regrb(bus->sdiodev, |
2191 | NULL); | 2168 | SBSDIO_FUNC1_WFRAMEBCLO, NULL); |
2192 | lo = brcmf_sdcard_cfg_read(bus->sdiodev, | ||
2193 | SDIO_FUNC_1, | ||
2194 | SBSDIO_FUNC1_WFRAMEBCLO, | ||
2195 | NULL); | ||
2196 | bus->f1regdata += 2; | 2169 | bus->f1regdata += 2; |
2197 | if ((hi == 0) && (lo == 0)) | 2170 | if ((hi == 0) && (lo == 0)) |
2198 | break; | 2171 | break; |
@@ -2219,7 +2192,6 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
2219 | { | 2192 | { |
2220 | struct sk_buff *pkt; | 2193 | struct sk_buff *pkt; |
2221 | u32 intstatus = 0; | 2194 | u32 intstatus = 0; |
2222 | uint retries = 0; | ||
2223 | int ret = 0, prec_out; | 2195 | int ret = 0, prec_out; |
2224 | uint cnt = 0; | 2196 | uint cnt = 0; |
2225 | uint datalen; | 2197 | uint datalen; |
@@ -2249,11 +2221,11 @@ static uint brcmf_sdbrcm_sendfromq(struct brcmf_sdio *bus, uint maxframes) | |||
2249 | /* In poll mode, need to check for other events */ | 2221 | /* In poll mode, need to check for other events */ |
2250 | if (!bus->intr && cnt) { | 2222 | if (!bus->intr && cnt) { |
2251 | /* Check device status, signal pending interrupt */ | 2223 | /* Check device status, signal pending interrupt */ |
2252 | r_sdreg32(bus, &intstatus, | 2224 | ret = r_sdreg32(bus, &intstatus, |
2253 | offsetof(struct sdpcmd_regs, intstatus), | 2225 | offsetof(struct sdpcmd_regs, |
2254 | &retries); | 2226 | intstatus)); |
2255 | bus->f2txdata++; | 2227 | bus->f2txdata++; |
2256 | if (brcmf_sdcard_regfail(bus->sdiodev)) | 2228 | if (ret != 0) |
2257 | break; | 2229 | break; |
2258 | if (intstatus & bus->hostintmask) | 2230 | if (intstatus & bus->hostintmask) |
2259 | bus->ipend = true; | 2231 | bus->ipend = true; |
@@ -2275,7 +2247,6 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) | |||
2275 | { | 2247 | { |
2276 | u32 local_hostintmask; | 2248 | u32 local_hostintmask; |
2277 | u8 saveclk; | 2249 | u8 saveclk; |
2278 | uint retries; | ||
2279 | int err; | 2250 | int err; |
2280 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 2251 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
2281 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 2252 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
@@ -2303,7 +2274,7 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) | |||
2303 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); | 2274 | brcmf_sdbrcm_clkctl(bus, CLK_AVAIL, false); |
2304 | 2275 | ||
2305 | /* Disable and clear interrupts at the chip level also */ | 2276 | /* Disable and clear interrupts at the chip level also */ |
2306 | w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask), &retries); | 2277 | w_sdreg32(bus, 0, offsetof(struct sdpcmd_regs, hostintmask)); |
2307 | local_hostintmask = bus->hostintmask; | 2278 | local_hostintmask = bus->hostintmask; |
2308 | bus->hostintmask = 0; | 2279 | bus->hostintmask = 0; |
2309 | 2280 | ||
@@ -2311,24 +2282,23 @@ static void brcmf_sdbrcm_bus_stop(struct device *dev) | |||
2311 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2282 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
2312 | 2283 | ||
2313 | /* Force clocks on backplane to be sure F2 interrupt propagates */ | 2284 | /* Force clocks on backplane to be sure F2 interrupt propagates */ |
2314 | saveclk = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 2285 | saveclk = brcmf_sdio_regrb(bus->sdiodev, |
2315 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | 2286 | SBSDIO_FUNC1_CHIPCLKCSR, &err); |
2316 | if (!err) { | 2287 | if (!err) { |
2317 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 2288 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
2318 | SBSDIO_FUNC1_CHIPCLKCSR, | 2289 | (saveclk | SBSDIO_FORCE_HT), &err); |
2319 | (saveclk | SBSDIO_FORCE_HT), &err); | ||
2320 | } | 2290 | } |
2321 | if (err) | 2291 | if (err) |
2322 | brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err); | 2292 | brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err); |
2323 | 2293 | ||
2324 | /* Turn off the bus (F2), free any pending packets */ | 2294 | /* Turn off the bus (F2), free any pending packets */ |
2325 | brcmf_dbg(INTR, "disable SDIO interrupts\n"); | 2295 | brcmf_dbg(INTR, "disable SDIO interrupts\n"); |
2326 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, | 2296 | brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, SDIO_FUNC_ENABLE_1, |
2327 | SDIO_FUNC_ENABLE_1, NULL); | 2297 | NULL); |
2328 | 2298 | ||
2329 | /* Clear any pending interrupts now that F2 is disabled */ | 2299 | /* Clear any pending interrupts now that F2 is disabled */ |
2330 | w_sdreg32(bus, local_hostintmask, | 2300 | w_sdreg32(bus, local_hostintmask, |
2331 | offsetof(struct sdpcmd_regs, intstatus), &retries); | 2301 | offsetof(struct sdpcmd_regs, intstatus)); |
2332 | 2302 | ||
2333 | /* Turn off the backplane clock (only) */ | 2303 | /* Turn off the backplane clock (only) */ |
2334 | brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); | 2304 | brcmf_sdbrcm_clkctl(bus, CLK_SDONLY, false); |
@@ -2373,12 +2343,12 @@ static inline void brcmf_sdbrcm_clrintr(struct brcmf_sdio *bus) | |||
2373 | static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | 2343 | static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) |
2374 | { | 2344 | { |
2375 | u32 intstatus, newstatus = 0; | 2345 | u32 intstatus, newstatus = 0; |
2376 | uint retries = 0; | ||
2377 | uint rxlimit = bus->rxbound; /* Rx frames to read before resched */ | 2346 | uint rxlimit = bus->rxbound; /* Rx frames to read before resched */ |
2378 | uint txlimit = bus->txbound; /* Tx frames to send before resched */ | 2347 | uint txlimit = bus->txbound; /* Tx frames to send before resched */ |
2379 | uint framecnt = 0; /* Temporary counter of tx/rx frames */ | 2348 | uint framecnt = 0; /* Temporary counter of tx/rx frames */ |
2380 | bool rxdone = true; /* Flag for no more read data */ | 2349 | bool rxdone = true; /* Flag for no more read data */ |
2381 | bool resched = false; /* Flag indicating resched wanted */ | 2350 | bool resched = false; /* Flag indicating resched wanted */ |
2351 | int err; | ||
2382 | 2352 | ||
2383 | brcmf_dbg(TRACE, "Enter\n"); | 2353 | brcmf_dbg(TRACE, "Enter\n"); |
2384 | 2354 | ||
@@ -2389,13 +2359,12 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2389 | 2359 | ||
2390 | /* If waiting for HTAVAIL, check status */ | 2360 | /* If waiting for HTAVAIL, check status */ |
2391 | if (bus->clkstate == CLK_PENDING) { | 2361 | if (bus->clkstate == CLK_PENDING) { |
2392 | int err; | ||
2393 | u8 clkctl, devctl = 0; | 2362 | u8 clkctl, devctl = 0; |
2394 | 2363 | ||
2395 | #ifdef DEBUG | 2364 | #ifdef DEBUG |
2396 | /* Check for inconsistent device control */ | 2365 | /* Check for inconsistent device control */ |
2397 | devctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 2366 | devctl = brcmf_sdio_regrb(bus->sdiodev, |
2398 | SBSDIO_DEVICE_CTL, &err); | 2367 | SBSDIO_DEVICE_CTL, &err); |
2399 | if (err) { | 2368 | if (err) { |
2400 | brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", err); | 2369 | brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", err); |
2401 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2370 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
@@ -2403,8 +2372,8 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2403 | #endif /* DEBUG */ | 2372 | #endif /* DEBUG */ |
2404 | 2373 | ||
2405 | /* Read CSR, if clock on switch to AVAIL, else ignore */ | 2374 | /* Read CSR, if clock on switch to AVAIL, else ignore */ |
2406 | clkctl = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 2375 | clkctl = brcmf_sdio_regrb(bus->sdiodev, |
2407 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | 2376 | SBSDIO_FUNC1_CHIPCLKCSR, &err); |
2408 | if (err) { | 2377 | if (err) { |
2409 | brcmf_dbg(ERROR, "error reading CSR: %d\n", | 2378 | brcmf_dbg(ERROR, "error reading CSR: %d\n", |
2410 | err); | 2379 | err); |
@@ -2415,17 +2384,16 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2415 | devctl, clkctl); | 2384 | devctl, clkctl); |
2416 | 2385 | ||
2417 | if (SBSDIO_HTAV(clkctl)) { | 2386 | if (SBSDIO_HTAV(clkctl)) { |
2418 | devctl = brcmf_sdcard_cfg_read(bus->sdiodev, | 2387 | devctl = brcmf_sdio_regrb(bus->sdiodev, |
2419 | SDIO_FUNC_1, | 2388 | SBSDIO_DEVICE_CTL, &err); |
2420 | SBSDIO_DEVICE_CTL, &err); | ||
2421 | if (err) { | 2389 | if (err) { |
2422 | brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", | 2390 | brcmf_dbg(ERROR, "error reading DEVCTL: %d\n", |
2423 | err); | 2391 | err); |
2424 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2392 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
2425 | } | 2393 | } |
2426 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; | 2394 | devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; |
2427 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 2395 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_DEVICE_CTL, |
2428 | SBSDIO_DEVICE_CTL, devctl, &err); | 2396 | devctl, &err); |
2429 | if (err) { | 2397 | if (err) { |
2430 | brcmf_dbg(ERROR, "error writing DEVCTL: %d\n", | 2398 | brcmf_dbg(ERROR, "error writing DEVCTL: %d\n", |
2431 | err); | 2399 | err); |
@@ -2447,17 +2415,17 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2447 | /* Pending interrupt indicates new device status */ | 2415 | /* Pending interrupt indicates new device status */ |
2448 | if (bus->ipend) { | 2416 | if (bus->ipend) { |
2449 | bus->ipend = false; | 2417 | bus->ipend = false; |
2450 | r_sdreg32(bus, &newstatus, | 2418 | err = r_sdreg32(bus, &newstatus, |
2451 | offsetof(struct sdpcmd_regs, intstatus), &retries); | 2419 | offsetof(struct sdpcmd_regs, intstatus)); |
2452 | bus->f1regdata++; | 2420 | bus->f1regdata++; |
2453 | if (brcmf_sdcard_regfail(bus->sdiodev)) | 2421 | if (err != 0) |
2454 | newstatus = 0; | 2422 | newstatus = 0; |
2455 | newstatus &= bus->hostintmask; | 2423 | newstatus &= bus->hostintmask; |
2456 | bus->fcstate = !!(newstatus & I_HMB_FC_STATE); | 2424 | bus->fcstate = !!(newstatus & I_HMB_FC_STATE); |
2457 | if (newstatus) { | 2425 | if (newstatus) { |
2458 | w_sdreg32(bus, newstatus, | 2426 | err = w_sdreg32(bus, newstatus, |
2459 | offsetof(struct sdpcmd_regs, intstatus), | 2427 | offsetof(struct sdpcmd_regs, |
2460 | &retries); | 2428 | intstatus)); |
2461 | bus->f1regdata++; | 2429 | bus->f1regdata++; |
2462 | } | 2430 | } |
2463 | } | 2431 | } |
@@ -2472,11 +2440,11 @@ static bool brcmf_sdbrcm_dpc(struct brcmf_sdio *bus) | |||
2472 | */ | 2440 | */ |
2473 | if (intstatus & I_HMB_FC_CHANGE) { | 2441 | if (intstatus & I_HMB_FC_CHANGE) { |
2474 | intstatus &= ~I_HMB_FC_CHANGE; | 2442 | intstatus &= ~I_HMB_FC_CHANGE; |
2475 | w_sdreg32(bus, I_HMB_FC_CHANGE, | 2443 | err = w_sdreg32(bus, I_HMB_FC_CHANGE, |
2476 | offsetof(struct sdpcmd_regs, intstatus), &retries); | 2444 | offsetof(struct sdpcmd_regs, intstatus)); |
2477 | 2445 | ||
2478 | r_sdreg32(bus, &newstatus, | 2446 | err = r_sdreg32(bus, &newstatus, |
2479 | offsetof(struct sdpcmd_regs, intstatus), &retries); | 2447 | offsetof(struct sdpcmd_regs, intstatus)); |
2480 | bus->f1regdata += 2; | 2448 | bus->f1regdata += 2; |
2481 | bus->fcstate = | 2449 | bus->fcstate = |
2482 | !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)); | 2450 | !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)); |
@@ -2546,21 +2514,18 @@ clkwait: | |||
2546 | 2514 | ||
2547 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); | 2515 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); |
2548 | 2516 | ||
2549 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 2517 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, |
2550 | SBSDIO_FUNC1_FRAMECTRL, SFC_WF_TERM, | 2518 | SFC_WF_TERM, &err); |
2551 | NULL); | ||
2552 | bus->f1regdata++; | 2519 | bus->f1regdata++; |
2553 | 2520 | ||
2554 | for (i = 0; i < 3; i++) { | 2521 | for (i = 0; i < 3; i++) { |
2555 | u8 hi, lo; | 2522 | u8 hi, lo; |
2556 | hi = brcmf_sdcard_cfg_read(bus->sdiodev, | 2523 | hi = brcmf_sdio_regrb(bus->sdiodev, |
2557 | SDIO_FUNC_1, | 2524 | SBSDIO_FUNC1_WFRAMEBCHI, |
2558 | SBSDIO_FUNC1_WFRAMEBCHI, | 2525 | &err); |
2559 | NULL); | 2526 | lo = brcmf_sdio_regrb(bus->sdiodev, |
2560 | lo = brcmf_sdcard_cfg_read(bus->sdiodev, | 2527 | SBSDIO_FUNC1_WFRAMEBCLO, |
2561 | SDIO_FUNC_1, | 2528 | &err); |
2562 | SBSDIO_FUNC1_WFRAMEBCLO, | ||
2563 | NULL); | ||
2564 | bus->f1regdata += 2; | 2529 | bus->f1regdata += 2; |
2565 | if ((hi == 0) && (lo == 0)) | 2530 | if ((hi == 0) && (lo == 0)) |
2566 | break; | 2531 | break; |
@@ -2587,10 +2552,8 @@ clkwait: | |||
2587 | else await next interrupt */ | 2552 | else await next interrupt */ |
2588 | /* On failed register access, all bets are off: | 2553 | /* On failed register access, all bets are off: |
2589 | no resched or interrupts */ | 2554 | no resched or interrupts */ |
2590 | if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) || | 2555 | if ((bus->sdiodev->bus_if->state == BRCMF_BUS_DOWN) || (err != 0)) { |
2591 | brcmf_sdcard_regfail(bus->sdiodev)) { | 2556 | brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation\n"); |
2592 | brcmf_dbg(ERROR, "failed backplane access over SDIO, halting operation %d\n", | ||
2593 | brcmf_sdcard_regfail(bus->sdiodev)); | ||
2594 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 2557 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
2595 | bus->intstatus = 0; | 2558 | bus->intstatus = 0; |
2596 | } else if (bus->clkstate == CLK_PENDING) { | 2559 | } else if (bus->clkstate == CLK_PENDING) { |
@@ -2886,19 +2849,16 @@ static int brcmf_tx_frame(struct brcmf_sdio *bus, u8 *frame, u16 len) | |||
2886 | 2849 | ||
2887 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); | 2850 | brcmf_sdcard_abort(bus->sdiodev, SDIO_FUNC_2); |
2888 | 2851 | ||
2889 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 2852 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_FRAMECTRL, |
2890 | SBSDIO_FUNC1_FRAMECTRL, | 2853 | SFC_WF_TERM, NULL); |
2891 | SFC_WF_TERM, NULL); | ||
2892 | bus->f1regdata++; | 2854 | bus->f1regdata++; |
2893 | 2855 | ||
2894 | for (i = 0; i < 3; i++) { | 2856 | for (i = 0; i < 3; i++) { |
2895 | u8 hi, lo; | 2857 | u8 hi, lo; |
2896 | hi = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 2858 | hi = brcmf_sdio_regrb(bus->sdiodev, |
2897 | SBSDIO_FUNC1_WFRAMEBCHI, | 2859 | SBSDIO_FUNC1_WFRAMEBCHI, NULL); |
2898 | NULL); | 2860 | lo = brcmf_sdio_regrb(bus->sdiodev, |
2899 | lo = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 2861 | SBSDIO_FUNC1_WFRAMEBCLO, NULL); |
2900 | SBSDIO_FUNC1_WFRAMEBCLO, | ||
2901 | NULL); | ||
2902 | bus->f1regdata += 2; | 2862 | bus->f1regdata += 2; |
2903 | if (hi == 0 && lo == 0) | 2863 | if (hi == 0 && lo == 0) |
2904 | break; | 2864 | break; |
@@ -3188,7 +3148,6 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus) | |||
3188 | 3148 | ||
3189 | static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter) | 3149 | static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter) |
3190 | { | 3150 | { |
3191 | uint retries; | ||
3192 | int bcmerror = 0; | 3151 | int bcmerror = 0; |
3193 | struct chip_info *ci = bus->ci; | 3152 | struct chip_info *ci = bus->ci; |
3194 | 3153 | ||
@@ -3222,7 +3181,7 @@ static int brcmf_sdbrcm_download_state(struct brcmf_sdio *bus, bool enter) | |||
3222 | } | 3181 | } |
3223 | 3182 | ||
3224 | w_sdreg32(bus, 0xFFFFFFFF, | 3183 | w_sdreg32(bus, 0xFFFFFFFF, |
3225 | offsetof(struct sdpcmd_regs, intstatus), &retries); | 3184 | offsetof(struct sdpcmd_regs, intstatus)); |
3226 | 3185 | ||
3227 | ci->resetcore(bus->sdiodev, ci, BCMA_CORE_ARM_CM3); | 3186 | ci->resetcore(bus->sdiodev, ci, BCMA_CORE_ARM_CM3); |
3228 | 3187 | ||
@@ -3444,7 +3403,6 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) | |||
3444 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 3403 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
3445 | struct brcmf_sdio *bus = sdiodev->bus; | 3404 | struct brcmf_sdio *bus = sdiodev->bus; |
3446 | unsigned long timeout; | 3405 | unsigned long timeout; |
3447 | uint retries = 0; | ||
3448 | u8 ready, enable; | 3406 | u8 ready, enable; |
3449 | int err, ret = 0; | 3407 | int err, ret = 0; |
3450 | u8 saveclk; | 3408 | u8 saveclk; |
@@ -3472,13 +3430,11 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) | |||
3472 | goto exit; | 3430 | goto exit; |
3473 | 3431 | ||
3474 | /* Force clocks on backplane to be sure F2 interrupt propagates */ | 3432 | /* Force clocks on backplane to be sure F2 interrupt propagates */ |
3475 | saveclk = | 3433 | saveclk = brcmf_sdio_regrb(bus->sdiodev, |
3476 | brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | 3434 | SBSDIO_FUNC1_CHIPCLKCSR, &err); |
3477 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | ||
3478 | if (!err) { | 3435 | if (!err) { |
3479 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 3436 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
3480 | SBSDIO_FUNC1_CHIPCLKCSR, | 3437 | (saveclk | SBSDIO_FORCE_HT), &err); |
3481 | (saveclk | SBSDIO_FORCE_HT), &err); | ||
3482 | } | 3438 | } |
3483 | if (err) { | 3439 | if (err) { |
3484 | brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err); | 3440 | brcmf_dbg(ERROR, "Failed to force clock for F2: err %d\n", err); |
@@ -3487,17 +3443,16 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) | |||
3487 | 3443 | ||
3488 | /* Enable function 2 (frame transfers) */ | 3444 | /* Enable function 2 (frame transfers) */ |
3489 | w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, | 3445 | w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT, |
3490 | offsetof(struct sdpcmd_regs, tosbmailboxdata), &retries); | 3446 | offsetof(struct sdpcmd_regs, tosbmailboxdata)); |
3491 | enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2); | 3447 | enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2); |
3492 | 3448 | ||
3493 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, | 3449 | brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, enable, NULL); |
3494 | enable, NULL); | ||
3495 | 3450 | ||
3496 | timeout = jiffies + msecs_to_jiffies(BRCMF_WAIT_F2RDY); | 3451 | timeout = jiffies + msecs_to_jiffies(BRCMF_WAIT_F2RDY); |
3497 | ready = 0; | 3452 | ready = 0; |
3498 | while (enable != ready) { | 3453 | while (enable != ready) { |
3499 | ready = brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_0, | 3454 | ready = brcmf_sdio_regrb(bus->sdiodev, |
3500 | SDIO_CCCR_IORx, NULL); | 3455 | SDIO_CCCR_IORx, NULL); |
3501 | if (time_after(jiffies, timeout)) | 3456 | if (time_after(jiffies, timeout)) |
3502 | break; | 3457 | break; |
3503 | else if (time_after(jiffies, timeout - BRCMF_WAIT_F2RDY + 50)) | 3458 | else if (time_after(jiffies, timeout - BRCMF_WAIT_F2RDY + 50)) |
@@ -3512,21 +3467,18 @@ static int brcmf_sdbrcm_bus_init(struct device *dev) | |||
3512 | /* Set up the interrupt mask and enable interrupts */ | 3467 | /* Set up the interrupt mask and enable interrupts */ |
3513 | bus->hostintmask = HOSTINTMASK; | 3468 | bus->hostintmask = HOSTINTMASK; |
3514 | w_sdreg32(bus, bus->hostintmask, | 3469 | w_sdreg32(bus, bus->hostintmask, |
3515 | offsetof(struct sdpcmd_regs, hostintmask), &retries); | 3470 | offsetof(struct sdpcmd_regs, hostintmask)); |
3516 | 3471 | ||
3517 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 3472 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_WATERMARK, 8, &err); |
3518 | SBSDIO_WATERMARK, 8, &err); | ||
3519 | } else { | 3473 | } else { |
3520 | /* Disable F2 again */ | 3474 | /* Disable F2 again */ |
3521 | enable = SDIO_FUNC_ENABLE_1; | 3475 | enable = SDIO_FUNC_ENABLE_1; |
3522 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, | 3476 | brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, enable, NULL); |
3523 | SDIO_CCCR_IOEx, enable, NULL); | ||
3524 | ret = -ENODEV; | 3477 | ret = -ENODEV; |
3525 | } | 3478 | } |
3526 | 3479 | ||
3527 | /* Restore previous clock setting */ | 3480 | /* Restore previous clock setting */ |
3528 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 3481 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); |
3529 | SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); | ||
3530 | 3482 | ||
3531 | if (ret == 0) { | 3483 | if (ret == 0) { |
3532 | ret = brcmf_sdio_intr_register(bus->sdiodev); | 3484 | ret = brcmf_sdio_intr_register(bus->sdiodev); |
@@ -3606,9 +3558,9 @@ static bool brcmf_sdbrcm_bus_watchdog(struct brcmf_sdio *bus) | |||
3606 | 3558 | ||
3607 | if (!bus->dpc_sched) { | 3559 | if (!bus->dpc_sched) { |
3608 | u8 devpend; | 3560 | u8 devpend; |
3609 | devpend = brcmf_sdcard_cfg_read(bus->sdiodev, | 3561 | devpend = brcmf_sdio_regrb(bus->sdiodev, |
3610 | SDIO_FUNC_0, SDIO_CCCR_INTx, | 3562 | SDIO_CCCR_INTx, |
3611 | NULL); | 3563 | NULL); |
3612 | intstatus = | 3564 | intstatus = |
3613 | devpend & (INTR_STATUS_FUNC1 | | 3565 | devpend & (INTR_STATUS_FUNC1 | |
3614 | INTR_STATUS_FUNC2); | 3566 | INTR_STATUS_FUNC2); |
@@ -3732,24 +3684,18 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) | |||
3732 | 3684 | ||
3733 | bus->alp_only = true; | 3685 | bus->alp_only = true; |
3734 | 3686 | ||
3735 | /* Return the window to backplane enumeration space for core access */ | ||
3736 | if (brcmf_sdcard_set_sbaddr_window(bus->sdiodev, SI_ENUM_BASE)) | ||
3737 | brcmf_dbg(ERROR, "FAILED to return to SI_ENUM_BASE\n"); | ||
3738 | |||
3739 | pr_debug("F1 signature read @0x18000000=0x%4x\n", | 3687 | pr_debug("F1 signature read @0x18000000=0x%4x\n", |
3740 | brcmf_sdcard_reg_read(bus->sdiodev, SI_ENUM_BASE, 4)); | 3688 | brcmf_sdio_regrl(bus->sdiodev, SI_ENUM_BASE, NULL)); |
3741 | 3689 | ||
3742 | /* | 3690 | /* |
3743 | * Force PLL off until brcmf_sdio_chip_attach() | 3691 | * Force PLL off until brcmf_sdio_chip_attach() |
3744 | * programs PLL control regs | 3692 | * programs PLL control regs |
3745 | */ | 3693 | */ |
3746 | 3694 | ||
3747 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 3695 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, |
3748 | SBSDIO_FUNC1_CHIPCLKCSR, | 3696 | BRCMF_INIT_CLKCTL1, &err); |
3749 | BRCMF_INIT_CLKCTL1, &err); | ||
3750 | if (!err) | 3697 | if (!err) |
3751 | clkctl = | 3698 | clkctl = brcmf_sdio_regrb(bus->sdiodev, |
3752 | brcmf_sdcard_cfg_read(bus->sdiodev, SDIO_FUNC_1, | ||
3753 | SBSDIO_FUNC1_CHIPCLKCSR, &err); | 3699 | SBSDIO_FUNC1_CHIPCLKCSR, &err); |
3754 | 3700 | ||
3755 | if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) { | 3701 | if (err || ((clkctl & ~SBSDIO_AVBITS) != BRCMF_INIT_CLKCTL1)) { |
@@ -3782,9 +3728,8 @@ brcmf_sdbrcm_probe_attach(struct brcmf_sdio *bus, u32 regsva) | |||
3782 | idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); | 3728 | idx = brcmf_sdio_chip_getinfidx(bus->ci, BCMA_CORE_SDIO_DEV); |
3783 | reg_addr = bus->ci->c_inf[idx].base + | 3729 | reg_addr = bus->ci->c_inf[idx].base + |
3784 | offsetof(struct sdpcmd_regs, corecontrol); | 3730 | offsetof(struct sdpcmd_regs, corecontrol); |
3785 | reg_val = brcmf_sdcard_reg_read(bus->sdiodev, reg_addr, sizeof(u32)); | 3731 | reg_val = brcmf_sdio_regrl(bus->sdiodev, reg_addr, NULL); |
3786 | brcmf_sdcard_reg_write(bus->sdiodev, reg_addr, sizeof(u32), | 3732 | brcmf_sdio_regwl(bus->sdiodev, reg_addr, reg_val | CC_BPRESEN, NULL); |
3787 | reg_val | CC_BPRESEN); | ||
3788 | 3733 | ||
3789 | brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN); | 3734 | brcmu_pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN); |
3790 | 3735 | ||
@@ -3809,16 +3754,15 @@ static bool brcmf_sdbrcm_probe_init(struct brcmf_sdio *bus) | |||
3809 | brcmf_dbg(TRACE, "Enter\n"); | 3754 | brcmf_dbg(TRACE, "Enter\n"); |
3810 | 3755 | ||
3811 | /* Disable F2 to clear any intermediate frame state on the dongle */ | 3756 | /* Disable F2 to clear any intermediate frame state on the dongle */ |
3812 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_0, SDIO_CCCR_IOEx, | 3757 | brcmf_sdio_regwb(bus->sdiodev, SDIO_CCCR_IOEx, |
3813 | SDIO_FUNC_ENABLE_1, NULL); | 3758 | SDIO_FUNC_ENABLE_1, NULL); |
3814 | 3759 | ||
3815 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; | 3760 | bus->sdiodev->bus_if->state = BRCMF_BUS_DOWN; |
3816 | bus->sleeping = false; | 3761 | bus->sleeping = false; |
3817 | bus->rxflow = false; | 3762 | bus->rxflow = false; |
3818 | 3763 | ||
3819 | /* Done with backplane-dependent accesses, can drop clock... */ | 3764 | /* Done with backplane-dependent accesses, can drop clock... */ |
3820 | brcmf_sdcard_cfg_write(bus->sdiodev, SDIO_FUNC_1, | 3765 | brcmf_sdio_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); |
3821 | SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); | ||
3822 | 3766 | ||
3823 | /* ...and initialize clock/power states */ | 3767 | /* ...and initialize clock/power states */ |
3824 | bus->clkstate = CLK_SDONLY; | 3768 | bus->clkstate = CLK_SDONLY; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c index 1534efc21631..f8e1f1c84d08 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_chip.c | |||
@@ -93,8 +93,9 @@ brcmf_sdio_sb_corerev(struct brcmf_sdio_dev *sdiodev, | |||
93 | 93 | ||
94 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 94 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
95 | 95 | ||
96 | regdata = brcmf_sdcard_reg_read(sdiodev, | 96 | regdata = brcmf_sdio_regrl(sdiodev, |
97 | CORE_SB(ci->c_inf[idx].base, sbidhigh), 4); | 97 | CORE_SB(ci->c_inf[idx].base, sbidhigh), |
98 | NULL); | ||
98 | return SBCOREREV(regdata); | 99 | return SBCOREREV(regdata); |
99 | } | 100 | } |
100 | 101 | ||
@@ -118,8 +119,9 @@ brcmf_sdio_sb_iscoreup(struct brcmf_sdio_dev *sdiodev, | |||
118 | 119 | ||
119 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 120 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
120 | 121 | ||
121 | regdata = brcmf_sdcard_reg_read(sdiodev, | 122 | regdata = brcmf_sdio_regrl(sdiodev, |
122 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | 123 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
124 | NULL); | ||
123 | regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT | | 125 | regdata &= (SSB_TMSLOW_RESET | SSB_TMSLOW_REJECT | |
124 | SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK); | 126 | SSB_IMSTATE_REJECT | SSB_TMSLOW_CLOCK); |
125 | return (SSB_TMSLOW_CLOCK == regdata); | 127 | return (SSB_TMSLOW_CLOCK == regdata); |
@@ -135,13 +137,13 @@ brcmf_sdio_ai_iscoreup(struct brcmf_sdio_dev *sdiodev, | |||
135 | 137 | ||
136 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 138 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
137 | 139 | ||
138 | regdata = brcmf_sdcard_reg_read(sdiodev, | 140 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
139 | ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4); | 141 | NULL); |
140 | ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK; | 142 | ret = (regdata & (BCMA_IOCTL_FGC | BCMA_IOCTL_CLK)) == BCMA_IOCTL_CLK; |
141 | 143 | ||
142 | regdata = brcmf_sdcard_reg_read(sdiodev, | 144 | regdata = brcmf_sdio_regrl(sdiodev, |
143 | ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | 145 | ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, |
144 | 4); | 146 | NULL); |
145 | ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0); | 147 | ret = ret && ((regdata & BCMA_RESET_CTL_RESET) == 0); |
146 | 148 | ||
147 | return ret; | 149 | return ret; |
@@ -151,84 +153,85 @@ static void | |||
151 | brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev, | 153 | brcmf_sdio_sb_coredisable(struct brcmf_sdio_dev *sdiodev, |
152 | struct chip_info *ci, u16 coreid) | 154 | struct chip_info *ci, u16 coreid) |
153 | { | 155 | { |
154 | u32 regdata; | 156 | u32 regdata, base; |
155 | u8 idx; | 157 | u8 idx; |
156 | 158 | ||
157 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 159 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
160 | base = ci->c_inf[idx].base; | ||
158 | 161 | ||
159 | regdata = brcmf_sdcard_reg_read(sdiodev, | 162 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL); |
160 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | ||
161 | if (regdata & SSB_TMSLOW_RESET) | 163 | if (regdata & SSB_TMSLOW_RESET) |
162 | return; | 164 | return; |
163 | 165 | ||
164 | regdata = brcmf_sdcard_reg_read(sdiodev, | 166 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), NULL); |
165 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | ||
166 | if ((regdata & SSB_TMSLOW_CLOCK) != 0) { | 167 | if ((regdata & SSB_TMSLOW_CLOCK) != 0) { |
167 | /* | 168 | /* |
168 | * set target reject and spin until busy is clear | 169 | * set target reject and spin until busy is clear |
169 | * (preserve core-specific bits) | 170 | * (preserve core-specific bits) |
170 | */ | 171 | */ |
171 | regdata = brcmf_sdcard_reg_read(sdiodev, | 172 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), |
172 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | 173 | NULL); |
173 | brcmf_sdcard_reg_write(sdiodev, | 174 | brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow), |
174 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), | 175 | regdata | SSB_TMSLOW_REJECT, NULL); |
175 | 4, regdata | SSB_TMSLOW_REJECT); | 176 | |
176 | 177 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), | |
177 | regdata = brcmf_sdcard_reg_read(sdiodev, | 178 | NULL); |
178 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | ||
179 | udelay(1); | 179 | udelay(1); |
180 | SPINWAIT((brcmf_sdcard_reg_read(sdiodev, | 180 | SPINWAIT((brcmf_sdio_regrl(sdiodev, |
181 | CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4) & | 181 | CORE_SB(base, sbtmstatehigh), |
182 | NULL) & | ||
182 | SSB_TMSHIGH_BUSY), 100000); | 183 | SSB_TMSHIGH_BUSY), 100000); |
183 | 184 | ||
184 | regdata = brcmf_sdcard_reg_read(sdiodev, | 185 | regdata = brcmf_sdio_regrl(sdiodev, |
185 | CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4); | 186 | CORE_SB(base, sbtmstatehigh), |
187 | NULL); | ||
186 | if (regdata & SSB_TMSHIGH_BUSY) | 188 | if (regdata & SSB_TMSHIGH_BUSY) |
187 | brcmf_dbg(ERROR, "core state still busy\n"); | 189 | brcmf_dbg(ERROR, "core state still busy\n"); |
188 | 190 | ||
189 | regdata = brcmf_sdcard_reg_read(sdiodev, | 191 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbidlow), |
190 | CORE_SB(ci->c_inf[idx].base, sbidlow), 4); | 192 | NULL); |
191 | if (regdata & SSB_IDLOW_INITIATOR) { | 193 | if (regdata & SSB_IDLOW_INITIATOR) { |
192 | regdata = brcmf_sdcard_reg_read(sdiodev, | 194 | regdata = brcmf_sdio_regrl(sdiodev, |
193 | CORE_SB(ci->c_inf[idx].base, sbimstate), 4) | | 195 | CORE_SB(base, sbimstate), |
194 | SSB_IMSTATE_REJECT; | 196 | NULL); |
195 | brcmf_sdcard_reg_write(sdiodev, | 197 | regdata |= SSB_IMSTATE_REJECT; |
196 | CORE_SB(ci->c_inf[idx].base, sbimstate), 4, | 198 | brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbimstate), |
197 | regdata); | 199 | regdata, NULL); |
198 | regdata = brcmf_sdcard_reg_read(sdiodev, | 200 | regdata = brcmf_sdio_regrl(sdiodev, |
199 | CORE_SB(ci->c_inf[idx].base, sbimstate), 4); | 201 | CORE_SB(base, sbimstate), |
202 | NULL); | ||
200 | udelay(1); | 203 | udelay(1); |
201 | SPINWAIT((brcmf_sdcard_reg_read(sdiodev, | 204 | SPINWAIT((brcmf_sdio_regrl(sdiodev, |
202 | CORE_SB(ci->c_inf[idx].base, sbimstate), 4) & | 205 | CORE_SB(base, sbimstate), |
206 | NULL) & | ||
203 | SSB_IMSTATE_BUSY), 100000); | 207 | SSB_IMSTATE_BUSY), 100000); |
204 | } | 208 | } |
205 | 209 | ||
206 | /* set reset and reject while enabling the clocks */ | 210 | /* set reset and reject while enabling the clocks */ |
207 | brcmf_sdcard_reg_write(sdiodev, | 211 | regdata = SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | |
208 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4, | 212 | SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET; |
209 | (SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | | 213 | brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow), |
210 | SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET)); | 214 | regdata, NULL); |
211 | regdata = brcmf_sdcard_reg_read(sdiodev, | 215 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbtmstatelow), |
212 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | 216 | NULL); |
213 | udelay(10); | 217 | udelay(10); |
214 | 218 | ||
215 | /* clear the initiator reject bit */ | 219 | /* clear the initiator reject bit */ |
216 | regdata = brcmf_sdcard_reg_read(sdiodev, | 220 | regdata = brcmf_sdio_regrl(sdiodev, CORE_SB(base, sbidlow), |
217 | CORE_SB(ci->c_inf[idx].base, sbidlow), 4); | 221 | NULL); |
218 | if (regdata & SSB_IDLOW_INITIATOR) { | 222 | if (regdata & SSB_IDLOW_INITIATOR) { |
219 | regdata = brcmf_sdcard_reg_read(sdiodev, | 223 | regdata = brcmf_sdio_regrl(sdiodev, |
220 | CORE_SB(ci->c_inf[idx].base, sbimstate), 4) & | 224 | CORE_SB(base, sbimstate), |
221 | ~SSB_IMSTATE_REJECT; | 225 | NULL); |
222 | brcmf_sdcard_reg_write(sdiodev, | 226 | regdata &= ~SSB_IMSTATE_REJECT; |
223 | CORE_SB(ci->c_inf[idx].base, sbimstate), 4, | 227 | brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbimstate), |
224 | regdata); | 228 | regdata, NULL); |
225 | } | 229 | } |
226 | } | 230 | } |
227 | 231 | ||
228 | /* leave reset and reject asserted */ | 232 | /* leave reset and reject asserted */ |
229 | brcmf_sdcard_reg_write(sdiodev, | 233 | brcmf_sdio_regwl(sdiodev, CORE_SB(base, sbtmstatelow), |
230 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4, | 234 | (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET), NULL); |
231 | (SSB_TMSLOW_REJECT | SSB_TMSLOW_RESET)); | ||
232 | udelay(1); | 235 | udelay(1); |
233 | } | 236 | } |
234 | 237 | ||
@@ -242,20 +245,19 @@ brcmf_sdio_ai_coredisable(struct brcmf_sdio_dev *sdiodev, | |||
242 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); | 245 | idx = brcmf_sdio_chip_getinfidx(ci, coreid); |
243 | 246 | ||
244 | /* if core is already in reset, just return */ | 247 | /* if core is already in reset, just return */ |
245 | regdata = brcmf_sdcard_reg_read(sdiodev, | 248 | regdata = brcmf_sdio_regrl(sdiodev, |
246 | ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | 249 | ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, |
247 | 4); | 250 | NULL); |
248 | if ((regdata & BCMA_RESET_CTL_RESET) != 0) | 251 | if ((regdata & BCMA_RESET_CTL_RESET) != 0) |
249 | return; | 252 | return; |
250 | 253 | ||
251 | brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 254 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, 0, NULL); |
252 | 4, 0); | 255 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
253 | regdata = brcmf_sdcard_reg_read(sdiodev, | 256 | NULL); |
254 | ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4); | ||
255 | udelay(10); | 257 | udelay(10); |
256 | 258 | ||
257 | brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | 259 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, |
258 | 4, BCMA_RESET_CTL_RESET); | 260 | BCMA_RESET_CTL_RESET, NULL); |
259 | udelay(1); | 261 | udelay(1); |
260 | } | 262 | } |
261 | 263 | ||
@@ -279,41 +281,47 @@ brcmf_sdio_sb_resetcore(struct brcmf_sdio_dev *sdiodev, | |||
279 | * set reset while enabling the clock and | 281 | * set reset while enabling the clock and |
280 | * forcing them on throughout the core | 282 | * forcing them on throughout the core |
281 | */ | 283 | */ |
282 | brcmf_sdcard_reg_write(sdiodev, | 284 | brcmf_sdio_regwl(sdiodev, |
283 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4, | 285 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
284 | SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET); | 286 | SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK | SSB_TMSLOW_RESET, |
285 | regdata = brcmf_sdcard_reg_read(sdiodev, | 287 | NULL); |
286 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | 288 | regdata = brcmf_sdio_regrl(sdiodev, |
289 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), | ||
290 | NULL); | ||
287 | udelay(1); | 291 | udelay(1); |
288 | 292 | ||
289 | /* clear any serror */ | 293 | /* clear any serror */ |
290 | regdata = brcmf_sdcard_reg_read(sdiodev, | 294 | regdata = brcmf_sdio_regrl(sdiodev, |
291 | CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4); | 295 | CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), |
296 | NULL); | ||
292 | if (regdata & SSB_TMSHIGH_SERR) | 297 | if (regdata & SSB_TMSHIGH_SERR) |
293 | brcmf_sdcard_reg_write(sdiodev, | 298 | brcmf_sdio_regwl(sdiodev, |
294 | CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), 4, 0); | 299 | CORE_SB(ci->c_inf[idx].base, sbtmstatehigh), |
300 | 0, NULL); | ||
295 | 301 | ||
296 | regdata = brcmf_sdcard_reg_read(sdiodev, | 302 | regdata = brcmf_sdio_regrl(sdiodev, |
297 | CORE_SB(ci->c_inf[idx].base, sbimstate), 4); | 303 | CORE_SB(ci->c_inf[idx].base, sbimstate), |
304 | NULL); | ||
298 | if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) | 305 | if (regdata & (SSB_IMSTATE_IBE | SSB_IMSTATE_TO)) |
299 | brcmf_sdcard_reg_write(sdiodev, | 306 | brcmf_sdio_regwl(sdiodev, |
300 | CORE_SB(ci->c_inf[idx].base, sbimstate), 4, | 307 | CORE_SB(ci->c_inf[idx].base, sbimstate), |
301 | regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO)); | 308 | regdata & ~(SSB_IMSTATE_IBE | SSB_IMSTATE_TO), |
309 | NULL); | ||
302 | 310 | ||
303 | /* clear reset and allow it to propagate throughout the core */ | 311 | /* clear reset and allow it to propagate throughout the core */ |
304 | brcmf_sdcard_reg_write(sdiodev, | 312 | brcmf_sdio_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
305 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4, | 313 | SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK, NULL); |
306 | SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK); | 314 | regdata = brcmf_sdio_regrl(sdiodev, |
307 | regdata = brcmf_sdcard_reg_read(sdiodev, | 315 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
308 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | 316 | NULL); |
309 | udelay(1); | 317 | udelay(1); |
310 | 318 | ||
311 | /* leave clock enabled */ | 319 | /* leave clock enabled */ |
312 | brcmf_sdcard_reg_write(sdiodev, | 320 | brcmf_sdio_regwl(sdiodev, CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
313 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), | 321 | SSB_TMSLOW_CLOCK, NULL); |
314 | 4, SSB_TMSLOW_CLOCK); | 322 | regdata = brcmf_sdio_regrl(sdiodev, |
315 | regdata = brcmf_sdcard_reg_read(sdiodev, | 323 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), |
316 | CORE_SB(ci->c_inf[idx].base, sbtmstatelow), 4); | 324 | NULL); |
317 | udelay(1); | 325 | udelay(1); |
318 | } | 326 | } |
319 | 327 | ||
@@ -330,18 +338,18 @@ brcmf_sdio_ai_resetcore(struct brcmf_sdio_dev *sdiodev, | |||
330 | brcmf_sdio_ai_coredisable(sdiodev, ci, coreid); | 338 | brcmf_sdio_ai_coredisable(sdiodev, ci, coreid); |
331 | 339 | ||
332 | /* now do initialization sequence */ | 340 | /* now do initialization sequence */ |
333 | brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 341 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
334 | 4, BCMA_IOCTL_FGC | BCMA_IOCTL_CLK); | 342 | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK, NULL); |
335 | regdata = brcmf_sdcard_reg_read(sdiodev, | 343 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
336 | ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4); | 344 | NULL); |
337 | brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, | 345 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_RESET_CTL, |
338 | 4, 0); | 346 | 0, NULL); |
339 | udelay(1); | 347 | udelay(1); |
340 | 348 | ||
341 | brcmf_sdcard_reg_write(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, | 349 | brcmf_sdio_regwl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
342 | 4, BCMA_IOCTL_CLK); | 350 | BCMA_IOCTL_CLK, NULL); |
343 | regdata = brcmf_sdcard_reg_read(sdiodev, | 351 | regdata = brcmf_sdio_regrl(sdiodev, ci->c_inf[idx].wrapbase+BCMA_IOCTL, |
344 | ci->c_inf[idx].wrapbase+BCMA_IOCTL, 4); | 352 | NULL); |
345 | udelay(1); | 353 | udelay(1); |
346 | } | 354 | } |
347 | 355 | ||
@@ -358,8 +366,9 @@ static int brcmf_sdio_chip_recognition(struct brcmf_sdio_dev *sdiodev, | |||
358 | */ | 366 | */ |
359 | ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON; | 367 | ci->c_inf[0].id = BCMA_CORE_CHIPCOMMON; |
360 | ci->c_inf[0].base = regs; | 368 | ci->c_inf[0].base = regs; |
361 | regdata = brcmf_sdcard_reg_read(sdiodev, | 369 | regdata = brcmf_sdio_regrl(sdiodev, |
362 | CORE_CC_REG(ci->c_inf[0].base, chipid), 4); | 370 | CORE_CC_REG(ci->c_inf[0].base, chipid), |
371 | NULL); | ||
363 | ci->chip = regdata & CID_ID_MASK; | 372 | ci->chip = regdata & CID_ID_MASK; |
364 | ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; | 373 | ci->chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; |
365 | ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT; | 374 | ci->socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT; |
@@ -428,8 +437,7 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev) | |||
428 | 437 | ||
429 | /* Try forcing SDIO core to do ALPAvail request only */ | 438 | /* Try forcing SDIO core to do ALPAvail request only */ |
430 | clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; | 439 | clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; |
431 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, | 440 | brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); |
432 | SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); | ||
433 | if (err) { | 441 | if (err) { |
434 | brcmf_dbg(ERROR, "error writing for HT off\n"); | 442 | brcmf_dbg(ERROR, "error writing for HT off\n"); |
435 | return err; | 443 | return err; |
@@ -437,8 +445,8 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev) | |||
437 | 445 | ||
438 | /* If register supported, wait for ALPAvail and then force ALP */ | 446 | /* If register supported, wait for ALPAvail and then force ALP */ |
439 | /* This may take up to 15 milliseconds */ | 447 | /* This may take up to 15 milliseconds */ |
440 | clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1, | 448 | clkval = brcmf_sdio_regrb(sdiodev, |
441 | SBSDIO_FUNC1_CHIPCLKCSR, NULL); | 449 | SBSDIO_FUNC1_CHIPCLKCSR, NULL); |
442 | 450 | ||
443 | if ((clkval & ~SBSDIO_AVBITS) != clkset) { | 451 | if ((clkval & ~SBSDIO_AVBITS) != clkset) { |
444 | brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n", | 452 | brcmf_dbg(ERROR, "ChipClkCSR access: wrote 0x%02x read 0x%02x\n", |
@@ -446,8 +454,8 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev) | |||
446 | return -EACCES; | 454 | return -EACCES; |
447 | } | 455 | } |
448 | 456 | ||
449 | SPINWAIT(((clkval = brcmf_sdcard_cfg_read(sdiodev, SDIO_FUNC_1, | 457 | SPINWAIT(((clkval = brcmf_sdio_regrb(sdiodev, |
450 | SBSDIO_FUNC1_CHIPCLKCSR, NULL)), | 458 | SBSDIO_FUNC1_CHIPCLKCSR, NULL)), |
451 | !SBSDIO_ALPAV(clkval)), | 459 | !SBSDIO_ALPAV(clkval)), |
452 | PMU_MAX_TRANSITION_DLY); | 460 | PMU_MAX_TRANSITION_DLY); |
453 | if (!SBSDIO_ALPAV(clkval)) { | 461 | if (!SBSDIO_ALPAV(clkval)) { |
@@ -457,13 +465,11 @@ brcmf_sdio_chip_buscoreprep(struct brcmf_sdio_dev *sdiodev) | |||
457 | } | 465 | } |
458 | 466 | ||
459 | clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP; | 467 | clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP; |
460 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, | 468 | brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); |
461 | SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); | ||
462 | udelay(65); | 469 | udelay(65); |
463 | 470 | ||
464 | /* Also, disable the extra SDIO pull-ups */ | 471 | /* Also, disable the extra SDIO pull-ups */ |
465 | brcmf_sdcard_cfg_write(sdiodev, SDIO_FUNC_1, | 472 | brcmf_sdio_regwb(sdiodev, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); |
466 | SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); | ||
467 | 473 | ||
468 | return 0; | 474 | return 0; |
469 | } | 475 | } |
@@ -472,18 +478,22 @@ static void | |||
472 | brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev, | 478 | brcmf_sdio_chip_buscoresetup(struct brcmf_sdio_dev *sdiodev, |
473 | struct chip_info *ci) | 479 | struct chip_info *ci) |
474 | { | 480 | { |
481 | u32 base = ci->c_inf[0].base; | ||
482 | |||
475 | /* get chipcommon rev */ | 483 | /* get chipcommon rev */ |
476 | ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id); | 484 | ci->c_inf[0].rev = ci->corerev(sdiodev, ci, ci->c_inf[0].id); |
477 | 485 | ||
478 | /* get chipcommon capabilites */ | 486 | /* get chipcommon capabilites */ |
479 | ci->c_inf[0].caps = | 487 | ci->c_inf[0].caps = brcmf_sdio_regrl(sdiodev, |
480 | brcmf_sdcard_reg_read(sdiodev, | 488 | CORE_CC_REG(base, capabilities), |
481 | CORE_CC_REG(ci->c_inf[0].base, capabilities), 4); | 489 | NULL); |
482 | 490 | ||
483 | /* get pmu caps & rev */ | 491 | /* get pmu caps & rev */ |
484 | if (ci->c_inf[0].caps & CC_CAP_PMU) { | 492 | if (ci->c_inf[0].caps & CC_CAP_PMU) { |
485 | ci->pmucaps = brcmf_sdcard_reg_read(sdiodev, | 493 | ci->pmucaps = |
486 | CORE_CC_REG(ci->c_inf[0].base, pmucapabilities), 4); | 494 | brcmf_sdio_regrl(sdiodev, |
495 | CORE_CC_REG(base, pmucapabilities), | ||
496 | NULL); | ||
487 | ci->pmurev = ci->pmucaps & PCAP_REV_MASK; | 497 | ci->pmurev = ci->pmucaps & PCAP_REV_MASK; |
488 | } | 498 | } |
489 | 499 | ||
@@ -523,10 +533,10 @@ int brcmf_sdio_chip_attach(struct brcmf_sdio_dev *sdiodev, | |||
523 | 533 | ||
524 | brcmf_sdio_chip_buscoresetup(sdiodev, ci); | 534 | brcmf_sdio_chip_buscoresetup(sdiodev, ci); |
525 | 535 | ||
526 | brcmf_sdcard_reg_write(sdiodev, | 536 | brcmf_sdio_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopullup), |
527 | CORE_CC_REG(ci->c_inf[0].base, gpiopullup), 4, 0); | 537 | 0, NULL); |
528 | brcmf_sdcard_reg_write(sdiodev, | 538 | brcmf_sdio_regwl(sdiodev, CORE_CC_REG(ci->c_inf[0].base, gpiopulldown), |
529 | CORE_CC_REG(ci->c_inf[0].base, gpiopulldown), 4, 0); | 539 | 0, NULL); |
530 | 540 | ||
531 | *ci_ptr = ci; | 541 | *ci_ptr = ci; |
532 | return 0; | 542 | return 0; |
@@ -562,6 +572,7 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | |||
562 | u32 str_mask = 0; | 572 | u32 str_mask = 0; |
563 | u32 str_shift = 0; | 573 | u32 str_shift = 0; |
564 | char chn[8]; | 574 | char chn[8]; |
575 | u32 base = ci->c_inf[0].base; | ||
565 | 576 | ||
566 | if (!(ci->c_inf[0].caps & CC_CAP_PMU)) | 577 | if (!(ci->c_inf[0].caps & CC_CAP_PMU)) |
567 | return; | 578 | return; |
@@ -591,17 +602,17 @@ brcmf_sdio_chip_drivestrengthinit(struct brcmf_sdio_dev *sdiodev, | |||
591 | } | 602 | } |
592 | } | 603 | } |
593 | 604 | ||
594 | brcmf_sdcard_reg_write(sdiodev, | 605 | brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr), |
595 | CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr), | 606 | 1, NULL); |
596 | 4, 1); | 607 | cc_data_temp = |
597 | cc_data_temp = brcmf_sdcard_reg_read(sdiodev, | 608 | brcmf_sdio_regrl(sdiodev, |
598 | CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr), 4); | 609 | CORE_CC_REG(base, chipcontrol_addr), |
610 | NULL); | ||
599 | cc_data_temp &= ~str_mask; | 611 | cc_data_temp &= ~str_mask; |
600 | drivestrength_sel <<= str_shift; | 612 | drivestrength_sel <<= str_shift; |
601 | cc_data_temp |= drivestrength_sel; | 613 | cc_data_temp |= drivestrength_sel; |
602 | brcmf_sdcard_reg_write(sdiodev, | 614 | brcmf_sdio_regwl(sdiodev, CORE_CC_REG(base, chipcontrol_addr), |
603 | CORE_CC_REG(ci->c_inf[0].base, chipcontrol_addr), | 615 | cc_data_temp, NULL); |
604 | 4, cc_data_temp); | ||
605 | 616 | ||
606 | brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n", | 617 | brcmf_dbg(INFO, "SDIO: %dmA drive strength selected, set to 0x%08x\n", |
607 | drivestrength, cc_data_temp); | 618 | drivestrength, cc_data_temp); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h index 7010eaf71f99..29bf78d264e0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h | |||
@@ -40,6 +40,10 @@ | |||
40 | /* Maximum number of I/O funcs */ | 40 | /* Maximum number of I/O funcs */ |
41 | #define SDIOD_MAX_IOFUNCS 7 | 41 | #define SDIOD_MAX_IOFUNCS 7 |
42 | 42 | ||
43 | /* mask of register map */ | ||
44 | #define REG_F0_REG_MASK 0x7FF | ||
45 | #define REG_F1_MISC_MASK 0x1FFFF | ||
46 | |||
43 | /* as of sdiod rev 0, supports 3 functions */ | 47 | /* as of sdiod rev 0, supports 3 functions */ |
44 | #define SBSDIO_NUM_FUNCTION 3 | 48 | #define SBSDIO_NUM_FUNCTION 3 |
45 | 49 | ||
@@ -142,7 +146,6 @@ struct brcmf_sdio_dev { | |||
142 | u8 num_funcs; /* Supported funcs on client */ | 146 | u8 num_funcs; /* Supported funcs on client */ |
143 | u32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; | 147 | u32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; |
144 | u32 sbwad; /* Save backplane window address */ | 148 | u32 sbwad; /* Save backplane window address */ |
145 | bool regfail; /* status of last reg_r/w call */ | ||
146 | void *bus; | 149 | void *bus; |
147 | atomic_t suspend; /* suspend flag */ | 150 | atomic_t suspend; /* suspend flag */ |
148 | wait_queue_head_t request_byte_wait; | 151 | wait_queue_head_t request_byte_wait; |
@@ -164,31 +167,13 @@ struct brcmf_sdio_dev { | |||
164 | extern int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev); | 167 | extern int brcmf_sdio_intr_register(struct brcmf_sdio_dev *sdiodev); |
165 | extern int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev); | 168 | extern int brcmf_sdio_intr_unregister(struct brcmf_sdio_dev *sdiodev); |
166 | 169 | ||
167 | /* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface). | 170 | /* sdio device register access interface */ |
168 | * fn: function number | 171 | extern u8 brcmf_sdio_regrb(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); |
169 | * addr: unmodified SDIO-space address | 172 | extern u32 brcmf_sdio_regrl(struct brcmf_sdio_dev *sdiodev, u32 addr, int *ret); |
170 | * data: data byte to write | 173 | extern void brcmf_sdio_regwb(struct brcmf_sdio_dev *sdiodev, u32 addr, |
171 | * err: pointer to error code (or NULL) | 174 | u8 data, int *ret); |
172 | */ | 175 | extern void brcmf_sdio_regwl(struct brcmf_sdio_dev *sdiodev, u32 addr, |
173 | extern u8 brcmf_sdcard_cfg_read(struct brcmf_sdio_dev *sdiodev, uint func, | 176 | u32 data, int *ret); |
174 | u32 addr, int *err); | ||
175 | extern void brcmf_sdcard_cfg_write(struct brcmf_sdio_dev *sdiodev, uint func, | ||
176 | u32 addr, u8 data, int *err); | ||
177 | |||
178 | /* Synchronous access to device (client) core registers via CMD53 to F1. | ||
179 | * addr: backplane address (i.e. >= regsva from attach) | ||
180 | * size: register width in bytes (2 or 4) | ||
181 | * data: data for register write | ||
182 | */ | ||
183 | extern u32 | ||
184 | brcmf_sdcard_reg_read(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size); | ||
185 | |||
186 | extern u32 | ||
187 | brcmf_sdcard_reg_write(struct brcmf_sdio_dev *sdiodev, u32 addr, uint size, | ||
188 | u32 data); | ||
189 | |||
190 | /* Indicate if last reg read/write failed */ | ||
191 | extern bool brcmf_sdcard_regfail(struct brcmf_sdio_dev *sdiodev); | ||
192 | 177 | ||
193 | /* Buffer transfer to/from device (client) core via cmd53. | 178 | /* Buffer transfer to/from device (client) core via cmd53. |
194 | * fn: function number | 179 | * fn: function number |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/Makefile b/drivers/net/wireless/brcm80211/brcmsmac/Makefile index c2eb2d0af386..e227c4c68ef9 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmsmac/Makefile | |||
@@ -39,10 +39,7 @@ BRCMSMAC_OFILES := \ | |||
39 | phy/phytbl_lcn.o \ | 39 | phy/phytbl_lcn.o \ |
40 | phy/phytbl_n.o \ | 40 | phy/phytbl_n.o \ |
41 | phy/phy_qmath.o \ | 41 | phy/phy_qmath.o \ |
42 | otp.o \ | ||
43 | srom.o \ | ||
44 | dma.o \ | 42 | dma.o \ |
45 | nicpci.o \ | ||
46 | brcms_trace_events.o | 43 | brcms_trace_events.o |
47 | 44 | ||
48 | MODULEPFX := brcmsmac | 45 | MODULEPFX := brcmsmac |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c index c93ea35bceec..6d8b7213643a 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 19 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
20 | 20 | ||
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/pci.h> | ||
23 | 22 | ||
24 | #include <defs.h> | 23 | #include <defs.h> |
25 | #include <chipcommon.h> | 24 | #include <chipcommon.h> |
@@ -29,8 +28,6 @@ | |||
29 | #include "types.h" | 28 | #include "types.h" |
30 | #include "pub.h" | 29 | #include "pub.h" |
31 | #include "pmu.h" | 30 | #include "pmu.h" |
32 | #include "srom.h" | ||
33 | #include "nicpci.h" | ||
34 | #include "aiutils.h" | 31 | #include "aiutils.h" |
35 | 32 | ||
36 | /* slow_clk_ctl */ | 33 | /* slow_clk_ctl */ |
@@ -321,7 +318,6 @@ | |||
321 | #define IS_SIM(chippkg) \ | 318 | #define IS_SIM(chippkg) \ |
322 | ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) | 319 | ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) |
323 | 320 | ||
324 | #define PCI(sih) (ai_get_buscoretype(sih) == PCI_CORE_ID) | ||
325 | #define PCIE(sih) (ai_get_buscoretype(sih) == PCIE_CORE_ID) | 321 | #define PCIE(sih) (ai_get_buscoretype(sih) == PCIE_CORE_ID) |
326 | 322 | ||
327 | #define PCI_FORCEHT(sih) (PCIE(sih) && (ai_get_chip_id(sih) == BCM4716_CHIP_ID)) | 323 | #define PCI_FORCEHT(sih) (PCIE(sih) && (ai_get_chip_id(sih) == BCM4716_CHIP_ID)) |
@@ -454,36 +450,9 @@ struct aidmp { | |||
454 | u32 componentid3; /* 0xffc */ | 450 | u32 componentid3; /* 0xffc */ |
455 | }; | 451 | }; |
456 | 452 | ||
457 | /* return true if PCIE capability exists in the pci config space */ | ||
458 | static bool ai_ispcie(struct si_info *sii) | ||
459 | { | ||
460 | u8 cap_ptr; | ||
461 | |||
462 | cap_ptr = | ||
463 | pcicore_find_pci_capability(sii->pcibus, PCI_CAP_ID_EXP, NULL, | ||
464 | NULL); | ||
465 | if (!cap_ptr) | ||
466 | return false; | ||
467 | |||
468 | return true; | ||
469 | } | ||
470 | |||
471 | static bool ai_buscore_prep(struct si_info *sii) | ||
472 | { | ||
473 | /* kludge to enable the clock on the 4306 which lacks a slowclock */ | ||
474 | if (!ai_ispcie(sii)) | ||
475 | ai_clkctl_xtal(&sii->pub, XTAL | PLL, ON); | ||
476 | return true; | ||
477 | } | ||
478 | |||
479 | static bool | 453 | static bool |
480 | ai_buscore_setup(struct si_info *sii, struct bcma_device *cc) | 454 | ai_buscore_setup(struct si_info *sii, struct bcma_device *cc) |
481 | { | 455 | { |
482 | struct bcma_device *pci = NULL; | ||
483 | struct bcma_device *pcie = NULL; | ||
484 | struct bcma_device *core; | ||
485 | |||
486 | |||
487 | /* no cores found, bail out */ | 456 | /* no cores found, bail out */ |
488 | if (cc->bus->nr_cores == 0) | 457 | if (cc->bus->nr_cores == 0) |
489 | return false; | 458 | return false; |
@@ -492,8 +461,7 @@ ai_buscore_setup(struct si_info *sii, struct bcma_device *cc) | |||
492 | sii->pub.ccrev = cc->id.rev; | 461 | sii->pub.ccrev = cc->id.rev; |
493 | 462 | ||
494 | /* get chipcommon chipstatus */ | 463 | /* get chipcommon chipstatus */ |
495 | if (ai_get_ccrev(&sii->pub) >= 11) | 464 | sii->chipst = bcma_read32(cc, CHIPCREGOFFS(chipstatus)); |
496 | sii->chipst = bcma_read32(cc, CHIPCREGOFFS(chipstatus)); | ||
497 | 465 | ||
498 | /* get chipcommon capabilites */ | 466 | /* get chipcommon capabilites */ |
499 | sii->pub.cccaps = bcma_read32(cc, CHIPCREGOFFS(capabilities)); | 467 | sii->pub.cccaps = bcma_read32(cc, CHIPCREGOFFS(capabilities)); |
@@ -506,64 +474,18 @@ ai_buscore_setup(struct si_info *sii, struct bcma_device *cc) | |||
506 | } | 474 | } |
507 | 475 | ||
508 | /* figure out buscore */ | 476 | /* figure out buscore */ |
509 | list_for_each_entry(core, &cc->bus->cores, list) { | 477 | sii->buscore = ai_findcore(&sii->pub, PCIE_CORE_ID, 0); |
510 | uint cid, crev; | ||
511 | |||
512 | cid = core->id.id; | ||
513 | crev = core->id.rev; | ||
514 | |||
515 | if (cid == PCI_CORE_ID) { | ||
516 | pci = core; | ||
517 | } else if (cid == PCIE_CORE_ID) { | ||
518 | pcie = core; | ||
519 | } | ||
520 | } | ||
521 | |||
522 | if (pci && pcie) { | ||
523 | if (ai_ispcie(sii)) | ||
524 | pci = NULL; | ||
525 | else | ||
526 | pcie = NULL; | ||
527 | } | ||
528 | if (pci) { | ||
529 | sii->buscore = pci; | ||
530 | } else if (pcie) { | ||
531 | sii->buscore = pcie; | ||
532 | } | ||
533 | |||
534 | /* fixup necessary chip/core configurations */ | ||
535 | if (!sii->pch) { | ||
536 | sii->pch = pcicore_init(&sii->pub, sii->icbus->drv_pci.core); | ||
537 | if (sii->pch == NULL) | ||
538 | return false; | ||
539 | } | ||
540 | if (ai_pci_fixcfg(&sii->pub)) | ||
541 | return false; | ||
542 | 478 | ||
543 | return true; | 479 | return true; |
544 | } | 480 | } |
545 | 481 | ||
546 | /* | ||
547 | * get boardtype and boardrev | ||
548 | */ | ||
549 | static __used void ai_nvram_process(struct si_info *sii) | ||
550 | { | ||
551 | uint w = 0; | ||
552 | |||
553 | /* do a pci config read to get subsystem id and subvendor id */ | ||
554 | pci_read_config_dword(sii->pcibus, PCI_SUBSYSTEM_VENDOR_ID, &w); | ||
555 | |||
556 | sii->pub.boardvendor = w & 0xffff; | ||
557 | sii->pub.boardtype = (w >> 16) & 0xffff; | ||
558 | } | ||
559 | |||
560 | static struct si_info *ai_doattach(struct si_info *sii, | 482 | static struct si_info *ai_doattach(struct si_info *sii, |
561 | struct bcma_bus *pbus) | 483 | struct bcma_bus *pbus) |
562 | { | 484 | { |
563 | struct si_pub *sih = &sii->pub; | 485 | struct si_pub *sih = &sii->pub; |
564 | u32 w, savewin; | 486 | u32 w, savewin; |
565 | struct bcma_device *cc; | 487 | struct bcma_device *cc; |
566 | uint socitype; | 488 | struct ssb_sprom *sprom = &pbus->sprom; |
567 | 489 | ||
568 | savewin = 0; | 490 | savewin = 0; |
569 | 491 | ||
@@ -573,38 +495,15 @@ static struct si_info *ai_doattach(struct si_info *sii, | |||
573 | /* switch to Chipcommon core */ | 495 | /* switch to Chipcommon core */ |
574 | cc = pbus->drv_cc.core; | 496 | cc = pbus->drv_cc.core; |
575 | 497 | ||
576 | /* bus/core/clk setup for register access */ | 498 | sih->chip = pbus->chipinfo.id; |
577 | if (!ai_buscore_prep(sii)) | 499 | sih->chiprev = pbus->chipinfo.rev; |
578 | return NULL; | 500 | sih->chippkg = pbus->chipinfo.pkg; |
501 | sih->boardvendor = pbus->boardinfo.vendor; | ||
502 | sih->boardtype = pbus->boardinfo.type; | ||
579 | 503 | ||
580 | /* | ||
581 | * ChipID recognition. | ||
582 | * We assume we can read chipid at offset 0 from the regs arg. | ||
583 | * If we add other chiptypes (or if we need to support old sdio | ||
584 | * hosts w/o chipcommon), some way of recognizing them needs to | ||
585 | * be added here. | ||
586 | */ | ||
587 | w = bcma_read32(cc, CHIPCREGOFFS(chipid)); | ||
588 | socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; | ||
589 | /* Might as wll fill in chip id rev & pkg */ | ||
590 | sih->chip = w & CID_ID_MASK; | ||
591 | sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; | ||
592 | sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; | ||
593 | |||
594 | /* scan for cores */ | ||
595 | if (socitype != SOCI_AI) | ||
596 | return NULL; | ||
597 | |||
598 | SI_MSG("Found chip type AI (0x%08x)\n", w); | ||
599 | if (!ai_buscore_setup(sii, cc)) | 504 | if (!ai_buscore_setup(sii, cc)) |
600 | goto exit; | 505 | goto exit; |
601 | 506 | ||
602 | /* Init nvram from sprom/otp if they exist */ | ||
603 | if (srom_var_init(&sii->pub)) | ||
604 | goto exit; | ||
605 | |||
606 | ai_nvram_process(sii); | ||
607 | |||
608 | /* === NVRAM, clock is ready === */ | 507 | /* === NVRAM, clock is ready === */ |
609 | bcma_write32(cc, CHIPCREGOFFS(gpiopullup), 0); | 508 | bcma_write32(cc, CHIPCREGOFFS(gpiopullup), 0); |
610 | bcma_write32(cc, CHIPCREGOFFS(gpiopulldown), 0); | 509 | bcma_write32(cc, CHIPCREGOFFS(gpiopulldown), 0); |
@@ -617,15 +516,13 @@ static struct si_info *ai_doattach(struct si_info *sii, | |||
617 | } | 516 | } |
618 | 517 | ||
619 | /* setup the GPIO based LED powersave register */ | 518 | /* setup the GPIO based LED powersave register */ |
620 | w = getintvar(sih, BRCMS_SROM_LEDDC); | 519 | w = (sprom->leddc_on_time << BCMA_CC_GPIOTIMER_ONTIME_SHIFT) | |
520 | (sprom->leddc_off_time << BCMA_CC_GPIOTIMER_OFFTIME_SHIFT); | ||
621 | if (w == 0) | 521 | if (w == 0) |
622 | w = DEFAULT_GPIOTIMERVAL; | 522 | w = DEFAULT_GPIOTIMERVAL; |
623 | ai_cc_reg(sih, offsetof(struct chipcregs, gpiotimerval), | 523 | ai_cc_reg(sih, offsetof(struct chipcregs, gpiotimerval), |
624 | ~0, w); | 524 | ~0, w); |
625 | 525 | ||
626 | if (PCIE(sih)) | ||
627 | pcicore_attach(sii->pch, SI_DOATTACH); | ||
628 | |||
629 | if (ai_get_chip_id(sih) == BCM43224_CHIP_ID) { | 526 | if (ai_get_chip_id(sih) == BCM43224_CHIP_ID) { |
630 | /* | 527 | /* |
631 | * enable 12 mA drive strenth for 43224 and | 528 | * enable 12 mA drive strenth for 43224 and |
@@ -659,9 +556,6 @@ static struct si_info *ai_doattach(struct si_info *sii, | |||
659 | return sii; | 556 | return sii; |
660 | 557 | ||
661 | exit: | 558 | exit: |
662 | if (sii->pch) | ||
663 | pcicore_deinit(sii->pch); | ||
664 | sii->pch = NULL; | ||
665 | 559 | ||
666 | return NULL; | 560 | return NULL; |
667 | } | 561 | } |
@@ -700,11 +594,6 @@ void ai_detach(struct si_pub *sih) | |||
700 | if (sii == NULL) | 594 | if (sii == NULL) |
701 | return; | 595 | return; |
702 | 596 | ||
703 | if (sii->pch) | ||
704 | pcicore_deinit(sii->pch); | ||
705 | sii->pch = NULL; | ||
706 | |||
707 | srom_free_vars(sih); | ||
708 | kfree(sii); | 597 | kfree(sii); |
709 | } | 598 | } |
710 | 599 | ||
@@ -755,21 +644,7 @@ uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val) | |||
755 | /* return the slow clock source - LPO, XTAL, or PCI */ | 644 | /* return the slow clock source - LPO, XTAL, or PCI */ |
756 | static uint ai_slowclk_src(struct si_pub *sih, struct bcma_device *cc) | 645 | static uint ai_slowclk_src(struct si_pub *sih, struct bcma_device *cc) |
757 | { | 646 | { |
758 | struct si_info *sii; | 647 | return SCC_SS_XTAL; |
759 | u32 val; | ||
760 | |||
761 | sii = (struct si_info *)sih; | ||
762 | if (ai_get_ccrev(&sii->pub) < 6) { | ||
763 | pci_read_config_dword(sii->pcibus, PCI_GPIO_OUT, | ||
764 | &val); | ||
765 | if (val & PCI_CFG_GPIO_SCS) | ||
766 | return SCC_SS_PCI; | ||
767 | return SCC_SS_XTAL; | ||
768 | } else if (ai_get_ccrev(&sii->pub) < 10) { | ||
769 | return bcma_read32(cc, CHIPCREGOFFS(slow_clk_ctl)) & | ||
770 | SCC_SS_MASK; | ||
771 | } else /* Insta-clock */ | ||
772 | return SCC_SS_XTAL; | ||
773 | } | 648 | } |
774 | 649 | ||
775 | /* | 650 | /* |
@@ -779,36 +654,12 @@ static uint ai_slowclk_src(struct si_pub *sih, struct bcma_device *cc) | |||
779 | static uint ai_slowclk_freq(struct si_pub *sih, bool max_freq, | 654 | static uint ai_slowclk_freq(struct si_pub *sih, bool max_freq, |
780 | struct bcma_device *cc) | 655 | struct bcma_device *cc) |
781 | { | 656 | { |
782 | u32 slowclk; | ||
783 | uint div; | 657 | uint div; |
784 | 658 | ||
785 | slowclk = ai_slowclk_src(sih, cc); | 659 | /* Chipc rev 10 is InstaClock */ |
786 | if (ai_get_ccrev(sih) < 6) { | 660 | div = bcma_read32(cc, CHIPCREGOFFS(system_clk_ctl)); |
787 | if (slowclk == SCC_SS_PCI) | 661 | div = 4 * ((div >> SYCC_CD_SHIFT) + 1); |
788 | return max_freq ? (PCIMAXFREQ / 64) | 662 | return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div); |
789 | : (PCIMINFREQ / 64); | ||
790 | else | ||
791 | return max_freq ? (XTALMAXFREQ / 32) | ||
792 | : (XTALMINFREQ / 32); | ||
793 | } else if (ai_get_ccrev(sih) < 10) { | ||
794 | div = 4 * | ||
795 | (((bcma_read32(cc, CHIPCREGOFFS(slow_clk_ctl)) & | ||
796 | SCC_CD_MASK) >> SCC_CD_SHIFT) + 1); | ||
797 | if (slowclk == SCC_SS_LPO) | ||
798 | return max_freq ? LPOMAXFREQ : LPOMINFREQ; | ||
799 | else if (slowclk == SCC_SS_XTAL) | ||
800 | return max_freq ? (XTALMAXFREQ / div) | ||
801 | : (XTALMINFREQ / div); | ||
802 | else if (slowclk == SCC_SS_PCI) | ||
803 | return max_freq ? (PCIMAXFREQ / div) | ||
804 | : (PCIMINFREQ / div); | ||
805 | } else { | ||
806 | /* Chipc rev 10 is InstaClock */ | ||
807 | div = bcma_read32(cc, CHIPCREGOFFS(system_clk_ctl)); | ||
808 | div = 4 * ((div >> SYCC_CD_SHIFT) + 1); | ||
809 | return max_freq ? XTALMAXFREQ : (XTALMINFREQ / div); | ||
810 | } | ||
811 | return 0; | ||
812 | } | 663 | } |
813 | 664 | ||
814 | static void | 665 | static void |
@@ -831,8 +682,7 @@ ai_clkctl_setdelay(struct si_pub *sih, struct bcma_device *cc) | |||
831 | 682 | ||
832 | /* Starting with 4318 it is ILP that is used for the delays */ | 683 | /* Starting with 4318 it is ILP that is used for the delays */ |
833 | slowmaxfreq = | 684 | slowmaxfreq = |
834 | ai_slowclk_freq(sih, | 685 | ai_slowclk_freq(sih, false, cc); |
835 | (ai_get_ccrev(sih) >= 10) ? false : true, cc); | ||
836 | 686 | ||
837 | pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; | 687 | pll_on_delay = ((slowmaxfreq * pll_delay) + 999999) / 1000000; |
838 | fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; | 688 | fref_sel_delay = ((slowmaxfreq * FREF_DELAY) + 999999) / 1000000; |
@@ -854,9 +704,8 @@ void ai_clkctl_init(struct si_pub *sih) | |||
854 | return; | 704 | return; |
855 | 705 | ||
856 | /* set all Instaclk chip ILP to 1 MHz */ | 706 | /* set all Instaclk chip ILP to 1 MHz */ |
857 | if (ai_get_ccrev(sih) >= 10) | 707 | bcma_maskset32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_CD_MASK, |
858 | bcma_maskset32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_CD_MASK, | 708 | (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); |
859 | (ILP_DIV_1MHZ << SYCC_CD_SHIFT)); | ||
860 | 709 | ||
861 | ai_clkctl_setdelay(sih, cc); | 710 | ai_clkctl_setdelay(sih, cc); |
862 | } | 711 | } |
@@ -891,140 +740,6 @@ u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih) | |||
891 | return fpdelay; | 740 | return fpdelay; |
892 | } | 741 | } |
893 | 742 | ||
894 | /* turn primary xtal and/or pll off/on */ | ||
895 | int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on) | ||
896 | { | ||
897 | struct si_info *sii; | ||
898 | u32 in, out, outen; | ||
899 | |||
900 | sii = (struct si_info *)sih; | ||
901 | |||
902 | /* pcie core doesn't have any mapping to control the xtal pu */ | ||
903 | if (PCIE(sih)) | ||
904 | return -1; | ||
905 | |||
906 | pci_read_config_dword(sii->pcibus, PCI_GPIO_IN, &in); | ||
907 | pci_read_config_dword(sii->pcibus, PCI_GPIO_OUT, &out); | ||
908 | pci_read_config_dword(sii->pcibus, PCI_GPIO_OUTEN, &outen); | ||
909 | |||
910 | /* | ||
911 | * Avoid glitching the clock if GPRS is already using it. | ||
912 | * We can't actually read the state of the PLLPD so we infer it | ||
913 | * by the value of XTAL_PU which *is* readable via gpioin. | ||
914 | */ | ||
915 | if (on && (in & PCI_CFG_GPIO_XTAL)) | ||
916 | return 0; | ||
917 | |||
918 | if (what & XTAL) | ||
919 | outen |= PCI_CFG_GPIO_XTAL; | ||
920 | if (what & PLL) | ||
921 | outen |= PCI_CFG_GPIO_PLL; | ||
922 | |||
923 | if (on) { | ||
924 | /* turn primary xtal on */ | ||
925 | if (what & XTAL) { | ||
926 | out |= PCI_CFG_GPIO_XTAL; | ||
927 | if (what & PLL) | ||
928 | out |= PCI_CFG_GPIO_PLL; | ||
929 | pci_write_config_dword(sii->pcibus, | ||
930 | PCI_GPIO_OUT, out); | ||
931 | pci_write_config_dword(sii->pcibus, | ||
932 | PCI_GPIO_OUTEN, outen); | ||
933 | udelay(XTAL_ON_DELAY); | ||
934 | } | ||
935 | |||
936 | /* turn pll on */ | ||
937 | if (what & PLL) { | ||
938 | out &= ~PCI_CFG_GPIO_PLL; | ||
939 | pci_write_config_dword(sii->pcibus, | ||
940 | PCI_GPIO_OUT, out); | ||
941 | mdelay(2); | ||
942 | } | ||
943 | } else { | ||
944 | if (what & XTAL) | ||
945 | out &= ~PCI_CFG_GPIO_XTAL; | ||
946 | if (what & PLL) | ||
947 | out |= PCI_CFG_GPIO_PLL; | ||
948 | pci_write_config_dword(sii->pcibus, | ||
949 | PCI_GPIO_OUT, out); | ||
950 | pci_write_config_dword(sii->pcibus, | ||
951 | PCI_GPIO_OUTEN, outen); | ||
952 | } | ||
953 | |||
954 | return 0; | ||
955 | } | ||
956 | |||
957 | /* clk control mechanism through chipcommon, no policy checking */ | ||
958 | static bool _ai_clkctl_cc(struct si_info *sii, uint mode) | ||
959 | { | ||
960 | struct bcma_device *cc; | ||
961 | u32 scc; | ||
962 | |||
963 | /* chipcommon cores prior to rev6 don't support dynamic clock control */ | ||
964 | if (ai_get_ccrev(&sii->pub) < 6) | ||
965 | return false; | ||
966 | |||
967 | cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0); | ||
968 | |||
969 | if (!(ai_get_cccaps(&sii->pub) & CC_CAP_PWR_CTL) && | ||
970 | (ai_get_ccrev(&sii->pub) < 20)) | ||
971 | return mode == CLK_FAST; | ||
972 | |||
973 | switch (mode) { | ||
974 | case CLK_FAST: /* FORCEHT, fast (pll) clock */ | ||
975 | if (ai_get_ccrev(&sii->pub) < 10) { | ||
976 | /* | ||
977 | * don't forget to force xtal back | ||
978 | * on before we clear SCC_DYN_XTAL.. | ||
979 | */ | ||
980 | ai_clkctl_xtal(&sii->pub, XTAL, ON); | ||
981 | bcma_maskset32(cc, CHIPCREGOFFS(slow_clk_ctl), | ||
982 | (SCC_XC | SCC_FS | SCC_IP), SCC_IP); | ||
983 | } else if (ai_get_ccrev(&sii->pub) < 20) { | ||
984 | bcma_set32(cc, CHIPCREGOFFS(system_clk_ctl), SYCC_HR); | ||
985 | } else { | ||
986 | bcma_set32(cc, CHIPCREGOFFS(clk_ctl_st), CCS_FORCEHT); | ||
987 | } | ||
988 | |||
989 | /* wait for the PLL */ | ||
990 | if (ai_get_cccaps(&sii->pub) & CC_CAP_PMU) { | ||
991 | u32 htavail = CCS_HTAVAIL; | ||
992 | SPINWAIT(((bcma_read32(cc, CHIPCREGOFFS(clk_ctl_st)) & | ||
993 | htavail) == 0), PMU_MAX_TRANSITION_DLY); | ||
994 | } else { | ||
995 | udelay(PLL_DELAY); | ||
996 | } | ||
997 | break; | ||
998 | |||
999 | case CLK_DYNAMIC: /* enable dynamic clock control */ | ||
1000 | if (ai_get_ccrev(&sii->pub) < 10) { | ||
1001 | scc = bcma_read32(cc, CHIPCREGOFFS(slow_clk_ctl)); | ||
1002 | scc &= ~(SCC_FS | SCC_IP | SCC_XC); | ||
1003 | if ((scc & SCC_SS_MASK) != SCC_SS_XTAL) | ||
1004 | scc |= SCC_XC; | ||
1005 | bcma_write32(cc, CHIPCREGOFFS(slow_clk_ctl), scc); | ||
1006 | |||
1007 | /* | ||
1008 | * for dynamic control, we have to | ||
1009 | * release our xtal_pu "force on" | ||
1010 | */ | ||
1011 | if (scc & SCC_XC) | ||
1012 | ai_clkctl_xtal(&sii->pub, XTAL, OFF); | ||
1013 | } else if (ai_get_ccrev(&sii->pub) < 20) { | ||
1014 | /* Instaclock */ | ||
1015 | bcma_mask32(cc, CHIPCREGOFFS(system_clk_ctl), ~SYCC_HR); | ||
1016 | } else { | ||
1017 | bcma_mask32(cc, CHIPCREGOFFS(clk_ctl_st), ~CCS_FORCEHT); | ||
1018 | } | ||
1019 | break; | ||
1020 | |||
1021 | default: | ||
1022 | break; | ||
1023 | } | ||
1024 | |||
1025 | return mode == CLK_FAST; | ||
1026 | } | ||
1027 | |||
1028 | /* | 743 | /* |
1029 | * clock control policy function throught chipcommon | 744 | * clock control policy function throught chipcommon |
1030 | * | 745 | * |
@@ -1033,133 +748,53 @@ static bool _ai_clkctl_cc(struct si_info *sii, uint mode) | |||
1033 | * this is a wrapper over the next internal function | 748 | * this is a wrapper over the next internal function |
1034 | * to allow flexible policy settings for outside caller | 749 | * to allow flexible policy settings for outside caller |
1035 | */ | 750 | */ |
1036 | bool ai_clkctl_cc(struct si_pub *sih, uint mode) | 751 | bool ai_clkctl_cc(struct si_pub *sih, enum bcma_clkmode mode) |
1037 | { | 752 | { |
1038 | struct si_info *sii; | 753 | struct si_info *sii; |
754 | struct bcma_device *cc; | ||
1039 | 755 | ||
1040 | sii = (struct si_info *)sih; | 756 | sii = (struct si_info *)sih; |
1041 | 757 | ||
1042 | /* chipcommon cores prior to rev6 don't support dynamic clock control */ | ||
1043 | if (ai_get_ccrev(sih) < 6) | ||
1044 | return false; | ||
1045 | |||
1046 | if (PCI_FORCEHT(sih)) | 758 | if (PCI_FORCEHT(sih)) |
1047 | return mode == CLK_FAST; | 759 | return mode == BCMA_CLKMODE_FAST; |
1048 | 760 | ||
1049 | return _ai_clkctl_cc(sii, mode); | 761 | cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0); |
762 | bcma_core_set_clockmode(cc, mode); | ||
763 | return mode == BCMA_CLKMODE_FAST; | ||
1050 | } | 764 | } |
1051 | 765 | ||
1052 | void ai_pci_up(struct si_pub *sih) | 766 | void ai_pci_up(struct si_pub *sih) |
1053 | { | 767 | { |
1054 | struct si_info *sii; | 768 | struct si_info *sii; |
769 | struct bcma_device *cc; | ||
1055 | 770 | ||
1056 | sii = (struct si_info *)sih; | 771 | sii = (struct si_info *)sih; |
1057 | 772 | ||
1058 | if (PCI_FORCEHT(sih)) | 773 | if (PCI_FORCEHT(sih)) { |
1059 | _ai_clkctl_cc(sii, CLK_FAST); | 774 | cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0); |
775 | bcma_core_set_clockmode(cc, BCMA_CLKMODE_FAST); | ||
776 | } | ||
1060 | 777 | ||
1061 | if (PCIE(sih)) | 778 | if (PCIE(sih)) |
1062 | pcicore_up(sii->pch, SI_PCIUP); | 779 | bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, true); |
1063 | |||
1064 | } | ||
1065 | |||
1066 | /* Unconfigure and/or apply various WARs when system is going to sleep mode */ | ||
1067 | void ai_pci_sleep(struct si_pub *sih) | ||
1068 | { | ||
1069 | struct si_info *sii; | ||
1070 | |||
1071 | sii = (struct si_info *)sih; | ||
1072 | |||
1073 | pcicore_sleep(sii->pch); | ||
1074 | } | 780 | } |
1075 | 781 | ||
1076 | /* Unconfigure and/or apply various WARs when going down */ | 782 | /* Unconfigure and/or apply various WARs when going down */ |
1077 | void ai_pci_down(struct si_pub *sih) | 783 | void ai_pci_down(struct si_pub *sih) |
1078 | { | 784 | { |
1079 | struct si_info *sii; | 785 | struct si_info *sii; |
786 | struct bcma_device *cc; | ||
1080 | 787 | ||
1081 | sii = (struct si_info *)sih; | 788 | sii = (struct si_info *)sih; |
1082 | 789 | ||
1083 | /* release FORCEHT since chip is going to "down" state */ | 790 | /* release FORCEHT since chip is going to "down" state */ |
1084 | if (PCI_FORCEHT(sih)) | 791 | if (PCI_FORCEHT(sih)) { |
1085 | _ai_clkctl_cc(sii, CLK_DYNAMIC); | 792 | cc = ai_findcore(&sii->pub, BCMA_CORE_CHIPCOMMON, 0); |
1086 | 793 | bcma_core_set_clockmode(cc, BCMA_CLKMODE_DYNAMIC); | |
1087 | pcicore_down(sii->pch, SI_PCIDOWN); | ||
1088 | } | ||
1089 | |||
1090 | /* | ||
1091 | * Configure the pci core for pci client (NIC) action | ||
1092 | * coremask is the bitvec of cores by index to be enabled. | ||
1093 | */ | ||
1094 | void ai_pci_setup(struct si_pub *sih, uint coremask) | ||
1095 | { | ||
1096 | struct si_info *sii; | ||
1097 | u32 w; | ||
1098 | |||
1099 | sii = (struct si_info *)sih; | ||
1100 | |||
1101 | /* | ||
1102 | * Enable sb->pci interrupts. Assume | ||
1103 | * PCI rev 2.3 support was added in pci core rev 6 and things changed.. | ||
1104 | */ | ||
1105 | if (PCIE(sih) || (PCI(sih) && (ai_get_buscorerev(sih) >= 6))) { | ||
1106 | /* pci config write to set this core bit in PCIIntMask */ | ||
1107 | pci_read_config_dword(sii->pcibus, PCI_INT_MASK, &w); | ||
1108 | w |= (coremask << PCI_SBIM_SHIFT); | ||
1109 | pci_write_config_dword(sii->pcibus, PCI_INT_MASK, w); | ||
1110 | } | ||
1111 | |||
1112 | if (PCI(sih)) { | ||
1113 | pcicore_pci_setup(sii->pch); | ||
1114 | } | 794 | } |
1115 | } | ||
1116 | 795 | ||
1117 | /* | 796 | if (PCIE(sih)) |
1118 | * Fixup SROMless PCI device's configuration. | 797 | bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, false); |
1119 | * The current core may be changed upon return. | ||
1120 | */ | ||
1121 | int ai_pci_fixcfg(struct si_pub *sih) | ||
1122 | { | ||
1123 | struct si_info *sii = (struct si_info *)sih; | ||
1124 | |||
1125 | /* Fixup PI in SROM shadow area to enable the correct PCI core access */ | ||
1126 | /* check 'pi' is correct and fix it if not */ | ||
1127 | pcicore_fixcfg(sii->pch); | ||
1128 | pcicore_hwup(sii->pch); | ||
1129 | return 0; | ||
1130 | } | ||
1131 | |||
1132 | /* mask&set gpiocontrol bits */ | ||
1133 | u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val, u8 priority) | ||
1134 | { | ||
1135 | uint regoff; | ||
1136 | |||
1137 | regoff = offsetof(struct chipcregs, gpiocontrol); | ||
1138 | return ai_cc_reg(sih, regoff, mask, val); | ||
1139 | } | ||
1140 | |||
1141 | void ai_chipcontrl_epa4331(struct si_pub *sih, bool on) | ||
1142 | { | ||
1143 | struct bcma_device *cc; | ||
1144 | u32 val; | ||
1145 | |||
1146 | cc = ai_findcore(sih, CC_CORE_ID, 0); | ||
1147 | |||
1148 | if (on) { | ||
1149 | if (ai_get_chippkg(sih) == 9 || ai_get_chippkg(sih) == 0xb) | ||
1150 | /* Ext PA Controls for 4331 12x9 Package */ | ||
1151 | bcma_set32(cc, CHIPCREGOFFS(chipcontrol), | ||
1152 | CCTRL4331_EXTPA_EN | | ||
1153 | CCTRL4331_EXTPA_ON_GPIO2_5); | ||
1154 | else | ||
1155 | /* Ext PA Controls for 4331 12x12 Package */ | ||
1156 | bcma_set32(cc, CHIPCREGOFFS(chipcontrol), | ||
1157 | CCTRL4331_EXTPA_EN); | ||
1158 | } else { | ||
1159 | val &= ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5); | ||
1160 | bcma_mask32(cc, CHIPCREGOFFS(chipcontrol), | ||
1161 | ~(CCTRL4331_EXTPA_EN | CCTRL4331_EXTPA_ON_GPIO2_5)); | ||
1162 | } | ||
1163 | } | 798 | } |
1164 | 799 | ||
1165 | /* Enable BT-COEX & Ex-PA for 4313 */ | 800 | /* Enable BT-COEX & Ex-PA for 4313 */ |
@@ -1181,6 +816,9 @@ bool ai_deviceremoved(struct si_pub *sih) | |||
1181 | 816 | ||
1182 | sii = (struct si_info *)sih; | 817 | sii = (struct si_info *)sih; |
1183 | 818 | ||
819 | if (sii->icbus->hosttype != BCMA_HOSTTYPE_PCI) | ||
820 | return false; | ||
821 | |||
1184 | pci_read_config_dword(sii->pcibus, PCI_VENDOR_ID, &w); | 822 | pci_read_config_dword(sii->pcibus, PCI_VENDOR_ID, &w); |
1185 | if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM) | 823 | if ((w & 0xFFFF) != PCI_VENDOR_ID_BROADCOM) |
1186 | return true; | 824 | return true; |
@@ -1188,45 +826,6 @@ bool ai_deviceremoved(struct si_pub *sih) | |||
1188 | return false; | 826 | return false; |
1189 | } | 827 | } |
1190 | 828 | ||
1191 | bool ai_is_sprom_available(struct si_pub *sih) | ||
1192 | { | ||
1193 | struct si_info *sii = (struct si_info *)sih; | ||
1194 | |||
1195 | if (ai_get_ccrev(sih) >= 31) { | ||
1196 | struct bcma_device *cc; | ||
1197 | u32 sromctrl; | ||
1198 | |||
1199 | if ((ai_get_cccaps(sih) & CC_CAP_SROM) == 0) | ||
1200 | return false; | ||
1201 | |||
1202 | cc = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); | ||
1203 | sromctrl = bcma_read32(cc, CHIPCREGOFFS(sromcontrol)); | ||
1204 | return sromctrl & SRC_PRESENT; | ||
1205 | } | ||
1206 | |||
1207 | switch (ai_get_chip_id(sih)) { | ||
1208 | case BCM4313_CHIP_ID: | ||
1209 | return (sii->chipst & CST4313_SPROM_PRESENT) != 0; | ||
1210 | default: | ||
1211 | return true; | ||
1212 | } | ||
1213 | } | ||
1214 | |||
1215 | bool ai_is_otp_disabled(struct si_pub *sih) | ||
1216 | { | ||
1217 | struct si_info *sii = (struct si_info *)sih; | ||
1218 | |||
1219 | switch (ai_get_chip_id(sih)) { | ||
1220 | case BCM4313_CHIP_ID: | ||
1221 | return (sii->chipst & CST4313_OTP_PRESENT) == 0; | ||
1222 | /* These chips always have their OTP on */ | ||
1223 | case BCM43224_CHIP_ID: | ||
1224 | case BCM43225_CHIP_ID: | ||
1225 | default: | ||
1226 | return false; | ||
1227 | } | ||
1228 | } | ||
1229 | |||
1230 | uint ai_get_buscoretype(struct si_pub *sih) | 829 | uint ai_get_buscoretype(struct si_pub *sih) |
1231 | { | 830 | { |
1232 | struct si_info *sii = (struct si_info *)sih; | 831 | struct si_info *sii = (struct si_info *)sih; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h index f84c6f781692..d9f04a683bdb 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.h | |||
@@ -113,10 +113,6 @@ | |||
113 | #define XTAL 0x1 /* primary crystal oscillator (2050) */ | 113 | #define XTAL 0x1 /* primary crystal oscillator (2050) */ |
114 | #define PLL 0x2 /* main chip pll */ | 114 | #define PLL 0x2 /* main chip pll */ |
115 | 115 | ||
116 | /* clkctl clk mode */ | ||
117 | #define CLK_FAST 0 /* force fast (pll) clock */ | ||
118 | #define CLK_DYNAMIC 2 /* enable dynamic clock control */ | ||
119 | |||
120 | /* GPIO usage priorities */ | 116 | /* GPIO usage priorities */ |
121 | #define GPIO_DRV_PRIORITY 0 /* Driver */ | 117 | #define GPIO_DRV_PRIORITY 0 /* Driver */ |
122 | #define GPIO_APP_PRIORITY 1 /* Application */ | 118 | #define GPIO_APP_PRIORITY 1 /* Application */ |
@@ -172,9 +168,7 @@ struct si_info { | |||
172 | struct si_pub pub; /* back plane public state (must be first) */ | 168 | struct si_pub pub; /* back plane public state (must be first) */ |
173 | struct bcma_bus *icbus; /* handle to soc interconnect bus */ | 169 | struct bcma_bus *icbus; /* handle to soc interconnect bus */ |
174 | struct pci_dev *pcibus; /* handle to pci bus */ | 170 | struct pci_dev *pcibus; /* handle to pci bus */ |
175 | struct pcicore_info *pch; /* PCI/E core handle */ | ||
176 | struct bcma_device *buscore; | 171 | struct bcma_device *buscore; |
177 | struct list_head var_list; /* list of srom variables */ | ||
178 | 172 | ||
179 | u32 chipst; /* chip status */ | 173 | u32 chipst; /* chip status */ |
180 | }; | 174 | }; |
@@ -197,38 +191,20 @@ extern u32 ai_core_cflags(struct bcma_device *core, u32 mask, u32 val); | |||
197 | extern struct si_pub *ai_attach(struct bcma_bus *pbus); | 191 | extern struct si_pub *ai_attach(struct bcma_bus *pbus); |
198 | extern void ai_detach(struct si_pub *sih); | 192 | extern void ai_detach(struct si_pub *sih); |
199 | extern uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val); | 193 | extern uint ai_cc_reg(struct si_pub *sih, uint regoff, u32 mask, u32 val); |
200 | extern void ai_pci_setup(struct si_pub *sih, uint coremask); | ||
201 | extern void ai_clkctl_init(struct si_pub *sih); | 194 | extern void ai_clkctl_init(struct si_pub *sih); |
202 | extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih); | 195 | extern u16 ai_clkctl_fast_pwrup_delay(struct si_pub *sih); |
203 | extern bool ai_clkctl_cc(struct si_pub *sih, uint mode); | 196 | extern bool ai_clkctl_cc(struct si_pub *sih, uint mode); |
204 | extern int ai_clkctl_xtal(struct si_pub *sih, uint what, bool on); | ||
205 | extern bool ai_deviceremoved(struct si_pub *sih); | 197 | extern bool ai_deviceremoved(struct si_pub *sih); |
206 | extern u32 ai_gpiocontrol(struct si_pub *sih, u32 mask, u32 val, | ||
207 | u8 priority); | ||
208 | |||
209 | /* OTP status */ | ||
210 | extern bool ai_is_otp_disabled(struct si_pub *sih); | ||
211 | |||
212 | /* SPROM availability */ | ||
213 | extern bool ai_is_sprom_available(struct si_pub *sih); | ||
214 | 198 | ||
215 | extern void ai_pci_sleep(struct si_pub *sih); | ||
216 | extern void ai_pci_down(struct si_pub *sih); | 199 | extern void ai_pci_down(struct si_pub *sih); |
217 | extern void ai_pci_up(struct si_pub *sih); | 200 | extern void ai_pci_up(struct si_pub *sih); |
218 | extern int ai_pci_fixcfg(struct si_pub *sih); | ||
219 | 201 | ||
220 | extern void ai_chipcontrl_epa4331(struct si_pub *sih, bool on); | ||
221 | /* Enable Ex-PA for 4313 */ | 202 | /* Enable Ex-PA for 4313 */ |
222 | extern void ai_epa_4313war(struct si_pub *sih); | 203 | extern void ai_epa_4313war(struct si_pub *sih); |
223 | 204 | ||
224 | extern uint ai_get_buscoretype(struct si_pub *sih); | 205 | extern uint ai_get_buscoretype(struct si_pub *sih); |
225 | extern uint ai_get_buscorerev(struct si_pub *sih); | 206 | extern uint ai_get_buscorerev(struct si_pub *sih); |
226 | 207 | ||
227 | static inline int ai_get_ccrev(struct si_pub *sih) | ||
228 | { | ||
229 | return sih->ccrev; | ||
230 | } | ||
231 | |||
232 | static inline u32 ai_get_cccaps(struct si_pub *sih) | 208 | static inline u32 ai_get_cccaps(struct si_pub *sih) |
233 | { | 209 | { |
234 | return sih->cccaps; | 210 | return sih->cccaps; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/antsel.c b/drivers/net/wireless/brcm80211/brcmsmac/antsel.c index a47ce25cb9a2..55e12c327911 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/antsel.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/antsel.c | |||
@@ -108,7 +108,7 @@ brcms_c_antsel_init_cfg(struct antsel_info *asi, struct brcms_antselcfg *antsel, | |||
108 | struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc) | 108 | struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc) |
109 | { | 109 | { |
110 | struct antsel_info *asi; | 110 | struct antsel_info *asi; |
111 | struct si_pub *sih = wlc->hw->sih; | 111 | struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom; |
112 | 112 | ||
113 | asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC); | 113 | asi = kzalloc(sizeof(struct antsel_info), GFP_ATOMIC); |
114 | if (!asi) | 114 | if (!asi) |
@@ -118,7 +118,7 @@ struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc) | |||
118 | asi->pub = wlc->pub; | 118 | asi->pub = wlc->pub; |
119 | asi->antsel_type = ANTSEL_NA; | 119 | asi->antsel_type = ANTSEL_NA; |
120 | asi->antsel_avail = false; | 120 | asi->antsel_avail = false; |
121 | asi->antsel_antswitch = (u8) getintvar(sih, BRCMS_SROM_ANTSWITCH); | 121 | asi->antsel_antswitch = sprom->antswitch; |
122 | 122 | ||
123 | if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) { | 123 | if ((asi->pub->sromrev >= 4) && (asi->antsel_antswitch != 0)) { |
124 | switch (asi->antsel_antswitch) { | 124 | switch (asi->antsel_antswitch) { |
@@ -128,12 +128,12 @@ struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc) | |||
128 | /* 4321/2 board with 2x3 switch logic */ | 128 | /* 4321/2 board with 2x3 switch logic */ |
129 | asi->antsel_type = ANTSEL_2x3; | 129 | asi->antsel_type = ANTSEL_2x3; |
130 | /* Antenna selection availability */ | 130 | /* Antenna selection availability */ |
131 | if (((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) || | 131 | if ((sprom->ant_available_bg == 7) || |
132 | ((u16) getintvar(sih, BRCMS_SROM_AA5G) == 7)) { | 132 | (sprom->ant_available_a == 7)) { |
133 | asi->antsel_avail = true; | 133 | asi->antsel_avail = true; |
134 | } else if ( | 134 | } else if ( |
135 | (u16) getintvar(sih, BRCMS_SROM_AA2G) == 3 || | 135 | sprom->ant_available_bg == 3 || |
136 | (u16) getintvar(sih, BRCMS_SROM_AA5G) == 3) { | 136 | sprom->ant_available_a == 3) { |
137 | asi->antsel_avail = false; | 137 | asi->antsel_avail = false; |
138 | } else { | 138 | } else { |
139 | asi->antsel_avail = false; | 139 | asi->antsel_avail = false; |
@@ -146,8 +146,8 @@ struct antsel_info *brcms_c_antsel_attach(struct brcms_c_info *wlc) | |||
146 | break; | 146 | break; |
147 | } | 147 | } |
148 | } else if ((asi->pub->sromrev == 4) && | 148 | } else if ((asi->pub->sromrev == 4) && |
149 | ((u16) getintvar(sih, BRCMS_SROM_AA2G) == 7) && | 149 | (sprom->ant_available_bg == 7) && |
150 | ((u16) getintvar(sih, BRCMS_SROM_AA5G) == 0)) { | 150 | (sprom->ant_available_a == 0)) { |
151 | /* hack to match old 4321CB2 cards with 2of3 antenna switch */ | 151 | /* hack to match old 4321CB2 cards with 2of3 antenna switch */ |
152 | asi->antsel_type = ANTSEL_2x3; | 152 | asi->antsel_type = ANTSEL_2x3; |
153 | asi->antsel_avail = true; | 153 | asi->antsel_avail = true; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/channel.c b/drivers/net/wireless/brcm80211/brcmsmac/channel.c index 0efe88e25a9a..eb77ac3cfb6b 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/channel.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/channel.c | |||
@@ -1110,7 +1110,7 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc) | |||
1110 | char country_abbrev[BRCM_CNTRY_BUF_SZ]; | 1110 | char country_abbrev[BRCM_CNTRY_BUF_SZ]; |
1111 | const struct country_info *country; | 1111 | const struct country_info *country; |
1112 | struct brcms_pub *pub = wlc->pub; | 1112 | struct brcms_pub *pub = wlc->pub; |
1113 | char *ccode; | 1113 | struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom; |
1114 | 1114 | ||
1115 | BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); | 1115 | BCMMSG(wlc->wiphy, "wl%d\n", wlc->pub->unit); |
1116 | 1116 | ||
@@ -1122,9 +1122,8 @@ struct brcms_cm_info *brcms_c_channel_mgr_attach(struct brcms_c_info *wlc) | |||
1122 | wlc->cmi = wlc_cm; | 1122 | wlc->cmi = wlc_cm; |
1123 | 1123 | ||
1124 | /* store the country code for passing up as a regulatory hint */ | 1124 | /* store the country code for passing up as a regulatory hint */ |
1125 | ccode = getvar(wlc->hw->sih, BRCMS_SROM_CCODE); | 1125 | if (sprom->alpha2 && brcms_c_country_valid(sprom->alpha2)) |
1126 | if (ccode && brcms_c_country_valid(ccode)) | 1126 | strncpy(wlc->pub->srom_ccode, sprom->alpha2, sizeof(sprom->alpha2)); |
1127 | strncpy(wlc->pub->srom_ccode, ccode, BRCM_CNTRY_BUF_SZ - 1); | ||
1128 | 1127 | ||
1129 | /* | 1128 | /* |
1130 | * internal country information which must match | 1129 | * internal country information which must match |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index aa15558f75c8..50f92a0b7c41 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/bcma/bcma.h> | 25 | #include <linux/bcma/bcma.h> |
26 | #include <net/mac80211.h> | 26 | #include <net/mac80211.h> |
27 | #include <defs.h> | 27 | #include <defs.h> |
28 | #include "nicpci.h" | ||
29 | #include "phy/phy_int.h" | 28 | #include "phy/phy_int.h" |
30 | #include "d11.h" | 29 | #include "d11.h" |
31 | #include "channel.h" | 30 | #include "channel.h" |
@@ -770,7 +769,7 @@ void brcms_dpc(unsigned long data) | |||
770 | * Precondition: Since this function is called in brcms_pci_probe() context, | 769 | * Precondition: Since this function is called in brcms_pci_probe() context, |
771 | * no locking is required. | 770 | * no locking is required. |
772 | */ | 771 | */ |
773 | static int brcms_request_fw(struct brcms_info *wl, struct pci_dev *pdev) | 772 | static int brcms_request_fw(struct brcms_info *wl, struct bcma_device *pdev) |
774 | { | 773 | { |
775 | int status; | 774 | int status; |
776 | struct device *device = &pdev->dev; | 775 | struct device *device = &pdev->dev; |
@@ -1022,7 +1021,7 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) | |||
1022 | spin_lock_init(&wl->isr_lock); | 1021 | spin_lock_init(&wl->isr_lock); |
1023 | 1022 | ||
1024 | /* prepare ucode */ | 1023 | /* prepare ucode */ |
1025 | if (brcms_request_fw(wl, pdev->bus->host_pci) < 0) { | 1024 | if (brcms_request_fw(wl, pdev) < 0) { |
1026 | wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in " | 1025 | wiphy_err(wl->wiphy, "%s: Failed to find firmware usually in " |
1027 | "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm"); | 1026 | "%s\n", KBUILD_MODNAME, "/lib/firmware/brcm"); |
1028 | brcms_release_fw(wl); | 1027 | brcms_release_fw(wl); |
@@ -1043,12 +1042,12 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) | |||
1043 | wl->pub->ieee_hw = hw; | 1042 | wl->pub->ieee_hw = hw; |
1044 | 1043 | ||
1045 | /* register our interrupt handler */ | 1044 | /* register our interrupt handler */ |
1046 | if (request_irq(pdev->bus->host_pci->irq, brcms_isr, | 1045 | if (request_irq(pdev->irq, brcms_isr, |
1047 | IRQF_SHARED, KBUILD_MODNAME, wl)) { | 1046 | IRQF_SHARED, KBUILD_MODNAME, wl)) { |
1048 | wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit); | 1047 | wiphy_err(wl->wiphy, "wl%d: request_irq() failed\n", unit); |
1049 | goto fail; | 1048 | goto fail; |
1050 | } | 1049 | } |
1051 | wl->irq = pdev->bus->host_pci->irq; | 1050 | wl->irq = pdev->irq; |
1052 | 1051 | ||
1053 | /* register module */ | 1052 | /* register module */ |
1054 | brcms_c_module_register(wl->pub, "linux", wl, NULL); | 1053 | brcms_c_module_register(wl->pub, "linux", wl, NULL); |
@@ -1098,7 +1097,7 @@ static int __devinit brcms_bcma_probe(struct bcma_device *pdev) | |||
1098 | 1097 | ||
1099 | dev_info(&pdev->dev, "mfg %x core %x rev %d class %d irq %d\n", | 1098 | dev_info(&pdev->dev, "mfg %x core %x rev %d class %d irq %d\n", |
1100 | pdev->id.manuf, pdev->id.id, pdev->id.rev, pdev->id.class, | 1099 | pdev->id.manuf, pdev->id.id, pdev->id.rev, pdev->id.class, |
1101 | pdev->bus->host_pci->irq); | 1100 | pdev->irq); |
1102 | 1101 | ||
1103 | if ((pdev->id.manuf != BCMA_MANUF_BCM) || | 1102 | if ((pdev->id.manuf != BCMA_MANUF_BCM) || |
1104 | (pdev->id.id != BCMA_CORE_80211)) | 1103 | (pdev->id.id != BCMA_CORE_80211)) |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index b4d92792c502..19db4052c44c 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -1219,7 +1219,7 @@ static void brcms_b_wait_for_wake(struct brcms_hardware *wlc_hw) | |||
1219 | } | 1219 | } |
1220 | 1220 | ||
1221 | /* control chip clock to save power, enable dynamic clock or force fast clock */ | 1221 | /* control chip clock to save power, enable dynamic clock or force fast clock */ |
1222 | static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode) | 1222 | static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, enum bcma_clkmode mode) |
1223 | { | 1223 | { |
1224 | if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU) { | 1224 | if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU) { |
1225 | /* new chips with PMU, CCS_FORCEHT will distribute the HT clock | 1225 | /* new chips with PMU, CCS_FORCEHT will distribute the HT clock |
@@ -1229,7 +1229,7 @@ static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode) | |||
1229 | */ | 1229 | */ |
1230 | 1230 | ||
1231 | if (wlc_hw->clk) { | 1231 | if (wlc_hw->clk) { |
1232 | if (mode == CLK_FAST) { | 1232 | if (mode == BCMA_CLKMODE_FAST) { |
1233 | bcma_set32(wlc_hw->d11core, | 1233 | bcma_set32(wlc_hw->d11core, |
1234 | D11REGOFFS(clk_ctl_st), | 1234 | D11REGOFFS(clk_ctl_st), |
1235 | CCS_FORCEHT); | 1235 | CCS_FORCEHT); |
@@ -1260,7 +1260,7 @@ static void brcms_b_clkctl_clk(struct brcms_hardware *wlc_hw, uint mode) | |||
1260 | ~CCS_FORCEHT); | 1260 | ~CCS_FORCEHT); |
1261 | } | 1261 | } |
1262 | } | 1262 | } |
1263 | wlc_hw->forcefastclk = (mode == CLK_FAST); | 1263 | wlc_hw->forcefastclk = (mode == BCMA_CLKMODE_FAST); |
1264 | } else { | 1264 | } else { |
1265 | 1265 | ||
1266 | /* old chips w/o PMU, force HT through cc, | 1266 | /* old chips w/o PMU, force HT through cc, |
@@ -1567,7 +1567,7 @@ void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw) | |||
1567 | /* request FAST clock if not on */ | 1567 | /* request FAST clock if not on */ |
1568 | fastclk = wlc_hw->forcefastclk; | 1568 | fastclk = wlc_hw->forcefastclk; |
1569 | if (!fastclk) | 1569 | if (!fastclk) |
1570 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 1570 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST); |
1571 | 1571 | ||
1572 | wlc_phy_bw_state_set(wlc_hw->band->pi, bw); | 1572 | wlc_phy_bw_state_set(wlc_hw->band->pi, bw); |
1573 | 1573 | ||
@@ -1576,7 +1576,7 @@ void brcms_b_bw_set(struct brcms_hardware *wlc_hw, u16 bw) | |||
1576 | 1576 | ||
1577 | /* restore the clk */ | 1577 | /* restore the clk */ |
1578 | if (!fastclk) | 1578 | if (!fastclk) |
1579 | brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); | 1579 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_DYNAMIC); |
1580 | } | 1580 | } |
1581 | 1581 | ||
1582 | static void brcms_b_upd_synthpu(struct brcms_hardware *wlc_hw) | 1582 | static void brcms_b_upd_synthpu(struct brcms_hardware *wlc_hw) |
@@ -1882,27 +1882,20 @@ static bool brcms_c_validboardtype(struct brcms_hardware *wlc_hw) | |||
1882 | return true; | 1882 | return true; |
1883 | } | 1883 | } |
1884 | 1884 | ||
1885 | static char *brcms_c_get_macaddr(struct brcms_hardware *wlc_hw) | 1885 | static void brcms_c_get_macaddr(struct brcms_hardware *wlc_hw, u8 etheraddr[ETH_ALEN]) |
1886 | { | 1886 | { |
1887 | enum brcms_srom_id var_id = BRCMS_SROM_MACADDR; | 1887 | struct ssb_sprom *sprom = &wlc_hw->d11core->bus->sprom; |
1888 | char *macaddr; | ||
1889 | 1888 | ||
1890 | /* If macaddr exists, use it (Sromrev4, CIS, ...). */ | 1889 | /* If macaddr exists, use it (Sromrev4, CIS, ...). */ |
1891 | macaddr = getvar(wlc_hw->sih, var_id); | 1890 | if (!is_zero_ether_addr(sprom->il0mac)) { |
1892 | if (macaddr != NULL) | 1891 | memcpy(etheraddr, sprom->il0mac, 6); |
1893 | return macaddr; | 1892 | return; |
1893 | } | ||
1894 | 1894 | ||
1895 | if (wlc_hw->_nbands > 1) | 1895 | if (wlc_hw->_nbands > 1) |
1896 | var_id = BRCMS_SROM_ET1MACADDR; | 1896 | memcpy(etheraddr, sprom->et1mac, 6); |
1897 | else | 1897 | else |
1898 | var_id = BRCMS_SROM_IL0MACADDR; | 1898 | memcpy(etheraddr, sprom->il0mac, 6); |
1899 | |||
1900 | macaddr = getvar(wlc_hw->sih, var_id); | ||
1901 | if (macaddr == NULL) | ||
1902 | wiphy_err(wlc_hw->wlc->wiphy, "wl%d: wlc_get_macaddr: macaddr " | ||
1903 | "getvar(%d) not found\n", wlc_hw->unit, var_id); | ||
1904 | |||
1905 | return macaddr; | ||
1906 | } | 1899 | } |
1907 | 1900 | ||
1908 | /* power both the pll and external oscillator on/off */ | 1901 | /* power both the pll and external oscillator on/off */ |
@@ -1917,9 +1910,6 @@ static void brcms_b_xtal(struct brcms_hardware *wlc_hw, bool want) | |||
1917 | if (!want && wlc_hw->pllreq) | 1910 | if (!want && wlc_hw->pllreq) |
1918 | return; | 1911 | return; |
1919 | 1912 | ||
1920 | if (wlc_hw->sih) | ||
1921 | ai_clkctl_xtal(wlc_hw->sih, XTAL | PLL, want); | ||
1922 | |||
1923 | wlc_hw->sbclk = want; | 1913 | wlc_hw->sbclk = want; |
1924 | if (!wlc_hw->sbclk) { | 1914 | if (!wlc_hw->sbclk) { |
1925 | wlc_hw->clk = false; | 1915 | wlc_hw->clk = false; |
@@ -2004,7 +1994,7 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) | |||
2004 | /* request FAST clock if not on */ | 1994 | /* request FAST clock if not on */ |
2005 | fastclk = wlc_hw->forcefastclk; | 1995 | fastclk = wlc_hw->forcefastclk; |
2006 | if (!fastclk) | 1996 | if (!fastclk) |
2007 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 1997 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST); |
2008 | 1998 | ||
2009 | /* reset the dma engines except first time thru */ | 1999 | /* reset the dma engines except first time thru */ |
2010 | if (bcma_core_is_enabled(wlc_hw->d11core)) { | 2000 | if (bcma_core_is_enabled(wlc_hw->d11core)) { |
@@ -2053,7 +2043,7 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) | |||
2053 | brcms_c_mctrl_reset(wlc_hw); | 2043 | brcms_c_mctrl_reset(wlc_hw); |
2054 | 2044 | ||
2055 | if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU) | 2045 | if (ai_get_cccaps(wlc_hw->sih) & CC_CAP_PMU) |
2056 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 2046 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST); |
2057 | 2047 | ||
2058 | brcms_b_phy_reset(wlc_hw); | 2048 | brcms_b_phy_reset(wlc_hw); |
2059 | 2049 | ||
@@ -2065,7 +2055,7 @@ void brcms_b_corereset(struct brcms_hardware *wlc_hw, u32 flags) | |||
2065 | 2055 | ||
2066 | /* restore the clk setting */ | 2056 | /* restore the clk setting */ |
2067 | if (!fastclk) | 2057 | if (!fastclk) |
2068 | brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); | 2058 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_DYNAMIC); |
2069 | } | 2059 | } |
2070 | 2060 | ||
2071 | /* txfifo sizes needs to be modified(increased) since the newer cores | 2061 | /* txfifo sizes needs to be modified(increased) since the newer cores |
@@ -2218,7 +2208,7 @@ static void brcms_c_gpio_init(struct brcms_c_info *wlc) | |||
2218 | gm |= gc |= BOARD_GPIO_PACTRL; | 2208 | gm |= gc |= BOARD_GPIO_PACTRL; |
2219 | 2209 | ||
2220 | /* apply to gpiocontrol register */ | 2210 | /* apply to gpiocontrol register */ |
2221 | ai_gpiocontrol(wlc_hw->sih, gm, gc, GPIO_DRV_PRIORITY); | 2211 | bcma_chipco_gpio_control(&wlc_hw->d11core->bus->drv_cc, gm, gc); |
2222 | } | 2212 | } |
2223 | 2213 | ||
2224 | static void brcms_ucode_write(struct brcms_hardware *wlc_hw, | 2214 | static void brcms_ucode_write(struct brcms_hardware *wlc_hw, |
@@ -3371,7 +3361,7 @@ static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec) { | |||
3371 | /* request FAST clock if not on */ | 3361 | /* request FAST clock if not on */ |
3372 | fastclk = wlc_hw->forcefastclk; | 3362 | fastclk = wlc_hw->forcefastclk; |
3373 | if (!fastclk) | 3363 | if (!fastclk) |
3374 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 3364 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST); |
3375 | 3365 | ||
3376 | /* disable interrupts */ | 3366 | /* disable interrupts */ |
3377 | macintmask = brcms_intrsoff(wlc->wl); | 3367 | macintmask = brcms_intrsoff(wlc->wl); |
@@ -3405,7 +3395,7 @@ static brcms_b_init(struct brcms_hardware *wlc_hw, u16 chanspec) { | |||
3405 | 3395 | ||
3406 | /* restore the clk */ | 3396 | /* restore the clk */ |
3407 | if (!fastclk) | 3397 | if (!fastclk) |
3408 | brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); | 3398 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_DYNAMIC); |
3409 | } | 3399 | } |
3410 | 3400 | ||
3411 | static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc, | 3401 | static void brcms_c_set_phy_chanspec(struct brcms_c_info *wlc, |
@@ -4436,17 +4426,22 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, | |||
4436 | uint unit, bool piomode) | 4426 | uint unit, bool piomode) |
4437 | { | 4427 | { |
4438 | struct brcms_hardware *wlc_hw; | 4428 | struct brcms_hardware *wlc_hw; |
4439 | char *macaddr = NULL; | ||
4440 | uint err = 0; | 4429 | uint err = 0; |
4441 | uint j; | 4430 | uint j; |
4442 | bool wme = false; | 4431 | bool wme = false; |
4443 | struct shared_phy_params sha_params; | 4432 | struct shared_phy_params sha_params; |
4444 | struct wiphy *wiphy = wlc->wiphy; | 4433 | struct wiphy *wiphy = wlc->wiphy; |
4445 | struct pci_dev *pcidev = core->bus->host_pci; | 4434 | struct pci_dev *pcidev = core->bus->host_pci; |
4435 | struct ssb_sprom *sprom = &core->bus->sprom; | ||
4446 | 4436 | ||
4447 | BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, | 4437 | if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) |
4448 | pcidev->vendor, | 4438 | BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, |
4449 | pcidev->device); | 4439 | pcidev->vendor, |
4440 | pcidev->device); | ||
4441 | else | ||
4442 | BCMMSG(wlc->wiphy, "wl%d: vendor 0x%x device 0x%x\n", unit, | ||
4443 | core->bus->boardinfo.vendor, | ||
4444 | core->bus->boardinfo.type); | ||
4450 | 4445 | ||
4451 | wme = true; | 4446 | wme = true; |
4452 | 4447 | ||
@@ -4472,7 +4467,8 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, | |||
4472 | } | 4467 | } |
4473 | 4468 | ||
4474 | /* verify again the device is supported */ | 4469 | /* verify again the device is supported */ |
4475 | if (!brcms_c_chipmatch(pcidev->vendor, pcidev->device)) { | 4470 | if (core->bus->hosttype == BCMA_HOSTTYPE_PCI && |
4471 | !brcms_c_chipmatch(pcidev->vendor, pcidev->device)) { | ||
4476 | wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported " | 4472 | wiphy_err(wiphy, "wl%d: brcms_b_attach: Unsupported " |
4477 | "vendor/device (0x%x/0x%x)\n", | 4473 | "vendor/device (0x%x/0x%x)\n", |
4478 | unit, pcidev->vendor, pcidev->device); | 4474 | unit, pcidev->vendor, pcidev->device); |
@@ -4480,8 +4476,13 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, | |||
4480 | goto fail; | 4476 | goto fail; |
4481 | } | 4477 | } |
4482 | 4478 | ||
4483 | wlc_hw->vendorid = pcidev->vendor; | 4479 | if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) { |
4484 | wlc_hw->deviceid = pcidev->device; | 4480 | wlc_hw->vendorid = pcidev->vendor; |
4481 | wlc_hw->deviceid = pcidev->device; | ||
4482 | } else { | ||
4483 | wlc_hw->vendorid = core->bus->boardinfo.vendor; | ||
4484 | wlc_hw->deviceid = core->bus->boardinfo.type; | ||
4485 | } | ||
4485 | 4486 | ||
4486 | wlc_hw->d11core = core; | 4487 | wlc_hw->d11core = core; |
4487 | wlc_hw->corerev = core->id.rev; | 4488 | wlc_hw->corerev = core->id.rev; |
@@ -4501,7 +4502,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, | |||
4501 | * is still false; But it will be called again inside wlc_corereset, | 4502 | * is still false; But it will be called again inside wlc_corereset, |
4502 | * after d11 is out of reset. | 4503 | * after d11 is out of reset. |
4503 | */ | 4504 | */ |
4504 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 4505 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST); |
4505 | brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); | 4506 | brcms_b_corereset(wlc_hw, BRCMS_USE_COREFLAGS); |
4506 | 4507 | ||
4507 | if (!brcms_b_validate_chip_access(wlc_hw)) { | 4508 | if (!brcms_b_validate_chip_access(wlc_hw)) { |
@@ -4512,7 +4513,7 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, | |||
4512 | } | 4513 | } |
4513 | 4514 | ||
4514 | /* get the board rev, used just below */ | 4515 | /* get the board rev, used just below */ |
4515 | j = getintvar(wlc_hw->sih, BRCMS_SROM_BOARDREV); | 4516 | j = sprom->board_rev; |
4516 | /* promote srom boardrev of 0xFF to 1 */ | 4517 | /* promote srom boardrev of 0xFF to 1 */ |
4517 | if (j == BOARDREV_PROMOTABLE) | 4518 | if (j == BOARDREV_PROMOTABLE) |
4518 | j = BOARDREV_PROMOTED; | 4519 | j = BOARDREV_PROMOTED; |
@@ -4525,11 +4526,9 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, | |||
4525 | err = 15; | 4526 | err = 15; |
4526 | goto fail; | 4527 | goto fail; |
4527 | } | 4528 | } |
4528 | wlc_hw->sromrev = (u8) getintvar(wlc_hw->sih, BRCMS_SROM_REV); | 4529 | wlc_hw->sromrev = sprom->revision; |
4529 | wlc_hw->boardflags = (u32) getintvar(wlc_hw->sih, | 4530 | wlc_hw->boardflags = sprom->boardflags_lo + (sprom->boardflags_hi << 16); |
4530 | BRCMS_SROM_BOARDFLAGS); | 4531 | wlc_hw->boardflags2 = sprom->boardflags2_lo + (sprom->boardflags2_hi << 16); |
4531 | wlc_hw->boardflags2 = (u32) getintvar(wlc_hw->sih, | ||
4532 | BRCMS_SROM_BOARDFLAGS2); | ||
4533 | 4532 | ||
4534 | if (wlc_hw->boardflags & BFL_NOPLLDOWN) | 4533 | if (wlc_hw->boardflags & BFL_NOPLLDOWN) |
4535 | brcms_b_pllreq(wlc_hw, true, BRCMS_PLLREQ_SHARED); | 4534 | brcms_b_pllreq(wlc_hw, true, BRCMS_PLLREQ_SHARED); |
@@ -4702,25 +4701,18 @@ static int brcms_b_attach(struct brcms_c_info *wlc, struct bcma_device *core, | |||
4702 | */ | 4701 | */ |
4703 | 4702 | ||
4704 | /* init etheraddr state variables */ | 4703 | /* init etheraddr state variables */ |
4705 | macaddr = brcms_c_get_macaddr(wlc_hw); | 4704 | brcms_c_get_macaddr(wlc_hw, wlc_hw->etheraddr); |
4706 | if (macaddr == NULL) { | 4705 | |
4707 | wiphy_err(wiphy, "wl%d: brcms_b_attach: macaddr not found\n", | 4706 | if (is_broadcast_ether_addr(wlc_hw->etheraddr) || |
4708 | unit); | ||
4709 | err = 21; | ||
4710 | goto fail; | ||
4711 | } | ||
4712 | if (!mac_pton(macaddr, wlc_hw->etheraddr) || | ||
4713 | is_broadcast_ether_addr(wlc_hw->etheraddr) || | ||
4714 | is_zero_ether_addr(wlc_hw->etheraddr)) { | 4707 | is_zero_ether_addr(wlc_hw->etheraddr)) { |
4715 | wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr %s\n", | 4708 | wiphy_err(wiphy, "wl%d: brcms_b_attach: bad macaddr\n", |
4716 | unit, macaddr); | 4709 | unit); |
4717 | err = 22; | 4710 | err = 22; |
4718 | goto fail; | 4711 | goto fail; |
4719 | } | 4712 | } |
4720 | 4713 | ||
4721 | BCMMSG(wlc->wiphy, "deviceid 0x%x nbands %d board 0x%x macaddr: %s\n", | 4714 | BCMMSG(wlc->wiphy, "deviceid 0x%x nbands %d board 0x%x\n", |
4722 | wlc_hw->deviceid, wlc_hw->_nbands, ai_get_boardtype(wlc_hw->sih), | 4715 | wlc_hw->deviceid, wlc_hw->_nbands, ai_get_boardtype(wlc_hw->sih)); |
4723 | macaddr); | ||
4724 | 4716 | ||
4725 | return err; | 4717 | return err; |
4726 | 4718 | ||
@@ -4770,16 +4762,16 @@ static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc) | |||
4770 | int aa; | 4762 | int aa; |
4771 | uint unit; | 4763 | uint unit; |
4772 | int bandtype; | 4764 | int bandtype; |
4773 | struct si_pub *sih = wlc->hw->sih; | 4765 | struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom; |
4774 | 4766 | ||
4775 | unit = wlc->pub->unit; | 4767 | unit = wlc->pub->unit; |
4776 | bandtype = wlc->band->bandtype; | 4768 | bandtype = wlc->band->bandtype; |
4777 | 4769 | ||
4778 | /* get antennas available */ | 4770 | /* get antennas available */ |
4779 | if (bandtype == BRCM_BAND_5G) | 4771 | if (bandtype == BRCM_BAND_5G) |
4780 | aa = (s8) getintvar(sih, BRCMS_SROM_AA5G); | 4772 | aa = sprom->ant_available_a; |
4781 | else | 4773 | else |
4782 | aa = (s8) getintvar(sih, BRCMS_SROM_AA2G); | 4774 | aa = sprom->ant_available_bg; |
4783 | 4775 | ||
4784 | if ((aa < 1) || (aa > 15)) { | 4776 | if ((aa < 1) || (aa > 15)) { |
4785 | wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in" | 4777 | wiphy_err(wlc->wiphy, "wl%d: %s: Invalid antennas available in" |
@@ -4799,9 +4791,9 @@ static bool brcms_c_attach_stf_ant_init(struct brcms_c_info *wlc) | |||
4799 | 4791 | ||
4800 | /* Compute Antenna Gain */ | 4792 | /* Compute Antenna Gain */ |
4801 | if (bandtype == BRCM_BAND_5G) | 4793 | if (bandtype == BRCM_BAND_5G) |
4802 | wlc->band->antgain = (s8) getintvar(sih, BRCMS_SROM_AG1); | 4794 | wlc->band->antgain = sprom->antenna_gain.a1; |
4803 | else | 4795 | else |
4804 | wlc->band->antgain = (s8) getintvar(sih, BRCMS_SROM_AG0); | 4796 | wlc->band->antgain = sprom->antenna_gain.a0; |
4805 | 4797 | ||
4806 | brcms_c_attach_antgain_init(wlc); | 4798 | brcms_c_attach_antgain_init(wlc); |
4807 | 4799 | ||
@@ -4952,15 +4944,6 @@ static int brcms_b_detach(struct brcms_c_info *wlc) | |||
4952 | 4944 | ||
4953 | callbacks = 0; | 4945 | callbacks = 0; |
4954 | 4946 | ||
4955 | if (wlc_hw->sih) { | ||
4956 | /* | ||
4957 | * detach interrupt sync mechanism since interrupt is disabled | ||
4958 | * and per-port interrupt object may has been freed. this must | ||
4959 | * be done before sb core switch | ||
4960 | */ | ||
4961 | ai_pci_sleep(wlc_hw->sih); | ||
4962 | } | ||
4963 | |||
4964 | brcms_b_detach_dmapio(wlc_hw); | 4947 | brcms_b_detach_dmapio(wlc_hw); |
4965 | 4948 | ||
4966 | band = wlc_hw->band; | 4949 | band = wlc_hw->band; |
@@ -5047,9 +5030,7 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw) | |||
5047 | */ | 5030 | */ |
5048 | brcms_b_xtal(wlc_hw, ON); | 5031 | brcms_b_xtal(wlc_hw, ON); |
5049 | ai_clkctl_init(wlc_hw->sih); | 5032 | ai_clkctl_init(wlc_hw->sih); |
5050 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 5033 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST); |
5051 | |||
5052 | ai_pci_fixcfg(wlc_hw->sih); | ||
5053 | 5034 | ||
5054 | /* | 5035 | /* |
5055 | * TODO: test suspend/resume | 5036 | * TODO: test suspend/resume |
@@ -5078,8 +5059,6 @@ static void brcms_b_hw_up(struct brcms_hardware *wlc_hw) | |||
5078 | 5059 | ||
5079 | static int brcms_b_up_prep(struct brcms_hardware *wlc_hw) | 5060 | static int brcms_b_up_prep(struct brcms_hardware *wlc_hw) |
5080 | { | 5061 | { |
5081 | uint coremask; | ||
5082 | |||
5083 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); | 5062 | BCMMSG(wlc_hw->wlc->wiphy, "wl%d\n", wlc_hw->unit); |
5084 | 5063 | ||
5085 | /* | 5064 | /* |
@@ -5088,15 +5067,14 @@ static int brcms_b_up_prep(struct brcms_hardware *wlc_hw) | |||
5088 | */ | 5067 | */ |
5089 | brcms_b_xtal(wlc_hw, ON); | 5068 | brcms_b_xtal(wlc_hw, ON); |
5090 | ai_clkctl_init(wlc_hw->sih); | 5069 | ai_clkctl_init(wlc_hw->sih); |
5091 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 5070 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST); |
5092 | 5071 | ||
5093 | /* | 5072 | /* |
5094 | * Configure pci/pcmcia here instead of in brcms_c_attach() | 5073 | * Configure pci/pcmcia here instead of in brcms_c_attach() |
5095 | * to allow mfg hotswap: down, hotswap (chip power cycle), up. | 5074 | * to allow mfg hotswap: down, hotswap (chip power cycle), up. |
5096 | */ | 5075 | */ |
5097 | coremask = (1 << wlc_hw->wlc->core->coreidx); | 5076 | bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci, wlc_hw->d11core, |
5098 | 5077 | true); | |
5099 | ai_pci_setup(wlc_hw->sih, coremask); | ||
5100 | 5078 | ||
5101 | /* | 5079 | /* |
5102 | * Need to read the hwradio status here to cover the case where the | 5080 | * Need to read the hwradio status here to cover the case where the |
@@ -5126,7 +5104,7 @@ static int brcms_b_up_finish(struct brcms_hardware *wlc_hw) | |||
5126 | wlc_phy_hw_state_upd(wlc_hw->band->pi, true); | 5104 | wlc_phy_hw_state_upd(wlc_hw->band->pi, true); |
5127 | 5105 | ||
5128 | /* FULLY enable dynamic power control and d11 core interrupt */ | 5106 | /* FULLY enable dynamic power control and d11 core interrupt */ |
5129 | brcms_b_clkctl_clk(wlc_hw, CLK_DYNAMIC); | 5107 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_DYNAMIC); |
5130 | brcms_intrson(wlc_hw->wlc->wl); | 5108 | brcms_intrson(wlc_hw->wlc->wl); |
5131 | return 0; | 5109 | return 0; |
5132 | } | 5110 | } |
@@ -5267,7 +5245,7 @@ static int brcms_b_bmac_down_prep(struct brcms_hardware *wlc_hw) | |||
5267 | brcms_intrsoff(wlc_hw->wlc->wl); | 5245 | brcms_intrsoff(wlc_hw->wlc->wl); |
5268 | 5246 | ||
5269 | /* ensure we're running on the pll clock again */ | 5247 | /* ensure we're running on the pll clock again */ |
5270 | brcms_b_clkctl_clk(wlc_hw, CLK_FAST); | 5248 | brcms_b_clkctl_clk(wlc_hw, BCMA_CLKMODE_FAST); |
5271 | } | 5249 | } |
5272 | /* down phy at the last of this stage */ | 5250 | /* down phy at the last of this stage */ |
5273 | callbacks += wlc_phy_down(wlc_hw->band->pi); | 5251 | callbacks += wlc_phy_down(wlc_hw->band->pi); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c b/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c deleted file mode 100644 index 7fad6dc19258..000000000000 --- a/drivers/net/wireless/brcm80211/brcmsmac/nicpci.c +++ /dev/null | |||
@@ -1,826 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 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 | #include <linux/slab.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/pci.h> | ||
20 | |||
21 | #include <defs.h> | ||
22 | #include <soc.h> | ||
23 | #include <chipcommon.h> | ||
24 | #include "aiutils.h" | ||
25 | #include "pub.h" | ||
26 | #include "nicpci.h" | ||
27 | |||
28 | /* SPROM offsets */ | ||
29 | #define SRSH_ASPM_OFFSET 4 /* word 4 */ | ||
30 | #define SRSH_ASPM_ENB 0x18 /* bit 3, 4 */ | ||
31 | #define SRSH_ASPM_L1_ENB 0x10 /* bit 4 */ | ||
32 | #define SRSH_ASPM_L0s_ENB 0x8 /* bit 3 */ | ||
33 | |||
34 | #define SRSH_PCIE_MISC_CONFIG 5 /* word 5 */ | ||
35 | #define SRSH_L23READY_EXIT_NOPERST 0x8000 /* bit 15 */ | ||
36 | #define SRSH_CLKREQ_OFFSET_REV5 20 /* word 20 for srom rev <= 5 */ | ||
37 | #define SRSH_CLKREQ_ENB 0x0800 /* bit 11 */ | ||
38 | #define SRSH_BD_OFFSET 6 /* word 6 */ | ||
39 | |||
40 | /* chipcontrol */ | ||
41 | #define CHIPCTRL_4321_PLL_DOWN 0x800000/* serdes PLL down override */ | ||
42 | |||
43 | /* MDIO control */ | ||
44 | #define MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */ | ||
45 | #define MDIOCTL_DIVISOR_VAL 0x2 | ||
46 | #define MDIOCTL_PREAM_EN 0x80 /* Enable preamble sequnce */ | ||
47 | #define MDIOCTL_ACCESS_DONE 0x100 /* Transaction complete */ | ||
48 | |||
49 | /* MDIO Data */ | ||
50 | #define MDIODATA_MASK 0x0000ffff /* data 2 bytes */ | ||
51 | #define MDIODATA_TA 0x00020000 /* Turnaround */ | ||
52 | |||
53 | #define MDIODATA_REGADDR_SHF 18 /* Regaddr shift */ | ||
54 | #define MDIODATA_REGADDR_MASK 0x007c0000 /* Regaddr Mask */ | ||
55 | #define MDIODATA_DEVADDR_SHF 23 /* Physmedia devaddr shift */ | ||
56 | #define MDIODATA_DEVADDR_MASK 0x0f800000 | ||
57 | /* Physmedia devaddr Mask */ | ||
58 | |||
59 | /* MDIO Data for older revisions < 10 */ | ||
60 | #define MDIODATA_REGADDR_SHF_OLD 18 /* Regaddr shift */ | ||
61 | #define MDIODATA_REGADDR_MASK_OLD 0x003c0000 | ||
62 | /* Regaddr Mask */ | ||
63 | #define MDIODATA_DEVADDR_SHF_OLD 22 /* Physmedia devaddr shift */ | ||
64 | #define MDIODATA_DEVADDR_MASK_OLD 0x0fc00000 | ||
65 | /* Physmedia devaddr Mask */ | ||
66 | |||
67 | /* Transactions flags */ | ||
68 | #define MDIODATA_WRITE 0x10000000 | ||
69 | #define MDIODATA_READ 0x20000000 | ||
70 | #define MDIODATA_START 0x40000000 | ||
71 | |||
72 | #define MDIODATA_DEV_ADDR 0x0 /* dev address for serdes */ | ||
73 | #define MDIODATA_BLK_ADDR 0x1F /* blk address for serdes */ | ||
74 | |||
75 | /* serdes regs (rev < 10) */ | ||
76 | #define MDIODATA_DEV_PLL 0x1d /* SERDES PLL Dev */ | ||
77 | #define MDIODATA_DEV_TX 0x1e /* SERDES TX Dev */ | ||
78 | #define MDIODATA_DEV_RX 0x1f /* SERDES RX Dev */ | ||
79 | |||
80 | /* SERDES RX registers */ | ||
81 | #define SERDES_RX_CTRL 1 /* Rx cntrl */ | ||
82 | #define SERDES_RX_TIMER1 2 /* Rx Timer1 */ | ||
83 | #define SERDES_RX_CDR 6 /* CDR */ | ||
84 | #define SERDES_RX_CDRBW 7 /* CDR BW */ | ||
85 | /* SERDES RX control register */ | ||
86 | #define SERDES_RX_CTRL_FORCE 0x80 /* rxpolarity_force */ | ||
87 | #define SERDES_RX_CTRL_POLARITY 0x40 /* rxpolarity_value */ | ||
88 | |||
89 | /* SERDES PLL registers */ | ||
90 | #define SERDES_PLL_CTRL 1 /* PLL control reg */ | ||
91 | #define PLL_CTRL_FREQDET_EN 0x4000 /* bit 14 is FREQDET on */ | ||
92 | |||
93 | /* Linkcontrol reg offset in PCIE Cap */ | ||
94 | #define PCIE_CAP_LINKCTRL_OFFSET 16 /* offset in pcie cap */ | ||
95 | #define PCIE_CAP_LCREG_ASPML0s 0x01 /* ASPM L0s in linkctrl */ | ||
96 | #define PCIE_CAP_LCREG_ASPML1 0x02 /* ASPM L1 in linkctrl */ | ||
97 | #define PCIE_CLKREQ_ENAB 0x100 /* CLKREQ Enab in linkctrl */ | ||
98 | |||
99 | #define PCIE_ASPM_ENAB 3 /* ASPM L0s & L1 in linkctrl */ | ||
100 | #define PCIE_ASPM_L1_ENAB 2 /* ASPM L0s & L1 in linkctrl */ | ||
101 | #define PCIE_ASPM_L0s_ENAB 1 /* ASPM L0s & L1 in linkctrl */ | ||
102 | #define PCIE_ASPM_DISAB 0 /* ASPM L0s & L1 in linkctrl */ | ||
103 | |||
104 | /* Power management threshold */ | ||
105 | #define PCIE_L1THRESHOLDTIME_MASK 0xFF00 /* bits 8 - 15 */ | ||
106 | #define PCIE_L1THRESHOLDTIME_SHIFT 8 /* PCIE_L1THRESHOLDTIME_SHIFT */ | ||
107 | #define PCIE_L1THRESHOLD_WARVAL 0x72 /* WAR value */ | ||
108 | #define PCIE_ASPMTIMER_EXTEND 0x01000000 | ||
109 | /* > rev7: | ||
110 | * enable extend ASPM timer | ||
111 | */ | ||
112 | |||
113 | /* different register spaces to access thru pcie indirect access */ | ||
114 | #define PCIE_CONFIGREGS 1 /* Access to config space */ | ||
115 | #define PCIE_PCIEREGS 2 /* Access to pcie registers */ | ||
116 | |||
117 | /* PCIE protocol PHY diagnostic registers */ | ||
118 | #define PCIE_PLP_STATUSREG 0x204 /* Status */ | ||
119 | |||
120 | /* Status reg PCIE_PLP_STATUSREG */ | ||
121 | #define PCIE_PLP_POLARITYINV_STAT 0x10 | ||
122 | |||
123 | /* PCIE protocol DLLP diagnostic registers */ | ||
124 | #define PCIE_DLLP_LCREG 0x100 /* Link Control */ | ||
125 | #define PCIE_DLLP_PMTHRESHREG 0x128 /* Power Management Threshold */ | ||
126 | |||
127 | /* PCIE protocol TLP diagnostic registers */ | ||
128 | #define PCIE_TLP_WORKAROUNDSREG 0x004 /* TLP Workarounds */ | ||
129 | |||
130 | /* Sonics to PCI translation types */ | ||
131 | #define SBTOPCI_PREF 0x4 /* prefetch enable */ | ||
132 | #define SBTOPCI_BURST 0x8 /* burst enable */ | ||
133 | #define SBTOPCI_RC_READMULTI 0x20 /* memory read multiple */ | ||
134 | |||
135 | #define PCI_CLKRUN_DSBL 0x8000 /* Bit 15 forceClkrun */ | ||
136 | |||
137 | /* PCI core index in SROM shadow area */ | ||
138 | #define SRSH_PI_OFFSET 0 /* first word */ | ||
139 | #define SRSH_PI_MASK 0xf000 /* bit 15:12 */ | ||
140 | #define SRSH_PI_SHIFT 12 /* bit 15:12 */ | ||
141 | |||
142 | #define PCIREGOFFS(field) offsetof(struct sbpciregs, field) | ||
143 | #define PCIEREGOFFS(field) offsetof(struct sbpcieregs, field) | ||
144 | |||
145 | /* Sonics side: PCI core and host control registers */ | ||
146 | struct sbpciregs { | ||
147 | u32 control; /* PCI control */ | ||
148 | u32 PAD[3]; | ||
149 | u32 arbcontrol; /* PCI arbiter control */ | ||
150 | u32 clkrun; /* Clkrun Control (>=rev11) */ | ||
151 | u32 PAD[2]; | ||
152 | u32 intstatus; /* Interrupt status */ | ||
153 | u32 intmask; /* Interrupt mask */ | ||
154 | u32 sbtopcimailbox; /* Sonics to PCI mailbox */ | ||
155 | u32 PAD[9]; | ||
156 | u32 bcastaddr; /* Sonics broadcast address */ | ||
157 | u32 bcastdata; /* Sonics broadcast data */ | ||
158 | u32 PAD[2]; | ||
159 | u32 gpioin; /* ro: gpio input (>=rev2) */ | ||
160 | u32 gpioout; /* rw: gpio output (>=rev2) */ | ||
161 | u32 gpioouten; /* rw: gpio output enable (>= rev2) */ | ||
162 | u32 gpiocontrol; /* rw: gpio control (>= rev2) */ | ||
163 | u32 PAD[36]; | ||
164 | u32 sbtopci0; /* Sonics to PCI translation 0 */ | ||
165 | u32 sbtopci1; /* Sonics to PCI translation 1 */ | ||
166 | u32 sbtopci2; /* Sonics to PCI translation 2 */ | ||
167 | u32 PAD[189]; | ||
168 | u32 pcicfg[4][64]; /* 0x400 - 0x7FF, PCI Cfg Space (>=rev8) */ | ||
169 | u16 sprom[36]; /* SPROM shadow Area */ | ||
170 | u32 PAD[46]; | ||
171 | }; | ||
172 | |||
173 | /* SB side: PCIE core and host control registers */ | ||
174 | struct sbpcieregs { | ||
175 | u32 control; /* host mode only */ | ||
176 | u32 PAD[2]; | ||
177 | u32 biststatus; /* bist Status: 0x00C */ | ||
178 | u32 gpiosel; /* PCIE gpio sel: 0x010 */ | ||
179 | u32 gpioouten; /* PCIE gpio outen: 0x14 */ | ||
180 | u32 PAD[2]; | ||
181 | u32 intstatus; /* Interrupt status: 0x20 */ | ||
182 | u32 intmask; /* Interrupt mask: 0x24 */ | ||
183 | u32 sbtopcimailbox; /* sb to pcie mailbox: 0x028 */ | ||
184 | u32 PAD[53]; | ||
185 | u32 sbtopcie0; /* sb to pcie translation 0: 0x100 */ | ||
186 | u32 sbtopcie1; /* sb to pcie translation 1: 0x104 */ | ||
187 | u32 sbtopcie2; /* sb to pcie translation 2: 0x108 */ | ||
188 | u32 PAD[5]; | ||
189 | |||
190 | /* pcie core supports in direct access to config space */ | ||
191 | u32 configaddr; /* pcie config space access: Address field: 0x120 */ | ||
192 | u32 configdata; /* pcie config space access: Data field: 0x124 */ | ||
193 | |||
194 | /* mdio access to serdes */ | ||
195 | u32 mdiocontrol; /* controls the mdio access: 0x128 */ | ||
196 | u32 mdiodata; /* Data to the mdio access: 0x12c */ | ||
197 | |||
198 | /* pcie protocol phy/dllp/tlp register indirect access mechanism */ | ||
199 | u32 pcieindaddr; /* indirect access to | ||
200 | * the internal register: 0x130 | ||
201 | */ | ||
202 | u32 pcieinddata; /* Data to/from the internal regsiter: 0x134 */ | ||
203 | |||
204 | u32 clkreqenctrl; /* >= rev 6, Clkreq rdma control : 0x138 */ | ||
205 | u32 PAD[177]; | ||
206 | u32 pciecfg[4][64]; /* 0x400 - 0x7FF, PCIE Cfg Space */ | ||
207 | u16 sprom[64]; /* SPROM shadow Area */ | ||
208 | }; | ||
209 | |||
210 | struct pcicore_info { | ||
211 | struct bcma_device *core; | ||
212 | struct si_pub *sih; /* System interconnect handle */ | ||
213 | struct pci_dev *dev; | ||
214 | u8 pciecap_lcreg_offset;/* PCIE capability LCreg offset | ||
215 | * in the config space | ||
216 | */ | ||
217 | bool pcie_pr42767; | ||
218 | u8 pcie_polarity; | ||
219 | u8 pcie_war_aspm_ovr; /* Override ASPM/Clkreq settings */ | ||
220 | |||
221 | u8 pmecap_offset; /* PM Capability offset in the config space */ | ||
222 | bool pmecap; /* Capable of generating PME */ | ||
223 | }; | ||
224 | |||
225 | #define PCIE_ASPM(sih) \ | ||
226 | ((ai_get_buscoretype(sih) == PCIE_CORE_ID) && \ | ||
227 | ((ai_get_buscorerev(sih) >= 3) && \ | ||
228 | (ai_get_buscorerev(sih) <= 5))) | ||
229 | |||
230 | |||
231 | /* delay needed between the mdio control/ mdiodata register data access */ | ||
232 | static void pr28829_delay(void) | ||
233 | { | ||
234 | udelay(10); | ||
235 | } | ||
236 | |||
237 | /* Initialize the PCI core. | ||
238 | * It's caller's responsibility to make sure that this is done only once | ||
239 | */ | ||
240 | struct pcicore_info *pcicore_init(struct si_pub *sih, struct bcma_device *core) | ||
241 | { | ||
242 | struct pcicore_info *pi; | ||
243 | |||
244 | /* alloc struct pcicore_info */ | ||
245 | pi = kzalloc(sizeof(struct pcicore_info), GFP_ATOMIC); | ||
246 | if (pi == NULL) | ||
247 | return NULL; | ||
248 | |||
249 | pi->sih = sih; | ||
250 | pi->dev = core->bus->host_pci; | ||
251 | pi->core = core; | ||
252 | |||
253 | if (core->id.id == PCIE_CORE_ID) { | ||
254 | u8 cap_ptr; | ||
255 | cap_ptr = pcicore_find_pci_capability(pi->dev, PCI_CAP_ID_EXP, | ||
256 | NULL, NULL); | ||
257 | pi->pciecap_lcreg_offset = cap_ptr + PCIE_CAP_LINKCTRL_OFFSET; | ||
258 | } | ||
259 | return pi; | ||
260 | } | ||
261 | |||
262 | void pcicore_deinit(struct pcicore_info *pch) | ||
263 | { | ||
264 | kfree(pch); | ||
265 | } | ||
266 | |||
267 | /* return cap_offset if requested capability exists in the PCI config space */ | ||
268 | /* Note that it's caller's responsibility to make sure it's a pci bus */ | ||
269 | u8 | ||
270 | pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id, | ||
271 | unsigned char *buf, u32 *buflen) | ||
272 | { | ||
273 | u8 cap_id; | ||
274 | u8 cap_ptr = 0; | ||
275 | u32 bufsize; | ||
276 | u8 byte_val; | ||
277 | |||
278 | /* check for Header type 0 */ | ||
279 | pci_read_config_byte(dev, PCI_HEADER_TYPE, &byte_val); | ||
280 | if ((byte_val & 0x7f) != PCI_HEADER_TYPE_NORMAL) | ||
281 | goto end; | ||
282 | |||
283 | /* check if the capability pointer field exists */ | ||
284 | pci_read_config_byte(dev, PCI_STATUS, &byte_val); | ||
285 | if (!(byte_val & PCI_STATUS_CAP_LIST)) | ||
286 | goto end; | ||
287 | |||
288 | pci_read_config_byte(dev, PCI_CAPABILITY_LIST, &cap_ptr); | ||
289 | /* check if the capability pointer is 0x00 */ | ||
290 | if (cap_ptr == 0x00) | ||
291 | goto end; | ||
292 | |||
293 | /* loop thru the capability list | ||
294 | * and see if the pcie capability exists | ||
295 | */ | ||
296 | |||
297 | pci_read_config_byte(dev, cap_ptr, &cap_id); | ||
298 | |||
299 | while (cap_id != req_cap_id) { | ||
300 | pci_read_config_byte(dev, cap_ptr + 1, &cap_ptr); | ||
301 | if (cap_ptr == 0x00) | ||
302 | break; | ||
303 | pci_read_config_byte(dev, cap_ptr, &cap_id); | ||
304 | } | ||
305 | if (cap_id != req_cap_id) | ||
306 | goto end; | ||
307 | |||
308 | /* found the caller requested capability */ | ||
309 | if (buf != NULL && buflen != NULL) { | ||
310 | u8 cap_data; | ||
311 | |||
312 | bufsize = *buflen; | ||
313 | if (!bufsize) | ||
314 | goto end; | ||
315 | *buflen = 0; | ||
316 | /* copy the capability data excluding cap ID and next ptr */ | ||
317 | cap_data = cap_ptr + 2; | ||
318 | if ((bufsize + cap_data) > PCI_SZPCR) | ||
319 | bufsize = PCI_SZPCR - cap_data; | ||
320 | *buflen = bufsize; | ||
321 | while (bufsize--) { | ||
322 | pci_read_config_byte(dev, cap_data, buf); | ||
323 | cap_data++; | ||
324 | buf++; | ||
325 | } | ||
326 | } | ||
327 | end: | ||
328 | return cap_ptr; | ||
329 | } | ||
330 | |||
331 | /* ***** Register Access API */ | ||
332 | static uint | ||
333 | pcie_readreg(struct bcma_device *core, uint addrtype, uint offset) | ||
334 | { | ||
335 | uint retval = 0xFFFFFFFF; | ||
336 | |||
337 | switch (addrtype) { | ||
338 | case PCIE_CONFIGREGS: | ||
339 | bcma_write32(core, PCIEREGOFFS(configaddr), offset); | ||
340 | (void)bcma_read32(core, PCIEREGOFFS(configaddr)); | ||
341 | retval = bcma_read32(core, PCIEREGOFFS(configdata)); | ||
342 | break; | ||
343 | case PCIE_PCIEREGS: | ||
344 | bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset); | ||
345 | (void)bcma_read32(core, PCIEREGOFFS(pcieindaddr)); | ||
346 | retval = bcma_read32(core, PCIEREGOFFS(pcieinddata)); | ||
347 | break; | ||
348 | } | ||
349 | |||
350 | return retval; | ||
351 | } | ||
352 | |||
353 | static uint pcie_writereg(struct bcma_device *core, uint addrtype, | ||
354 | uint offset, uint val) | ||
355 | { | ||
356 | switch (addrtype) { | ||
357 | case PCIE_CONFIGREGS: | ||
358 | bcma_write32(core, PCIEREGOFFS(configaddr), offset); | ||
359 | bcma_write32(core, PCIEREGOFFS(configdata), val); | ||
360 | break; | ||
361 | case PCIE_PCIEREGS: | ||
362 | bcma_write32(core, PCIEREGOFFS(pcieindaddr), offset); | ||
363 | bcma_write32(core, PCIEREGOFFS(pcieinddata), val); | ||
364 | break; | ||
365 | default: | ||
366 | break; | ||
367 | } | ||
368 | return 0; | ||
369 | } | ||
370 | |||
371 | static bool pcie_mdiosetblock(struct pcicore_info *pi, uint blk) | ||
372 | { | ||
373 | uint mdiodata, i = 0; | ||
374 | uint pcie_serdes_spinwait = 200; | ||
375 | |||
376 | mdiodata = (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | | ||
377 | (MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | | ||
378 | (MDIODATA_BLK_ADDR << MDIODATA_REGADDR_SHF) | | ||
379 | (blk << 4)); | ||
380 | bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata); | ||
381 | |||
382 | pr28829_delay(); | ||
383 | /* retry till the transaction is complete */ | ||
384 | while (i < pcie_serdes_spinwait) { | ||
385 | if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) & | ||
386 | MDIOCTL_ACCESS_DONE) | ||
387 | break; | ||
388 | |||
389 | udelay(1000); | ||
390 | i++; | ||
391 | } | ||
392 | |||
393 | if (i >= pcie_serdes_spinwait) | ||
394 | return false; | ||
395 | |||
396 | return true; | ||
397 | } | ||
398 | |||
399 | static int | ||
400 | pcie_mdioop(struct pcicore_info *pi, uint physmedia, uint regaddr, bool write, | ||
401 | uint *val) | ||
402 | { | ||
403 | uint mdiodata; | ||
404 | uint i = 0; | ||
405 | uint pcie_serdes_spinwait = 10; | ||
406 | |||
407 | /* enable mdio access to SERDES */ | ||
408 | bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), | ||
409 | MDIOCTL_PREAM_EN | MDIOCTL_DIVISOR_VAL); | ||
410 | |||
411 | if (ai_get_buscorerev(pi->sih) >= 10) { | ||
412 | /* new serdes is slower in rw, | ||
413 | * using two layers of reg address mapping | ||
414 | */ | ||
415 | if (!pcie_mdiosetblock(pi, physmedia)) | ||
416 | return 1; | ||
417 | mdiodata = ((MDIODATA_DEV_ADDR << MDIODATA_DEVADDR_SHF) | | ||
418 | (regaddr << MDIODATA_REGADDR_SHF)); | ||
419 | pcie_serdes_spinwait *= 20; | ||
420 | } else { | ||
421 | mdiodata = ((physmedia << MDIODATA_DEVADDR_SHF_OLD) | | ||
422 | (regaddr << MDIODATA_REGADDR_SHF_OLD)); | ||
423 | } | ||
424 | |||
425 | if (!write) | ||
426 | mdiodata |= (MDIODATA_START | MDIODATA_READ | MDIODATA_TA); | ||
427 | else | ||
428 | mdiodata |= (MDIODATA_START | MDIODATA_WRITE | MDIODATA_TA | | ||
429 | *val); | ||
430 | |||
431 | bcma_write32(pi->core, PCIEREGOFFS(mdiodata), mdiodata); | ||
432 | |||
433 | pr28829_delay(); | ||
434 | |||
435 | /* retry till the transaction is complete */ | ||
436 | while (i < pcie_serdes_spinwait) { | ||
437 | if (bcma_read32(pi->core, PCIEREGOFFS(mdiocontrol)) & | ||
438 | MDIOCTL_ACCESS_DONE) { | ||
439 | if (!write) { | ||
440 | pr28829_delay(); | ||
441 | *val = (bcma_read32(pi->core, | ||
442 | PCIEREGOFFS(mdiodata)) & | ||
443 | MDIODATA_MASK); | ||
444 | } | ||
445 | /* Disable mdio access to SERDES */ | ||
446 | bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0); | ||
447 | return 0; | ||
448 | } | ||
449 | udelay(1000); | ||
450 | i++; | ||
451 | } | ||
452 | |||
453 | /* Timed out. Disable mdio access to SERDES. */ | ||
454 | bcma_write32(pi->core, PCIEREGOFFS(mdiocontrol), 0); | ||
455 | return 1; | ||
456 | } | ||
457 | |||
458 | /* use the mdio interface to read from mdio slaves */ | ||
459 | static int | ||
460 | pcie_mdioread(struct pcicore_info *pi, uint physmedia, uint regaddr, | ||
461 | uint *regval) | ||
462 | { | ||
463 | return pcie_mdioop(pi, physmedia, regaddr, false, regval); | ||
464 | } | ||
465 | |||
466 | /* use the mdio interface to write to mdio slaves */ | ||
467 | static int | ||
468 | pcie_mdiowrite(struct pcicore_info *pi, uint physmedia, uint regaddr, uint val) | ||
469 | { | ||
470 | return pcie_mdioop(pi, physmedia, regaddr, true, &val); | ||
471 | } | ||
472 | |||
473 | /* ***** Support functions ***** */ | ||
474 | static u8 pcie_clkreq(struct pcicore_info *pi, u32 mask, u32 val) | ||
475 | { | ||
476 | u32 reg_val; | ||
477 | u8 offset; | ||
478 | |||
479 | offset = pi->pciecap_lcreg_offset; | ||
480 | if (!offset) | ||
481 | return 0; | ||
482 | |||
483 | pci_read_config_dword(pi->dev, offset, ®_val); | ||
484 | /* set operation */ | ||
485 | if (mask) { | ||
486 | if (val) | ||
487 | reg_val |= PCIE_CLKREQ_ENAB; | ||
488 | else | ||
489 | reg_val &= ~PCIE_CLKREQ_ENAB; | ||
490 | pci_write_config_dword(pi->dev, offset, reg_val); | ||
491 | pci_read_config_dword(pi->dev, offset, ®_val); | ||
492 | } | ||
493 | if (reg_val & PCIE_CLKREQ_ENAB) | ||
494 | return 1; | ||
495 | else | ||
496 | return 0; | ||
497 | } | ||
498 | |||
499 | static void pcie_extendL1timer(struct pcicore_info *pi, bool extend) | ||
500 | { | ||
501 | u32 w; | ||
502 | struct si_pub *sih = pi->sih; | ||
503 | |||
504 | if (ai_get_buscoretype(sih) != PCIE_CORE_ID || | ||
505 | ai_get_buscorerev(sih) < 7) | ||
506 | return; | ||
507 | |||
508 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); | ||
509 | if (extend) | ||
510 | w |= PCIE_ASPMTIMER_EXTEND; | ||
511 | else | ||
512 | w &= ~PCIE_ASPMTIMER_EXTEND; | ||
513 | pcie_writereg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG, w); | ||
514 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_PMTHRESHREG); | ||
515 | } | ||
516 | |||
517 | /* centralized clkreq control policy */ | ||
518 | static void pcie_clkreq_upd(struct pcicore_info *pi, uint state) | ||
519 | { | ||
520 | struct si_pub *sih = pi->sih; | ||
521 | |||
522 | switch (state) { | ||
523 | case SI_DOATTACH: | ||
524 | if (PCIE_ASPM(sih)) | ||
525 | pcie_clkreq(pi, 1, 0); | ||
526 | break; | ||
527 | case SI_PCIDOWN: | ||
528 | /* turn on serdes PLL down */ | ||
529 | if (ai_get_buscorerev(sih) == 6) { | ||
530 | ai_cc_reg(sih, | ||
531 | offsetof(struct chipcregs, chipcontrol_addr), | ||
532 | ~0, 0); | ||
533 | ai_cc_reg(sih, | ||
534 | offsetof(struct chipcregs, chipcontrol_data), | ||
535 | ~0x40, 0); | ||
536 | } else if (pi->pcie_pr42767) { | ||
537 | pcie_clkreq(pi, 1, 1); | ||
538 | } | ||
539 | break; | ||
540 | case SI_PCIUP: | ||
541 | /* turn off serdes PLL down */ | ||
542 | if (ai_get_buscorerev(sih) == 6) { | ||
543 | ai_cc_reg(sih, | ||
544 | offsetof(struct chipcregs, chipcontrol_addr), | ||
545 | ~0, 0); | ||
546 | ai_cc_reg(sih, | ||
547 | offsetof(struct chipcregs, chipcontrol_data), | ||
548 | ~0x40, 0x40); | ||
549 | } else if (PCIE_ASPM(sih)) { /* disable clkreq */ | ||
550 | pcie_clkreq(pi, 1, 0); | ||
551 | } | ||
552 | break; | ||
553 | } | ||
554 | } | ||
555 | |||
556 | /* ***** PCI core WARs ***** */ | ||
557 | /* Done only once at attach time */ | ||
558 | static void pcie_war_polarity(struct pcicore_info *pi) | ||
559 | { | ||
560 | u32 w; | ||
561 | |||
562 | if (pi->pcie_polarity != 0) | ||
563 | return; | ||
564 | |||
565 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_PLP_STATUSREG); | ||
566 | |||
567 | /* Detect the current polarity at attach and force that polarity and | ||
568 | * disable changing the polarity | ||
569 | */ | ||
570 | if ((w & PCIE_PLP_POLARITYINV_STAT) == 0) | ||
571 | pi->pcie_polarity = SERDES_RX_CTRL_FORCE; | ||
572 | else | ||
573 | pi->pcie_polarity = (SERDES_RX_CTRL_FORCE | | ||
574 | SERDES_RX_CTRL_POLARITY); | ||
575 | } | ||
576 | |||
577 | /* enable ASPM and CLKREQ if srom doesn't have it */ | ||
578 | /* Needs to happen when update to shadow SROM is needed | ||
579 | * : Coming out of 'standby'/'hibernate' | ||
580 | * : If pcie_war_aspm_ovr state changed | ||
581 | */ | ||
582 | static void pcie_war_aspm_clkreq(struct pcicore_info *pi) | ||
583 | { | ||
584 | struct si_pub *sih = pi->sih; | ||
585 | u16 val16; | ||
586 | u32 w; | ||
587 | |||
588 | if (!PCIE_ASPM(sih)) | ||
589 | return; | ||
590 | |||
591 | /* bypass this on QT or VSIM */ | ||
592 | val16 = bcma_read16(pi->core, PCIEREGOFFS(sprom[SRSH_ASPM_OFFSET])); | ||
593 | |||
594 | val16 &= ~SRSH_ASPM_ENB; | ||
595 | if (pi->pcie_war_aspm_ovr == PCIE_ASPM_ENAB) | ||
596 | val16 |= SRSH_ASPM_ENB; | ||
597 | else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L1_ENAB) | ||
598 | val16 |= SRSH_ASPM_L1_ENB; | ||
599 | else if (pi->pcie_war_aspm_ovr == PCIE_ASPM_L0s_ENAB) | ||
600 | val16 |= SRSH_ASPM_L0s_ENB; | ||
601 | |||
602 | bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_ASPM_OFFSET]), val16); | ||
603 | |||
604 | pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w); | ||
605 | w &= ~PCIE_ASPM_ENAB; | ||
606 | w |= pi->pcie_war_aspm_ovr; | ||
607 | pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w); | ||
608 | |||
609 | val16 = bcma_read16(pi->core, | ||
610 | PCIEREGOFFS(sprom[SRSH_CLKREQ_OFFSET_REV5])); | ||
611 | |||
612 | if (pi->pcie_war_aspm_ovr != PCIE_ASPM_DISAB) { | ||
613 | val16 |= SRSH_CLKREQ_ENB; | ||
614 | pi->pcie_pr42767 = true; | ||
615 | } else | ||
616 | val16 &= ~SRSH_CLKREQ_ENB; | ||
617 | |||
618 | bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_CLKREQ_OFFSET_REV5]), | ||
619 | val16); | ||
620 | } | ||
621 | |||
622 | /* Apply the polarity determined at the start */ | ||
623 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | ||
624 | static void pcie_war_serdes(struct pcicore_info *pi) | ||
625 | { | ||
626 | u32 w = 0; | ||
627 | |||
628 | if (pi->pcie_polarity != 0) | ||
629 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CTRL, | ||
630 | pi->pcie_polarity); | ||
631 | |||
632 | pcie_mdioread(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, &w); | ||
633 | if (w & PLL_CTRL_FREQDET_EN) { | ||
634 | w &= ~PLL_CTRL_FREQDET_EN; | ||
635 | pcie_mdiowrite(pi, MDIODATA_DEV_PLL, SERDES_PLL_CTRL, w); | ||
636 | } | ||
637 | } | ||
638 | |||
639 | /* Fix MISC config to allow coming out of L2/L3-Ready state w/o PRST */ | ||
640 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | ||
641 | static void pcie_misc_config_fixup(struct pcicore_info *pi) | ||
642 | { | ||
643 | u16 val16; | ||
644 | |||
645 | val16 = bcma_read16(pi->core, | ||
646 | PCIEREGOFFS(sprom[SRSH_PCIE_MISC_CONFIG])); | ||
647 | |||
648 | if ((val16 & SRSH_L23READY_EXIT_NOPERST) == 0) { | ||
649 | val16 |= SRSH_L23READY_EXIT_NOPERST; | ||
650 | bcma_write16(pi->core, | ||
651 | PCIEREGOFFS(sprom[SRSH_PCIE_MISC_CONFIG]), val16); | ||
652 | } | ||
653 | } | ||
654 | |||
655 | /* quick hack for testing */ | ||
656 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | ||
657 | static void pcie_war_noplldown(struct pcicore_info *pi) | ||
658 | { | ||
659 | /* turn off serdes PLL down */ | ||
660 | ai_cc_reg(pi->sih, offsetof(struct chipcregs, chipcontrol), | ||
661 | CHIPCTRL_4321_PLL_DOWN, CHIPCTRL_4321_PLL_DOWN); | ||
662 | |||
663 | /* clear srom shadow backdoor */ | ||
664 | bcma_write16(pi->core, PCIEREGOFFS(sprom[SRSH_BD_OFFSET]), 0); | ||
665 | } | ||
666 | |||
667 | /* Needs to happen when coming out of 'standby'/'hibernate' */ | ||
668 | static void pcie_war_pci_setup(struct pcicore_info *pi) | ||
669 | { | ||
670 | struct si_pub *sih = pi->sih; | ||
671 | u32 w; | ||
672 | |||
673 | if (ai_get_buscorerev(sih) == 0 || ai_get_buscorerev(sih) == 1) { | ||
674 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, | ||
675 | PCIE_TLP_WORKAROUNDSREG); | ||
676 | w |= 0x8; | ||
677 | pcie_writereg(pi->core, PCIE_PCIEREGS, | ||
678 | PCIE_TLP_WORKAROUNDSREG, w); | ||
679 | } | ||
680 | |||
681 | if (ai_get_buscorerev(sih) == 1) { | ||
682 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_LCREG); | ||
683 | w |= 0x40; | ||
684 | pcie_writereg(pi->core, PCIE_PCIEREGS, PCIE_DLLP_LCREG, w); | ||
685 | } | ||
686 | |||
687 | if (ai_get_buscorerev(sih) == 0) { | ||
688 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_TIMER1, 0x8128); | ||
689 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDR, 0x0100); | ||
690 | pcie_mdiowrite(pi, MDIODATA_DEV_RX, SERDES_RX_CDRBW, 0x1466); | ||
691 | } else if (PCIE_ASPM(sih)) { | ||
692 | /* Change the L1 threshold for better performance */ | ||
693 | w = pcie_readreg(pi->core, PCIE_PCIEREGS, | ||
694 | PCIE_DLLP_PMTHRESHREG); | ||
695 | w &= ~PCIE_L1THRESHOLDTIME_MASK; | ||
696 | w |= PCIE_L1THRESHOLD_WARVAL << PCIE_L1THRESHOLDTIME_SHIFT; | ||
697 | pcie_writereg(pi->core, PCIE_PCIEREGS, | ||
698 | PCIE_DLLP_PMTHRESHREG, w); | ||
699 | |||
700 | pcie_war_serdes(pi); | ||
701 | |||
702 | pcie_war_aspm_clkreq(pi); | ||
703 | } else if (ai_get_buscorerev(pi->sih) == 7) | ||
704 | pcie_war_noplldown(pi); | ||
705 | |||
706 | /* Note that the fix is actually in the SROM, | ||
707 | * that's why this is open-ended | ||
708 | */ | ||
709 | if (ai_get_buscorerev(pi->sih) >= 6) | ||
710 | pcie_misc_config_fixup(pi); | ||
711 | } | ||
712 | |||
713 | /* ***** Functions called during driver state changes ***** */ | ||
714 | void pcicore_attach(struct pcicore_info *pi, int state) | ||
715 | { | ||
716 | struct si_pub *sih = pi->sih; | ||
717 | u32 bfl2 = (u32)getintvar(sih, BRCMS_SROM_BOARDFLAGS2); | ||
718 | |||
719 | /* Determine if this board needs override */ | ||
720 | if (PCIE_ASPM(sih)) { | ||
721 | if (bfl2 & BFL2_PCIEWAR_OVR) | ||
722 | pi->pcie_war_aspm_ovr = PCIE_ASPM_DISAB; | ||
723 | else | ||
724 | pi->pcie_war_aspm_ovr = PCIE_ASPM_ENAB; | ||
725 | } | ||
726 | |||
727 | /* These need to happen in this order only */ | ||
728 | pcie_war_polarity(pi); | ||
729 | |||
730 | pcie_war_serdes(pi); | ||
731 | |||
732 | pcie_war_aspm_clkreq(pi); | ||
733 | |||
734 | pcie_clkreq_upd(pi, state); | ||
735 | |||
736 | } | ||
737 | |||
738 | void pcicore_hwup(struct pcicore_info *pi) | ||
739 | { | ||
740 | if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID) | ||
741 | return; | ||
742 | |||
743 | pcie_war_pci_setup(pi); | ||
744 | } | ||
745 | |||
746 | void pcicore_up(struct pcicore_info *pi, int state) | ||
747 | { | ||
748 | if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID) | ||
749 | return; | ||
750 | |||
751 | /* Restore L1 timer for better performance */ | ||
752 | pcie_extendL1timer(pi, true); | ||
753 | |||
754 | pcie_clkreq_upd(pi, state); | ||
755 | } | ||
756 | |||
757 | /* When the device is going to enter D3 state | ||
758 | * (or the system is going to enter S3/S4 states) | ||
759 | */ | ||
760 | void pcicore_sleep(struct pcicore_info *pi) | ||
761 | { | ||
762 | u32 w; | ||
763 | |||
764 | if (!pi || !PCIE_ASPM(pi->sih)) | ||
765 | return; | ||
766 | |||
767 | pci_read_config_dword(pi->dev, pi->pciecap_lcreg_offset, &w); | ||
768 | w &= ~PCIE_CAP_LCREG_ASPML1; | ||
769 | pci_write_config_dword(pi->dev, pi->pciecap_lcreg_offset, w); | ||
770 | |||
771 | pi->pcie_pr42767 = false; | ||
772 | } | ||
773 | |||
774 | void pcicore_down(struct pcicore_info *pi, int state) | ||
775 | { | ||
776 | if (!pi || ai_get_buscoretype(pi->sih) != PCIE_CORE_ID) | ||
777 | return; | ||
778 | |||
779 | pcie_clkreq_upd(pi, state); | ||
780 | |||
781 | /* Reduce L1 timer for better power savings */ | ||
782 | pcie_extendL1timer(pi, false); | ||
783 | } | ||
784 | |||
785 | void pcicore_fixcfg(struct pcicore_info *pi) | ||
786 | { | ||
787 | struct bcma_device *core = pi->core; | ||
788 | u16 val16; | ||
789 | uint regoff; | ||
790 | |||
791 | switch (pi->core->id.id) { | ||
792 | case BCMA_CORE_PCI: | ||
793 | regoff = PCIREGOFFS(sprom[SRSH_PI_OFFSET]); | ||
794 | break; | ||
795 | |||
796 | case BCMA_CORE_PCIE: | ||
797 | regoff = PCIEREGOFFS(sprom[SRSH_PI_OFFSET]); | ||
798 | break; | ||
799 | |||
800 | default: | ||
801 | return; | ||
802 | } | ||
803 | |||
804 | val16 = bcma_read16(pi->core, regoff); | ||
805 | if (((val16 & SRSH_PI_MASK) >> SRSH_PI_SHIFT) != | ||
806 | (u16)core->core_index) { | ||
807 | val16 = ((u16)core->core_index << SRSH_PI_SHIFT) | | ||
808 | (val16 & ~SRSH_PI_MASK); | ||
809 | bcma_write16(pi->core, regoff, val16); | ||
810 | } | ||
811 | } | ||
812 | |||
813 | /* precondition: current core is pci core */ | ||
814 | void | ||
815 | pcicore_pci_setup(struct pcicore_info *pi) | ||
816 | { | ||
817 | bcma_set32(pi->core, PCIREGOFFS(sbtopci2), | ||
818 | SBTOPCI_PREF | SBTOPCI_BURST); | ||
819 | |||
820 | if (pi->core->id.rev >= 11) { | ||
821 | bcma_set32(pi->core, PCIREGOFFS(sbtopci2), | ||
822 | SBTOPCI_RC_READMULTI); | ||
823 | bcma_set32(pi->core, PCIREGOFFS(clkrun), PCI_CLKRUN_DSBL); | ||
824 | (void)bcma_read32(pi->core, PCIREGOFFS(clkrun)); | ||
825 | } | ||
826 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h b/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h deleted file mode 100644 index 9fc3ead540a8..000000000000 --- a/drivers/net/wireless/brcm80211/brcmsmac/nicpci.h +++ /dev/null | |||
@@ -1,77 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 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 _BRCM_NICPCI_H_ | ||
18 | #define _BRCM_NICPCI_H_ | ||
19 | |||
20 | #include "types.h" | ||
21 | |||
22 | /* PCI configuration address space size */ | ||
23 | #define PCI_SZPCR 256 | ||
24 | |||
25 | /* Brcm PCI configuration registers */ | ||
26 | /* backplane address space accessed by BAR0 */ | ||
27 | #define PCI_BAR0_WIN 0x80 | ||
28 | /* sprom property control */ | ||
29 | #define PCI_SPROM_CONTROL 0x88 | ||
30 | /* mask of PCI and other cores interrupts */ | ||
31 | #define PCI_INT_MASK 0x94 | ||
32 | /* backplane core interrupt mask bits offset */ | ||
33 | #define PCI_SBIM_SHIFT 8 | ||
34 | /* backplane address space accessed by second 4KB of BAR0 */ | ||
35 | #define PCI_BAR0_WIN2 0xac | ||
36 | /* pci config space gpio input (>=rev3) */ | ||
37 | #define PCI_GPIO_IN 0xb0 | ||
38 | /* pci config space gpio output (>=rev3) */ | ||
39 | #define PCI_GPIO_OUT 0xb4 | ||
40 | /* pci config space gpio output enable (>=rev3) */ | ||
41 | #define PCI_GPIO_OUTEN 0xb8 | ||
42 | |||
43 | /* bar0 + 4K accesses external sprom */ | ||
44 | #define PCI_BAR0_SPROM_OFFSET (4 * 1024) | ||
45 | /* bar0 + 6K accesses pci core registers */ | ||
46 | #define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) | ||
47 | /* | ||
48 | * pci core SB registers are at the end of the | ||
49 | * 8KB window, so their address is the "regular" | ||
50 | * address plus 4K | ||
51 | */ | ||
52 | #define PCI_BAR0_PCISBR_OFFSET (4 * 1024) | ||
53 | /* bar0 window size Match with corerev 13 */ | ||
54 | #define PCI_BAR0_WINSZ (16 * 1024) | ||
55 | /* On pci corerev >= 13 and all pcie, the bar0 is now 16KB and it maps: */ | ||
56 | /* bar0 + 8K accesses pci/pcie core registers */ | ||
57 | #define PCI_16KB0_PCIREGS_OFFSET (8 * 1024) | ||
58 | /* bar0 + 12K accesses chipc core registers */ | ||
59 | #define PCI_16KB0_CCREGS_OFFSET (12 * 1024) | ||
60 | |||
61 | struct sbpciregs; | ||
62 | struct sbpcieregs; | ||
63 | |||
64 | extern struct pcicore_info *pcicore_init(struct si_pub *sih, | ||
65 | struct bcma_device *core); | ||
66 | extern void pcicore_deinit(struct pcicore_info *pch); | ||
67 | extern void pcicore_attach(struct pcicore_info *pch, int state); | ||
68 | extern void pcicore_hwup(struct pcicore_info *pch); | ||
69 | extern void pcicore_up(struct pcicore_info *pch, int state); | ||
70 | extern void pcicore_sleep(struct pcicore_info *pch); | ||
71 | extern void pcicore_down(struct pcicore_info *pch, int state); | ||
72 | extern u8 pcicore_find_pci_capability(struct pci_dev *dev, u8 req_cap_id, | ||
73 | unsigned char *buf, u32 *buflen); | ||
74 | extern void pcicore_fixcfg(struct pcicore_info *pch); | ||
75 | extern void pcicore_pci_setup(struct pcicore_info *pch); | ||
76 | |||
77 | #endif /* _BRCM_NICPCI_H_ */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/otp.c b/drivers/net/wireless/brcm80211/brcmsmac/otp.c deleted file mode 100644 index f1ca12625860..000000000000 --- a/drivers/net/wireless/brcm80211/brcmsmac/otp.c +++ /dev/null | |||
@@ -1,410 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 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 | #include <linux/io.h> | ||
18 | #include <linux/errno.h> | ||
19 | #include <linux/string.h> | ||
20 | |||
21 | #include <brcm_hw_ids.h> | ||
22 | #include <chipcommon.h> | ||
23 | #include "aiutils.h" | ||
24 | #include "otp.h" | ||
25 | |||
26 | #define OTPS_GUP_MASK 0x00000f00 | ||
27 | #define OTPS_GUP_SHIFT 8 | ||
28 | /* h/w subregion is programmed */ | ||
29 | #define OTPS_GUP_HW 0x00000100 | ||
30 | /* s/w subregion is programmed */ | ||
31 | #define OTPS_GUP_SW 0x00000200 | ||
32 | /* chipid/pkgopt subregion is programmed */ | ||
33 | #define OTPS_GUP_CI 0x00000400 | ||
34 | /* fuse subregion is programmed */ | ||
35 | #define OTPS_GUP_FUSE 0x00000800 | ||
36 | |||
37 | /* Fields in otpprog in rev >= 21 */ | ||
38 | #define OTPP_COL_MASK 0x000000ff | ||
39 | #define OTPP_COL_SHIFT 0 | ||
40 | #define OTPP_ROW_MASK 0x0000ff00 | ||
41 | #define OTPP_ROW_SHIFT 8 | ||
42 | #define OTPP_OC_MASK 0x0f000000 | ||
43 | #define OTPP_OC_SHIFT 24 | ||
44 | #define OTPP_READERR 0x10000000 | ||
45 | #define OTPP_VALUE_MASK 0x20000000 | ||
46 | #define OTPP_VALUE_SHIFT 29 | ||
47 | #define OTPP_START_BUSY 0x80000000 | ||
48 | #define OTPP_READ 0x40000000 | ||
49 | |||
50 | /* Opcodes for OTPP_OC field */ | ||
51 | #define OTPPOC_READ 0 | ||
52 | #define OTPPOC_BIT_PROG 1 | ||
53 | #define OTPPOC_VERIFY 3 | ||
54 | #define OTPPOC_INIT 4 | ||
55 | #define OTPPOC_SET 5 | ||
56 | #define OTPPOC_RESET 6 | ||
57 | #define OTPPOC_OCST 7 | ||
58 | #define OTPPOC_ROW_LOCK 8 | ||
59 | #define OTPPOC_PRESCN_TEST 9 | ||
60 | |||
61 | #define OTPTYPE_IPX(ccrev) ((ccrev) == 21 || (ccrev) >= 23) | ||
62 | |||
63 | #define OTPP_TRIES 10000000 /* # of tries for OTPP */ | ||
64 | |||
65 | #define MAXNUMRDES 9 /* Maximum OTP redundancy entries */ | ||
66 | |||
67 | /* Fixed size subregions sizes in words */ | ||
68 | #define OTPGU_CI_SZ 2 | ||
69 | |||
70 | struct otpinfo; | ||
71 | |||
72 | /* OTP function struct */ | ||
73 | struct otp_fn_s { | ||
74 | int (*init)(struct si_pub *sih, struct otpinfo *oi); | ||
75 | int (*read_region)(struct otpinfo *oi, int region, u16 *data, | ||
76 | uint *wlen); | ||
77 | }; | ||
78 | |||
79 | struct otpinfo { | ||
80 | struct bcma_device *core; /* chipc core */ | ||
81 | const struct otp_fn_s *fn; /* OTP functions */ | ||
82 | struct si_pub *sih; /* Saved sb handle */ | ||
83 | |||
84 | /* IPX OTP section */ | ||
85 | u16 wsize; /* Size of otp in words */ | ||
86 | u16 rows; /* Geometry */ | ||
87 | u16 cols; /* Geometry */ | ||
88 | u32 status; /* Flag bits (lock/prog/rv). | ||
89 | * (Reflected only when OTP is power cycled) | ||
90 | */ | ||
91 | u16 hwbase; /* hardware subregion offset */ | ||
92 | u16 hwlim; /* hardware subregion boundary */ | ||
93 | u16 swbase; /* software subregion offset */ | ||
94 | u16 swlim; /* software subregion boundary */ | ||
95 | u16 fbase; /* fuse subregion offset */ | ||
96 | u16 flim; /* fuse subregion boundary */ | ||
97 | int otpgu_base; /* offset to General Use Region */ | ||
98 | }; | ||
99 | |||
100 | /* OTP layout */ | ||
101 | /* CC revs 21, 24 and 27 OTP General Use Region word offset */ | ||
102 | #define REVA4_OTPGU_BASE 12 | ||
103 | |||
104 | /* CC revs 23, 25, 26, 28 and above OTP General Use Region word offset */ | ||
105 | #define REVB8_OTPGU_BASE 20 | ||
106 | |||
107 | /* CC rev 36 OTP General Use Region word offset */ | ||
108 | #define REV36_OTPGU_BASE 12 | ||
109 | |||
110 | /* Subregion word offsets in General Use region */ | ||
111 | #define OTPGU_HSB_OFF 0 | ||
112 | #define OTPGU_SFB_OFF 1 | ||
113 | #define OTPGU_CI_OFF 2 | ||
114 | #define OTPGU_P_OFF 3 | ||
115 | #define OTPGU_SROM_OFF 4 | ||
116 | |||
117 | /* Flag bit offsets in General Use region */ | ||
118 | #define OTPGU_HWP_OFF 60 | ||
119 | #define OTPGU_SWP_OFF 61 | ||
120 | #define OTPGU_CIP_OFF 62 | ||
121 | #define OTPGU_FUSEP_OFF 63 | ||
122 | #define OTPGU_CIP_MSK 0x4000 | ||
123 | #define OTPGU_P_MSK 0xf000 | ||
124 | #define OTPGU_P_SHIFT (OTPGU_HWP_OFF % 16) | ||
125 | |||
126 | /* OTP Size */ | ||
127 | #define OTP_SZ_FU_324 ((roundup(324, 8))/8) /* 324 bits */ | ||
128 | #define OTP_SZ_FU_288 (288/8) /* 288 bits */ | ||
129 | #define OTP_SZ_FU_216 (216/8) /* 216 bits */ | ||
130 | #define OTP_SZ_FU_72 (72/8) /* 72 bits */ | ||
131 | #define OTP_SZ_CHECKSUM (16/8) /* 16 bits */ | ||
132 | #define OTP4315_SWREG_SZ 178 /* 178 bytes */ | ||
133 | #define OTP_SZ_FU_144 (144/8) /* 144 bits */ | ||
134 | |||
135 | static u16 | ||
136 | ipxotp_otpr(struct otpinfo *oi, uint wn) | ||
137 | { | ||
138 | return bcma_read16(oi->core, | ||
139 | CHIPCREGOFFS(sromotp[wn])); | ||
140 | } | ||
141 | |||
142 | /* | ||
143 | * Calculate max HW/SW region byte size by subtracting fuse region | ||
144 | * and checksum size, osizew is oi->wsize (OTP size - GU size) in words | ||
145 | */ | ||
146 | static int ipxotp_max_rgnsz(struct si_pub *sih, int osizew) | ||
147 | { | ||
148 | int ret = 0; | ||
149 | |||
150 | switch (ai_get_chip_id(sih)) { | ||
151 | case BCM43224_CHIP_ID: | ||
152 | case BCM43225_CHIP_ID: | ||
153 | ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM; | ||
154 | break; | ||
155 | case BCM4313_CHIP_ID: | ||
156 | ret = osizew * 2 - OTP_SZ_FU_72 - OTP_SZ_CHECKSUM; | ||
157 | break; | ||
158 | default: | ||
159 | break; /* Don't know about this chip */ | ||
160 | } | ||
161 | |||
162 | return ret; | ||
163 | } | ||
164 | |||
165 | static void _ipxotp_init(struct otpinfo *oi) | ||
166 | { | ||
167 | uint k; | ||
168 | u32 otpp, st; | ||
169 | int ccrev = ai_get_ccrev(oi->sih); | ||
170 | |||
171 | |||
172 | /* | ||
173 | * record word offset of General Use Region | ||
174 | * for various chipcommon revs | ||
175 | */ | ||
176 | if (ccrev == 21 || ccrev == 24 | ||
177 | || ccrev == 27) { | ||
178 | oi->otpgu_base = REVA4_OTPGU_BASE; | ||
179 | } else if (ccrev == 36) { | ||
180 | /* | ||
181 | * OTP size greater than equal to 2KB (128 words), | ||
182 | * otpgu_base is similar to rev23 | ||
183 | */ | ||
184 | if (oi->wsize >= 128) | ||
185 | oi->otpgu_base = REVB8_OTPGU_BASE; | ||
186 | else | ||
187 | oi->otpgu_base = REV36_OTPGU_BASE; | ||
188 | } else if (ccrev == 23 || ccrev >= 25) { | ||
189 | oi->otpgu_base = REVB8_OTPGU_BASE; | ||
190 | } | ||
191 | |||
192 | /* First issue an init command so the status is up to date */ | ||
193 | otpp = | ||
194 | OTPP_START_BUSY | ((OTPPOC_INIT << OTPP_OC_SHIFT) & OTPP_OC_MASK); | ||
195 | |||
196 | bcma_write32(oi->core, CHIPCREGOFFS(otpprog), otpp); | ||
197 | st = bcma_read32(oi->core, CHIPCREGOFFS(otpprog)); | ||
198 | for (k = 0; (st & OTPP_START_BUSY) && (k < OTPP_TRIES); k++) | ||
199 | st = bcma_read32(oi->core, CHIPCREGOFFS(otpprog)); | ||
200 | if (k >= OTPP_TRIES) | ||
201 | return; | ||
202 | |||
203 | /* Read OTP lock bits and subregion programmed indication bits */ | ||
204 | oi->status = bcma_read32(oi->core, CHIPCREGOFFS(otpstatus)); | ||
205 | |||
206 | if ((ai_get_chip_id(oi->sih) == BCM43224_CHIP_ID) | ||
207 | || (ai_get_chip_id(oi->sih) == BCM43225_CHIP_ID)) { | ||
208 | u32 p_bits; | ||
209 | p_bits = (ipxotp_otpr(oi, oi->otpgu_base + OTPGU_P_OFF) & | ||
210 | OTPGU_P_MSK) >> OTPGU_P_SHIFT; | ||
211 | oi->status |= (p_bits << OTPS_GUP_SHIFT); | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * h/w region base and fuse region limit are fixed to | ||
216 | * the top and the bottom of the general use region. | ||
217 | * Everything else can be flexible. | ||
218 | */ | ||
219 | oi->hwbase = oi->otpgu_base + OTPGU_SROM_OFF; | ||
220 | oi->hwlim = oi->wsize; | ||
221 | if (oi->status & OTPS_GUP_HW) { | ||
222 | oi->hwlim = | ||
223 | ipxotp_otpr(oi, oi->otpgu_base + OTPGU_HSB_OFF) / 16; | ||
224 | oi->swbase = oi->hwlim; | ||
225 | } else | ||
226 | oi->swbase = oi->hwbase; | ||
227 | |||
228 | /* subtract fuse and checksum from beginning */ | ||
229 | oi->swlim = ipxotp_max_rgnsz(oi->sih, oi->wsize) / 2; | ||
230 | |||
231 | if (oi->status & OTPS_GUP_SW) { | ||
232 | oi->swlim = | ||
233 | ipxotp_otpr(oi, oi->otpgu_base + OTPGU_SFB_OFF) / 16; | ||
234 | oi->fbase = oi->swlim; | ||
235 | } else | ||
236 | oi->fbase = oi->swbase; | ||
237 | |||
238 | oi->flim = oi->wsize; | ||
239 | } | ||
240 | |||
241 | static int ipxotp_init(struct si_pub *sih, struct otpinfo *oi) | ||
242 | { | ||
243 | /* Make sure we're running IPX OTP */ | ||
244 | if (!OTPTYPE_IPX(ai_get_ccrev(sih))) | ||
245 | return -EBADE; | ||
246 | |||
247 | /* Make sure OTP is not disabled */ | ||
248 | if (ai_is_otp_disabled(sih)) | ||
249 | return -EBADE; | ||
250 | |||
251 | /* Check for otp size */ | ||
252 | switch ((ai_get_cccaps(sih) & CC_CAP_OTPSIZE) >> CC_CAP_OTPSIZE_SHIFT) { | ||
253 | case 0: | ||
254 | /* Nothing there */ | ||
255 | return -EBADE; | ||
256 | case 1: /* 32x64 */ | ||
257 | oi->rows = 32; | ||
258 | oi->cols = 64; | ||
259 | oi->wsize = 128; | ||
260 | break; | ||
261 | case 2: /* 64x64 */ | ||
262 | oi->rows = 64; | ||
263 | oi->cols = 64; | ||
264 | oi->wsize = 256; | ||
265 | break; | ||
266 | case 5: /* 96x64 */ | ||
267 | oi->rows = 96; | ||
268 | oi->cols = 64; | ||
269 | oi->wsize = 384; | ||
270 | break; | ||
271 | case 7: /* 16x64 *//* 1024 bits */ | ||
272 | oi->rows = 16; | ||
273 | oi->cols = 64; | ||
274 | oi->wsize = 64; | ||
275 | break; | ||
276 | default: | ||
277 | /* Don't know the geometry */ | ||
278 | return -EBADE; | ||
279 | } | ||
280 | |||
281 | /* Retrieve OTP region info */ | ||
282 | _ipxotp_init(oi); | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static int | ||
287 | ipxotp_read_region(struct otpinfo *oi, int region, u16 *data, uint *wlen) | ||
288 | { | ||
289 | uint base, i, sz; | ||
290 | |||
291 | /* Validate region selection */ | ||
292 | switch (region) { | ||
293 | case OTP_HW_RGN: | ||
294 | sz = (uint) oi->hwlim - oi->hwbase; | ||
295 | if (!(oi->status & OTPS_GUP_HW)) { | ||
296 | *wlen = sz; | ||
297 | return -ENODATA; | ||
298 | } | ||
299 | if (*wlen < sz) { | ||
300 | *wlen = sz; | ||
301 | return -EOVERFLOW; | ||
302 | } | ||
303 | base = oi->hwbase; | ||
304 | break; | ||
305 | case OTP_SW_RGN: | ||
306 | sz = ((uint) oi->swlim - oi->swbase); | ||
307 | if (!(oi->status & OTPS_GUP_SW)) { | ||
308 | *wlen = sz; | ||
309 | return -ENODATA; | ||
310 | } | ||
311 | if (*wlen < sz) { | ||
312 | *wlen = sz; | ||
313 | return -EOVERFLOW; | ||
314 | } | ||
315 | base = oi->swbase; | ||
316 | break; | ||
317 | case OTP_CI_RGN: | ||
318 | sz = OTPGU_CI_SZ; | ||
319 | if (!(oi->status & OTPS_GUP_CI)) { | ||
320 | *wlen = sz; | ||
321 | return -ENODATA; | ||
322 | } | ||
323 | if (*wlen < sz) { | ||
324 | *wlen = sz; | ||
325 | return -EOVERFLOW; | ||
326 | } | ||
327 | base = oi->otpgu_base + OTPGU_CI_OFF; | ||
328 | break; | ||
329 | case OTP_FUSE_RGN: | ||
330 | sz = (uint) oi->flim - oi->fbase; | ||
331 | if (!(oi->status & OTPS_GUP_FUSE)) { | ||
332 | *wlen = sz; | ||
333 | return -ENODATA; | ||
334 | } | ||
335 | if (*wlen < sz) { | ||
336 | *wlen = sz; | ||
337 | return -EOVERFLOW; | ||
338 | } | ||
339 | base = oi->fbase; | ||
340 | break; | ||
341 | case OTP_ALL_RGN: | ||
342 | sz = ((uint) oi->flim - oi->hwbase); | ||
343 | if (!(oi->status & (OTPS_GUP_HW | OTPS_GUP_SW))) { | ||
344 | *wlen = sz; | ||
345 | return -ENODATA; | ||
346 | } | ||
347 | if (*wlen < sz) { | ||
348 | *wlen = sz; | ||
349 | return -EOVERFLOW; | ||
350 | } | ||
351 | base = oi->hwbase; | ||
352 | break; | ||
353 | default: | ||
354 | return -EINVAL; | ||
355 | } | ||
356 | |||
357 | /* Read the data */ | ||
358 | for (i = 0; i < sz; i++) | ||
359 | data[i] = ipxotp_otpr(oi, base + i); | ||
360 | |||
361 | *wlen = sz; | ||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static const struct otp_fn_s ipxotp_fn = { | ||
366 | (int (*)(struct si_pub *, struct otpinfo *)) ipxotp_init, | ||
367 | (int (*)(struct otpinfo *, int, u16 *, uint *)) ipxotp_read_region, | ||
368 | }; | ||
369 | |||
370 | static int otp_init(struct si_pub *sih, struct otpinfo *oi) | ||
371 | { | ||
372 | int ret; | ||
373 | |||
374 | memset(oi, 0, sizeof(struct otpinfo)); | ||
375 | |||
376 | oi->core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); | ||
377 | |||
378 | if (OTPTYPE_IPX(ai_get_ccrev(sih))) | ||
379 | oi->fn = &ipxotp_fn; | ||
380 | |||
381 | if (oi->fn == NULL) | ||
382 | return -EBADE; | ||
383 | |||
384 | oi->sih = sih; | ||
385 | |||
386 | ret = (oi->fn->init)(sih, oi); | ||
387 | |||
388 | return ret; | ||
389 | } | ||
390 | |||
391 | int | ||
392 | otp_read_region(struct si_pub *sih, int region, u16 *data, uint *wlen) { | ||
393 | struct otpinfo otpinfo; | ||
394 | struct otpinfo *oi = &otpinfo; | ||
395 | int err = 0; | ||
396 | |||
397 | if (ai_is_otp_disabled(sih)) { | ||
398 | err = -EPERM; | ||
399 | goto out; | ||
400 | } | ||
401 | |||
402 | err = otp_init(sih, oi); | ||
403 | if (err) | ||
404 | goto out; | ||
405 | |||
406 | err = ((oi)->fn->read_region)(oi, region, data, wlen); | ||
407 | |||
408 | out: | ||
409 | return err; | ||
410 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/otp.h b/drivers/net/wireless/brcm80211/brcmsmac/otp.h deleted file mode 100644 index 6b6d31cf9569..000000000000 --- a/drivers/net/wireless/brcm80211/brcmsmac/otp.h +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 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 _BRCM_OTP_H_ | ||
18 | #define _BRCM_OTP_H_ | ||
19 | |||
20 | #include "types.h" | ||
21 | |||
22 | /* OTP regions */ | ||
23 | #define OTP_HW_RGN 1 | ||
24 | #define OTP_SW_RGN 2 | ||
25 | #define OTP_CI_RGN 4 | ||
26 | #define OTP_FUSE_RGN 8 | ||
27 | /* From h/w region to end of OTP including checksum */ | ||
28 | #define OTP_ALL_RGN 0xf | ||
29 | |||
30 | /* OTP Size */ | ||
31 | #define OTP_SZ_MAX (6144/8) /* maximum bytes in one CIS */ | ||
32 | |||
33 | extern int otp_read_region(struct si_pub *sih, int region, u16 *data, | ||
34 | uint *wlen); | ||
35 | |||
36 | #endif /* _BRCM_OTP_H_ */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c index 0fce56235f38..abfd78822fb8 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c | |||
@@ -4817,28 +4817,23 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) | |||
4817 | s8 txpwr = 0; | 4817 | s8 txpwr = 0; |
4818 | int i; | 4818 | int i; |
4819 | struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; | 4819 | struct brcms_phy_lcnphy *pi_lcn = pi->u.pi_lcnphy; |
4820 | struct phy_shim_info *shim = pi->sh->physhim; | 4820 | struct ssb_sprom *sprom = &pi->d11core->bus->sprom; |
4821 | 4821 | ||
4822 | if (CHSPEC_IS2G(pi->radio_chanspec)) { | 4822 | if (CHSPEC_IS2G(pi->radio_chanspec)) { |
4823 | u16 cckpo = 0; | 4823 | u16 cckpo = 0; |
4824 | u32 offset_ofdm, offset_mcs; | 4824 | u32 offset_ofdm, offset_mcs; |
4825 | 4825 | ||
4826 | pi_lcn->lcnphy_tr_isolation_mid = | 4826 | pi_lcn->lcnphy_tr_isolation_mid = sprom->fem.ghz2.tr_iso; |
4827 | (u8)wlapi_getintvar(shim, BRCMS_SROM_TRISO2G); | ||
4828 | 4827 | ||
4829 | pi_lcn->lcnphy_rx_power_offset = | 4828 | pi_lcn->lcnphy_rx_power_offset = sprom->rxpo2g; |
4830 | (u8)wlapi_getintvar(shim, BRCMS_SROM_RXPO2G); | ||
4831 | 4829 | ||
4832 | pi->txpa_2g[0] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B0); | 4830 | pi->txpa_2g[0] = sprom->pa0b0; |
4833 | pi->txpa_2g[1] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B1); | 4831 | pi->txpa_2g[1] = sprom->pa0b1; |
4834 | pi->txpa_2g[2] = (s16)wlapi_getintvar(shim, BRCMS_SROM_PA0B2); | 4832 | pi->txpa_2g[2] = sprom->pa0b2; |
4835 | 4833 | ||
4836 | pi_lcn->lcnphy_rssi_vf = | 4834 | pi_lcn->lcnphy_rssi_vf = sprom->rssismf2g; |
4837 | (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMF2G); | 4835 | pi_lcn->lcnphy_rssi_vc = sprom->rssismc2g; |
4838 | pi_lcn->lcnphy_rssi_vc = | 4836 | pi_lcn->lcnphy_rssi_gs = sprom->rssisav2g; |
4839 | (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISMC2G); | ||
4840 | pi_lcn->lcnphy_rssi_gs = | ||
4841 | (u8)wlapi_getintvar(shim, BRCMS_SROM_RSSISAV2G); | ||
4842 | 4837 | ||
4843 | pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf; | 4838 | pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf; |
4844 | pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc; | 4839 | pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc; |
@@ -4848,7 +4843,7 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) | |||
4848 | pi_lcn->lcnphy_rssi_vc_hightemp = pi_lcn->lcnphy_rssi_vc; | 4843 | pi_lcn->lcnphy_rssi_vc_hightemp = pi_lcn->lcnphy_rssi_vc; |
4849 | pi_lcn->lcnphy_rssi_gs_hightemp = pi_lcn->lcnphy_rssi_gs; | 4844 | pi_lcn->lcnphy_rssi_gs_hightemp = pi_lcn->lcnphy_rssi_gs; |
4850 | 4845 | ||
4851 | txpwr = (s8)wlapi_getintvar(shim, BRCMS_SROM_MAXP2GA0); | 4846 | txpwr = sprom->core_pwr_info[0].maxpwr_2g; |
4852 | pi->tx_srom_max_2g = txpwr; | 4847 | pi->tx_srom_max_2g = txpwr; |
4853 | 4848 | ||
4854 | for (i = 0; i < PWRTBL_NUM_COEFF; i++) { | 4849 | for (i = 0; i < PWRTBL_NUM_COEFF; i++) { |
@@ -4856,8 +4851,8 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) | |||
4856 | pi->txpa_2g_high_temp[i] = pi->txpa_2g[i]; | 4851 | pi->txpa_2g_high_temp[i] = pi->txpa_2g[i]; |
4857 | } | 4852 | } |
4858 | 4853 | ||
4859 | cckpo = (u16)wlapi_getintvar(shim, BRCMS_SROM_CCK2GPO); | 4854 | cckpo = sprom->cck2gpo; |
4860 | offset_ofdm = (u32)wlapi_getintvar(shim, BRCMS_SROM_OFDM2GPO); | 4855 | offset_ofdm = sprom->ofdm2gpo; |
4861 | if (cckpo) { | 4856 | if (cckpo) { |
4862 | uint max_pwr_chan = txpwr; | 4857 | uint max_pwr_chan = txpwr; |
4863 | 4858 | ||
@@ -4876,7 +4871,7 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) | |||
4876 | } else { | 4871 | } else { |
4877 | u8 opo = 0; | 4872 | u8 opo = 0; |
4878 | 4873 | ||
4879 | opo = (u8)wlapi_getintvar(shim, BRCMS_SROM_OPO); | 4874 | opo = sprom->opo; |
4880 | 4875 | ||
4881 | for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) | 4876 | for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) |
4882 | pi->tx_srom_max_rate_2g[i] = txpwr; | 4877 | pi->tx_srom_max_rate_2g[i] = txpwr; |
@@ -4886,12 +4881,8 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) | |||
4886 | ((offset_ofdm & 0xf) * 2); | 4881 | ((offset_ofdm & 0xf) * 2); |
4887 | offset_ofdm >>= 4; | 4882 | offset_ofdm >>= 4; |
4888 | } | 4883 | } |
4889 | offset_mcs = | 4884 | offset_mcs = sprom->mcs2gpo[1] << 16; |
4890 | wlapi_getintvar(shim, | 4885 | offset_mcs |= sprom->mcs2gpo[0]; |
4891 | BRCMS_SROM_MCS2GPO1) << 16; | ||
4892 | offset_mcs |= | ||
4893 | (u16) wlapi_getintvar(shim, | ||
4894 | BRCMS_SROM_MCS2GPO0); | ||
4895 | pi_lcn->lcnphy_mcs20_po = offset_mcs; | 4886 | pi_lcn->lcnphy_mcs20_po = offset_mcs; |
4896 | for (i = TXP_FIRST_SISO_MCS_20; | 4887 | for (i = TXP_FIRST_SISO_MCS_20; |
4897 | i <= TXP_LAST_SISO_MCS_20; i++) { | 4888 | i <= TXP_LAST_SISO_MCS_20; i++) { |
@@ -4901,25 +4892,17 @@ static bool wlc_phy_txpwr_srom_read_lcnphy(struct brcms_phy *pi) | |||
4901 | } | 4892 | } |
4902 | } | 4893 | } |
4903 | 4894 | ||
4904 | pi_lcn->lcnphy_rawtempsense = | 4895 | pi_lcn->lcnphy_rawtempsense = sprom->rawtempsense; |
4905 | (u16)wlapi_getintvar(shim, BRCMS_SROM_RAWTEMPSENSE); | 4896 | pi_lcn->lcnphy_measPower = sprom->measpower; |
4906 | pi_lcn->lcnphy_measPower = | 4897 | pi_lcn->lcnphy_tempsense_slope = sprom->tempsense_slope; |
4907 | (u8)wlapi_getintvar(shim, BRCMS_SROM_MEASPOWER); | 4898 | pi_lcn->lcnphy_hw_iqcal_en = sprom->hw_iqcal_en; |
4908 | pi_lcn->lcnphy_tempsense_slope = | 4899 | pi_lcn->lcnphy_iqcal_swp_dis = sprom->iqcal_swp_dis; |
4909 | (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_SLOPE); | 4900 | pi_lcn->lcnphy_tempcorrx = sprom->tempcorrx; |
4910 | pi_lcn->lcnphy_hw_iqcal_en = | 4901 | pi_lcn->lcnphy_tempsense_option = sprom->tempsense_option; |
4911 | (bool)wlapi_getintvar(shim, BRCMS_SROM_HW_IQCAL_EN); | 4902 | pi_lcn->lcnphy_freqoffset_corr = sprom->freqoffset_corr; |
4912 | pi_lcn->lcnphy_iqcal_swp_dis = | 4903 | if (sprom->ant_available_bg > 1) |
4913 | (bool)wlapi_getintvar(shim, BRCMS_SROM_IQCAL_SWP_DIS); | ||
4914 | pi_lcn->lcnphy_tempcorrx = | ||
4915 | (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPCORRX); | ||
4916 | pi_lcn->lcnphy_tempsense_option = | ||
4917 | (u8)wlapi_getintvar(shim, BRCMS_SROM_TEMPSENSE_OPTION); | ||
4918 | pi_lcn->lcnphy_freqoffset_corr = | ||
4919 | (u8)wlapi_getintvar(shim, BRCMS_SROM_FREQOFFSET_CORR); | ||
4920 | if ((u8)wlapi_getintvar(shim, BRCMS_SROM_AA2G) > 1) | ||
4921 | wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi, | 4904 | wlc_phy_ant_rxdiv_set((struct brcms_phy_pub *) pi, |
4922 | (u8) wlapi_getintvar(shim, BRCMS_SROM_AA2G)); | 4905 | sprom->ant_available_bg); |
4923 | } | 4906 | } |
4924 | pi_lcn->lcnphy_cck_dig_filt_type = -1; | 4907 | pi_lcn->lcnphy_cck_dig_filt_type = -1; |
4925 | 4908 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c index 812b6e38526e..13b261517cce 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy/phy_n.c | |||
@@ -14386,30 +14386,30 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi) | |||
14386 | { | 14386 | { |
14387 | u16 bw40po, cddpo, stbcpo, bwduppo; | 14387 | u16 bw40po, cddpo, stbcpo, bwduppo; |
14388 | uint band_num; | 14388 | uint band_num; |
14389 | struct phy_shim_info *shim = pi->sh->physhim; | 14389 | struct ssb_sprom *sprom = &pi->d11core->bus->sprom; |
14390 | 14390 | ||
14391 | if (pi->sh->sromrev >= 9) | 14391 | if (pi->sh->sromrev >= 9) |
14392 | return; | 14392 | return; |
14393 | 14393 | ||
14394 | bw40po = (u16) wlapi_getintvar(shim, BRCMS_SROM_BW40PO); | 14394 | bw40po = sprom->bw40po; |
14395 | pi->bw402gpo = bw40po & 0xf; | 14395 | pi->bw402gpo = bw40po & 0xf; |
14396 | pi->bw405gpo = (bw40po & 0xf0) >> 4; | 14396 | pi->bw405gpo = (bw40po & 0xf0) >> 4; |
14397 | pi->bw405glpo = (bw40po & 0xf00) >> 8; | 14397 | pi->bw405glpo = (bw40po & 0xf00) >> 8; |
14398 | pi->bw405ghpo = (bw40po & 0xf000) >> 12; | 14398 | pi->bw405ghpo = (bw40po & 0xf000) >> 12; |
14399 | 14399 | ||
14400 | cddpo = (u16) wlapi_getintvar(shim, BRCMS_SROM_CDDPO); | 14400 | cddpo = sprom->cddpo; |
14401 | pi->cdd2gpo = cddpo & 0xf; | 14401 | pi->cdd2gpo = cddpo & 0xf; |
14402 | pi->cdd5gpo = (cddpo & 0xf0) >> 4; | 14402 | pi->cdd5gpo = (cddpo & 0xf0) >> 4; |
14403 | pi->cdd5glpo = (cddpo & 0xf00) >> 8; | 14403 | pi->cdd5glpo = (cddpo & 0xf00) >> 8; |
14404 | pi->cdd5ghpo = (cddpo & 0xf000) >> 12; | 14404 | pi->cdd5ghpo = (cddpo & 0xf000) >> 12; |
14405 | 14405 | ||
14406 | stbcpo = (u16) wlapi_getintvar(shim, BRCMS_SROM_STBCPO); | 14406 | stbcpo = sprom->stbcpo; |
14407 | pi->stbc2gpo = stbcpo & 0xf; | 14407 | pi->stbc2gpo = stbcpo & 0xf; |
14408 | pi->stbc5gpo = (stbcpo & 0xf0) >> 4; | 14408 | pi->stbc5gpo = (stbcpo & 0xf0) >> 4; |
14409 | pi->stbc5glpo = (stbcpo & 0xf00) >> 8; | 14409 | pi->stbc5glpo = (stbcpo & 0xf00) >> 8; |
14410 | pi->stbc5ghpo = (stbcpo & 0xf000) >> 12; | 14410 | pi->stbc5ghpo = (stbcpo & 0xf000) >> 12; |
14411 | 14411 | ||
14412 | bwduppo = (u16) wlapi_getintvar(shim, BRCMS_SROM_BWDUPPO); | 14412 | bwduppo = sprom->bwduppo; |
14413 | pi->bwdup2gpo = bwduppo & 0xf; | 14413 | pi->bwdup2gpo = bwduppo & 0xf; |
14414 | pi->bwdup5gpo = (bwduppo & 0xf0) >> 4; | 14414 | pi->bwdup5gpo = (bwduppo & 0xf0) >> 4; |
14415 | pi->bwdup5glpo = (bwduppo & 0xf00) >> 8; | 14415 | pi->bwdup5glpo = (bwduppo & 0xf00) >> 8; |
@@ -14419,242 +14419,137 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi) | |||
14419 | band_num++) { | 14419 | band_num++) { |
14420 | switch (band_num) { | 14420 | switch (band_num) { |
14421 | case 0: | 14421 | case 0: |
14422 | |||
14423 | pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g = | 14422 | pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_2g = |
14424 | (s8) wlapi_getintvar(shim, | 14423 | sprom->core_pwr_info[0].maxpwr_2g; |
14425 | BRCMS_SROM_MAXP2GA0); | ||
14426 | pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g = | 14424 | pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_2g = |
14427 | (s8) wlapi_getintvar(shim, | 14425 | sprom->core_pwr_info[1].maxpwr_2g; |
14428 | BRCMS_SROM_MAXP2GA1); | ||
14429 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 = | 14426 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_a1 = |
14430 | (s16) wlapi_getintvar(shim, | 14427 | sprom->core_pwr_info[0].pa_2g[0]; |
14431 | BRCMS_SROM_PA2GW0A0); | ||
14432 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 = | 14428 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_a1 = |
14433 | (s16) wlapi_getintvar(shim, | 14429 | sprom->core_pwr_info[1].pa_2g[0]; |
14434 | BRCMS_SROM_PA2GW0A1); | ||
14435 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 = | 14430 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b0 = |
14436 | (s16) wlapi_getintvar(shim, | 14431 | sprom->core_pwr_info[0].pa_2g[1]; |
14437 | BRCMS_SROM_PA2GW1A0); | ||
14438 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 = | 14432 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b0 = |
14439 | (s16) wlapi_getintvar(shim, | 14433 | sprom->core_pwr_info[1].pa_2g[1]; |
14440 | BRCMS_SROM_PA2GW1A1); | ||
14441 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 = | 14434 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_2g_b1 = |
14442 | (s16) wlapi_getintvar(shim, | 14435 | sprom->core_pwr_info[0].pa_2g[2]; |
14443 | BRCMS_SROM_PA2GW2A0); | ||
14444 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 = | 14436 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_2g_b1 = |
14445 | (s16) wlapi_getintvar(shim, | 14437 | sprom->core_pwr_info[1].pa_2g[2]; |
14446 | BRCMS_SROM_PA2GW2A1); | ||
14447 | pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g = | 14438 | pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_2g = |
14448 | (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT2GA0); | 14439 | sprom->core_pwr_info[0].itssi_2g; |
14449 | pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g = | 14440 | pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_2g = |
14450 | (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT2GA1); | 14441 | sprom->core_pwr_info[1].itssi_2g; |
14451 | 14442 | ||
14452 | pi->cck2gpo = (u16) wlapi_getintvar(shim, | 14443 | pi->cck2gpo = sprom->cck2gpo; |
14453 | BRCMS_SROM_CCK2GPO); | 14444 | |
14454 | 14445 | pi->ofdm2gpo = sprom->ofdm2gpo; | |
14455 | pi->ofdm2gpo = | 14446 | |
14456 | (u32) wlapi_getintvar(shim, | 14447 | pi->mcs2gpo[0] = sprom->mcs2gpo[0]; |
14457 | BRCMS_SROM_OFDM2GPO); | 14448 | pi->mcs2gpo[1] = sprom->mcs2gpo[1]; |
14458 | 14449 | pi->mcs2gpo[2] = sprom->mcs2gpo[2]; | |
14459 | pi->mcs2gpo[0] = | 14450 | pi->mcs2gpo[3] = sprom->mcs2gpo[3]; |
14460 | (u16) wlapi_getintvar(shim, | 14451 | pi->mcs2gpo[4] = sprom->mcs2gpo[4]; |
14461 | BRCMS_SROM_MCS2GPO0); | 14452 | pi->mcs2gpo[5] = sprom->mcs2gpo[5]; |
14462 | pi->mcs2gpo[1] = | 14453 | pi->mcs2gpo[6] = sprom->mcs2gpo[6]; |
14463 | (u16) wlapi_getintvar(shim, | 14454 | pi->mcs2gpo[7] = sprom->mcs2gpo[7]; |
14464 | BRCMS_SROM_MCS2GPO1); | ||
14465 | pi->mcs2gpo[2] = | ||
14466 | (u16) wlapi_getintvar(shim, | ||
14467 | BRCMS_SROM_MCS2GPO2); | ||
14468 | pi->mcs2gpo[3] = | ||
14469 | (u16) wlapi_getintvar(shim, | ||
14470 | BRCMS_SROM_MCS2GPO3); | ||
14471 | pi->mcs2gpo[4] = | ||
14472 | (u16) wlapi_getintvar(shim, | ||
14473 | BRCMS_SROM_MCS2GPO4); | ||
14474 | pi->mcs2gpo[5] = | ||
14475 | (u16) wlapi_getintvar(shim, | ||
14476 | BRCMS_SROM_MCS2GPO5); | ||
14477 | pi->mcs2gpo[6] = | ||
14478 | (u16) wlapi_getintvar(shim, | ||
14479 | BRCMS_SROM_MCS2GPO6); | ||
14480 | pi->mcs2gpo[7] = | ||
14481 | (u16) wlapi_getintvar(shim, | ||
14482 | BRCMS_SROM_MCS2GPO7); | ||
14483 | break; | 14455 | break; |
14484 | case 1: | 14456 | case 1: |
14485 | 14457 | ||
14486 | pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm = | 14458 | pi->nphy_pwrctrl_info[PHY_CORE_0].max_pwr_5gm = |
14487 | (s8) wlapi_getintvar(shim, BRCMS_SROM_MAXP5GA0); | 14459 | sprom->core_pwr_info[0].maxpwr_5g; |
14488 | pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm = | 14460 | pi->nphy_pwrctrl_info[PHY_CORE_1].max_pwr_5gm = |
14489 | (s8) wlapi_getintvar(shim, | 14461 | sprom->core_pwr_info[1].maxpwr_5g; |
14490 | BRCMS_SROM_MAXP5GA1); | ||
14491 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 = | 14462 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_a1 = |
14492 | (s16) wlapi_getintvar(shim, | 14463 | sprom->core_pwr_info[0].pa_5g[0]; |
14493 | BRCMS_SROM_PA5GW0A0); | ||
14494 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 = | 14464 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_a1 = |
14495 | (s16) wlapi_getintvar(shim, | 14465 | sprom->core_pwr_info[1].pa_5g[0]; |
14496 | BRCMS_SROM_PA5GW0A1); | ||
14497 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 = | 14466 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b0 = |
14498 | (s16) wlapi_getintvar(shim, | 14467 | sprom->core_pwr_info[0].pa_5g[1]; |
14499 | BRCMS_SROM_PA5GW1A0); | ||
14500 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 = | 14468 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b0 = |
14501 | (s16) wlapi_getintvar(shim, | 14469 | sprom->core_pwr_info[1].pa_5g[1]; |
14502 | BRCMS_SROM_PA5GW1A1); | ||
14503 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 = | 14470 | pi->nphy_pwrctrl_info[PHY_CORE_0].pwrdet_5gm_b1 = |
14504 | (s16) wlapi_getintvar(shim, | 14471 | sprom->core_pwr_info[0].pa_5g[2]; |
14505 | BRCMS_SROM_PA5GW2A0); | ||
14506 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 = | 14472 | pi->nphy_pwrctrl_info[PHY_CORE_1].pwrdet_5gm_b1 = |
14507 | (s16) wlapi_getintvar(shim, | 14473 | sprom->core_pwr_info[1].pa_5g[2]; |
14508 | BRCMS_SROM_PA5GW2A1); | ||
14509 | pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm = | 14474 | pi->nphy_pwrctrl_info[PHY_CORE_0].idle_targ_5gm = |
14510 | (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT5GA0); | 14475 | sprom->core_pwr_info[0].itssi_5g; |
14511 | pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm = | 14476 | pi->nphy_pwrctrl_info[PHY_CORE_1].idle_targ_5gm = |
14512 | (s8) wlapi_getintvar(shim, BRCMS_SROM_ITT5GA1); | 14477 | sprom->core_pwr_info[1].itssi_5g; |
14513 | 14478 | ||
14514 | pi->ofdm5gpo = | 14479 | pi->ofdm5gpo = sprom->ofdm5gpo; |
14515 | (u32) wlapi_getintvar(shim, | 14480 | |
14516 | BRCMS_SROM_OFDM5GPO); | 14481 | pi->mcs5gpo[0] = sprom->mcs5gpo[0]; |
14517 | 14482 | pi->mcs5gpo[1] = sprom->mcs5gpo[1]; | |
14518 | pi->mcs5gpo[0] = | 14483 | pi->mcs5gpo[2] = sprom->mcs5gpo[2]; |
14519 | (u16) wlapi_getintvar(shim, | 14484 | pi->mcs5gpo[3] = sprom->mcs5gpo[3]; |
14520 | BRCMS_SROM_MCS5GPO0); | 14485 | pi->mcs5gpo[4] = sprom->mcs5gpo[4]; |
14521 | pi->mcs5gpo[1] = | 14486 | pi->mcs5gpo[5] = sprom->mcs5gpo[5]; |
14522 | (u16) wlapi_getintvar(shim, | 14487 | pi->mcs5gpo[6] = sprom->mcs5gpo[6]; |
14523 | BRCMS_SROM_MCS5GPO1); | 14488 | pi->mcs5gpo[7] = sprom->mcs5gpo[7]; |
14524 | pi->mcs5gpo[2] = | ||
14525 | (u16) wlapi_getintvar(shim, | ||
14526 | BRCMS_SROM_MCS5GPO2); | ||
14527 | pi->mcs5gpo[3] = | ||
14528 | (u16) wlapi_getintvar(shim, | ||
14529 | BRCMS_SROM_MCS5GPO3); | ||
14530 | pi->mcs5gpo[4] = | ||
14531 | (u16) wlapi_getintvar(shim, | ||
14532 | BRCMS_SROM_MCS5GPO4); | ||
14533 | pi->mcs5gpo[5] = | ||
14534 | (u16) wlapi_getintvar(shim, | ||
14535 | BRCMS_SROM_MCS5GPO5); | ||
14536 | pi->mcs5gpo[6] = | ||
14537 | (u16) wlapi_getintvar(shim, | ||
14538 | BRCMS_SROM_MCS5GPO6); | ||
14539 | pi->mcs5gpo[7] = | ||
14540 | (u16) wlapi_getintvar(shim, | ||
14541 | BRCMS_SROM_MCS5GPO7); | ||
14542 | break; | 14489 | break; |
14543 | case 2: | 14490 | case 2: |
14544 | 14491 | ||
14545 | pi->nphy_pwrctrl_info[0].max_pwr_5gl = | 14492 | pi->nphy_pwrctrl_info[0].max_pwr_5gl = |
14546 | (s8) wlapi_getintvar(shim, | 14493 | sprom->core_pwr_info[0].maxpwr_5gl; |
14547 | BRCMS_SROM_MAXP5GLA0); | ||
14548 | pi->nphy_pwrctrl_info[1].max_pwr_5gl = | 14494 | pi->nphy_pwrctrl_info[1].max_pwr_5gl = |
14549 | (s8) wlapi_getintvar(shim, | 14495 | sprom->core_pwr_info[1].maxpwr_5gl; |
14550 | BRCMS_SROM_MAXP5GLA1); | ||
14551 | pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 = | 14496 | pi->nphy_pwrctrl_info[0].pwrdet_5gl_a1 = |
14552 | (s16) wlapi_getintvar(shim, | 14497 | sprom->core_pwr_info[0].pa_5gl[0]; |
14553 | BRCMS_SROM_PA5GLW0A0); | ||
14554 | pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 = | 14498 | pi->nphy_pwrctrl_info[1].pwrdet_5gl_a1 = |
14555 | (s16) wlapi_getintvar(shim, | 14499 | sprom->core_pwr_info[1].pa_5gl[0]; |
14556 | BRCMS_SROM_PA5GLW0A1); | ||
14557 | pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 = | 14500 | pi->nphy_pwrctrl_info[0].pwrdet_5gl_b0 = |
14558 | (s16) wlapi_getintvar(shim, | 14501 | sprom->core_pwr_info[0].pa_5gl[1]; |
14559 | BRCMS_SROM_PA5GLW1A0); | ||
14560 | pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 = | 14502 | pi->nphy_pwrctrl_info[1].pwrdet_5gl_b0 = |
14561 | (s16) wlapi_getintvar(shim, | 14503 | sprom->core_pwr_info[1].pa_5gl[1]; |
14562 | BRCMS_SROM_PA5GLW1A1); | ||
14563 | pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 = | 14504 | pi->nphy_pwrctrl_info[0].pwrdet_5gl_b1 = |
14564 | (s16) wlapi_getintvar(shim, | 14505 | sprom->core_pwr_info[0].pa_5gl[2]; |
14565 | BRCMS_SROM_PA5GLW2A0); | ||
14566 | pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 = | 14506 | pi->nphy_pwrctrl_info[1].pwrdet_5gl_b1 = |
14567 | (s16) wlapi_getintvar(shim, | 14507 | sprom->core_pwr_info[1].pa_5gl[2]; |
14568 | BRCMS_SROM_PA5GLW2A1); | ||
14569 | pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0; | 14508 | pi->nphy_pwrctrl_info[0].idle_targ_5gl = 0; |
14570 | pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0; | 14509 | pi->nphy_pwrctrl_info[1].idle_targ_5gl = 0; |
14571 | 14510 | ||
14572 | pi->ofdm5glpo = | 14511 | pi->ofdm5glpo = sprom->ofdm5glpo; |
14573 | (u32) wlapi_getintvar(shim, | 14512 | |
14574 | BRCMS_SROM_OFDM5GLPO); | 14513 | pi->mcs5glpo[0] = sprom->mcs5glpo[0]; |
14575 | 14514 | pi->mcs5glpo[1] = sprom->mcs5glpo[1]; | |
14576 | pi->mcs5glpo[0] = | 14515 | pi->mcs5glpo[2] = sprom->mcs5glpo[2]; |
14577 | (u16) wlapi_getintvar(shim, | 14516 | pi->mcs5glpo[3] = sprom->mcs5glpo[3]; |
14578 | BRCMS_SROM_MCS5GLPO0); | 14517 | pi->mcs5glpo[4] = sprom->mcs5glpo[4]; |
14579 | pi->mcs5glpo[1] = | 14518 | pi->mcs5glpo[5] = sprom->mcs5glpo[5]; |
14580 | (u16) wlapi_getintvar(shim, | 14519 | pi->mcs5glpo[6] = sprom->mcs5glpo[6]; |
14581 | BRCMS_SROM_MCS5GLPO1); | 14520 | pi->mcs5glpo[7] = sprom->mcs5glpo[7]; |
14582 | pi->mcs5glpo[2] = | ||
14583 | (u16) wlapi_getintvar(shim, | ||
14584 | BRCMS_SROM_MCS5GLPO2); | ||
14585 | pi->mcs5glpo[3] = | ||
14586 | (u16) wlapi_getintvar(shim, | ||
14587 | BRCMS_SROM_MCS5GLPO3); | ||
14588 | pi->mcs5glpo[4] = | ||
14589 | (u16) wlapi_getintvar(shim, | ||
14590 | BRCMS_SROM_MCS5GLPO4); | ||
14591 | pi->mcs5glpo[5] = | ||
14592 | (u16) wlapi_getintvar(shim, | ||
14593 | BRCMS_SROM_MCS5GLPO5); | ||
14594 | pi->mcs5glpo[6] = | ||
14595 | (u16) wlapi_getintvar(shim, | ||
14596 | BRCMS_SROM_MCS5GLPO6); | ||
14597 | pi->mcs5glpo[7] = | ||
14598 | (u16) wlapi_getintvar(shim, | ||
14599 | BRCMS_SROM_MCS5GLPO7); | ||
14600 | break; | 14521 | break; |
14601 | case 3: | 14522 | case 3: |
14602 | 14523 | ||
14603 | pi->nphy_pwrctrl_info[0].max_pwr_5gh = | 14524 | pi->nphy_pwrctrl_info[0].max_pwr_5gh = |
14604 | (s8) wlapi_getintvar(shim, | 14525 | sprom->core_pwr_info[0].maxpwr_5gh; |
14605 | BRCMS_SROM_MAXP5GHA0); | ||
14606 | pi->nphy_pwrctrl_info[1].max_pwr_5gh = | 14526 | pi->nphy_pwrctrl_info[1].max_pwr_5gh = |
14607 | (s8) wlapi_getintvar(shim, | 14527 | sprom->core_pwr_info[1].maxpwr_5gh; |
14608 | BRCMS_SROM_MAXP5GHA1); | ||
14609 | pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 = | 14528 | pi->nphy_pwrctrl_info[0].pwrdet_5gh_a1 = |
14610 | (s16) wlapi_getintvar(shim, | 14529 | sprom->core_pwr_info[0].pa_5gh[0]; |
14611 | BRCMS_SROM_PA5GHW0A0); | ||
14612 | pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 = | 14530 | pi->nphy_pwrctrl_info[1].pwrdet_5gh_a1 = |
14613 | (s16) wlapi_getintvar(shim, | 14531 | sprom->core_pwr_info[1].pa_5gh[0]; |
14614 | BRCMS_SROM_PA5GHW0A1); | ||
14615 | pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 = | 14532 | pi->nphy_pwrctrl_info[0].pwrdet_5gh_b0 = |
14616 | (s16) wlapi_getintvar(shim, | 14533 | sprom->core_pwr_info[0].pa_5gh[1]; |
14617 | BRCMS_SROM_PA5GHW1A0); | ||
14618 | pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 = | 14534 | pi->nphy_pwrctrl_info[1].pwrdet_5gh_b0 = |
14619 | (s16) wlapi_getintvar(shim, | 14535 | sprom->core_pwr_info[1].pa_5gh[1]; |
14620 | BRCMS_SROM_PA5GHW1A1); | ||
14621 | pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 = | 14536 | pi->nphy_pwrctrl_info[0].pwrdet_5gh_b1 = |
14622 | (s16) wlapi_getintvar(shim, | 14537 | sprom->core_pwr_info[0].pa_5gh[2]; |
14623 | BRCMS_SROM_PA5GHW2A0); | ||
14624 | pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 = | 14538 | pi->nphy_pwrctrl_info[1].pwrdet_5gh_b1 = |
14625 | (s16) wlapi_getintvar(shim, | 14539 | sprom->core_pwr_info[1].pa_5gh[2]; |
14626 | BRCMS_SROM_PA5GHW2A1); | ||
14627 | pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0; | 14540 | pi->nphy_pwrctrl_info[0].idle_targ_5gh = 0; |
14628 | pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0; | 14541 | pi->nphy_pwrctrl_info[1].idle_targ_5gh = 0; |
14629 | 14542 | ||
14630 | pi->ofdm5ghpo = | 14543 | pi->ofdm5ghpo = sprom->ofdm5ghpo; |
14631 | (u32) wlapi_getintvar(shim, | 14544 | |
14632 | BRCMS_SROM_OFDM5GHPO); | 14545 | pi->mcs5ghpo[0] = sprom->mcs5ghpo[0]; |
14633 | 14546 | pi->mcs5ghpo[1] = sprom->mcs5ghpo[1]; | |
14634 | pi->mcs5ghpo[0] = | 14547 | pi->mcs5ghpo[2] = sprom->mcs5ghpo[2]; |
14635 | (u16) wlapi_getintvar(shim, | 14548 | pi->mcs5ghpo[3] = sprom->mcs5ghpo[3]; |
14636 | BRCMS_SROM_MCS5GHPO0); | 14549 | pi->mcs5ghpo[4] = sprom->mcs5ghpo[4]; |
14637 | pi->mcs5ghpo[1] = | 14550 | pi->mcs5ghpo[5] = sprom->mcs5ghpo[5]; |
14638 | (u16) wlapi_getintvar(shim, | 14551 | pi->mcs5ghpo[6] = sprom->mcs5ghpo[6]; |
14639 | BRCMS_SROM_MCS5GHPO1); | 14552 | pi->mcs5ghpo[7] = sprom->mcs5ghpo[7]; |
14640 | pi->mcs5ghpo[2] = | ||
14641 | (u16) wlapi_getintvar(shim, | ||
14642 | BRCMS_SROM_MCS5GHPO2); | ||
14643 | pi->mcs5ghpo[3] = | ||
14644 | (u16) wlapi_getintvar(shim, | ||
14645 | BRCMS_SROM_MCS5GHPO3); | ||
14646 | pi->mcs5ghpo[4] = | ||
14647 | (u16) wlapi_getintvar(shim, | ||
14648 | BRCMS_SROM_MCS5GHPO4); | ||
14649 | pi->mcs5ghpo[5] = | ||
14650 | (u16) wlapi_getintvar(shim, | ||
14651 | BRCMS_SROM_MCS5GHPO5); | ||
14652 | pi->mcs5ghpo[6] = | ||
14653 | (u16) wlapi_getintvar(shim, | ||
14654 | BRCMS_SROM_MCS5GHPO6); | ||
14655 | pi->mcs5ghpo[7] = | ||
14656 | (u16) wlapi_getintvar(shim, | ||
14657 | BRCMS_SROM_MCS5GHPO7); | ||
14658 | break; | 14553 | break; |
14659 | } | 14554 | } |
14660 | } | 14555 | } |
@@ -14664,45 +14559,34 @@ static void wlc_phy_txpwr_srom_read_ppr_nphy(struct brcms_phy *pi) | |||
14664 | 14559 | ||
14665 | static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi) | 14560 | static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi) |
14666 | { | 14561 | { |
14667 | struct phy_shim_info *shim = pi->sh->physhim; | 14562 | struct ssb_sprom *sprom = &pi->d11core->bus->sprom; |
14668 | 14563 | ||
14669 | pi->antswitch = (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWITCH); | 14564 | pi->antswitch = sprom->antswitch; |
14670 | pi->aa2g = (u8) wlapi_getintvar(shim, BRCMS_SROM_AA2G); | 14565 | pi->aa2g = sprom->ant_available_bg; |
14671 | pi->aa5g = (u8) wlapi_getintvar(shim, BRCMS_SROM_AA5G); | 14566 | pi->aa5g = sprom->ant_available_a; |
14672 | 14567 | ||
14673 | pi->srom_fem2g.tssipos = (u8) wlapi_getintvar(shim, | 14568 | pi->srom_fem2g.tssipos = sprom->fem.ghz2.tssipos; |
14674 | BRCMS_SROM_TSSIPOS2G); | 14569 | pi->srom_fem2g.extpagain = sprom->fem.ghz2.extpa_gain; |
14675 | pi->srom_fem2g.extpagain = (u8) wlapi_getintvar(shim, | 14570 | pi->srom_fem2g.pdetrange = sprom->fem.ghz2.pdet_range; |
14676 | BRCMS_SROM_EXTPAGAIN2G); | 14571 | pi->srom_fem2g.triso = sprom->fem.ghz2.tr_iso; |
14677 | pi->srom_fem2g.pdetrange = (u8) wlapi_getintvar(shim, | 14572 | pi->srom_fem2g.antswctrllut = sprom->fem.ghz2.antswlut; |
14678 | BRCMS_SROM_PDETRANGE2G); | 14573 | |
14679 | pi->srom_fem2g.triso = (u8) wlapi_getintvar(shim, BRCMS_SROM_TRISO2G); | 14574 | pi->srom_fem5g.tssipos = sprom->fem.ghz5.tssipos; |
14680 | pi->srom_fem2g.antswctrllut = | 14575 | pi->srom_fem5g.extpagain = sprom->fem.ghz5.extpa_gain; |
14681 | (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL2G); | 14576 | pi->srom_fem5g.pdetrange = sprom->fem.ghz5.pdet_range; |
14682 | 14577 | pi->srom_fem5g.triso = sprom->fem.ghz5.tr_iso; | |
14683 | pi->srom_fem5g.tssipos = (u8) wlapi_getintvar(shim, | 14578 | if (sprom->fem.ghz5.antswlut) |
14684 | BRCMS_SROM_TSSIPOS5G); | 14579 | pi->srom_fem5g.antswctrllut = sprom->fem.ghz5.antswlut; |
14685 | pi->srom_fem5g.extpagain = (u8) wlapi_getintvar(shim, | ||
14686 | BRCMS_SROM_EXTPAGAIN5G); | ||
14687 | pi->srom_fem5g.pdetrange = (u8) wlapi_getintvar(shim, | ||
14688 | BRCMS_SROM_PDETRANGE5G); | ||
14689 | pi->srom_fem5g.triso = (u8) wlapi_getintvar(shim, BRCMS_SROM_TRISO5G); | ||
14690 | if (wlapi_getvar(shim, BRCMS_SROM_ANTSWCTL5G)) | ||
14691 | pi->srom_fem5g.antswctrllut = | ||
14692 | (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL5G); | ||
14693 | else | 14580 | else |
14694 | pi->srom_fem5g.antswctrllut = | 14581 | pi->srom_fem5g.antswctrllut = sprom->fem.ghz2.antswlut; |
14695 | (u8) wlapi_getintvar(shim, BRCMS_SROM_ANTSWCTL2G); | ||
14696 | 14582 | ||
14697 | wlc_phy_txpower_ipa_upd(pi); | 14583 | wlc_phy_txpower_ipa_upd(pi); |
14698 | 14584 | ||
14699 | pi->phy_txcore_disable_temp = | 14585 | pi->phy_txcore_disable_temp = sprom->tempthresh; |
14700 | (s16) wlapi_getintvar(shim, BRCMS_SROM_TEMPTHRESH); | ||
14701 | if (pi->phy_txcore_disable_temp == 0) | 14586 | if (pi->phy_txcore_disable_temp == 0) |
14702 | pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP; | 14587 | pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP; |
14703 | 14588 | ||
14704 | pi->phy_tempsense_offset = (s8) wlapi_getintvar(shim, | 14589 | pi->phy_tempsense_offset = sprom->tempoffset; |
14705 | BRCMS_SROM_TEMPOFFSET); | ||
14706 | if (pi->phy_tempsense_offset != 0) { | 14590 | if (pi->phy_tempsense_offset != 0) { |
14707 | if (pi->phy_tempsense_offset > | 14591 | if (pi->phy_tempsense_offset > |
14708 | (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET)) | 14592 | (NPHY_SROM_TEMPSHIFT + NPHY_SROM_MAXTEMPOFFSET)) |
@@ -14717,8 +14601,7 @@ static bool wlc_phy_txpwr_srom_read_nphy(struct brcms_phy *pi) | |||
14717 | pi->phy_txcore_enable_temp = | 14601 | pi->phy_txcore_enable_temp = |
14718 | pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP; | 14602 | pi->phy_txcore_disable_temp - PHY_HYSTERESIS_DELTATEMP; |
14719 | 14603 | ||
14720 | pi->phycal_tempdelta = | 14604 | pi->phycal_tempdelta = sprom->phycal_tempdelta; |
14721 | (u8) wlapi_getintvar(shim, BRCMS_SROM_PHYCAL_TEMPDELTA); | ||
14722 | if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA) | 14605 | if (pi->phycal_tempdelta > NPHY_CAL_MAXTEMPDELTA) |
14723 | pi->phycal_tempdelta = 0; | 14606 | pi->phycal_tempdelta = 0; |
14724 | 14607 | ||
@@ -21460,7 +21343,7 @@ void wlc_phy_antsel_init(struct brcms_phy_pub *ppi, bool lut_init) | |||
21460 | write_phy_reg(pi, 0xc8, 0x0); | 21343 | write_phy_reg(pi, 0xc8, 0x0); |
21461 | write_phy_reg(pi, 0xc9, 0x0); | 21344 | write_phy_reg(pi, 0xc9, 0x0); |
21462 | 21345 | ||
21463 | ai_gpiocontrol(pi->sh->sih, mask, mask, GPIO_DRV_PRIORITY); | 21346 | bcma_chipco_gpio_control(&pi->d11core->bus->drv_cc, mask, mask); |
21464 | 21347 | ||
21465 | mc = bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); | 21348 | mc = bcma_read32(pi->d11core, D11REGOFFS(maccontrol)); |
21466 | mc &= ~MCTL_GPOUT_SEL_MASK; | 21349 | mc &= ~MCTL_GPOUT_SEL_MASK; |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c b/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c index 5926854f62e2..a0de5db0cd64 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.c | |||
@@ -214,12 +214,3 @@ wlapi_copyto_objmem(struct phy_shim_info *physhim, uint offset, const void *buf, | |||
214 | { | 214 | { |
215 | brcms_b_copyto_objmem(physhim->wlc_hw, offset, buf, l, sel); | 215 | brcms_b_copyto_objmem(physhim->wlc_hw, offset, buf, l, sel); |
216 | } | 216 | } |
217 | |||
218 | char *wlapi_getvar(struct phy_shim_info *physhim, enum brcms_srom_id id) | ||
219 | { | ||
220 | return getvar(physhim->wlc_hw->sih, id); | ||
221 | } | ||
222 | int wlapi_getintvar(struct phy_shim_info *physhim, enum brcms_srom_id id) | ||
223 | { | ||
224 | return getintvar(physhim->wlc_hw->sih, id); | ||
225 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h b/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h index 9168c459b185..2c5b66b75970 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/phy_shim.h | |||
@@ -175,8 +175,5 @@ extern void wlapi_copyto_objmem(struct phy_shim_info *physhim, uint, | |||
175 | extern void wlapi_high_update_phy_mode(struct phy_shim_info *physhim, | 175 | extern void wlapi_high_update_phy_mode(struct phy_shim_info *physhim, |
176 | u32 phy_mode); | 176 | u32 phy_mode); |
177 | extern u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim); | 177 | extern u16 wlapi_bmac_get_txant(struct phy_shim_info *physhim); |
178 | extern char *wlapi_getvar(struct phy_shim_info *physhim, enum brcms_srom_id id); | ||
179 | extern int wlapi_getintvar(struct phy_shim_info *physhim, | ||
180 | enum brcms_srom_id id); | ||
181 | 178 | ||
182 | #endif /* _BRCM_PHY_SHIM_H_ */ | 179 | #endif /* _BRCM_PHY_SHIM_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h index f0038ad7d7bf..aa5d67f8d874 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h | |||
@@ -22,232 +22,6 @@ | |||
22 | #include "types.h" | 22 | #include "types.h" |
23 | #include "defs.h" | 23 | #include "defs.h" |
24 | 24 | ||
25 | enum brcms_srom_id { | ||
26 | BRCMS_SROM_NULL, | ||
27 | BRCMS_SROM_CONT, | ||
28 | BRCMS_SROM_AA2G, | ||
29 | BRCMS_SROM_AA5G, | ||
30 | BRCMS_SROM_AG0, | ||
31 | BRCMS_SROM_AG1, | ||
32 | BRCMS_SROM_AG2, | ||
33 | BRCMS_SROM_AG3, | ||
34 | BRCMS_SROM_ANTSWCTL2G, | ||
35 | BRCMS_SROM_ANTSWCTL5G, | ||
36 | BRCMS_SROM_ANTSWITCH, | ||
37 | BRCMS_SROM_BOARDFLAGS2, | ||
38 | BRCMS_SROM_BOARDFLAGS, | ||
39 | BRCMS_SROM_BOARDNUM, | ||
40 | BRCMS_SROM_BOARDREV, | ||
41 | BRCMS_SROM_BOARDTYPE, | ||
42 | BRCMS_SROM_BW40PO, | ||
43 | BRCMS_SROM_BWDUPPO, | ||
44 | BRCMS_SROM_BXA2G, | ||
45 | BRCMS_SROM_BXA5G, | ||
46 | BRCMS_SROM_CC, | ||
47 | BRCMS_SROM_CCK2GPO, | ||
48 | BRCMS_SROM_CCKBW202GPO, | ||
49 | BRCMS_SROM_CCKBW20UL2GPO, | ||
50 | BRCMS_SROM_CCODE, | ||
51 | BRCMS_SROM_CDDPO, | ||
52 | BRCMS_SROM_DEVID, | ||
53 | BRCMS_SROM_ET1MACADDR, | ||
54 | BRCMS_SROM_EXTPAGAIN2G, | ||
55 | BRCMS_SROM_EXTPAGAIN5G, | ||
56 | BRCMS_SROM_FREQOFFSET_CORR, | ||
57 | BRCMS_SROM_HW_IQCAL_EN, | ||
58 | BRCMS_SROM_IL0MACADDR, | ||
59 | BRCMS_SROM_IQCAL_SWP_DIS, | ||
60 | BRCMS_SROM_LEDBH0, | ||
61 | BRCMS_SROM_LEDBH1, | ||
62 | BRCMS_SROM_LEDBH2, | ||
63 | BRCMS_SROM_LEDBH3, | ||
64 | BRCMS_SROM_LEDDC, | ||
65 | BRCMS_SROM_LEGOFDM40DUPPO, | ||
66 | BRCMS_SROM_LEGOFDMBW202GPO, | ||
67 | BRCMS_SROM_LEGOFDMBW205GHPO, | ||
68 | BRCMS_SROM_LEGOFDMBW205GLPO, | ||
69 | BRCMS_SROM_LEGOFDMBW205GMPO, | ||
70 | BRCMS_SROM_LEGOFDMBW20UL2GPO, | ||
71 | BRCMS_SROM_LEGOFDMBW20UL5GHPO, | ||
72 | BRCMS_SROM_LEGOFDMBW20UL5GLPO, | ||
73 | BRCMS_SROM_LEGOFDMBW20UL5GMPO, | ||
74 | BRCMS_SROM_MACADDR, | ||
75 | BRCMS_SROM_MCS2GPO0, | ||
76 | BRCMS_SROM_MCS2GPO1, | ||
77 | BRCMS_SROM_MCS2GPO2, | ||
78 | BRCMS_SROM_MCS2GPO3, | ||
79 | BRCMS_SROM_MCS2GPO4, | ||
80 | BRCMS_SROM_MCS2GPO5, | ||
81 | BRCMS_SROM_MCS2GPO6, | ||
82 | BRCMS_SROM_MCS2GPO7, | ||
83 | BRCMS_SROM_MCS32PO, | ||
84 | BRCMS_SROM_MCS5GHPO0, | ||
85 | BRCMS_SROM_MCS5GHPO1, | ||
86 | BRCMS_SROM_MCS5GHPO2, | ||
87 | BRCMS_SROM_MCS5GHPO3, | ||
88 | BRCMS_SROM_MCS5GHPO4, | ||
89 | BRCMS_SROM_MCS5GHPO5, | ||
90 | BRCMS_SROM_MCS5GHPO6, | ||
91 | BRCMS_SROM_MCS5GHPO7, | ||
92 | BRCMS_SROM_MCS5GLPO0, | ||
93 | BRCMS_SROM_MCS5GLPO1, | ||
94 | BRCMS_SROM_MCS5GLPO2, | ||
95 | BRCMS_SROM_MCS5GLPO3, | ||
96 | BRCMS_SROM_MCS5GLPO4, | ||
97 | BRCMS_SROM_MCS5GLPO5, | ||
98 | BRCMS_SROM_MCS5GLPO6, | ||
99 | BRCMS_SROM_MCS5GLPO7, | ||
100 | BRCMS_SROM_MCS5GPO0, | ||
101 | BRCMS_SROM_MCS5GPO1, | ||
102 | BRCMS_SROM_MCS5GPO2, | ||
103 | BRCMS_SROM_MCS5GPO3, | ||
104 | BRCMS_SROM_MCS5GPO4, | ||
105 | BRCMS_SROM_MCS5GPO5, | ||
106 | BRCMS_SROM_MCS5GPO6, | ||
107 | BRCMS_SROM_MCS5GPO7, | ||
108 | BRCMS_SROM_MCSBW202GPO, | ||
109 | BRCMS_SROM_MCSBW205GHPO, | ||
110 | BRCMS_SROM_MCSBW205GLPO, | ||
111 | BRCMS_SROM_MCSBW205GMPO, | ||
112 | BRCMS_SROM_MCSBW20UL2GPO, | ||
113 | BRCMS_SROM_MCSBW20UL5GHPO, | ||
114 | BRCMS_SROM_MCSBW20UL5GLPO, | ||
115 | BRCMS_SROM_MCSBW20UL5GMPO, | ||
116 | BRCMS_SROM_MCSBW402GPO, | ||
117 | BRCMS_SROM_MCSBW405GHPO, | ||
118 | BRCMS_SROM_MCSBW405GLPO, | ||
119 | BRCMS_SROM_MCSBW405GMPO, | ||
120 | BRCMS_SROM_MEASPOWER, | ||
121 | BRCMS_SROM_OFDM2GPO, | ||
122 | BRCMS_SROM_OFDM5GHPO, | ||
123 | BRCMS_SROM_OFDM5GLPO, | ||
124 | BRCMS_SROM_OFDM5GPO, | ||
125 | BRCMS_SROM_OPO, | ||
126 | BRCMS_SROM_PA0B0, | ||
127 | BRCMS_SROM_PA0B1, | ||
128 | BRCMS_SROM_PA0B2, | ||
129 | BRCMS_SROM_PA0ITSSIT, | ||
130 | BRCMS_SROM_PA0MAXPWR, | ||
131 | BRCMS_SROM_PA1B0, | ||
132 | BRCMS_SROM_PA1B1, | ||
133 | BRCMS_SROM_PA1B2, | ||
134 | BRCMS_SROM_PA1HIB0, | ||
135 | BRCMS_SROM_PA1HIB1, | ||
136 | BRCMS_SROM_PA1HIB2, | ||
137 | BRCMS_SROM_PA1HIMAXPWR, | ||
138 | BRCMS_SROM_PA1ITSSIT, | ||
139 | BRCMS_SROM_PA1LOB0, | ||
140 | BRCMS_SROM_PA1LOB1, | ||
141 | BRCMS_SROM_PA1LOB2, | ||
142 | BRCMS_SROM_PA1LOMAXPWR, | ||
143 | BRCMS_SROM_PA1MAXPWR, | ||
144 | BRCMS_SROM_PDETRANGE2G, | ||
145 | BRCMS_SROM_PDETRANGE5G, | ||
146 | BRCMS_SROM_PHYCAL_TEMPDELTA, | ||
147 | BRCMS_SROM_RAWTEMPSENSE, | ||
148 | BRCMS_SROM_REGREV, | ||
149 | BRCMS_SROM_REV, | ||
150 | BRCMS_SROM_RSSISAV2G, | ||
151 | BRCMS_SROM_RSSISAV5G, | ||
152 | BRCMS_SROM_RSSISMC2G, | ||
153 | BRCMS_SROM_RSSISMC5G, | ||
154 | BRCMS_SROM_RSSISMF2G, | ||
155 | BRCMS_SROM_RSSISMF5G, | ||
156 | BRCMS_SROM_RXCHAIN, | ||
157 | BRCMS_SROM_RXPO2G, | ||
158 | BRCMS_SROM_RXPO5G, | ||
159 | BRCMS_SROM_STBCPO, | ||
160 | BRCMS_SROM_TEMPCORRX, | ||
161 | BRCMS_SROM_TEMPOFFSET, | ||
162 | BRCMS_SROM_TEMPSENSE_OPTION, | ||
163 | BRCMS_SROM_TEMPSENSE_SLOPE, | ||
164 | BRCMS_SROM_TEMPTHRESH, | ||
165 | BRCMS_SROM_TRI2G, | ||
166 | BRCMS_SROM_TRI5GH, | ||
167 | BRCMS_SROM_TRI5GL, | ||
168 | BRCMS_SROM_TRI5G, | ||
169 | BRCMS_SROM_TRISO2G, | ||
170 | BRCMS_SROM_TRISO5G, | ||
171 | BRCMS_SROM_TSSIPOS2G, | ||
172 | BRCMS_SROM_TSSIPOS5G, | ||
173 | BRCMS_SROM_TXCHAIN, | ||
174 | /* | ||
175 | * per-path identifiers (see srom.c) | ||
176 | */ | ||
177 | BRCMS_SROM_ITT2GA0, | ||
178 | BRCMS_SROM_ITT2GA1, | ||
179 | BRCMS_SROM_ITT2GA2, | ||
180 | BRCMS_SROM_ITT2GA3, | ||
181 | BRCMS_SROM_ITT5GA0, | ||
182 | BRCMS_SROM_ITT5GA1, | ||
183 | BRCMS_SROM_ITT5GA2, | ||
184 | BRCMS_SROM_ITT5GA3, | ||
185 | BRCMS_SROM_MAXP2GA0, | ||
186 | BRCMS_SROM_MAXP2GA1, | ||
187 | BRCMS_SROM_MAXP2GA2, | ||
188 | BRCMS_SROM_MAXP2GA3, | ||
189 | BRCMS_SROM_MAXP5GA0, | ||
190 | BRCMS_SROM_MAXP5GA1, | ||
191 | BRCMS_SROM_MAXP5GA2, | ||
192 | BRCMS_SROM_MAXP5GA3, | ||
193 | BRCMS_SROM_MAXP5GHA0, | ||
194 | BRCMS_SROM_MAXP5GHA1, | ||
195 | BRCMS_SROM_MAXP5GHA2, | ||
196 | BRCMS_SROM_MAXP5GHA3, | ||
197 | BRCMS_SROM_MAXP5GLA0, | ||
198 | BRCMS_SROM_MAXP5GLA1, | ||
199 | BRCMS_SROM_MAXP5GLA2, | ||
200 | BRCMS_SROM_MAXP5GLA3, | ||
201 | BRCMS_SROM_PA2GW0A0, | ||
202 | BRCMS_SROM_PA2GW0A1, | ||
203 | BRCMS_SROM_PA2GW0A2, | ||
204 | BRCMS_SROM_PA2GW0A3, | ||
205 | BRCMS_SROM_PA2GW1A0, | ||
206 | BRCMS_SROM_PA2GW1A1, | ||
207 | BRCMS_SROM_PA2GW1A2, | ||
208 | BRCMS_SROM_PA2GW1A3, | ||
209 | BRCMS_SROM_PA2GW2A0, | ||
210 | BRCMS_SROM_PA2GW2A1, | ||
211 | BRCMS_SROM_PA2GW2A2, | ||
212 | BRCMS_SROM_PA2GW2A3, | ||
213 | BRCMS_SROM_PA5GHW0A0, | ||
214 | BRCMS_SROM_PA5GHW0A1, | ||
215 | BRCMS_SROM_PA5GHW0A2, | ||
216 | BRCMS_SROM_PA5GHW0A3, | ||
217 | BRCMS_SROM_PA5GHW1A0, | ||
218 | BRCMS_SROM_PA5GHW1A1, | ||
219 | BRCMS_SROM_PA5GHW1A2, | ||
220 | BRCMS_SROM_PA5GHW1A3, | ||
221 | BRCMS_SROM_PA5GHW2A0, | ||
222 | BRCMS_SROM_PA5GHW2A1, | ||
223 | BRCMS_SROM_PA5GHW2A2, | ||
224 | BRCMS_SROM_PA5GHW2A3, | ||
225 | BRCMS_SROM_PA5GLW0A0, | ||
226 | BRCMS_SROM_PA5GLW0A1, | ||
227 | BRCMS_SROM_PA5GLW0A2, | ||
228 | BRCMS_SROM_PA5GLW0A3, | ||
229 | BRCMS_SROM_PA5GLW1A0, | ||
230 | BRCMS_SROM_PA5GLW1A1, | ||
231 | BRCMS_SROM_PA5GLW1A2, | ||
232 | BRCMS_SROM_PA5GLW1A3, | ||
233 | BRCMS_SROM_PA5GLW2A0, | ||
234 | BRCMS_SROM_PA5GLW2A1, | ||
235 | BRCMS_SROM_PA5GLW2A2, | ||
236 | BRCMS_SROM_PA5GLW2A3, | ||
237 | BRCMS_SROM_PA5GW0A0, | ||
238 | BRCMS_SROM_PA5GW0A1, | ||
239 | BRCMS_SROM_PA5GW0A2, | ||
240 | BRCMS_SROM_PA5GW0A3, | ||
241 | BRCMS_SROM_PA5GW1A0, | ||
242 | BRCMS_SROM_PA5GW1A1, | ||
243 | BRCMS_SROM_PA5GW1A2, | ||
244 | BRCMS_SROM_PA5GW1A3, | ||
245 | BRCMS_SROM_PA5GW2A0, | ||
246 | BRCMS_SROM_PA5GW2A1, | ||
247 | BRCMS_SROM_PA5GW2A2, | ||
248 | BRCMS_SROM_PA5GW2A3, | ||
249 | }; | ||
250 | |||
251 | #define BRCMS_NUMRATES 16 /* max # of rates in a rateset */ | 25 | #define BRCMS_NUMRATES 16 /* max # of rates in a rateset */ |
252 | 26 | ||
253 | /* phy types */ | 27 | /* phy types */ |
@@ -565,8 +339,6 @@ extern void brcms_c_ampdu_flush(struct brcms_c_info *wlc, | |||
565 | struct ieee80211_sta *sta, u16 tid); | 339 | struct ieee80211_sta *sta, u16 tid); |
566 | extern void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, | 340 | extern void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, |
567 | u8 ba_wsize, uint max_rx_ampdu_bytes); | 341 | u8 ba_wsize, uint max_rx_ampdu_bytes); |
568 | extern char *getvar(struct si_pub *sih, enum brcms_srom_id id); | ||
569 | extern int getintvar(struct si_pub *sih, enum brcms_srom_id id); | ||
570 | extern int brcms_c_module_register(struct brcms_pub *pub, | 342 | extern int brcms_c_module_register(struct brcms_pub *pub, |
571 | const char *name, struct brcms_info *hdl, | 343 | const char *name, struct brcms_info *hdl, |
572 | int (*down_fn)(void *handle)); | 344 | int (*down_fn)(void *handle)); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/srom.c b/drivers/net/wireless/brcm80211/brcmsmac/srom.c deleted file mode 100644 index b96f4b9d74bd..000000000000 --- a/drivers/net/wireless/brcm80211/brcmsmac/srom.c +++ /dev/null | |||
@@ -1,980 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 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 | #include <linux/kernel.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/etherdevice.h> | ||
21 | #include <linux/crc8.h> | ||
22 | #include <stdarg.h> | ||
23 | |||
24 | #include <chipcommon.h> | ||
25 | #include <brcmu_utils.h> | ||
26 | #include "pub.h" | ||
27 | #include "nicpci.h" | ||
28 | #include "aiutils.h" | ||
29 | #include "otp.h" | ||
30 | #include "srom.h" | ||
31 | #include "soc.h" | ||
32 | |||
33 | /* | ||
34 | * SROM CRC8 polynomial value: | ||
35 | * | ||
36 | * x^8 + x^7 +x^6 + x^4 + x^2 + 1 | ||
37 | */ | ||
38 | #define SROM_CRC8_POLY 0xAB | ||
39 | |||
40 | /* Maximum srom: 6 Kilobits == 768 bytes */ | ||
41 | #define SROM_MAX 768 | ||
42 | |||
43 | /* PCI fields */ | ||
44 | #define PCI_F0DEVID 48 | ||
45 | |||
46 | #define SROM_WORDS 64 | ||
47 | |||
48 | #define SROM_SSID 2 | ||
49 | |||
50 | #define SROM_WL1LHMAXP 29 | ||
51 | |||
52 | #define SROM_WL1LPAB0 30 | ||
53 | #define SROM_WL1LPAB1 31 | ||
54 | #define SROM_WL1LPAB2 32 | ||
55 | |||
56 | #define SROM_WL1HPAB0 33 | ||
57 | #define SROM_WL1HPAB1 34 | ||
58 | #define SROM_WL1HPAB2 35 | ||
59 | |||
60 | #define SROM_MACHI_IL0 36 | ||
61 | #define SROM_MACMID_IL0 37 | ||
62 | #define SROM_MACLO_IL0 38 | ||
63 | #define SROM_MACHI_ET1 42 | ||
64 | #define SROM_MACMID_ET1 43 | ||
65 | #define SROM_MACLO_ET1 44 | ||
66 | |||
67 | #define SROM_BXARSSI2G 40 | ||
68 | #define SROM_BXARSSI5G 41 | ||
69 | |||
70 | #define SROM_TRI52G 42 | ||
71 | #define SROM_TRI5GHL 43 | ||
72 | |||
73 | #define SROM_RXPO52G 45 | ||
74 | |||
75 | #define SROM_AABREV 46 | ||
76 | /* Fields in AABREV */ | ||
77 | #define SROM_BR_MASK 0x00ff | ||
78 | #define SROM_CC_MASK 0x0f00 | ||
79 | #define SROM_CC_SHIFT 8 | ||
80 | #define SROM_AA0_MASK 0x3000 | ||
81 | #define SROM_AA0_SHIFT 12 | ||
82 | #define SROM_AA1_MASK 0xc000 | ||
83 | #define SROM_AA1_SHIFT 14 | ||
84 | |||
85 | #define SROM_WL0PAB0 47 | ||
86 | #define SROM_WL0PAB1 48 | ||
87 | #define SROM_WL0PAB2 49 | ||
88 | |||
89 | #define SROM_LEDBH10 50 | ||
90 | #define SROM_LEDBH32 51 | ||
91 | |||
92 | #define SROM_WL10MAXP 52 | ||
93 | |||
94 | #define SROM_WL1PAB0 53 | ||
95 | #define SROM_WL1PAB1 54 | ||
96 | #define SROM_WL1PAB2 55 | ||
97 | |||
98 | #define SROM_ITT 56 | ||
99 | |||
100 | #define SROM_BFL 57 | ||
101 | #define SROM_BFL2 28 | ||
102 | |||
103 | #define SROM_AG10 58 | ||
104 | |||
105 | #define SROM_CCODE 59 | ||
106 | |||
107 | #define SROM_OPO 60 | ||
108 | |||
109 | #define SROM_CRCREV 63 | ||
110 | |||
111 | #define SROM4_WORDS 220 | ||
112 | |||
113 | #define SROM4_TXCHAIN_MASK 0x000f | ||
114 | #define SROM4_RXCHAIN_MASK 0x00f0 | ||
115 | #define SROM4_SWITCH_MASK 0xff00 | ||
116 | |||
117 | /* Per-path fields */ | ||
118 | #define MAX_PATH_SROM 4 | ||
119 | |||
120 | #define SROM4_CRCREV 219 | ||
121 | |||
122 | /* SROM Rev 8: Make space for a 48word hardware header for PCIe rev >= 6. | ||
123 | * This is acombined srom for both MIMO and SISO boards, usable in | ||
124 | * the .130 4Kilobit OTP with hardware redundancy. | ||
125 | */ | ||
126 | #define SROM8_BREV 65 | ||
127 | |||
128 | #define SROM8_BFL0 66 | ||
129 | #define SROM8_BFL1 67 | ||
130 | #define SROM8_BFL2 68 | ||
131 | #define SROM8_BFL3 69 | ||
132 | |||
133 | #define SROM8_MACHI 70 | ||
134 | #define SROM8_MACMID 71 | ||
135 | #define SROM8_MACLO 72 | ||
136 | |||
137 | #define SROM8_CCODE 73 | ||
138 | #define SROM8_REGREV 74 | ||
139 | |||
140 | #define SROM8_LEDBH10 75 | ||
141 | #define SROM8_LEDBH32 76 | ||
142 | |||
143 | #define SROM8_LEDDC 77 | ||
144 | |||
145 | #define SROM8_AA 78 | ||
146 | |||
147 | #define SROM8_AG10 79 | ||
148 | #define SROM8_AG32 80 | ||
149 | |||
150 | #define SROM8_TXRXC 81 | ||
151 | |||
152 | #define SROM8_BXARSSI2G 82 | ||
153 | #define SROM8_BXARSSI5G 83 | ||
154 | #define SROM8_TRI52G 84 | ||
155 | #define SROM8_TRI5GHL 85 | ||
156 | #define SROM8_RXPO52G 86 | ||
157 | |||
158 | #define SROM8_FEM2G 87 | ||
159 | #define SROM8_FEM5G 88 | ||
160 | #define SROM8_FEM_ANTSWLUT_MASK 0xf800 | ||
161 | #define SROM8_FEM_ANTSWLUT_SHIFT 11 | ||
162 | #define SROM8_FEM_TR_ISO_MASK 0x0700 | ||
163 | #define SROM8_FEM_TR_ISO_SHIFT 8 | ||
164 | #define SROM8_FEM_PDET_RANGE_MASK 0x00f8 | ||
165 | #define SROM8_FEM_PDET_RANGE_SHIFT 3 | ||
166 | #define SROM8_FEM_EXTPA_GAIN_MASK 0x0006 | ||
167 | #define SROM8_FEM_EXTPA_GAIN_SHIFT 1 | ||
168 | #define SROM8_FEM_TSSIPOS_MASK 0x0001 | ||
169 | #define SROM8_FEM_TSSIPOS_SHIFT 0 | ||
170 | |||
171 | #define SROM8_THERMAL 89 | ||
172 | |||
173 | /* Temp sense related entries */ | ||
174 | #define SROM8_MPWR_RAWTS 90 | ||
175 | #define SROM8_TS_SLP_OPT_CORRX 91 | ||
176 | /* FOC: freiquency offset correction, HWIQ: H/W IOCAL enable, | ||
177 | * IQSWP: IQ CAL swap disable */ | ||
178 | #define SROM8_FOC_HWIQ_IQSWP 92 | ||
179 | |||
180 | /* Temperature delta for PHY calibration */ | ||
181 | #define SROM8_PHYCAL_TEMPDELTA 93 | ||
182 | |||
183 | /* Per-path offsets & fields */ | ||
184 | #define SROM8_PATH0 96 | ||
185 | #define SROM8_PATH1 112 | ||
186 | #define SROM8_PATH2 128 | ||
187 | #define SROM8_PATH3 144 | ||
188 | |||
189 | #define SROM8_2G_ITT_MAXP 0 | ||
190 | #define SROM8_2G_PA 1 | ||
191 | #define SROM8_5G_ITT_MAXP 4 | ||
192 | #define SROM8_5GLH_MAXP 5 | ||
193 | #define SROM8_5G_PA 6 | ||
194 | #define SROM8_5GL_PA 9 | ||
195 | #define SROM8_5GH_PA 12 | ||
196 | |||
197 | /* All the miriad power offsets */ | ||
198 | #define SROM8_2G_CCKPO 160 | ||
199 | |||
200 | #define SROM8_2G_OFDMPO 161 | ||
201 | #define SROM8_5G_OFDMPO 163 | ||
202 | #define SROM8_5GL_OFDMPO 165 | ||
203 | #define SROM8_5GH_OFDMPO 167 | ||
204 | |||
205 | #define SROM8_2G_MCSPO 169 | ||
206 | #define SROM8_5G_MCSPO 177 | ||
207 | #define SROM8_5GL_MCSPO 185 | ||
208 | #define SROM8_5GH_MCSPO 193 | ||
209 | |||
210 | #define SROM8_CDDPO 201 | ||
211 | #define SROM8_STBCPO 202 | ||
212 | #define SROM8_BW40PO 203 | ||
213 | #define SROM8_BWDUPPO 204 | ||
214 | |||
215 | /* SISO PA parameters are in the path0 spaces */ | ||
216 | #define SROM8_SISO 96 | ||
217 | |||
218 | /* Legacy names for SISO PA paramters */ | ||
219 | #define SROM8_W0_ITTMAXP (SROM8_SISO + SROM8_2G_ITT_MAXP) | ||
220 | #define SROM8_W0_PAB0 (SROM8_SISO + SROM8_2G_PA) | ||
221 | #define SROM8_W0_PAB1 (SROM8_SISO + SROM8_2G_PA + 1) | ||
222 | #define SROM8_W0_PAB2 (SROM8_SISO + SROM8_2G_PA + 2) | ||
223 | #define SROM8_W1_ITTMAXP (SROM8_SISO + SROM8_5G_ITT_MAXP) | ||
224 | #define SROM8_W1_MAXP_LCHC (SROM8_SISO + SROM8_5GLH_MAXP) | ||
225 | #define SROM8_W1_PAB0 (SROM8_SISO + SROM8_5G_PA) | ||
226 | #define SROM8_W1_PAB1 (SROM8_SISO + SROM8_5G_PA + 1) | ||
227 | #define SROM8_W1_PAB2 (SROM8_SISO + SROM8_5G_PA + 2) | ||
228 | #define SROM8_W1_PAB0_LC (SROM8_SISO + SROM8_5GL_PA) | ||
229 | #define SROM8_W1_PAB1_LC (SROM8_SISO + SROM8_5GL_PA + 1) | ||
230 | #define SROM8_W1_PAB2_LC (SROM8_SISO + SROM8_5GL_PA + 2) | ||
231 | #define SROM8_W1_PAB0_HC (SROM8_SISO + SROM8_5GH_PA) | ||
232 | #define SROM8_W1_PAB1_HC (SROM8_SISO + SROM8_5GH_PA + 1) | ||
233 | #define SROM8_W1_PAB2_HC (SROM8_SISO + SROM8_5GH_PA + 2) | ||
234 | |||
235 | /* SROM REV 9 */ | ||
236 | #define SROM9_2GPO_CCKBW20 160 | ||
237 | #define SROM9_2GPO_CCKBW20UL 161 | ||
238 | #define SROM9_2GPO_LOFDMBW20 162 | ||
239 | #define SROM9_2GPO_LOFDMBW20UL 164 | ||
240 | |||
241 | #define SROM9_5GLPO_LOFDMBW20 166 | ||
242 | #define SROM9_5GLPO_LOFDMBW20UL 168 | ||
243 | #define SROM9_5GMPO_LOFDMBW20 170 | ||
244 | #define SROM9_5GMPO_LOFDMBW20UL 172 | ||
245 | #define SROM9_5GHPO_LOFDMBW20 174 | ||
246 | #define SROM9_5GHPO_LOFDMBW20UL 176 | ||
247 | |||
248 | #define SROM9_2GPO_MCSBW20 178 | ||
249 | #define SROM9_2GPO_MCSBW20UL 180 | ||
250 | #define SROM9_2GPO_MCSBW40 182 | ||
251 | |||
252 | #define SROM9_5GLPO_MCSBW20 184 | ||
253 | #define SROM9_5GLPO_MCSBW20UL 186 | ||
254 | #define SROM9_5GLPO_MCSBW40 188 | ||
255 | #define SROM9_5GMPO_MCSBW20 190 | ||
256 | #define SROM9_5GMPO_MCSBW20UL 192 | ||
257 | #define SROM9_5GMPO_MCSBW40 194 | ||
258 | #define SROM9_5GHPO_MCSBW20 196 | ||
259 | #define SROM9_5GHPO_MCSBW20UL 198 | ||
260 | #define SROM9_5GHPO_MCSBW40 200 | ||
261 | |||
262 | #define SROM9_PO_MCS32 202 | ||
263 | #define SROM9_PO_LOFDM40DUP 203 | ||
264 | |||
265 | /* SROM flags (see sromvar_t) */ | ||
266 | |||
267 | /* value continues as described by the next entry */ | ||
268 | #define SRFL_MORE 1 | ||
269 | #define SRFL_NOFFS 2 /* value bits can't be all one's */ | ||
270 | #define SRFL_PRHEX 4 /* value is in hexdecimal format */ | ||
271 | #define SRFL_PRSIGN 8 /* value is in signed decimal format */ | ||
272 | #define SRFL_CCODE 0x10 /* value is in country code format */ | ||
273 | #define SRFL_ETHADDR 0x20 /* value is an Ethernet address */ | ||
274 | #define SRFL_LEDDC 0x40 /* value is an LED duty cycle */ | ||
275 | /* do not generate a nvram param, entry is for mfgc */ | ||
276 | #define SRFL_NOVAR 0x80 | ||
277 | |||
278 | /* Max. nvram variable table size */ | ||
279 | #define MAXSZ_NVRAM_VARS 4096 | ||
280 | |||
281 | /* | ||
282 | * indicates type of value. | ||
283 | */ | ||
284 | enum brcms_srom_var_type { | ||
285 | BRCMS_SROM_STRING, | ||
286 | BRCMS_SROM_SNUMBER, | ||
287 | BRCMS_SROM_UNUMBER | ||
288 | }; | ||
289 | |||
290 | /* | ||
291 | * storage type for srom variable. | ||
292 | * | ||
293 | * var_list: for linked list operations. | ||
294 | * varid: identifier of the variable. | ||
295 | * var_type: type of variable. | ||
296 | * buf: variable value when var_type == BRCMS_SROM_STRING. | ||
297 | * uval: unsigned variable value when var_type == BRCMS_SROM_UNUMBER. | ||
298 | * sval: signed variable value when var_type == BRCMS_SROM_SNUMBER. | ||
299 | */ | ||
300 | struct brcms_srom_list_head { | ||
301 | struct list_head var_list; | ||
302 | enum brcms_srom_id varid; | ||
303 | enum brcms_srom_var_type var_type; | ||
304 | union { | ||
305 | char buf[0]; | ||
306 | u32 uval; | ||
307 | s32 sval; | ||
308 | }; | ||
309 | }; | ||
310 | |||
311 | struct brcms_sromvar { | ||
312 | enum brcms_srom_id varid; | ||
313 | u32 revmask; | ||
314 | u32 flags; | ||
315 | u16 off; | ||
316 | u16 mask; | ||
317 | }; | ||
318 | |||
319 | struct brcms_varbuf { | ||
320 | char *base; /* pointer to buffer base */ | ||
321 | char *buf; /* pointer to current position */ | ||
322 | unsigned int size; /* current (residual) size in bytes */ | ||
323 | }; | ||
324 | |||
325 | /* | ||
326 | * Assumptions: | ||
327 | * - Ethernet address spans across 3 consecutive words | ||
328 | * | ||
329 | * Table rules: | ||
330 | * - Add multiple entries next to each other if a value spans across multiple | ||
331 | * words (even multiple fields in the same word) with each entry except the | ||
332 | * last having it's SRFL_MORE bit set. | ||
333 | * - Ethernet address entry does not follow above rule and must not have | ||
334 | * SRFL_MORE bit set. Its SRFL_ETHADDR bit implies it takes multiple words. | ||
335 | * - The last entry's name field must be NULL to indicate the end of the table. | ||
336 | * Other entries must have non-NULL name. | ||
337 | */ | ||
338 | static const struct brcms_sromvar pci_sromvars[] = { | ||
339 | {BRCMS_SROM_DEVID, 0xffffff00, SRFL_PRHEX | SRFL_NOVAR, PCI_F0DEVID, | ||
340 | 0xffff}, | ||
341 | {BRCMS_SROM_BOARDREV, 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff}, | ||
342 | {BRCMS_SROM_BOARDFLAGS, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL0, | ||
343 | 0xffff}, | ||
344 | {BRCMS_SROM_CONT, 0, 0, SROM8_BFL1, 0xffff}, | ||
345 | {BRCMS_SROM_BOARDFLAGS2, 0xffffff00, SRFL_PRHEX | SRFL_MORE, SROM8_BFL2, | ||
346 | 0xffff}, | ||
347 | {BRCMS_SROM_CONT, 0, 0, SROM8_BFL3, 0xffff}, | ||
348 | {BRCMS_SROM_BOARDTYPE, 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff}, | ||
349 | {BRCMS_SROM_BOARDNUM, 0xffffff00, 0, SROM8_MACLO, 0xffff}, | ||
350 | {BRCMS_SROM_REGREV, 0xffffff00, 0, SROM8_REGREV, 0x00ff}, | ||
351 | {BRCMS_SROM_LEDBH0, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0x00ff}, | ||
352 | {BRCMS_SROM_LEDBH1, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH10, 0xff00}, | ||
353 | {BRCMS_SROM_LEDBH2, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0x00ff}, | ||
354 | {BRCMS_SROM_LEDBH3, 0xffffff00, SRFL_NOFFS, SROM8_LEDBH32, 0xff00}, | ||
355 | {BRCMS_SROM_PA0B0, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB0, 0xffff}, | ||
356 | {BRCMS_SROM_PA0B1, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB1, 0xffff}, | ||
357 | {BRCMS_SROM_PA0B2, 0xffffff00, SRFL_PRHEX, SROM8_W0_PAB2, 0xffff}, | ||
358 | {BRCMS_SROM_PA0ITSSIT, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0xff00}, | ||
359 | {BRCMS_SROM_PA0MAXPWR, 0xffffff00, 0, SROM8_W0_ITTMAXP, 0x00ff}, | ||
360 | {BRCMS_SROM_OPO, 0xffffff00, 0, SROM8_2G_OFDMPO, 0x00ff}, | ||
361 | {BRCMS_SROM_AA2G, 0xffffff00, 0, SROM8_AA, 0x00ff}, | ||
362 | {BRCMS_SROM_AA5G, 0xffffff00, 0, SROM8_AA, 0xff00}, | ||
363 | {BRCMS_SROM_AG0, 0xffffff00, 0, SROM8_AG10, 0x00ff}, | ||
364 | {BRCMS_SROM_AG1, 0xffffff00, 0, SROM8_AG10, 0xff00}, | ||
365 | {BRCMS_SROM_AG2, 0xffffff00, 0, SROM8_AG32, 0x00ff}, | ||
366 | {BRCMS_SROM_AG3, 0xffffff00, 0, SROM8_AG32, 0xff00}, | ||
367 | {BRCMS_SROM_PA1B0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0, 0xffff}, | ||
368 | {BRCMS_SROM_PA1B1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1, 0xffff}, | ||
369 | {BRCMS_SROM_PA1B2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2, 0xffff}, | ||
370 | {BRCMS_SROM_PA1LOB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_LC, 0xffff}, | ||
371 | {BRCMS_SROM_PA1LOB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_LC, 0xffff}, | ||
372 | {BRCMS_SROM_PA1LOB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_LC, 0xffff}, | ||
373 | {BRCMS_SROM_PA1HIB0, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB0_HC, 0xffff}, | ||
374 | {BRCMS_SROM_PA1HIB1, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB1_HC, 0xffff}, | ||
375 | {BRCMS_SROM_PA1HIB2, 0xffffff00, SRFL_PRHEX, SROM8_W1_PAB2_HC, 0xffff}, | ||
376 | {BRCMS_SROM_PA1ITSSIT, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0xff00}, | ||
377 | {BRCMS_SROM_PA1MAXPWR, 0xffffff00, 0, SROM8_W1_ITTMAXP, 0x00ff}, | ||
378 | {BRCMS_SROM_PA1LOMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0xff00}, | ||
379 | {BRCMS_SROM_PA1HIMAXPWR, 0xffffff00, 0, SROM8_W1_MAXP_LCHC, 0x00ff}, | ||
380 | {BRCMS_SROM_BXA2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x1800}, | ||
381 | {BRCMS_SROM_RSSISAV2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x0700}, | ||
382 | {BRCMS_SROM_RSSISMC2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x00f0}, | ||
383 | {BRCMS_SROM_RSSISMF2G, 0xffffff00, 0, SROM8_BXARSSI2G, 0x000f}, | ||
384 | {BRCMS_SROM_BXA5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x1800}, | ||
385 | {BRCMS_SROM_RSSISAV5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x0700}, | ||
386 | {BRCMS_SROM_RSSISMC5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x00f0}, | ||
387 | {BRCMS_SROM_RSSISMF5G, 0xffffff00, 0, SROM8_BXARSSI5G, 0x000f}, | ||
388 | {BRCMS_SROM_TRI2G, 0xffffff00, 0, SROM8_TRI52G, 0x00ff}, | ||
389 | {BRCMS_SROM_TRI5G, 0xffffff00, 0, SROM8_TRI52G, 0xff00}, | ||
390 | {BRCMS_SROM_TRI5GL, 0xffffff00, 0, SROM8_TRI5GHL, 0x00ff}, | ||
391 | {BRCMS_SROM_TRI5GH, 0xffffff00, 0, SROM8_TRI5GHL, 0xff00}, | ||
392 | {BRCMS_SROM_RXPO2G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0x00ff}, | ||
393 | {BRCMS_SROM_RXPO5G, 0xffffff00, SRFL_PRSIGN, SROM8_RXPO52G, 0xff00}, | ||
394 | {BRCMS_SROM_TXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, | ||
395 | SROM4_TXCHAIN_MASK}, | ||
396 | {BRCMS_SROM_RXCHAIN, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, | ||
397 | SROM4_RXCHAIN_MASK}, | ||
398 | {BRCMS_SROM_ANTSWITCH, 0xffffff00, SRFL_NOFFS, SROM8_TXRXC, | ||
399 | SROM4_SWITCH_MASK}, | ||
400 | {BRCMS_SROM_TSSIPOS2G, 0xffffff00, 0, SROM8_FEM2G, | ||
401 | SROM8_FEM_TSSIPOS_MASK}, | ||
402 | {BRCMS_SROM_EXTPAGAIN2G, 0xffffff00, 0, SROM8_FEM2G, | ||
403 | SROM8_FEM_EXTPA_GAIN_MASK}, | ||
404 | {BRCMS_SROM_PDETRANGE2G, 0xffffff00, 0, SROM8_FEM2G, | ||
405 | SROM8_FEM_PDET_RANGE_MASK}, | ||
406 | {BRCMS_SROM_TRISO2G, 0xffffff00, 0, SROM8_FEM2G, SROM8_FEM_TR_ISO_MASK}, | ||
407 | {BRCMS_SROM_ANTSWCTL2G, 0xffffff00, 0, SROM8_FEM2G, | ||
408 | SROM8_FEM_ANTSWLUT_MASK}, | ||
409 | {BRCMS_SROM_TSSIPOS5G, 0xffffff00, 0, SROM8_FEM5G, | ||
410 | SROM8_FEM_TSSIPOS_MASK}, | ||
411 | {BRCMS_SROM_EXTPAGAIN5G, 0xffffff00, 0, SROM8_FEM5G, | ||
412 | SROM8_FEM_EXTPA_GAIN_MASK}, | ||
413 | {BRCMS_SROM_PDETRANGE5G, 0xffffff00, 0, SROM8_FEM5G, | ||
414 | SROM8_FEM_PDET_RANGE_MASK}, | ||
415 | {BRCMS_SROM_TRISO5G, 0xffffff00, 0, SROM8_FEM5G, SROM8_FEM_TR_ISO_MASK}, | ||
416 | {BRCMS_SROM_ANTSWCTL5G, 0xffffff00, 0, SROM8_FEM5G, | ||
417 | SROM8_FEM_ANTSWLUT_MASK}, | ||
418 | {BRCMS_SROM_TEMPTHRESH, 0xffffff00, 0, SROM8_THERMAL, 0xff00}, | ||
419 | {BRCMS_SROM_TEMPOFFSET, 0xffffff00, 0, SROM8_THERMAL, 0x00ff}, | ||
420 | |||
421 | {BRCMS_SROM_CCODE, 0xffffff00, SRFL_CCODE, SROM8_CCODE, 0xffff}, | ||
422 | {BRCMS_SROM_MACADDR, 0xffffff00, SRFL_ETHADDR, SROM8_MACHI, 0xffff}, | ||
423 | {BRCMS_SROM_LEDDC, 0xffffff00, SRFL_NOFFS | SRFL_LEDDC, SROM8_LEDDC, | ||
424 | 0xffff}, | ||
425 | {BRCMS_SROM_RAWTEMPSENSE, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, | ||
426 | 0x01ff}, | ||
427 | {BRCMS_SROM_MEASPOWER, 0xffffff00, SRFL_PRHEX, SROM8_MPWR_RAWTS, | ||
428 | 0xfe00}, | ||
429 | {BRCMS_SROM_TEMPSENSE_SLOPE, 0xffffff00, SRFL_PRHEX, | ||
430 | SROM8_TS_SLP_OPT_CORRX, 0x00ff}, | ||
431 | {BRCMS_SROM_TEMPCORRX, 0xffffff00, SRFL_PRHEX, SROM8_TS_SLP_OPT_CORRX, | ||
432 | 0xfc00}, | ||
433 | {BRCMS_SROM_TEMPSENSE_OPTION, 0xffffff00, SRFL_PRHEX, | ||
434 | SROM8_TS_SLP_OPT_CORRX, 0x0300}, | ||
435 | {BRCMS_SROM_FREQOFFSET_CORR, 0xffffff00, SRFL_PRHEX, | ||
436 | SROM8_FOC_HWIQ_IQSWP, 0x000f}, | ||
437 | {BRCMS_SROM_IQCAL_SWP_DIS, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, | ||
438 | 0x0010}, | ||
439 | {BRCMS_SROM_HW_IQCAL_EN, 0xffffff00, SRFL_PRHEX, SROM8_FOC_HWIQ_IQSWP, | ||
440 | 0x0020}, | ||
441 | {BRCMS_SROM_PHYCAL_TEMPDELTA, 0xffffff00, 0, SROM8_PHYCAL_TEMPDELTA, | ||
442 | 0x00ff}, | ||
443 | |||
444 | {BRCMS_SROM_CCK2GPO, 0x00000100, 0, SROM8_2G_CCKPO, 0xffff}, | ||
445 | {BRCMS_SROM_OFDM2GPO, 0x00000100, SRFL_MORE, SROM8_2G_OFDMPO, 0xffff}, | ||
446 | {BRCMS_SROM_CONT, 0, 0, SROM8_2G_OFDMPO + 1, 0xffff}, | ||
447 | {BRCMS_SROM_OFDM5GPO, 0x00000100, SRFL_MORE, SROM8_5G_OFDMPO, 0xffff}, | ||
448 | {BRCMS_SROM_CONT, 0, 0, SROM8_5G_OFDMPO + 1, 0xffff}, | ||
449 | {BRCMS_SROM_OFDM5GLPO, 0x00000100, SRFL_MORE, SROM8_5GL_OFDMPO, 0xffff}, | ||
450 | {BRCMS_SROM_CONT, 0, 0, SROM8_5GL_OFDMPO + 1, 0xffff}, | ||
451 | {BRCMS_SROM_OFDM5GHPO, 0x00000100, SRFL_MORE, SROM8_5GH_OFDMPO, 0xffff}, | ||
452 | {BRCMS_SROM_CONT, 0, 0, SROM8_5GH_OFDMPO + 1, 0xffff}, | ||
453 | {BRCMS_SROM_MCS2GPO0, 0x00000100, 0, SROM8_2G_MCSPO, 0xffff}, | ||
454 | {BRCMS_SROM_MCS2GPO1, 0x00000100, 0, SROM8_2G_MCSPO + 1, 0xffff}, | ||
455 | {BRCMS_SROM_MCS2GPO2, 0x00000100, 0, SROM8_2G_MCSPO + 2, 0xffff}, | ||
456 | {BRCMS_SROM_MCS2GPO3, 0x00000100, 0, SROM8_2G_MCSPO + 3, 0xffff}, | ||
457 | {BRCMS_SROM_MCS2GPO4, 0x00000100, 0, SROM8_2G_MCSPO + 4, 0xffff}, | ||
458 | {BRCMS_SROM_MCS2GPO5, 0x00000100, 0, SROM8_2G_MCSPO + 5, 0xffff}, | ||
459 | {BRCMS_SROM_MCS2GPO6, 0x00000100, 0, SROM8_2G_MCSPO + 6, 0xffff}, | ||
460 | {BRCMS_SROM_MCS2GPO7, 0x00000100, 0, SROM8_2G_MCSPO + 7, 0xffff}, | ||
461 | {BRCMS_SROM_MCS5GPO0, 0x00000100, 0, SROM8_5G_MCSPO, 0xffff}, | ||
462 | {BRCMS_SROM_MCS5GPO1, 0x00000100, 0, SROM8_5G_MCSPO + 1, 0xffff}, | ||
463 | {BRCMS_SROM_MCS5GPO2, 0x00000100, 0, SROM8_5G_MCSPO + 2, 0xffff}, | ||
464 | {BRCMS_SROM_MCS5GPO3, 0x00000100, 0, SROM8_5G_MCSPO + 3, 0xffff}, | ||
465 | {BRCMS_SROM_MCS5GPO4, 0x00000100, 0, SROM8_5G_MCSPO + 4, 0xffff}, | ||
466 | {BRCMS_SROM_MCS5GPO5, 0x00000100, 0, SROM8_5G_MCSPO + 5, 0xffff}, | ||
467 | {BRCMS_SROM_MCS5GPO6, 0x00000100, 0, SROM8_5G_MCSPO + 6, 0xffff}, | ||
468 | {BRCMS_SROM_MCS5GPO7, 0x00000100, 0, SROM8_5G_MCSPO + 7, 0xffff}, | ||
469 | {BRCMS_SROM_MCS5GLPO0, 0x00000100, 0, SROM8_5GL_MCSPO, 0xffff}, | ||
470 | {BRCMS_SROM_MCS5GLPO1, 0x00000100, 0, SROM8_5GL_MCSPO + 1, 0xffff}, | ||
471 | {BRCMS_SROM_MCS5GLPO2, 0x00000100, 0, SROM8_5GL_MCSPO + 2, 0xffff}, | ||
472 | {BRCMS_SROM_MCS5GLPO3, 0x00000100, 0, SROM8_5GL_MCSPO + 3, 0xffff}, | ||
473 | {BRCMS_SROM_MCS5GLPO4, 0x00000100, 0, SROM8_5GL_MCSPO + 4, 0xffff}, | ||
474 | {BRCMS_SROM_MCS5GLPO5, 0x00000100, 0, SROM8_5GL_MCSPO + 5, 0xffff}, | ||
475 | {BRCMS_SROM_MCS5GLPO6, 0x00000100, 0, SROM8_5GL_MCSPO + 6, 0xffff}, | ||
476 | {BRCMS_SROM_MCS5GLPO7, 0x00000100, 0, SROM8_5GL_MCSPO + 7, 0xffff}, | ||
477 | {BRCMS_SROM_MCS5GHPO0, 0x00000100, 0, SROM8_5GH_MCSPO, 0xffff}, | ||
478 | {BRCMS_SROM_MCS5GHPO1, 0x00000100, 0, SROM8_5GH_MCSPO + 1, 0xffff}, | ||
479 | {BRCMS_SROM_MCS5GHPO2, 0x00000100, 0, SROM8_5GH_MCSPO + 2, 0xffff}, | ||
480 | {BRCMS_SROM_MCS5GHPO3, 0x00000100, 0, SROM8_5GH_MCSPO + 3, 0xffff}, | ||
481 | {BRCMS_SROM_MCS5GHPO4, 0x00000100, 0, SROM8_5GH_MCSPO + 4, 0xffff}, | ||
482 | {BRCMS_SROM_MCS5GHPO5, 0x00000100, 0, SROM8_5GH_MCSPO + 5, 0xffff}, | ||
483 | {BRCMS_SROM_MCS5GHPO6, 0x00000100, 0, SROM8_5GH_MCSPO + 6, 0xffff}, | ||
484 | {BRCMS_SROM_MCS5GHPO7, 0x00000100, 0, SROM8_5GH_MCSPO + 7, 0xffff}, | ||
485 | {BRCMS_SROM_CDDPO, 0x00000100, 0, SROM8_CDDPO, 0xffff}, | ||
486 | {BRCMS_SROM_STBCPO, 0x00000100, 0, SROM8_STBCPO, 0xffff}, | ||
487 | {BRCMS_SROM_BW40PO, 0x00000100, 0, SROM8_BW40PO, 0xffff}, | ||
488 | {BRCMS_SROM_BWDUPPO, 0x00000100, 0, SROM8_BWDUPPO, 0xffff}, | ||
489 | |||
490 | /* power per rate from sromrev 9 */ | ||
491 | {BRCMS_SROM_CCKBW202GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20, 0xffff}, | ||
492 | {BRCMS_SROM_CCKBW20UL2GPO, 0xfffffe00, 0, SROM9_2GPO_CCKBW20UL, 0xffff}, | ||
493 | {BRCMS_SROM_LEGOFDMBW202GPO, 0xfffffe00, SRFL_MORE, | ||
494 | SROM9_2GPO_LOFDMBW20, 0xffff}, | ||
495 | {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20 + 1, 0xffff}, | ||
496 | {BRCMS_SROM_LEGOFDMBW20UL2GPO, 0xfffffe00, SRFL_MORE, | ||
497 | SROM9_2GPO_LOFDMBW20UL, 0xffff}, | ||
498 | {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_LOFDMBW20UL + 1, 0xffff}, | ||
499 | {BRCMS_SROM_LEGOFDMBW205GLPO, 0xfffffe00, SRFL_MORE, | ||
500 | SROM9_5GLPO_LOFDMBW20, 0xffff}, | ||
501 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20 + 1, 0xffff}, | ||
502 | {BRCMS_SROM_LEGOFDMBW20UL5GLPO, 0xfffffe00, SRFL_MORE, | ||
503 | SROM9_5GLPO_LOFDMBW20UL, 0xffff}, | ||
504 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_LOFDMBW20UL + 1, 0xffff}, | ||
505 | {BRCMS_SROM_LEGOFDMBW205GMPO, 0xfffffe00, SRFL_MORE, | ||
506 | SROM9_5GMPO_LOFDMBW20, 0xffff}, | ||
507 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20 + 1, 0xffff}, | ||
508 | {BRCMS_SROM_LEGOFDMBW20UL5GMPO, 0xfffffe00, SRFL_MORE, | ||
509 | SROM9_5GMPO_LOFDMBW20UL, 0xffff}, | ||
510 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_LOFDMBW20UL + 1, 0xffff}, | ||
511 | {BRCMS_SROM_LEGOFDMBW205GHPO, 0xfffffe00, SRFL_MORE, | ||
512 | SROM9_5GHPO_LOFDMBW20, 0xffff}, | ||
513 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20 + 1, 0xffff}, | ||
514 | {BRCMS_SROM_LEGOFDMBW20UL5GHPO, 0xfffffe00, SRFL_MORE, | ||
515 | SROM9_5GHPO_LOFDMBW20UL, 0xffff}, | ||
516 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_LOFDMBW20UL + 1, 0xffff}, | ||
517 | {BRCMS_SROM_MCSBW202GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20, | ||
518 | 0xffff}, | ||
519 | {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20 + 1, 0xffff}, | ||
520 | {BRCMS_SROM_MCSBW20UL2GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW20UL, | ||
521 | 0xffff}, | ||
522 | {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW20UL + 1, 0xffff}, | ||
523 | {BRCMS_SROM_MCSBW402GPO, 0xfffffe00, SRFL_MORE, SROM9_2GPO_MCSBW40, | ||
524 | 0xffff}, | ||
525 | {BRCMS_SROM_CONT, 0, 0, SROM9_2GPO_MCSBW40 + 1, 0xffff}, | ||
526 | {BRCMS_SROM_MCSBW205GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW20, | ||
527 | 0xffff}, | ||
528 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20 + 1, 0xffff}, | ||
529 | {BRCMS_SROM_MCSBW20UL5GLPO, 0xfffffe00, SRFL_MORE, | ||
530 | SROM9_5GLPO_MCSBW20UL, 0xffff}, | ||
531 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW20UL + 1, 0xffff}, | ||
532 | {BRCMS_SROM_MCSBW405GLPO, 0xfffffe00, SRFL_MORE, SROM9_5GLPO_MCSBW40, | ||
533 | 0xffff}, | ||
534 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GLPO_MCSBW40 + 1, 0xffff}, | ||
535 | {BRCMS_SROM_MCSBW205GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW20, | ||
536 | 0xffff}, | ||
537 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20 + 1, 0xffff}, | ||
538 | {BRCMS_SROM_MCSBW20UL5GMPO, 0xfffffe00, SRFL_MORE, | ||
539 | SROM9_5GMPO_MCSBW20UL, 0xffff}, | ||
540 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW20UL + 1, 0xffff}, | ||
541 | {BRCMS_SROM_MCSBW405GMPO, 0xfffffe00, SRFL_MORE, SROM9_5GMPO_MCSBW40, | ||
542 | 0xffff}, | ||
543 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GMPO_MCSBW40 + 1, 0xffff}, | ||
544 | {BRCMS_SROM_MCSBW205GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW20, | ||
545 | 0xffff}, | ||
546 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20 + 1, 0xffff}, | ||
547 | {BRCMS_SROM_MCSBW20UL5GHPO, 0xfffffe00, SRFL_MORE, | ||
548 | SROM9_5GHPO_MCSBW20UL, 0xffff}, | ||
549 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW20UL + 1, 0xffff}, | ||
550 | {BRCMS_SROM_MCSBW405GHPO, 0xfffffe00, SRFL_MORE, SROM9_5GHPO_MCSBW40, | ||
551 | 0xffff}, | ||
552 | {BRCMS_SROM_CONT, 0, 0, SROM9_5GHPO_MCSBW40 + 1, 0xffff}, | ||
553 | {BRCMS_SROM_MCS32PO, 0xfffffe00, 0, SROM9_PO_MCS32, 0xffff}, | ||
554 | {BRCMS_SROM_LEGOFDM40DUPPO, 0xfffffe00, 0, SROM9_PO_LOFDM40DUP, 0xffff}, | ||
555 | |||
556 | {BRCMS_SROM_NULL, 0, 0, 0, 0} | ||
557 | }; | ||
558 | |||
559 | static const struct brcms_sromvar perpath_pci_sromvars[] = { | ||
560 | {BRCMS_SROM_MAXP2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0x00ff}, | ||
561 | {BRCMS_SROM_ITT2GA0, 0xffffff00, 0, SROM8_2G_ITT_MAXP, 0xff00}, | ||
562 | {BRCMS_SROM_ITT5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0xff00}, | ||
563 | {BRCMS_SROM_PA2GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA, 0xffff}, | ||
564 | {BRCMS_SROM_PA2GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 1, 0xffff}, | ||
565 | {BRCMS_SROM_PA2GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_2G_PA + 2, 0xffff}, | ||
566 | {BRCMS_SROM_MAXP5GA0, 0xffffff00, 0, SROM8_5G_ITT_MAXP, 0x00ff}, | ||
567 | {BRCMS_SROM_MAXP5GHA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0x00ff}, | ||
568 | {BRCMS_SROM_MAXP5GLA0, 0xffffff00, 0, SROM8_5GLH_MAXP, 0xff00}, | ||
569 | {BRCMS_SROM_PA5GW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA, 0xffff}, | ||
570 | {BRCMS_SROM_PA5GW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 1, 0xffff}, | ||
571 | {BRCMS_SROM_PA5GW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5G_PA + 2, 0xffff}, | ||
572 | {BRCMS_SROM_PA5GLW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA, 0xffff}, | ||
573 | {BRCMS_SROM_PA5GLW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 1, | ||
574 | 0xffff}, | ||
575 | {BRCMS_SROM_PA5GLW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GL_PA + 2, | ||
576 | 0xffff}, | ||
577 | {BRCMS_SROM_PA5GHW0A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA, 0xffff}, | ||
578 | {BRCMS_SROM_PA5GHW1A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 1, | ||
579 | 0xffff}, | ||
580 | {BRCMS_SROM_PA5GHW2A0, 0xffffff00, SRFL_PRHEX, SROM8_5GH_PA + 2, | ||
581 | 0xffff}, | ||
582 | {BRCMS_SROM_NULL, 0, 0, 0, 0} | ||
583 | }; | ||
584 | |||
585 | /* crc table has the same contents for every device instance, so it can be | ||
586 | * shared between devices. */ | ||
587 | static u8 brcms_srom_crc8_table[CRC8_TABLE_SIZE]; | ||
588 | |||
589 | static uint mask_shift(u16 mask) | ||
590 | { | ||
591 | uint i; | ||
592 | for (i = 0; i < (sizeof(mask) << 3); i++) { | ||
593 | if (mask & (1 << i)) | ||
594 | return i; | ||
595 | } | ||
596 | return 0; | ||
597 | } | ||
598 | |||
599 | static uint mask_width(u16 mask) | ||
600 | { | ||
601 | int i; | ||
602 | for (i = (sizeof(mask) << 3) - 1; i >= 0; i--) { | ||
603 | if (mask & (1 << i)) | ||
604 | return (uint) (i - mask_shift(mask) + 1); | ||
605 | } | ||
606 | return 0; | ||
607 | } | ||
608 | |||
609 | static inline void le16_to_cpu_buf(u16 *buf, uint nwords) | ||
610 | { | ||
611 | while (nwords--) | ||
612 | *(buf + nwords) = le16_to_cpu(*(__le16 *)(buf + nwords)); | ||
613 | } | ||
614 | |||
615 | static inline void cpu_to_le16_buf(u16 *buf, uint nwords) | ||
616 | { | ||
617 | while (nwords--) | ||
618 | *(__le16 *)(buf + nwords) = cpu_to_le16(*(buf + nwords)); | ||
619 | } | ||
620 | |||
621 | /* | ||
622 | * convert binary srom data into linked list of srom variable items. | ||
623 | */ | ||
624 | static int | ||
625 | _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list) | ||
626 | { | ||
627 | struct brcms_srom_list_head *entry; | ||
628 | enum brcms_srom_id id; | ||
629 | u16 w; | ||
630 | u32 val = 0; | ||
631 | const struct brcms_sromvar *srv; | ||
632 | uint width; | ||
633 | uint flags; | ||
634 | u32 sr = (1 << sromrev); | ||
635 | uint p; | ||
636 | uint pb = SROM8_PATH0; | ||
637 | const uint psz = SROM8_PATH1 - SROM8_PATH0; | ||
638 | |||
639 | /* first store the srom revision */ | ||
640 | entry = kzalloc(sizeof(struct brcms_srom_list_head), GFP_KERNEL); | ||
641 | if (!entry) | ||
642 | return -ENOMEM; | ||
643 | |||
644 | entry->varid = BRCMS_SROM_REV; | ||
645 | entry->var_type = BRCMS_SROM_UNUMBER; | ||
646 | entry->uval = sromrev; | ||
647 | list_add(&entry->var_list, var_list); | ||
648 | |||
649 | for (srv = pci_sromvars; srv->varid != BRCMS_SROM_NULL; srv++) { | ||
650 | enum brcms_srom_var_type type; | ||
651 | u8 ea[ETH_ALEN]; | ||
652 | u8 extra_space = 0; | ||
653 | |||
654 | if ((srv->revmask & sr) == 0) | ||
655 | continue; | ||
656 | |||
657 | flags = srv->flags; | ||
658 | id = srv->varid; | ||
659 | |||
660 | /* This entry is for mfgc only. Don't generate param for it, */ | ||
661 | if (flags & SRFL_NOVAR) | ||
662 | continue; | ||
663 | |||
664 | if (flags & SRFL_ETHADDR) { | ||
665 | /* | ||
666 | * stored in string format XX:XX:XX:XX:XX:XX (17 chars) | ||
667 | */ | ||
668 | ea[0] = (srom[srv->off] >> 8) & 0xff; | ||
669 | ea[1] = srom[srv->off] & 0xff; | ||
670 | ea[2] = (srom[srv->off + 1] >> 8) & 0xff; | ||
671 | ea[3] = srom[srv->off + 1] & 0xff; | ||
672 | ea[4] = (srom[srv->off + 2] >> 8) & 0xff; | ||
673 | ea[5] = srom[srv->off + 2] & 0xff; | ||
674 | /* 17 characters + string terminator - union size */ | ||
675 | extra_space = 18 - sizeof(s32); | ||
676 | type = BRCMS_SROM_STRING; | ||
677 | } else { | ||
678 | w = srom[srv->off]; | ||
679 | val = (w & srv->mask) >> mask_shift(srv->mask); | ||
680 | width = mask_width(srv->mask); | ||
681 | |||
682 | while (srv->flags & SRFL_MORE) { | ||
683 | srv++; | ||
684 | if (srv->off == 0) | ||
685 | continue; | ||
686 | |||
687 | w = srom[srv->off]; | ||
688 | val += | ||
689 | ((w & srv->mask) >> mask_shift(srv-> | ||
690 | mask)) << | ||
691 | width; | ||
692 | width += mask_width(srv->mask); | ||
693 | } | ||
694 | |||
695 | if ((flags & SRFL_NOFFS) | ||
696 | && ((int)val == (1 << width) - 1)) | ||
697 | continue; | ||
698 | |||
699 | if (flags & SRFL_CCODE) { | ||
700 | type = BRCMS_SROM_STRING; | ||
701 | } else if (flags & SRFL_LEDDC) { | ||
702 | /* LED Powersave duty cycle has to be scaled: | ||
703 | *(oncount >> 24) (offcount >> 8) | ||
704 | */ | ||
705 | u32 w32 = /* oncount */ | ||
706 | (((val >> 8) & 0xff) << 24) | | ||
707 | /* offcount */ | ||
708 | (((val & 0xff)) << 8); | ||
709 | type = BRCMS_SROM_UNUMBER; | ||
710 | val = w32; | ||
711 | } else if ((flags & SRFL_PRSIGN) | ||
712 | && (val & (1 << (width - 1)))) { | ||
713 | type = BRCMS_SROM_SNUMBER; | ||
714 | val |= ~0 << width; | ||
715 | } else | ||
716 | type = BRCMS_SROM_UNUMBER; | ||
717 | } | ||
718 | |||
719 | entry = kzalloc(sizeof(struct brcms_srom_list_head) + | ||
720 | extra_space, GFP_KERNEL); | ||
721 | if (!entry) | ||
722 | return -ENOMEM; | ||
723 | entry->varid = id; | ||
724 | entry->var_type = type; | ||
725 | if (flags & SRFL_ETHADDR) { | ||
726 | snprintf(entry->buf, 18, "%pM", ea); | ||
727 | } else if (flags & SRFL_CCODE) { | ||
728 | if (val == 0) | ||
729 | entry->buf[0] = '\0'; | ||
730 | else | ||
731 | snprintf(entry->buf, 3, "%c%c", | ||
732 | (val >> 8), (val & 0xff)); | ||
733 | } else { | ||
734 | entry->uval = val; | ||
735 | } | ||
736 | |||
737 | list_add(&entry->var_list, var_list); | ||
738 | } | ||
739 | |||
740 | for (p = 0; p < MAX_PATH_SROM; p++) { | ||
741 | for (srv = perpath_pci_sromvars; | ||
742 | srv->varid != BRCMS_SROM_NULL; srv++) { | ||
743 | if ((srv->revmask & sr) == 0) | ||
744 | continue; | ||
745 | |||
746 | if (srv->flags & SRFL_NOVAR) | ||
747 | continue; | ||
748 | |||
749 | w = srom[pb + srv->off]; | ||
750 | val = (w & srv->mask) >> mask_shift(srv->mask); | ||
751 | width = mask_width(srv->mask); | ||
752 | |||
753 | /* Cheating: no per-path var is more than | ||
754 | * 1 word */ | ||
755 | if ((srv->flags & SRFL_NOFFS) | ||
756 | && ((int)val == (1 << width) - 1)) | ||
757 | continue; | ||
758 | |||
759 | entry = | ||
760 | kzalloc(sizeof(struct brcms_srom_list_head), | ||
761 | GFP_KERNEL); | ||
762 | if (!entry) | ||
763 | return -ENOMEM; | ||
764 | entry->varid = srv->varid+p; | ||
765 | entry->var_type = BRCMS_SROM_UNUMBER; | ||
766 | entry->uval = val; | ||
767 | list_add(&entry->var_list, var_list); | ||
768 | } | ||
769 | pb += psz; | ||
770 | } | ||
771 | return 0; | ||
772 | } | ||
773 | |||
774 | /* | ||
775 | * The crc check is done on a little-endian array, we need | ||
776 | * to switch the bytes around before checking crc (and | ||
777 | * then switch it back). | ||
778 | */ | ||
779 | static int do_crc_check(u16 *buf, unsigned nwords) | ||
780 | { | ||
781 | u8 crc; | ||
782 | |||
783 | cpu_to_le16_buf(buf, nwords); | ||
784 | crc = crc8(brcms_srom_crc8_table, (void *)buf, nwords << 1, CRC8_INIT_VALUE); | ||
785 | le16_to_cpu_buf(buf, nwords); | ||
786 | |||
787 | return crc == CRC8_GOOD_VALUE(brcms_srom_crc8_table); | ||
788 | } | ||
789 | |||
790 | /* | ||
791 | * Read in and validate sprom. | ||
792 | * Return 0 on success, nonzero on error. | ||
793 | */ | ||
794 | static int | ||
795 | sprom_read_pci(struct si_pub *sih, u16 *buf, uint nwords, bool check_crc) | ||
796 | { | ||
797 | int err = 0; | ||
798 | uint i; | ||
799 | struct bcma_device *core; | ||
800 | uint sprom_offset; | ||
801 | |||
802 | /* determine core to read */ | ||
803 | if (ai_get_ccrev(sih) < 32) { | ||
804 | core = ai_findcore(sih, BCMA_CORE_80211, 0); | ||
805 | sprom_offset = PCI_BAR0_SPROM_OFFSET; | ||
806 | } else { | ||
807 | core = ai_findcore(sih, BCMA_CORE_CHIPCOMMON, 0); | ||
808 | sprom_offset = CHIPCREGOFFS(sromotp); | ||
809 | } | ||
810 | |||
811 | /* read the sprom */ | ||
812 | for (i = 0; i < nwords; i++) | ||
813 | buf[i] = bcma_read16(core, sprom_offset+i*2); | ||
814 | |||
815 | if (buf[0] == 0xffff) | ||
816 | /* | ||
817 | * The hardware thinks that an srom that starts with | ||
818 | * 0xffff is blank, regardless of the rest of the | ||
819 | * content, so declare it bad. | ||
820 | */ | ||
821 | return -ENODATA; | ||
822 | |||
823 | if (check_crc && !do_crc_check(buf, nwords)) | ||
824 | err = -EIO; | ||
825 | |||
826 | return err; | ||
827 | } | ||
828 | |||
829 | static int otp_read_pci(struct si_pub *sih, u16 *buf, uint nwords) | ||
830 | { | ||
831 | u8 *otp; | ||
832 | uint sz = OTP_SZ_MAX / 2; /* size in words */ | ||
833 | int err = 0; | ||
834 | |||
835 | otp = kzalloc(OTP_SZ_MAX, GFP_ATOMIC); | ||
836 | if (otp == NULL) | ||
837 | return -ENOMEM; | ||
838 | |||
839 | err = otp_read_region(sih, OTP_HW_RGN, (u16 *) otp, &sz); | ||
840 | |||
841 | sz = min_t(uint, sz, nwords); | ||
842 | memcpy(buf, otp, sz * 2); | ||
843 | |||
844 | kfree(otp); | ||
845 | |||
846 | /* Check CRC */ | ||
847 | if (buf[0] == 0xffff) | ||
848 | /* The hardware thinks that an srom that starts with 0xffff | ||
849 | * is blank, regardless of the rest of the content, so declare | ||
850 | * it bad. | ||
851 | */ | ||
852 | return -ENODATA; | ||
853 | |||
854 | /* fixup the endianness so crc8 will pass */ | ||
855 | cpu_to_le16_buf(buf, sz); | ||
856 | if (crc8(brcms_srom_crc8_table, (u8 *) buf, sz * 2, | ||
857 | CRC8_INIT_VALUE) != CRC8_GOOD_VALUE(brcms_srom_crc8_table)) | ||
858 | err = -EIO; | ||
859 | else | ||
860 | /* now correct the endianness of the byte array */ | ||
861 | le16_to_cpu_buf(buf, sz); | ||
862 | |||
863 | return err; | ||
864 | } | ||
865 | |||
866 | /* | ||
867 | * Initialize nonvolatile variable table from sprom. | ||
868 | * Return 0 on success, nonzero on error. | ||
869 | */ | ||
870 | int srom_var_init(struct si_pub *sih) | ||
871 | { | ||
872 | u16 *srom; | ||
873 | u8 sromrev = 0; | ||
874 | u32 sr; | ||
875 | int err = 0; | ||
876 | |||
877 | /* | ||
878 | * Apply CRC over SROM content regardless SROM is present or not. | ||
879 | */ | ||
880 | srom = kmalloc(SROM_MAX, GFP_ATOMIC); | ||
881 | if (!srom) | ||
882 | return -ENOMEM; | ||
883 | |||
884 | crc8_populate_lsb(brcms_srom_crc8_table, SROM_CRC8_POLY); | ||
885 | if (ai_is_sprom_available(sih)) { | ||
886 | err = sprom_read_pci(sih, srom, SROM4_WORDS, true); | ||
887 | |||
888 | if (err == 0) | ||
889 | /* srom read and passed crc */ | ||
890 | /* top word of sprom contains version and crc8 */ | ||
891 | sromrev = srom[SROM4_CRCREV] & 0xff; | ||
892 | } else { | ||
893 | /* Use OTP if SPROM not available */ | ||
894 | err = otp_read_pci(sih, srom, SROM4_WORDS); | ||
895 | if (err == 0) | ||
896 | /* OTP only contain SROM rev8/rev9 for now */ | ||
897 | sromrev = srom[SROM4_CRCREV] & 0xff; | ||
898 | } | ||
899 | |||
900 | if (!err) { | ||
901 | struct si_info *sii = (struct si_info *)sih; | ||
902 | |||
903 | /* Bitmask for the sromrev */ | ||
904 | sr = 1 << sromrev; | ||
905 | |||
906 | /* | ||
907 | * srom version check: Current valid versions: 8, 9 | ||
908 | */ | ||
909 | if ((sr & 0x300) == 0) { | ||
910 | err = -EINVAL; | ||
911 | goto errout; | ||
912 | } | ||
913 | |||
914 | INIT_LIST_HEAD(&sii->var_list); | ||
915 | |||
916 | /* parse SROM into name=value pairs. */ | ||
917 | err = _initvars_srom_pci(sromrev, srom, &sii->var_list); | ||
918 | if (err) | ||
919 | srom_free_vars(sih); | ||
920 | } | ||
921 | |||
922 | errout: | ||
923 | kfree(srom); | ||
924 | return err; | ||
925 | } | ||
926 | |||
927 | void srom_free_vars(struct si_pub *sih) | ||
928 | { | ||
929 | struct si_info *sii; | ||
930 | struct brcms_srom_list_head *entry, *next; | ||
931 | |||
932 | sii = (struct si_info *)sih; | ||
933 | list_for_each_entry_safe(entry, next, &sii->var_list, var_list) { | ||
934 | list_del(&entry->var_list); | ||
935 | kfree(entry); | ||
936 | } | ||
937 | } | ||
938 | |||
939 | /* | ||
940 | * Search the name=value vars for a specific one and return its value. | ||
941 | * Returns NULL if not found. | ||
942 | */ | ||
943 | char *getvar(struct si_pub *sih, enum brcms_srom_id id) | ||
944 | { | ||
945 | struct si_info *sii; | ||
946 | struct brcms_srom_list_head *entry; | ||
947 | |||
948 | sii = (struct si_info *)sih; | ||
949 | |||
950 | list_for_each_entry(entry, &sii->var_list, var_list) | ||
951 | if (entry->varid == id) | ||
952 | return &entry->buf[0]; | ||
953 | |||
954 | /* nothing found */ | ||
955 | return NULL; | ||
956 | } | ||
957 | |||
958 | /* | ||
959 | * Search the vars for a specific one and return its value as | ||
960 | * an integer. Returns 0 if not found.- | ||
961 | */ | ||
962 | int getintvar(struct si_pub *sih, enum brcms_srom_id id) | ||
963 | { | ||
964 | struct si_info *sii; | ||
965 | struct brcms_srom_list_head *entry; | ||
966 | unsigned long res; | ||
967 | |||
968 | sii = (struct si_info *)sih; | ||
969 | |||
970 | list_for_each_entry(entry, &sii->var_list, var_list) | ||
971 | if (entry->varid == id) { | ||
972 | if (entry->var_type == BRCMS_SROM_SNUMBER || | ||
973 | entry->var_type == BRCMS_SROM_UNUMBER) | ||
974 | return (int)entry->sval; | ||
975 | else if (!kstrtoul(&entry->buf[0], 0, &res)) | ||
976 | return (int)res; | ||
977 | } | ||
978 | |||
979 | return 0; | ||
980 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/srom.h b/drivers/net/wireless/brcm80211/brcmsmac/srom.h deleted file mode 100644 index f2a58f262c99..000000000000 --- a/drivers/net/wireless/brcm80211/brcmsmac/srom.h +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 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 _BRCM_SROM_H_ | ||
18 | #define _BRCM_SROM_H_ | ||
19 | |||
20 | #include "types.h" | ||
21 | |||
22 | /* Prototypes */ | ||
23 | extern int srom_var_init(struct si_pub *sih); | ||
24 | extern void srom_free_vars(struct si_pub *sih); | ||
25 | |||
26 | extern int srom_read(struct si_pub *sih, uint bus, void *curmap, | ||
27 | uint byteoff, uint nbytes, u16 *buf, bool check_crc); | ||
28 | |||
29 | #endif /* _BRCM_SROM_H_ */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/stf.c b/drivers/net/wireless/brcm80211/brcmsmac/stf.c index d8f528eb180c..ed1d1aa71d2d 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/stf.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/stf.c | |||
@@ -370,9 +370,11 @@ void brcms_c_stf_phy_txant_upd(struct brcms_c_info *wlc) | |||
370 | 370 | ||
371 | void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc) | 371 | void brcms_c_stf_phy_chain_calc(struct brcms_c_info *wlc) |
372 | { | 372 | { |
373 | struct ssb_sprom *sprom = &wlc->hw->d11core->bus->sprom; | ||
374 | |||
373 | /* get available rx/tx chains */ | 375 | /* get available rx/tx chains */ |
374 | wlc->stf->hw_txchain = (u8) getintvar(wlc->hw->sih, BRCMS_SROM_TXCHAIN); | 376 | wlc->stf->hw_txchain = sprom->txchain; |
375 | wlc->stf->hw_rxchain = (u8) getintvar(wlc->hw->sih, BRCMS_SROM_RXCHAIN); | 377 | wlc->stf->hw_rxchain = sprom->rxchain; |
376 | 378 | ||
377 | /* these parameter are intended to be used for all PHY types */ | 379 | /* these parameter are intended to be used for all PHY types */ |
378 | if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) { | 380 | if (wlc->stf->hw_txchain == 0 || wlc->stf->hw_txchain == 0xf) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 01dc44267317..e55ec6c8a920 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/module.h> | 31 | #include <linux/module.h> |
32 | #include <linux/init.h> | 32 | #include <linux/init.h> |
33 | #include <linux/sched.h> | 33 | #include <linux/sched.h> |
34 | #include <net/mac80211.h> | ||
34 | 35 | ||
35 | #include "iwl-dev.h" | 36 | #include "iwl-dev.h" |
36 | #include "iwl-io.h" | 37 | #include "iwl-io.h" |
@@ -273,9 +274,20 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv) | |||
273 | return; | 274 | return; |
274 | } | 275 | } |
275 | 276 | ||
277 | /* | ||
278 | * Possible situations when BT needs to take over for receive, | ||
279 | * at the same time where STA needs to response to AP's frame(s), | ||
280 | * reduce the tx power of the required response frames, by that, | ||
281 | * allow the concurrent BT receive & WiFi transmit | ||
282 | * (BT - ANT A, WiFi -ANT B), without interference to one another | ||
283 | * | ||
284 | * Reduced tx power apply to control frames only (ACK/Back/CTS) | ||
285 | * when indicated by the BT config command | ||
286 | */ | ||
276 | basic.kill_ack_mask = priv->kill_ack_mask; | 287 | basic.kill_ack_mask = priv->kill_ack_mask; |
277 | basic.kill_cts_mask = priv->kill_cts_mask; | 288 | basic.kill_cts_mask = priv->kill_cts_mask; |
278 | basic.reduce_txpower = priv->reduced_txpower; | 289 | if (priv->reduced_txpower) |
290 | basic.reduce_txpower = IWLAGN_BT_REDUCED_TX_PWR; | ||
279 | basic.valid = priv->bt_valid; | 291 | basic.valid = priv->bt_valid; |
280 | 292 | ||
281 | /* | 293 | /* |
@@ -589,13 +601,31 @@ static bool iwlagn_set_kill_msk(struct iwl_priv *priv, | |||
589 | return need_update; | 601 | return need_update; |
590 | } | 602 | } |
591 | 603 | ||
604 | /* | ||
605 | * Upon RSSI changes, sends a bt config command with following changes | ||
606 | * 1. enable/disable "reduced control frames tx power | ||
607 | * 2. update the "kill)ack_mask" and "kill_cts_mask" | ||
608 | * | ||
609 | * If "reduced tx power" is enabled, uCode shall | ||
610 | * 1. ACK/Back/CTS rate shall reduced to 6Mbps | ||
611 | * 2. not use duplciate 20/40MHz mode | ||
612 | */ | ||
592 | static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv, | 613 | static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv, |
593 | struct iwl_bt_uart_msg *uart_msg) | 614 | struct iwl_bt_uart_msg *uart_msg) |
594 | { | 615 | { |
595 | bool need_update = false; | 616 | bool need_update = false; |
617 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | ||
618 | int ave_rssi; | ||
596 | 619 | ||
620 | ave_rssi = ieee80211_ave_rssi(ctx->vif); | ||
621 | if (!ave_rssi) { | ||
622 | /* no rssi data, no changes to reduce tx power */ | ||
623 | IWL_DEBUG_COEX(priv, "no rssi data available\n"); | ||
624 | return need_update; | ||
625 | } | ||
597 | if (!priv->reduced_txpower && | 626 | if (!priv->reduced_txpower && |
598 | !iwl_is_associated(priv, IWL_RXON_CTX_PAN) && | 627 | !iwl_is_associated(priv, IWL_RXON_CTX_PAN) && |
628 | (ave_rssi > BT_ENABLE_REDUCED_TXPOWER_THRESHOLD) && | ||
599 | (uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK | | 629 | (uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK | |
600 | BT_UART_MSG_FRAME3OBEX_MSK)) && | 630 | BT_UART_MSG_FRAME3OBEX_MSK)) && |
601 | !(uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK | | 631 | !(uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK | |
@@ -606,13 +636,14 @@ static bool iwlagn_fill_txpower_mode(struct iwl_priv *priv, | |||
606 | need_update = true; | 636 | need_update = true; |
607 | } else if (priv->reduced_txpower && | 637 | } else if (priv->reduced_txpower && |
608 | (iwl_is_associated(priv, IWL_RXON_CTX_PAN) || | 638 | (iwl_is_associated(priv, IWL_RXON_CTX_PAN) || |
639 | (ave_rssi < BT_DISABLE_REDUCED_TXPOWER_THRESHOLD) || | ||
609 | (uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK | | 640 | (uart_msg->frame3 & (BT_UART_MSG_FRAME3SCOESCO_MSK | |
610 | BT_UART_MSG_FRAME3SNIFF_MSK | BT_UART_MSG_FRAME3A2DP_MSK)) || | 641 | BT_UART_MSG_FRAME3SNIFF_MSK | BT_UART_MSG_FRAME3A2DP_MSK)) || |
611 | !(uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK | | 642 | !(uart_msg->frame3 & (BT_UART_MSG_FRAME3ACL_MSK | |
612 | BT_UART_MSG_FRAME3OBEX_MSK)))) { | 643 | BT_UART_MSG_FRAME3OBEX_MSK)))) { |
613 | /* disable reduced tx power */ | 644 | /* disable reduced tx power */ |
614 | priv->reduced_txpower = false; | 645 | priv->reduced_txpower = false; |
615 | priv->bt_valid &= ~IWLAGN_BT_VALID_REDUCED_TX_PWR; | 646 | priv->bt_valid |= IWLAGN_BT_VALID_REDUCED_TX_PWR; |
616 | need_update = true; | 647 | need_update = true; |
617 | } | 648 | } |
618 | 649 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c index 74fbee627306..0a3aa7c83003 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c | |||
@@ -61,6 +61,10 @@ void iwl_connection_init_rx_config(struct iwl_priv *priv, | |||
61 | RXON_FILTER_ACCEPT_GRP_MSK; | 61 | RXON_FILTER_ACCEPT_GRP_MSK; |
62 | break; | 62 | break; |
63 | 63 | ||
64 | case NL80211_IFTYPE_MONITOR: | ||
65 | ctx->staging.dev_type = RXON_DEV_TYPE_SNIFFER; | ||
66 | break; | ||
67 | |||
64 | default: | 68 | default: |
65 | IWL_ERR(priv, "Unsupported interface type %d\n", | 69 | IWL_ERR(priv, "Unsupported interface type %d\n", |
66 | ctx->vif->type); | 70 | ctx->vif->type); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index f2e9f298a947..3366e2e2f00f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -590,11 +590,17 @@ turn_off: | |||
590 | spin_unlock_bh(&priv->sta_lock); | 590 | spin_unlock_bh(&priv->sta_lock); |
591 | 591 | ||
592 | if (test_bit(txq_id, priv->agg_q_alloc)) { | 592 | if (test_bit(txq_id, priv->agg_q_alloc)) { |
593 | /* If the transport didn't know that we wanted to start | 593 | /* |
594 | * agreggation, don't tell it that we want to stop them | 594 | * If the transport didn't know that we wanted to start |
595 | * agreggation, don't tell it that we want to stop them. | ||
596 | * This can happen when we don't get the addBA response on | ||
597 | * time, or we hadn't time to drain the AC queues. | ||
595 | */ | 598 | */ |
596 | if (agg_state != IWL_AGG_STARTING) | 599 | if (agg_state == IWL_AGG_ON) |
597 | iwl_trans_tx_agg_disable(priv->trans, txq_id); | 600 | iwl_trans_tx_agg_disable(priv->trans, txq_id); |
601 | else | ||
602 | IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n", | ||
603 | agg_state); | ||
598 | iwlagn_dealloc_agg_txq(priv, txq_id); | 604 | iwlagn_dealloc_agg_txq(priv, txq_id); |
599 | } | 605 | } |
600 | 606 | ||
@@ -1300,10 +1306,11 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1300 | (u8 *) &ba_resp->sta_addr_lo32, | 1306 | (u8 *) &ba_resp->sta_addr_lo32, |
1301 | ba_resp->sta_id); | 1307 | ba_resp->sta_id); |
1302 | IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, " | 1308 | IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, " |
1303 | "scd_flow = %d, scd_ssn = %d\n", | 1309 | "scd_flow = %d, scd_ssn = %d sent:%d, acked:%d\n", |
1304 | ba_resp->tid, le16_to_cpu(ba_resp->seq_ctl), | 1310 | ba_resp->tid, le16_to_cpu(ba_resp->seq_ctl), |
1305 | (unsigned long long)le64_to_cpu(ba_resp->bitmap), | 1311 | (unsigned long long)le64_to_cpu(ba_resp->bitmap), |
1306 | scd_flow, ba_resp_scd_ssn); | 1312 | scd_flow, ba_resp_scd_ssn, ba_resp->txed, |
1313 | ba_resp->txed_2_done); | ||
1307 | 1314 | ||
1308 | /* Mark that the expected block-ack response arrived */ | 1315 | /* Mark that the expected block-ack response arrived */ |
1309 | agg->wait_for_ba = false; | 1316 | agg->wait_for_ba = false; |
@@ -1319,8 +1326,6 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
1319 | */ | 1326 | */ |
1320 | ba_resp->txed = ba_resp->txed_2_done; | 1327 | ba_resp->txed = ba_resp->txed_2_done; |
1321 | } | 1328 | } |
1322 | IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n", | ||
1323 | ba_resp->txed, ba_resp->txed_2_done); | ||
1324 | 1329 | ||
1325 | priv->tid_data[sta_id][tid].next_reclaimed = ba_resp_scd_ssn; | 1330 | priv->tid_data[sta_id][tid].next_reclaimed = ba_resp_scd_ssn; |
1326 | 1331 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 8d7637083fcf..ec36e2b020b6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -603,7 +603,7 @@ void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags) | |||
603 | priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; | 603 | priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY; |
604 | priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; | 604 | priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID; |
605 | priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes = | 605 | priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes = |
606 | BIT(NL80211_IFTYPE_ADHOC); | 606 | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MONITOR); |
607 | priv->contexts[IWL_RXON_CTX_BSS].interface_modes = | 607 | priv->contexts[IWL_RXON_CTX_BSS].interface_modes = |
608 | BIT(NL80211_IFTYPE_STATION); | 608 | BIT(NL80211_IFTYPE_STATION); |
609 | priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP; | 609 | priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 83a6930f3658..9af6a239b384 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -1910,6 +1910,8 @@ enum iwl_bt_kill_idx { | |||
1910 | IWLAGN_BT_VALID_REDUCED_TX_PWR | \ | 1910 | IWLAGN_BT_VALID_REDUCED_TX_PWR | \ |
1911 | IWLAGN_BT_VALID_3W_LUT) | 1911 | IWLAGN_BT_VALID_3W_LUT) |
1912 | 1912 | ||
1913 | #define IWLAGN_BT_REDUCED_TX_PWR BIT(0) | ||
1914 | |||
1913 | #define IWLAGN_BT_DECISION_LUT_SIZE 12 | 1915 | #define IWLAGN_BT_DECISION_LUT_SIZE 12 |
1914 | 1916 | ||
1915 | struct iwl_basic_bt_cmd { | 1917 | struct iwl_basic_bt_cmd { |
@@ -1923,6 +1925,10 @@ struct iwl_basic_bt_cmd { | |||
1923 | u8 bt3_timer_t2_value; | 1925 | u8 bt3_timer_t2_value; |
1924 | __le16 bt4_reaction_time; /* unused */ | 1926 | __le16 bt4_reaction_time; /* unused */ |
1925 | __le32 bt3_lookup_table[IWLAGN_BT_DECISION_LUT_SIZE]; | 1927 | __le32 bt3_lookup_table[IWLAGN_BT_DECISION_LUT_SIZE]; |
1928 | /* | ||
1929 | * bit 0: use reduced tx power for control frame | ||
1930 | * bit 1 - 7: reserved | ||
1931 | */ | ||
1926 | u8 reduce_txpower; | 1932 | u8 reduce_txpower; |
1927 | u8 reserved; | 1933 | u8 reserved; |
1928 | __le16 valid; | 1934 | __le16 valid; |
@@ -2272,7 +2278,6 @@ struct iwl_ssid_ie { | |||
2272 | #define IWL_GOOD_CRC_TH_DISABLED 0 | 2278 | #define IWL_GOOD_CRC_TH_DISABLED 0 |
2273 | #define IWL_GOOD_CRC_TH_DEFAULT cpu_to_le16(1) | 2279 | #define IWL_GOOD_CRC_TH_DEFAULT cpu_to_le16(1) |
2274 | #define IWL_GOOD_CRC_TH_NEVER cpu_to_le16(0xffff) | 2280 | #define IWL_GOOD_CRC_TH_NEVER cpu_to_le16(0xffff) |
2275 | #define IWL_MAX_SCAN_SIZE 1024 | ||
2276 | #define IWL_MAX_CMD_SIZE 4096 | 2281 | #define IWL_MAX_CMD_SIZE 4096 |
2277 | 2282 | ||
2278 | /* | 2283 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index d33cc9cc7d3f..ab2f4d7500a4 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c | |||
@@ -150,6 +150,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
150 | IEEE80211_HW_QUEUE_CONTROL | | 150 | IEEE80211_HW_QUEUE_CONTROL | |
151 | IEEE80211_HW_SUPPORTS_PS | | 151 | IEEE80211_HW_SUPPORTS_PS | |
152 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | | 152 | IEEE80211_HW_SUPPORTS_DYNAMIC_PS | |
153 | IEEE80211_HW_WANT_MONITOR_VIF | | ||
153 | IEEE80211_HW_SCAN_WHILE_IDLE; | 154 | IEEE80211_HW_SCAN_WHILE_IDLE; |
154 | 155 | ||
155 | hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE; | 156 | hw->offchannel_tx_hw_queue = IWL_AUX_QUEUE; |
@@ -223,8 +224,8 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, | |||
223 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 224 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
224 | 225 | ||
225 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; | 226 | hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; |
226 | /* we create the 802.11 header and a zero-length SSID element */ | 227 | /* we create the 802.11 header and a max-length SSID element */ |
227 | hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 2; | 228 | hw->wiphy->max_scan_ie_len = capa->max_probe_length - 24 - 34; |
228 | 229 | ||
229 | /* | 230 | /* |
230 | * We don't use all queues: 4 and 9 are unused and any | 231 | * We don't use all queues: 4 and 9 are unused and any |
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 8352265dbc4b..544ddf17f5bd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c | |||
@@ -253,6 +253,8 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv, | |||
253 | 253 | ||
254 | IWL_DEBUG_POWER(priv, "numSkipDtim = %u, dtimPeriod = %d\n", | 254 | IWL_DEBUG_POWER(priv, "numSkipDtim = %u, dtimPeriod = %d\n", |
255 | skip, period); | 255 | skip, period); |
256 | /* The power level here is 0-4 (used as array index), but user expects | ||
257 | to see 1-5 (according to spec). */ | ||
256 | IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1); | 258 | IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1); |
257 | } | 259 | } |
258 | 260 | ||
@@ -308,10 +310,12 @@ static void iwl_power_build_cmd(struct iwl_priv *priv, | |||
308 | priv->power_data.debug_sleep_level_override, | 310 | priv->power_data.debug_sleep_level_override, |
309 | dtimper); | 311 | dtimper); |
310 | else { | 312 | else { |
313 | /* Note that the user parameter is 1-5 (according to spec), | ||
314 | but we pass 0-4 because it acts as an array index. */ | ||
311 | if (iwlwifi_mod_params.power_level > IWL_POWER_INDEX_1 && | 315 | if (iwlwifi_mod_params.power_level > IWL_POWER_INDEX_1 && |
312 | iwlwifi_mod_params.power_level <= IWL_POWER_INDEX_5) | 316 | iwlwifi_mod_params.power_level <= IWL_POWER_NUM) |
313 | iwl_static_sleep_cmd(priv, cmd, | 317 | iwl_static_sleep_cmd(priv, cmd, |
314 | iwlwifi_mod_params.power_level, dtimper); | 318 | iwlwifi_mod_params.power_level - 1, dtimper); |
315 | else | 319 | else |
316 | iwl_static_sleep_cmd(priv, cmd, | 320 | iwl_static_sleep_cmd(priv, cmd, |
317 | IWL_POWER_INDEX_1, dtimper); | 321 | IWL_POWER_INDEX_1, dtimper); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index a8437a6bc18e..031d8e21f82f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #define IWL_PASSIVE_DWELL_TIME_52 (10) | 52 | #define IWL_PASSIVE_DWELL_TIME_52 (10) |
53 | #define IWL_PASSIVE_DWELL_BASE (100) | 53 | #define IWL_PASSIVE_DWELL_BASE (100) |
54 | #define IWL_CHANNEL_TUNE_TIME 5 | 54 | #define IWL_CHANNEL_TUNE_TIME 5 |
55 | #define MAX_SCAN_CHANNEL 50 | ||
55 | 56 | ||
56 | static int iwl_send_scan_abort(struct iwl_priv *priv) | 57 | static int iwl_send_scan_abort(struct iwl_priv *priv) |
57 | { | 58 | { |
@@ -616,7 +617,8 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
616 | */ | 617 | */ |
617 | 618 | ||
618 | static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta, | 619 | static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta, |
619 | const u8 *ies, int ie_len, int left) | 620 | const u8 *ies, int ie_len, const u8 *ssid, |
621 | u8 ssid_len, int left) | ||
620 | { | 622 | { |
621 | int len = 0; | 623 | int len = 0; |
622 | u8 *pos = NULL; | 624 | u8 *pos = NULL; |
@@ -638,14 +640,18 @@ static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta, | |||
638 | /* ...next IE... */ | 640 | /* ...next IE... */ |
639 | pos = &frame->u.probe_req.variable[0]; | 641 | pos = &frame->u.probe_req.variable[0]; |
640 | 642 | ||
641 | /* fill in our indirect SSID IE */ | 643 | /* fill in our SSID IE */ |
642 | left -= 2; | 644 | left -= ssid_len + 2; |
643 | if (left < 0) | 645 | if (left < 0) |
644 | return 0; | 646 | return 0; |
645 | *pos++ = WLAN_EID_SSID; | 647 | *pos++ = WLAN_EID_SSID; |
646 | *pos++ = 0; | 648 | *pos++ = ssid_len; |
649 | if (ssid && ssid_len) { | ||
650 | memcpy(pos, ssid, ssid_len); | ||
651 | pos += ssid_len; | ||
652 | } | ||
647 | 653 | ||
648 | len += 2; | 654 | len += ssid_len + 2; |
649 | 655 | ||
650 | if (WARN_ON(left < ie_len)) | 656 | if (WARN_ON(left < ie_len)) |
651 | return len; | 657 | return len; |
@@ -679,6 +685,15 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
679 | u8 active_chains; | 685 | u8 active_chains; |
680 | u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; | 686 | u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; |
681 | int ret; | 687 | int ret; |
688 | int scan_cmd_size = sizeof(struct iwl_scan_cmd) + | ||
689 | MAX_SCAN_CHANNEL * sizeof(struct iwl_scan_channel) + | ||
690 | priv->fw->ucode_capa.max_probe_length; | ||
691 | const u8 *ssid = NULL; | ||
692 | u8 ssid_len = 0; | ||
693 | |||
694 | if (WARN_ON_ONCE(priv->scan_request && | ||
695 | priv->scan_request->n_channels > MAX_SCAN_CHANNEL)) | ||
696 | return -EINVAL; | ||
682 | 697 | ||
683 | lockdep_assert_held(&priv->mutex); | 698 | lockdep_assert_held(&priv->mutex); |
684 | 699 | ||
@@ -686,8 +701,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
686 | ctx = iwl_rxon_ctx_from_vif(vif); | 701 | ctx = iwl_rxon_ctx_from_vif(vif); |
687 | 702 | ||
688 | if (!priv->scan_cmd) { | 703 | if (!priv->scan_cmd) { |
689 | priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) + | 704 | priv->scan_cmd = kmalloc(scan_cmd_size, GFP_KERNEL); |
690 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); | ||
691 | if (!priv->scan_cmd) { | 705 | if (!priv->scan_cmd) { |
692 | IWL_DEBUG_SCAN(priv, | 706 | IWL_DEBUG_SCAN(priv, |
693 | "fail to allocate memory for scan\n"); | 707 | "fail to allocate memory for scan\n"); |
@@ -695,7 +709,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
695 | } | 709 | } |
696 | } | 710 | } |
697 | scan = priv->scan_cmd; | 711 | scan = priv->scan_cmd; |
698 | memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE); | 712 | memset(scan, 0, scan_cmd_size); |
699 | 713 | ||
700 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; | 714 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; |
701 | scan->quiet_time = IWL_ACTIVE_QUIET_TIME; | 715 | scan->quiet_time = IWL_ACTIVE_QUIET_TIME; |
@@ -746,10 +760,18 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
746 | if (priv->scan_request->n_ssids) { | 760 | if (priv->scan_request->n_ssids) { |
747 | int i, p = 0; | 761 | int i, p = 0; |
748 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); | 762 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); |
749 | for (i = 0; i < priv->scan_request->n_ssids; i++) { | 763 | /* |
750 | /* always does wildcard anyway */ | 764 | * The highest priority SSID is inserted to the |
751 | if (!priv->scan_request->ssids[i].ssid_len) | 765 | * probe request template. |
752 | continue; | 766 | */ |
767 | ssid_len = priv->scan_request->ssids[0].ssid_len; | ||
768 | ssid = priv->scan_request->ssids[0].ssid; | ||
769 | |||
770 | /* | ||
771 | * Invert the order of ssids, the firmware will invert | ||
772 | * it back. | ||
773 | */ | ||
774 | for (i = priv->scan_request->n_ssids - 1; i >= 1; i--) { | ||
753 | scan->direct_scan[p].id = WLAN_EID_SSID; | 775 | scan->direct_scan[p].id = WLAN_EID_SSID; |
754 | scan->direct_scan[p].len = | 776 | scan->direct_scan[p].len = |
755 | priv->scan_request->ssids[i].ssid_len; | 777 | priv->scan_request->ssids[i].ssid_len; |
@@ -883,7 +905,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
883 | vif->addr, | 905 | vif->addr, |
884 | priv->scan_request->ie, | 906 | priv->scan_request->ie, |
885 | priv->scan_request->ie_len, | 907 | priv->scan_request->ie_len, |
886 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | 908 | ssid, ssid_len, |
909 | scan_cmd_size - sizeof(*scan)); | ||
887 | break; | 910 | break; |
888 | case IWL_SCAN_RADIO_RESET: | 911 | case IWL_SCAN_RADIO_RESET: |
889 | case IWL_SCAN_ROC: | 912 | case IWL_SCAN_ROC: |
@@ -891,7 +914,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
891 | cmd_len = iwl_fill_probe_req( | 914 | cmd_len = iwl_fill_probe_req( |
892 | (struct ieee80211_mgmt *)scan->data, | 915 | (struct ieee80211_mgmt *)scan->data, |
893 | iwl_bcast_addr, NULL, 0, | 916 | iwl_bcast_addr, NULL, 0, |
894 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | 917 | NULL, 0, |
918 | scan_cmd_size - sizeof(*scan)); | ||
895 | break; | 919 | break; |
896 | default: | 920 | default: |
897 | BUG(); | 921 | BUG(); |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 03c0c6b1372c..fb787df01666 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -746,6 +746,11 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
746 | hwsim_check_sta_magic(txi->control.sta); | 746 | hwsim_check_sta_magic(txi->control.sta); |
747 | 747 | ||
748 | ieee80211_tx_info_clear_status(txi); | 748 | ieee80211_tx_info_clear_status(txi); |
749 | |||
750 | /* frame was transmitted at most favorable rate at first attempt */ | ||
751 | txi->control.rates[0].count = 1; | ||
752 | txi->control.rates[1].idx = -1; | ||
753 | |||
749 | if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack) | 754 | if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack) |
750 | txi->flags |= IEEE80211_TX_STAT_ACK; | 755 | txi->flags |= IEEE80211_TX_STAT_ACK; |
751 | ieee80211_tx_status_irqsafe(hw, skb); | 756 | ieee80211_tx_status_irqsafe(hw, skb); |
diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile index 5c1a46bf1e11..3f66ebb0a630 100644 --- a/drivers/net/wireless/mwifiex/Makefile +++ b/drivers/net/wireless/mwifiex/Makefile | |||
@@ -29,6 +29,8 @@ mwifiex-y += scan.o | |||
29 | mwifiex-y += join.o | 29 | mwifiex-y += join.o |
30 | mwifiex-y += sta_ioctl.o | 30 | mwifiex-y += sta_ioctl.o |
31 | mwifiex-y += sta_cmd.o | 31 | mwifiex-y += sta_cmd.o |
32 | mwifiex-y += uap_cmd.o | ||
33 | mwifiex-y += ie.o | ||
32 | mwifiex-y += sta_cmdresp.o | 34 | mwifiex-y += sta_cmdresp.o |
33 | mwifiex-y += sta_event.o | 35 | mwifiex-y += sta_event.o |
34 | mwifiex-y += sta_tx.o | 36 | mwifiex-y += sta_tx.o |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index c78ea873a63a..87671446e24b 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -20,6 +20,23 @@ | |||
20 | #include "cfg80211.h" | 20 | #include "cfg80211.h" |
21 | #include "main.h" | 21 | #include "main.h" |
22 | 22 | ||
23 | static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = { | ||
24 | { | ||
25 | .max = 1, .types = BIT(NL80211_IFTYPE_STATION), | ||
26 | }, | ||
27 | { | ||
28 | .max = 1, .types = BIT(NL80211_IFTYPE_AP), | ||
29 | }, | ||
30 | }; | ||
31 | |||
32 | static const struct ieee80211_iface_combination mwifiex_iface_comb_ap_sta = { | ||
33 | .limits = mwifiex_ap_sta_limits, | ||
34 | .num_different_channels = 1, | ||
35 | .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits), | ||
36 | .max_interfaces = MWIFIEX_MAX_BSS_NUM, | ||
37 | .beacon_int_infra_match = true, | ||
38 | }; | ||
39 | |||
23 | /* | 40 | /* |
24 | * This function maps the nl802.11 channel type into driver channel type. | 41 | * This function maps the nl802.11 channel type into driver channel type. |
25 | * | 42 | * |
@@ -67,7 +84,7 @@ mwifiex_is_alg_wep(u32 cipher) | |||
67 | /* | 84 | /* |
68 | * This function retrieves the private structure from kernel wiphy structure. | 85 | * This function retrieves the private structure from kernel wiphy structure. |
69 | */ | 86 | */ |
70 | static void *mwifiex_cfg80211_get_priv(struct wiphy *wiphy) | 87 | static void *mwifiex_cfg80211_get_adapter(struct wiphy *wiphy) |
71 | { | 88 | { |
72 | return (void *) (*(unsigned long *) wiphy_priv(wiphy)); | 89 | return (void *) (*(unsigned long *) wiphy_priv(wiphy)); |
73 | } | 90 | } |
@@ -80,8 +97,10 @@ mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, | |||
80 | u8 key_index, bool pairwise, const u8 *mac_addr) | 97 | u8 key_index, bool pairwise, const u8 *mac_addr) |
81 | { | 98 | { |
82 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); | 99 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); |
100 | const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
101 | const u8 *peer_mac = pairwise ? mac_addr : bc_mac; | ||
83 | 102 | ||
84 | if (mwifiex_set_encode(priv, NULL, 0, key_index, 1)) { | 103 | if (mwifiex_set_encode(priv, NULL, 0, key_index, peer_mac, 1)) { |
85 | wiphy_err(wiphy, "deleting the crypto keys\n"); | 104 | wiphy_err(wiphy, "deleting the crypto keys\n"); |
86 | return -EFAULT; | 105 | return -EFAULT; |
87 | } | 106 | } |
@@ -98,7 +117,8 @@ mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy, | |||
98 | enum nl80211_tx_power_setting type, | 117 | enum nl80211_tx_power_setting type, |
99 | int mbm) | 118 | int mbm) |
100 | { | 119 | { |
101 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); | 120 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); |
121 | struct mwifiex_private *priv; | ||
102 | struct mwifiex_power_cfg power_cfg; | 122 | struct mwifiex_power_cfg power_cfg; |
103 | int dbm = MBM_TO_DBM(mbm); | 123 | int dbm = MBM_TO_DBM(mbm); |
104 | 124 | ||
@@ -109,6 +129,8 @@ mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy, | |||
109 | power_cfg.is_power_auto = 1; | 129 | power_cfg.is_power_auto = 1; |
110 | } | 130 | } |
111 | 131 | ||
132 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | ||
133 | |||
112 | return mwifiex_set_tx_power(priv, &power_cfg); | 134 | return mwifiex_set_tx_power(priv, &power_cfg); |
113 | } | 135 | } |
114 | 136 | ||
@@ -148,7 +170,7 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev, | |||
148 | if (!priv->sec_info.wep_enabled) | 170 | if (!priv->sec_info.wep_enabled) |
149 | return 0; | 171 | return 0; |
150 | 172 | ||
151 | if (mwifiex_set_encode(priv, NULL, 0, key_index, 0)) { | 173 | if (mwifiex_set_encode(priv, NULL, 0, key_index, NULL, 0)) { |
152 | wiphy_err(wiphy, "set default Tx key index\n"); | 174 | wiphy_err(wiphy, "set default Tx key index\n"); |
153 | return -EFAULT; | 175 | return -EFAULT; |
154 | } | 176 | } |
@@ -165,9 +187,11 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, | |||
165 | struct key_params *params) | 187 | struct key_params *params) |
166 | { | 188 | { |
167 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); | 189 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); |
190 | const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
191 | const u8 *peer_mac = pairwise ? mac_addr : bc_mac; | ||
168 | 192 | ||
169 | if (mwifiex_set_encode(priv, params->key, params->key_len, | 193 | if (mwifiex_set_encode(priv, params->key, params->key_len, |
170 | key_index, 0)) { | 194 | key_index, peer_mac, 0)) { |
171 | wiphy_err(wiphy, "crypto keys added\n"); | 195 | wiphy_err(wiphy, "crypto keys added\n"); |
172 | return -EFAULT; | 196 | return -EFAULT; |
173 | } | 197 | } |
@@ -192,13 +216,13 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) | |||
192 | enum ieee80211_band band; | 216 | enum ieee80211_band band; |
193 | struct ieee80211_supported_band *sband; | 217 | struct ieee80211_supported_band *sband; |
194 | struct ieee80211_channel *ch; | 218 | struct ieee80211_channel *ch; |
195 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); | 219 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); |
196 | struct mwifiex_adapter *adapter = priv->adapter; | 220 | struct mwifiex_private *priv; |
197 | struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg; | 221 | struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg; |
198 | 222 | ||
199 | /* Set country code */ | 223 | /* Set country code */ |
200 | domain_info->country_code[0] = priv->country_code[0]; | 224 | domain_info->country_code[0] = adapter->country_code[0]; |
201 | domain_info->country_code[1] = priv->country_code[1]; | 225 | domain_info->country_code[1] = adapter->country_code[1]; |
202 | domain_info->country_code[2] = ' '; | 226 | domain_info->country_code[2] = ' '; |
203 | 227 | ||
204 | band = mwifiex_band_to_radio_type(adapter->config_bands); | 228 | band = mwifiex_band_to_radio_type(adapter->config_bands); |
@@ -250,6 +274,8 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) | |||
250 | 274 | ||
251 | domain_info->no_of_triplet = no_of_triplet; | 275 | domain_info->no_of_triplet = no_of_triplet; |
252 | 276 | ||
277 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | ||
278 | |||
253 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, | 279 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, |
254 | HostCmd_ACT_GEN_SET, 0, NULL)) { | 280 | HostCmd_ACT_GEN_SET, 0, NULL)) { |
255 | wiphy_err(wiphy, "11D: setting domain info in FW\n"); | 281 | wiphy_err(wiphy, "11D: setting domain info in FW\n"); |
@@ -272,12 +298,12 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) | |||
272 | static int mwifiex_reg_notifier(struct wiphy *wiphy, | 298 | static int mwifiex_reg_notifier(struct wiphy *wiphy, |
273 | struct regulatory_request *request) | 299 | struct regulatory_request *request) |
274 | { | 300 | { |
275 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); | 301 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); |
276 | 302 | ||
277 | wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for domain" | 303 | wiphy_dbg(wiphy, "info: cfg80211 regulatory domain callback for %c%c\n", |
278 | " %c%c\n", request->alpha2[0], request->alpha2[1]); | 304 | request->alpha2[0], request->alpha2[1]); |
279 | 305 | ||
280 | memcpy(priv->country_code, request->alpha2, sizeof(request->alpha2)); | 306 | memcpy(adapter->country_code, request->alpha2, sizeof(request->alpha2)); |
281 | 307 | ||
282 | switch (request->initiator) { | 308 | switch (request->initiator) { |
283 | case NL80211_REGDOM_SET_BY_DRIVER: | 309 | case NL80211_REGDOM_SET_BY_DRIVER: |
@@ -361,33 +387,10 @@ mwifiex_set_rf_channel(struct mwifiex_private *priv, | |||
361 | if (mwifiex_bss_set_channel(priv, &cfp)) | 387 | if (mwifiex_bss_set_channel(priv, &cfp)) |
362 | return -EFAULT; | 388 | return -EFAULT; |
363 | 389 | ||
364 | return mwifiex_drv_change_adhoc_chan(priv, cfp.channel); | 390 | if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) |
365 | } | 391 | return mwifiex_drv_change_adhoc_chan(priv, cfp.channel); |
366 | |||
367 | /* | ||
368 | * CFG802.11 operation handler to set channel. | ||
369 | * | ||
370 | * This function can only be used when station is not connected. | ||
371 | */ | ||
372 | static int | ||
373 | mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, | ||
374 | struct ieee80211_channel *chan, | ||
375 | enum nl80211_channel_type channel_type) | ||
376 | { | ||
377 | struct mwifiex_private *priv; | ||
378 | |||
379 | if (dev) | ||
380 | priv = mwifiex_netdev_get_priv(dev); | ||
381 | else | 392 | else |
382 | priv = mwifiex_cfg80211_get_priv(wiphy); | 393 | return mwifiex_uap_set_channel(priv, cfp.channel); |
383 | |||
384 | if (priv->media_connected) { | ||
385 | wiphy_err(wiphy, "This setting is valid only when station " | ||
386 | "is not connected\n"); | ||
387 | return -EINVAL; | ||
388 | } | ||
389 | |||
390 | return mwifiex_set_rf_channel(priv, chan, channel_type); | ||
391 | } | 394 | } |
392 | 395 | ||
393 | /* | 396 | /* |
@@ -399,18 +402,13 @@ mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, | |||
399 | static int | 402 | static int |
400 | mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr) | 403 | mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr) |
401 | { | 404 | { |
402 | int ret; | ||
403 | |||
404 | if (frag_thr < MWIFIEX_FRAG_MIN_VALUE || | 405 | if (frag_thr < MWIFIEX_FRAG_MIN_VALUE || |
405 | frag_thr > MWIFIEX_FRAG_MAX_VALUE) | 406 | frag_thr > MWIFIEX_FRAG_MAX_VALUE) |
406 | return -EINVAL; | 407 | frag_thr = MWIFIEX_FRAG_MAX_VALUE; |
407 | |||
408 | /* Send request to firmware */ | ||
409 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, | ||
410 | HostCmd_ACT_GEN_SET, FRAG_THRESH_I, | ||
411 | &frag_thr); | ||
412 | 408 | ||
413 | return ret; | 409 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, |
410 | HostCmd_ACT_GEN_SET, FRAG_THRESH_I, | ||
411 | &frag_thr); | ||
414 | } | 412 | } |
415 | 413 | ||
416 | /* | 414 | /* |
@@ -439,19 +437,85 @@ mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr) | |||
439 | static int | 437 | static int |
440 | mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | 438 | mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) |
441 | { | 439 | { |
442 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); | 440 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); |
443 | int ret = 0; | 441 | struct mwifiex_private *priv; |
442 | struct mwifiex_uap_bss_param *bss_cfg; | ||
443 | int ret, bss_started, i; | ||
444 | |||
445 | for (i = 0; i < adapter->priv_num; i++) { | ||
446 | priv = adapter->priv[i]; | ||
447 | |||
448 | switch (priv->bss_role) { | ||
449 | case MWIFIEX_BSS_ROLE_UAP: | ||
450 | bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), | ||
451 | GFP_KERNEL); | ||
452 | if (!bss_cfg) | ||
453 | return -ENOMEM; | ||
454 | |||
455 | mwifiex_set_sys_config_invalid_data(bss_cfg); | ||
456 | |||
457 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) | ||
458 | bss_cfg->rts_threshold = wiphy->rts_threshold; | ||
459 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) | ||
460 | bss_cfg->frag_threshold = wiphy->frag_threshold; | ||
461 | if (changed & WIPHY_PARAM_RETRY_LONG) | ||
462 | bss_cfg->retry_limit = wiphy->retry_long; | ||
463 | |||
464 | bss_started = priv->bss_started; | ||
465 | |||
466 | ret = mwifiex_send_cmd_sync(priv, | ||
467 | HostCmd_CMD_UAP_BSS_STOP, | ||
468 | HostCmd_ACT_GEN_SET, 0, | ||
469 | NULL); | ||
470 | if (ret) { | ||
471 | wiphy_err(wiphy, "Failed to stop the BSS\n"); | ||
472 | kfree(bss_cfg); | ||
473 | return ret; | ||
474 | } | ||
444 | 475 | ||
445 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) { | 476 | ret = mwifiex_send_cmd_async(priv, |
446 | ret = mwifiex_set_rts(priv, wiphy->rts_threshold); | 477 | HostCmd_CMD_UAP_SYS_CONFIG, |
447 | if (ret) | 478 | HostCmd_ACT_GEN_SET, |
448 | return ret; | 479 | UAP_BSS_PARAMS_I, bss_cfg); |
449 | } | ||
450 | 480 | ||
451 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) | 481 | kfree(bss_cfg); |
452 | ret = mwifiex_set_frag(priv, wiphy->frag_threshold); | ||
453 | 482 | ||
454 | return ret; | 483 | if (ret) { |
484 | wiphy_err(wiphy, "Failed to set bss config\n"); | ||
485 | return ret; | ||
486 | } | ||
487 | |||
488 | if (!bss_started) | ||
489 | break; | ||
490 | |||
491 | ret = mwifiex_send_cmd_async(priv, | ||
492 | HostCmd_CMD_UAP_BSS_START, | ||
493 | HostCmd_ACT_GEN_SET, 0, | ||
494 | NULL); | ||
495 | if (ret) { | ||
496 | wiphy_err(wiphy, "Failed to start BSS\n"); | ||
497 | return ret; | ||
498 | } | ||
499 | |||
500 | break; | ||
501 | case MWIFIEX_BSS_ROLE_STA: | ||
502 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) { | ||
503 | ret = mwifiex_set_rts(priv, | ||
504 | wiphy->rts_threshold); | ||
505 | if (ret) | ||
506 | return ret; | ||
507 | } | ||
508 | if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { | ||
509 | ret = mwifiex_set_frag(priv, | ||
510 | wiphy->frag_threshold); | ||
511 | if (ret) | ||
512 | return ret; | ||
513 | } | ||
514 | break; | ||
515 | } | ||
516 | } | ||
517 | |||
518 | return 0; | ||
455 | } | 519 | } |
456 | 520 | ||
457 | /* | 521 | /* |
@@ -466,31 +530,59 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, | |||
466 | int ret; | 530 | int ret; |
467 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 531 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
468 | 532 | ||
469 | if (priv->bss_mode == type) { | 533 | switch (dev->ieee80211_ptr->iftype) { |
470 | wiphy_warn(wiphy, "already set to required type\n"); | ||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | priv->bss_mode = type; | ||
475 | |||
476 | switch (type) { | ||
477 | case NL80211_IFTYPE_ADHOC: | 534 | case NL80211_IFTYPE_ADHOC: |
478 | dev->ieee80211_ptr->iftype = NL80211_IFTYPE_ADHOC; | 535 | switch (type) { |
479 | wiphy_dbg(wiphy, "info: setting interface type to adhoc\n"); | 536 | case NL80211_IFTYPE_STATION: |
537 | break; | ||
538 | case NL80211_IFTYPE_UNSPECIFIED: | ||
539 | wiphy_warn(wiphy, "%s: kept type as IBSS\n", dev->name); | ||
540 | case NL80211_IFTYPE_ADHOC: /* This shouldn't happen */ | ||
541 | return 0; | ||
542 | case NL80211_IFTYPE_AP: | ||
543 | default: | ||
544 | wiphy_err(wiphy, "%s: changing to %d not supported\n", | ||
545 | dev->name, type); | ||
546 | return -EOPNOTSUPP; | ||
547 | } | ||
480 | break; | 548 | break; |
481 | case NL80211_IFTYPE_STATION: | 549 | case NL80211_IFTYPE_STATION: |
482 | dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; | 550 | switch (type) { |
483 | wiphy_dbg(wiphy, "info: setting interface type to managed\n"); | 551 | case NL80211_IFTYPE_ADHOC: |
552 | break; | ||
553 | case NL80211_IFTYPE_UNSPECIFIED: | ||
554 | wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name); | ||
555 | case NL80211_IFTYPE_STATION: /* This shouldn't happen */ | ||
556 | return 0; | ||
557 | case NL80211_IFTYPE_AP: | ||
558 | default: | ||
559 | wiphy_err(wiphy, "%s: changing to %d not supported\n", | ||
560 | dev->name, type); | ||
561 | return -EOPNOTSUPP; | ||
562 | } | ||
563 | break; | ||
564 | case NL80211_IFTYPE_AP: | ||
565 | switch (type) { | ||
566 | case NL80211_IFTYPE_UNSPECIFIED: | ||
567 | wiphy_warn(wiphy, "%s: kept type as AP\n", dev->name); | ||
568 | case NL80211_IFTYPE_AP: /* This shouldn't happen */ | ||
569 | return 0; | ||
570 | case NL80211_IFTYPE_ADHOC: | ||
571 | case NL80211_IFTYPE_STATION: | ||
572 | default: | ||
573 | wiphy_err(wiphy, "%s: changing to %d not supported\n", | ||
574 | dev->name, type); | ||
575 | return -EOPNOTSUPP; | ||
576 | } | ||
484 | break; | 577 | break; |
485 | case NL80211_IFTYPE_UNSPECIFIED: | ||
486 | dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; | ||
487 | wiphy_dbg(wiphy, "info: setting interface type to auto\n"); | ||
488 | return 0; | ||
489 | default: | 578 | default: |
490 | wiphy_err(wiphy, "unknown interface type: %d\n", type); | 579 | wiphy_err(wiphy, "%s: unknown iftype: %d\n", |
491 | return -EINVAL; | 580 | dev->name, dev->ieee80211_ptr->iftype); |
581 | return -EOPNOTSUPP; | ||
492 | } | 582 | } |
493 | 583 | ||
584 | dev->ieee80211_ptr->iftype = type; | ||
585 | priv->bss_mode = type; | ||
494 | mwifiex_deauthenticate(priv, NULL); | 586 | mwifiex_deauthenticate(priv, NULL); |
495 | 587 | ||
496 | priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; | 588 | priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; |
@@ -804,6 +896,90 @@ static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy, | |||
804 | return 0; | 896 | return 0; |
805 | } | 897 | } |
806 | 898 | ||
899 | /* cfg80211 operation handler for stop ap. | ||
900 | * Function stops BSS running at uAP interface. | ||
901 | */ | ||
902 | static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | ||
903 | { | ||
904 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
905 | |||
906 | if (mwifiex_del_mgmt_ies(priv)) | ||
907 | wiphy_err(wiphy, "Failed to delete mgmt IEs!\n"); | ||
908 | |||
909 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, | ||
910 | HostCmd_ACT_GEN_SET, 0, NULL)) { | ||
911 | wiphy_err(wiphy, "Failed to stop the BSS\n"); | ||
912 | return -1; | ||
913 | } | ||
914 | |||
915 | return 0; | ||
916 | } | ||
917 | |||
918 | /* cfg80211 operation handler for start_ap. | ||
919 | * Function sets beacon period, DTIM period, SSID and security into | ||
920 | * AP config structure. | ||
921 | * AP is configured with these settings and BSS is started. | ||
922 | */ | ||
923 | static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, | ||
924 | struct net_device *dev, | ||
925 | struct cfg80211_ap_settings *params) | ||
926 | { | ||
927 | struct mwifiex_uap_bss_param *bss_cfg; | ||
928 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
929 | |||
930 | if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) | ||
931 | return -1; | ||
932 | if (mwifiex_set_mgmt_ies(priv, params)) | ||
933 | return -1; | ||
934 | |||
935 | bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL); | ||
936 | if (!bss_cfg) | ||
937 | return -ENOMEM; | ||
938 | |||
939 | mwifiex_set_sys_config_invalid_data(bss_cfg); | ||
940 | |||
941 | if (params->beacon_interval) | ||
942 | bss_cfg->beacon_period = params->beacon_interval; | ||
943 | if (params->dtim_period) | ||
944 | bss_cfg->dtim_period = params->dtim_period; | ||
945 | |||
946 | if (params->ssid && params->ssid_len) { | ||
947 | memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len); | ||
948 | bss_cfg->ssid.ssid_len = params->ssid_len; | ||
949 | } | ||
950 | |||
951 | if (mwifiex_set_secure_params(priv, bss_cfg, params)) { | ||
952 | kfree(bss_cfg); | ||
953 | wiphy_err(wiphy, "Failed to parse secuirty parameters!\n"); | ||
954 | return -1; | ||
955 | } | ||
956 | |||
957 | if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, | ||
958 | HostCmd_ACT_GEN_SET, 0, NULL)) { | ||
959 | wiphy_err(wiphy, "Failed to stop the BSS\n"); | ||
960 | kfree(bss_cfg); | ||
961 | return -1; | ||
962 | } | ||
963 | |||
964 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG, | ||
965 | HostCmd_ACT_GEN_SET, | ||
966 | UAP_BSS_PARAMS_I, bss_cfg)) { | ||
967 | wiphy_err(wiphy, "Failed to set the SSID\n"); | ||
968 | kfree(bss_cfg); | ||
969 | return -1; | ||
970 | } | ||
971 | |||
972 | kfree(bss_cfg); | ||
973 | |||
974 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_BSS_START, | ||
975 | HostCmd_ACT_GEN_SET, 0, NULL)) { | ||
976 | wiphy_err(wiphy, "Failed to start the BSS\n"); | ||
977 | return -1; | ||
978 | } | ||
979 | |||
980 | return 0; | ||
981 | } | ||
982 | |||
807 | /* | 983 | /* |
808 | * CFG802.11 operation handler for disconnection request. | 984 | * CFG802.11 operation handler for disconnection request. |
809 | * | 985 | * |
@@ -923,7 +1099,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, | |||
923 | priv->wep_key_curr_index = 0; | 1099 | priv->wep_key_curr_index = 0; |
924 | priv->sec_info.encryption_mode = 0; | 1100 | priv->sec_info.encryption_mode = 0; |
925 | priv->sec_info.is_authtype_auto = 0; | 1101 | priv->sec_info.is_authtype_auto = 0; |
926 | ret = mwifiex_set_encode(priv, NULL, 0, 0, 1); | 1102 | ret = mwifiex_set_encode(priv, NULL, 0, 0, NULL, 1); |
927 | 1103 | ||
928 | if (mode == NL80211_IFTYPE_ADHOC) { | 1104 | if (mode == NL80211_IFTYPE_ADHOC) { |
929 | /* "privacy" is set only for ad-hoc mode */ | 1105 | /* "privacy" is set only for ad-hoc mode */ |
@@ -971,7 +1147,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, | |||
971 | " with key len %d\n", sme->key_len); | 1147 | " with key len %d\n", sme->key_len); |
972 | priv->wep_key_curr_index = sme->key_idx; | 1148 | priv->wep_key_curr_index = sme->key_idx; |
973 | ret = mwifiex_set_encode(priv, sme->key, sme->key_len, | 1149 | ret = mwifiex_set_encode(priv, sme->key, sme->key_len, |
974 | sme->key_idx, 0); | 1150 | sme->key_idx, NULL, 0); |
975 | } | 1151 | } |
976 | } | 1152 | } |
977 | done: | 1153 | done: |
@@ -1050,6 +1226,11 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
1050 | goto done; | 1226 | goto done; |
1051 | } | 1227 | } |
1052 | 1228 | ||
1229 | if (priv->bss_mode == NL80211_IFTYPE_AP) { | ||
1230 | wiphy_err(wiphy, "skip association request for AP interface\n"); | ||
1231 | goto done; | ||
1232 | } | ||
1233 | |||
1053 | wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", | 1234 | wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", |
1054 | (char *) sme->ssid, sme->bssid); | 1235 | (char *) sme->ssid, sme->bssid); |
1055 | 1236 | ||
@@ -1283,15 +1464,12 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
1283 | u32 *flags, | 1464 | u32 *flags, |
1284 | struct vif_params *params) | 1465 | struct vif_params *params) |
1285 | { | 1466 | { |
1286 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); | 1467 | struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); |
1287 | struct mwifiex_adapter *adapter; | 1468 | struct mwifiex_private *priv; |
1288 | struct net_device *dev; | 1469 | struct net_device *dev; |
1289 | void *mdev_priv; | 1470 | void *mdev_priv; |
1471 | struct wireless_dev *wdev; | ||
1290 | 1472 | ||
1291 | if (!priv) | ||
1292 | return NULL; | ||
1293 | |||
1294 | adapter = priv->adapter; | ||
1295 | if (!adapter) | 1473 | if (!adapter) |
1296 | return NULL; | 1474 | return NULL; |
1297 | 1475 | ||
@@ -1299,12 +1477,21 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
1299 | case NL80211_IFTYPE_UNSPECIFIED: | 1477 | case NL80211_IFTYPE_UNSPECIFIED: |
1300 | case NL80211_IFTYPE_STATION: | 1478 | case NL80211_IFTYPE_STATION: |
1301 | case NL80211_IFTYPE_ADHOC: | 1479 | case NL80211_IFTYPE_ADHOC: |
1480 | priv = adapter->priv[MWIFIEX_BSS_TYPE_STA]; | ||
1302 | if (priv->bss_mode) { | 1481 | if (priv->bss_mode) { |
1303 | wiphy_err(wiphy, "cannot create multiple" | 1482 | wiphy_err(wiphy, |
1304 | " station/adhoc interfaces\n"); | 1483 | "cannot create multiple sta/adhoc ifaces\n"); |
1305 | return NULL; | 1484 | return NULL; |
1306 | } | 1485 | } |
1307 | 1486 | ||
1487 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | ||
1488 | if (!wdev) | ||
1489 | return NULL; | ||
1490 | |||
1491 | wdev->wiphy = wiphy; | ||
1492 | priv->wdev = wdev; | ||
1493 | wdev->iftype = NL80211_IFTYPE_STATION; | ||
1494 | |||
1308 | if (type == NL80211_IFTYPE_UNSPECIFIED) | 1495 | if (type == NL80211_IFTYPE_UNSPECIFIED) |
1309 | priv->bss_mode = NL80211_IFTYPE_STATION; | 1496 | priv->bss_mode = NL80211_IFTYPE_STATION; |
1310 | else | 1497 | else |
@@ -1312,11 +1499,36 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
1312 | 1499 | ||
1313 | priv->bss_type = MWIFIEX_BSS_TYPE_STA; | 1500 | priv->bss_type = MWIFIEX_BSS_TYPE_STA; |
1314 | priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; | 1501 | priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; |
1315 | priv->bss_priority = 0; | 1502 | priv->bss_priority = MWIFIEX_BSS_ROLE_STA; |
1316 | priv->bss_role = MWIFIEX_BSS_ROLE_STA; | 1503 | priv->bss_role = MWIFIEX_BSS_ROLE_STA; |
1317 | priv->bss_num = 0; | 1504 | priv->bss_num = 0; |
1318 | 1505 | ||
1319 | break; | 1506 | break; |
1507 | case NL80211_IFTYPE_AP: | ||
1508 | priv = adapter->priv[MWIFIEX_BSS_TYPE_UAP]; | ||
1509 | |||
1510 | if (priv->bss_mode) { | ||
1511 | wiphy_err(wiphy, "Can't create multiple AP interfaces"); | ||
1512 | return NULL; | ||
1513 | } | ||
1514 | |||
1515 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | ||
1516 | if (!wdev) | ||
1517 | return NULL; | ||
1518 | |||
1519 | priv->wdev = wdev; | ||
1520 | wdev->wiphy = wiphy; | ||
1521 | wdev->iftype = NL80211_IFTYPE_AP; | ||
1522 | |||
1523 | priv->bss_type = MWIFIEX_BSS_TYPE_UAP; | ||
1524 | priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; | ||
1525 | priv->bss_priority = MWIFIEX_BSS_ROLE_UAP; | ||
1526 | priv->bss_role = MWIFIEX_BSS_ROLE_UAP; | ||
1527 | priv->bss_started = 0; | ||
1528 | priv->bss_num = 0; | ||
1529 | priv->bss_mode = type; | ||
1530 | |||
1531 | break; | ||
1320 | default: | 1532 | default: |
1321 | wiphy_err(wiphy, "type not supported\n"); | 1533 | wiphy_err(wiphy, "type not supported\n"); |
1322 | return NULL; | 1534 | return NULL; |
@@ -1329,6 +1541,15 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
1329 | goto error; | 1541 | goto error; |
1330 | } | 1542 | } |
1331 | 1543 | ||
1544 | mwifiex_init_priv_params(priv, dev); | ||
1545 | priv->netdev = dev; | ||
1546 | |||
1547 | mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv); | ||
1548 | |||
1549 | if (adapter->config_bands & BAND_A) | ||
1550 | mwifiex_setup_ht_caps( | ||
1551 | &wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv); | ||
1552 | |||
1332 | dev_net_set(dev, wiphy_net(wiphy)); | 1553 | dev_net_set(dev, wiphy_net(wiphy)); |
1333 | dev->ieee80211_ptr = priv->wdev; | 1554 | dev->ieee80211_ptr = priv->wdev; |
1334 | dev->ieee80211_ptr->iftype = priv->bss_mode; | 1555 | dev->ieee80211_ptr->iftype = priv->bss_mode; |
@@ -1343,9 +1564,6 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
1343 | mdev_priv = netdev_priv(dev); | 1564 | mdev_priv = netdev_priv(dev); |
1344 | *((unsigned long *) mdev_priv) = (unsigned long) priv; | 1565 | *((unsigned long *) mdev_priv) = (unsigned long) priv; |
1345 | 1566 | ||
1346 | priv->netdev = dev; | ||
1347 | mwifiex_init_priv_params(priv, dev); | ||
1348 | |||
1349 | SET_NETDEV_DEV(dev, adapter->dev); | 1567 | SET_NETDEV_DEV(dev, adapter->dev); |
1350 | 1568 | ||
1351 | /* Register network device */ | 1569 | /* Register network device */ |
@@ -1417,7 +1635,6 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
1417 | .get_station = mwifiex_cfg80211_get_station, | 1635 | .get_station = mwifiex_cfg80211_get_station, |
1418 | .dump_station = mwifiex_cfg80211_dump_station, | 1636 | .dump_station = mwifiex_cfg80211_dump_station, |
1419 | .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params, | 1637 | .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params, |
1420 | .set_channel = mwifiex_cfg80211_set_channel, | ||
1421 | .join_ibss = mwifiex_cfg80211_join_ibss, | 1638 | .join_ibss = mwifiex_cfg80211_join_ibss, |
1422 | .leave_ibss = mwifiex_cfg80211_leave_ibss, | 1639 | .leave_ibss = mwifiex_cfg80211_leave_ibss, |
1423 | .add_key = mwifiex_cfg80211_add_key, | 1640 | .add_key = mwifiex_cfg80211_add_key, |
@@ -1426,6 +1643,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
1426 | .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt, | 1643 | .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt, |
1427 | .set_tx_power = mwifiex_cfg80211_set_tx_power, | 1644 | .set_tx_power = mwifiex_cfg80211_set_tx_power, |
1428 | .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask, | 1645 | .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask, |
1646 | .start_ap = mwifiex_cfg80211_start_ap, | ||
1647 | .stop_ap = mwifiex_cfg80211_stop_ap, | ||
1429 | .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, | 1648 | .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, |
1430 | }; | 1649 | }; |
1431 | 1650 | ||
@@ -1436,82 +1655,67 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
1436 | * default parameters and handler function pointers, and finally | 1655 | * default parameters and handler function pointers, and finally |
1437 | * registers the device. | 1656 | * registers the device. |
1438 | */ | 1657 | */ |
1439 | int mwifiex_register_cfg80211(struct mwifiex_private *priv) | 1658 | |
1659 | int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | ||
1440 | { | 1660 | { |
1441 | int ret; | 1661 | int ret; |
1442 | void *wdev_priv; | 1662 | void *wdev_priv; |
1443 | struct wireless_dev *wdev; | 1663 | struct wiphy *wiphy; |
1444 | struct ieee80211_sta_ht_cap *ht_info; | 1664 | struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA]; |
1445 | u8 *country_code; | 1665 | u8 *country_code; |
1446 | 1666 | ||
1447 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | 1667 | /* create a new wiphy for use with cfg80211 */ |
1448 | if (!wdev) { | 1668 | wiphy = wiphy_new(&mwifiex_cfg80211_ops, |
1449 | dev_err(priv->adapter->dev, "%s: allocating wireless device\n", | 1669 | sizeof(struct mwifiex_adapter *)); |
1450 | __func__); | 1670 | if (!wiphy) { |
1451 | return -ENOMEM; | 1671 | dev_err(adapter->dev, "%s: creating new wiphy\n", __func__); |
1452 | } | ||
1453 | wdev->wiphy = | ||
1454 | wiphy_new(&mwifiex_cfg80211_ops, | ||
1455 | sizeof(struct mwifiex_private *)); | ||
1456 | if (!wdev->wiphy) { | ||
1457 | kfree(wdev); | ||
1458 | return -ENOMEM; | 1672 | return -ENOMEM; |
1459 | } | 1673 | } |
1460 | wdev->iftype = NL80211_IFTYPE_STATION; | 1674 | wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH; |
1461 | wdev->wiphy->max_scan_ssids = 10; | 1675 | wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; |
1462 | wdev->wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; | 1676 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
1463 | wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 1677 | BIT(NL80211_IFTYPE_ADHOC) | |
1464 | BIT(NL80211_IFTYPE_ADHOC); | 1678 | BIT(NL80211_IFTYPE_AP); |
1465 | 1679 | ||
1466 | wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz; | 1680 | wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz; |
1467 | ht_info = &wdev->wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap; | 1681 | if (adapter->config_bands & BAND_A) |
1468 | mwifiex_setup_ht_caps(ht_info, priv); | 1682 | wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz; |
1469 | 1683 | else | |
1470 | if (priv->adapter->config_bands & BAND_A) { | 1684 | wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; |
1471 | wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz; | 1685 | |
1472 | ht_info = &wdev->wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap; | 1686 | wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta; |
1473 | mwifiex_setup_ht_caps(ht_info, priv); | 1687 | wiphy->n_iface_combinations = 1; |
1474 | } else { | ||
1475 | wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; | ||
1476 | } | ||
1477 | 1688 | ||
1478 | /* Initialize cipher suits */ | 1689 | /* Initialize cipher suits */ |
1479 | wdev->wiphy->cipher_suites = mwifiex_cipher_suites; | 1690 | wiphy->cipher_suites = mwifiex_cipher_suites; |
1480 | wdev->wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); | 1691 | wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); |
1481 | 1692 | ||
1482 | memcpy(wdev->wiphy->perm_addr, priv->curr_addr, ETH_ALEN); | 1693 | memcpy(wiphy->perm_addr, priv->curr_addr, ETH_ALEN); |
1483 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 1694 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
1695 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_CUSTOM_REGULATORY; | ||
1484 | 1696 | ||
1485 | /* Reserve space for mwifiex specific private data for BSS */ | 1697 | /* Reserve space for mwifiex specific private data for BSS */ |
1486 | wdev->wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); | 1698 | wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); |
1487 | |||
1488 | wdev->wiphy->reg_notifier = mwifiex_reg_notifier; | ||
1489 | 1699 | ||
1490 | /* Set struct mwifiex_private pointer in wiphy_priv */ | 1700 | wiphy->reg_notifier = mwifiex_reg_notifier; |
1491 | wdev_priv = wiphy_priv(wdev->wiphy); | ||
1492 | 1701 | ||
1493 | *(unsigned long *) wdev_priv = (unsigned long) priv; | 1702 | /* Set struct mwifiex_adapter pointer in wiphy_priv */ |
1703 | wdev_priv = wiphy_priv(wiphy); | ||
1704 | *(unsigned long *)wdev_priv = (unsigned long)adapter; | ||
1494 | 1705 | ||
1495 | set_wiphy_dev(wdev->wiphy, (struct device *) priv->adapter->dev); | 1706 | set_wiphy_dev(wiphy, (struct device *)priv->adapter->dev); |
1496 | 1707 | ||
1497 | ret = wiphy_register(wdev->wiphy); | 1708 | ret = wiphy_register(wiphy); |
1498 | if (ret < 0) { | 1709 | if (ret < 0) { |
1499 | dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n", | 1710 | dev_err(adapter->dev, |
1500 | __func__); | 1711 | "%s: wiphy_register failed: %d\n", __func__, ret); |
1501 | wiphy_free(wdev->wiphy); | 1712 | wiphy_free(wiphy); |
1502 | kfree(wdev); | ||
1503 | return ret; | 1713 | return ret; |
1504 | } else { | ||
1505 | dev_dbg(priv->adapter->dev, | ||
1506 | "info: successfully registered wiphy device\n"); | ||
1507 | } | 1714 | } |
1508 | |||
1509 | country_code = mwifiex_11d_code_2_region(priv->adapter->region_code); | 1715 | country_code = mwifiex_11d_code_2_region(priv->adapter->region_code); |
1510 | if (country_code && regulatory_hint(wdev->wiphy, country_code)) | 1716 | if (country_code && regulatory_hint(wiphy, country_code)) |
1511 | dev_err(priv->adapter->dev, | 1717 | dev_err(adapter->dev, "regulatory_hint() failed\n"); |
1512 | "%s: regulatory_hint failed\n", __func__); | ||
1513 | |||
1514 | priv->wdev = wdev; | ||
1515 | 1718 | ||
1719 | adapter->wiphy = wiphy; | ||
1516 | return ret; | 1720 | return ret; |
1517 | } | 1721 | } |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.h b/drivers/net/wireless/mwifiex/cfg80211.h index 76c76c60438b..c5848934f111 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.h +++ b/drivers/net/wireless/mwifiex/cfg80211.h | |||
@@ -24,6 +24,6 @@ | |||
24 | 24 | ||
25 | #include "main.h" | 25 | #include "main.h" |
26 | 26 | ||
27 | int mwifiex_register_cfg80211(struct mwifiex_private *); | 27 | int mwifiex_register_cfg80211(struct mwifiex_adapter *); |
28 | 28 | ||
29 | #endif | 29 | #endif |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 1710beffb93a..51e023ec1de4 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -440,6 +440,11 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) | |||
440 | do_gettimeofday(&tstamp); | 440 | do_gettimeofday(&tstamp); |
441 | dev_dbg(adapter->dev, "event: %lu.%lu: cause: %#x\n", | 441 | dev_dbg(adapter->dev, "event: %lu.%lu: cause: %#x\n", |
442 | tstamp.tv_sec, tstamp.tv_usec, eventcause); | 442 | tstamp.tv_sec, tstamp.tv_usec, eventcause); |
443 | } else { | ||
444 | /* Handle PS_SLEEP/AWAKE events on STA */ | ||
445 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); | ||
446 | if (!priv) | ||
447 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | ||
443 | } | 448 | } |
444 | 449 | ||
445 | ret = mwifiex_process_sta_event(priv); | 450 | ret = mwifiex_process_sta_event(priv); |
@@ -540,8 +545,20 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, | |||
540 | 545 | ||
541 | /* Prepare command */ | 546 | /* Prepare command */ |
542 | if (cmd_no) { | 547 | if (cmd_no) { |
543 | ret = mwifiex_sta_prepare_cmd(priv, cmd_no, cmd_action, | 548 | switch (cmd_no) { |
544 | cmd_oid, data_buf, cmd_ptr); | 549 | case HostCmd_CMD_UAP_SYS_CONFIG: |
550 | case HostCmd_CMD_UAP_BSS_START: | ||
551 | case HostCmd_CMD_UAP_BSS_STOP: | ||
552 | ret = mwifiex_uap_prepare_cmd(priv, cmd_no, cmd_action, | ||
553 | cmd_oid, data_buf, | ||
554 | cmd_ptr); | ||
555 | break; | ||
556 | default: | ||
557 | ret = mwifiex_sta_prepare_cmd(priv, cmd_no, cmd_action, | ||
558 | cmd_oid, data_buf, | ||
559 | cmd_ptr); | ||
560 | break; | ||
561 | } | ||
545 | } else { | 562 | } else { |
546 | ret = mwifiex_cmd_host_cmd(priv, cmd_ptr, data_buf); | 563 | ret = mwifiex_cmd_host_cmd(priv, cmd_ptr, data_buf); |
547 | cmd_node->cmd_flag |= CMD_F_HOSTCMD; | 564 | cmd_node->cmd_flag |= CMD_F_HOSTCMD; |
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index d04aba4131dc..f918f66e5e27 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <linux/ieee80211.h> | 28 | #include <linux/ieee80211.h> |
29 | 29 | ||
30 | 30 | ||
31 | #define MWIFIEX_MAX_BSS_NUM (1) | 31 | #define MWIFIEX_MAX_BSS_NUM (2) |
32 | 32 | ||
33 | #define MWIFIEX_MIN_DATA_HEADER_LEN 36 /* sizeof(mwifiex_txpd) | 33 | #define MWIFIEX_MIN_DATA_HEADER_LEN 36 /* sizeof(mwifiex_txpd) |
34 | * + 4 byte alignment | 34 | * + 4 byte alignment |
@@ -55,11 +55,17 @@ | |||
55 | #define MWIFIEX_RX_DATA_BUF_SIZE (4 * 1024) | 55 | #define MWIFIEX_RX_DATA_BUF_SIZE (4 * 1024) |
56 | #define MWIFIEX_RX_CMD_BUF_SIZE (2 * 1024) | 56 | #define MWIFIEX_RX_CMD_BUF_SIZE (2 * 1024) |
57 | 57 | ||
58 | #define MAX_BEACON_PERIOD (4000) | ||
59 | #define MIN_BEACON_PERIOD (50) | ||
60 | #define MAX_DTIM_PERIOD (100) | ||
61 | #define MIN_DTIM_PERIOD (1) | ||
62 | |||
58 | #define MWIFIEX_RTS_MIN_VALUE (0) | 63 | #define MWIFIEX_RTS_MIN_VALUE (0) |
59 | #define MWIFIEX_RTS_MAX_VALUE (2347) | 64 | #define MWIFIEX_RTS_MAX_VALUE (2347) |
60 | #define MWIFIEX_FRAG_MIN_VALUE (256) | 65 | #define MWIFIEX_FRAG_MIN_VALUE (256) |
61 | #define MWIFIEX_FRAG_MAX_VALUE (2346) | 66 | #define MWIFIEX_FRAG_MAX_VALUE (2346) |
62 | 67 | ||
68 | #define MWIFIEX_RETRY_LIMIT 14 | ||
63 | #define MWIFIEX_SDIO_BLOCK_SIZE 256 | 69 | #define MWIFIEX_SDIO_BLOCK_SIZE 256 |
64 | 70 | ||
65 | #define MWIFIEX_BUF_FLAG_REQUEUED_PKT BIT(0) | 71 | #define MWIFIEX_BUF_FLAG_REQUEUED_PKT BIT(0) |
@@ -92,6 +98,11 @@ struct mwifiex_fw_image { | |||
92 | u32 fw_len; | 98 | u32 fw_len; |
93 | }; | 99 | }; |
94 | 100 | ||
101 | struct mwifiex_802_11_ssid { | ||
102 | u32 ssid_len; | ||
103 | u8 ssid[IEEE80211_MAX_SSID_LEN]; | ||
104 | }; | ||
105 | |||
95 | struct mwifiex_wait_queue { | 106 | struct mwifiex_wait_queue { |
96 | wait_queue_head_t wait; | 107 | wait_queue_head_t wait; |
97 | int status; | 108 | int status; |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 5f6adeb9b950..9f674bbebe65 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -93,6 +93,20 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
93 | 93 | ||
94 | #define CAL_SNR(RSSI, NF) ((s16)((s16)(RSSI)-(s16)(NF))) | 94 | #define CAL_SNR(RSSI, NF) ((s16)((s16)(RSSI)-(s16)(NF))) |
95 | 95 | ||
96 | #define UAP_BSS_PARAMS_I 0 | ||
97 | #define UAP_CUSTOM_IE_I 1 | ||
98 | #define MWIFIEX_AUTO_IDX_MASK 0xffff | ||
99 | #define MWIFIEX_DELETE_MASK 0x0000 | ||
100 | #define MGMT_MASK_ASSOC_REQ 0x01 | ||
101 | #define MGMT_MASK_REASSOC_REQ 0x04 | ||
102 | #define MGMT_MASK_ASSOC_RESP 0x02 | ||
103 | #define MGMT_MASK_REASSOC_RESP 0x08 | ||
104 | #define MGMT_MASK_PROBE_REQ 0x10 | ||
105 | #define MGMT_MASK_PROBE_RESP 0x20 | ||
106 | #define MGMT_MASK_BEACON 0x100 | ||
107 | |||
108 | #define TLV_TYPE_UAP_SSID 0x0000 | ||
109 | |||
96 | #define PROPRIETARY_TLV_BASE_ID 0x0100 | 110 | #define PROPRIETARY_TLV_BASE_ID 0x0100 |
97 | #define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) | 111 | #define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) |
98 | #define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1) | 112 | #define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1) |
@@ -104,14 +118,26 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
104 | #define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) | 118 | #define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) |
105 | #define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) | 119 | #define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) |
106 | #define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) | 120 | #define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) |
121 | #define TLV_TYPE_STA_MAC_ADDR (PROPRIETARY_TLV_BASE_ID + 32) | ||
107 | #define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) | 122 | #define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) |
123 | #define TLV_TYPE_UAP_BEACON_PERIOD (PROPRIETARY_TLV_BASE_ID + 44) | ||
124 | #define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45) | ||
125 | #define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51) | ||
126 | #define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60) | ||
127 | #define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64) | ||
128 | #define TLV_TYPE_UAP_AKMP (PROPRIETARY_TLV_BASE_ID + 65) | ||
129 | #define TLV_TYPE_UAP_FRAG_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 70) | ||
108 | #define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82) | 130 | #define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82) |
109 | #define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83) | 131 | #define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83) |
110 | #define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) | 132 | #define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) |
133 | #define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 93) | ||
111 | #define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) | 134 | #define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) |
135 | #define TLV_TYPE_UAP_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 104) | ||
112 | #define TLV_TYPE_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 105) | 136 | #define TLV_TYPE_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 105) |
113 | #define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113) | 137 | #define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113) |
114 | #define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 114) | 138 | #define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 114) |
139 | #define TLV_TYPE_PWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 145) | ||
140 | #define TLV_TYPE_GWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 146) | ||
115 | 141 | ||
116 | #define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 | 142 | #define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 |
117 | 143 | ||
@@ -209,6 +235,9 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
209 | #define HostCmd_CMD_RSSI_INFO 0x00a4 | 235 | #define HostCmd_CMD_RSSI_INFO 0x00a4 |
210 | #define HostCmd_CMD_FUNC_INIT 0x00a9 | 236 | #define HostCmd_CMD_FUNC_INIT 0x00a9 |
211 | #define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa | 237 | #define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa |
238 | #define HostCmd_CMD_UAP_SYS_CONFIG 0x00b0 | ||
239 | #define HostCmd_CMD_UAP_BSS_START 0x00b1 | ||
240 | #define HostCmd_CMD_UAP_BSS_STOP 0x00b2 | ||
212 | #define HostCmd_CMD_11N_CFG 0x00cd | 241 | #define HostCmd_CMD_11N_CFG 0x00cd |
213 | #define HostCmd_CMD_11N_ADDBA_REQ 0x00ce | 242 | #define HostCmd_CMD_11N_ADDBA_REQ 0x00ce |
214 | #define HostCmd_CMD_11N_ADDBA_RSP 0x00cf | 243 | #define HostCmd_CMD_11N_ADDBA_RSP 0x00cf |
@@ -223,6 +252,19 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
223 | #define HostCmd_CMD_SET_BSS_MODE 0x00f7 | 252 | #define HostCmd_CMD_SET_BSS_MODE 0x00f7 |
224 | #define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa | 253 | #define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa |
225 | 254 | ||
255 | #define PROTOCOL_NO_SECURITY 0x01 | ||
256 | #define PROTOCOL_STATIC_WEP 0x02 | ||
257 | #define PROTOCOL_WPA 0x08 | ||
258 | #define PROTOCOL_WPA2 0x20 | ||
259 | #define PROTOCOL_WPA2_MIXED 0x28 | ||
260 | #define PROTOCOL_EAP 0x40 | ||
261 | #define KEY_MGMT_NONE 0x04 | ||
262 | #define KEY_MGMT_PSK 0x02 | ||
263 | #define KEY_MGMT_EAP 0x01 | ||
264 | #define CIPHER_TKIP 0x04 | ||
265 | #define CIPHER_AES_CCMP 0x08 | ||
266 | #define VALID_CIPHER_BITMAP 0x0c | ||
267 | |||
226 | enum ENH_PS_MODES { | 268 | enum ENH_PS_MODES { |
227 | EN_PS = 1, | 269 | EN_PS = 1, |
228 | DIS_PS = 2, | 270 | DIS_PS = 2, |
@@ -313,15 +355,20 @@ enum ENH_PS_MODES { | |||
313 | #define EVENT_DATA_SNR_HIGH 0x00000027 | 355 | #define EVENT_DATA_SNR_HIGH 0x00000027 |
314 | #define EVENT_LINK_QUALITY 0x00000028 | 356 | #define EVENT_LINK_QUALITY 0x00000028 |
315 | #define EVENT_PORT_RELEASE 0x0000002b | 357 | #define EVENT_PORT_RELEASE 0x0000002b |
358 | #define EVENT_UAP_STA_DEAUTH 0x0000002c | ||
359 | #define EVENT_UAP_STA_ASSOC 0x0000002d | ||
360 | #define EVENT_UAP_BSS_START 0x0000002e | ||
316 | #define EVENT_PRE_BEACON_LOST 0x00000031 | 361 | #define EVENT_PRE_BEACON_LOST 0x00000031 |
317 | #define EVENT_ADDBA 0x00000033 | 362 | #define EVENT_ADDBA 0x00000033 |
318 | #define EVENT_DELBA 0x00000034 | 363 | #define EVENT_DELBA 0x00000034 |
319 | #define EVENT_BA_STREAM_TIEMOUT 0x00000037 | 364 | #define EVENT_BA_STREAM_TIEMOUT 0x00000037 |
320 | #define EVENT_AMSDU_AGGR_CTRL 0x00000042 | 365 | #define EVENT_AMSDU_AGGR_CTRL 0x00000042 |
366 | #define EVENT_UAP_BSS_IDLE 0x00000043 | ||
367 | #define EVENT_UAP_BSS_ACTIVE 0x00000044 | ||
321 | #define EVENT_WEP_ICV_ERR 0x00000046 | 368 | #define EVENT_WEP_ICV_ERR 0x00000046 |
322 | #define EVENT_HS_ACT_REQ 0x00000047 | 369 | #define EVENT_HS_ACT_REQ 0x00000047 |
323 | #define EVENT_BW_CHANGE 0x00000048 | 370 | #define EVENT_BW_CHANGE 0x00000048 |
324 | 371 | #define EVENT_UAP_MIC_COUNTERMEASURES 0x0000004c | |
325 | #define EVENT_HOSTWAKE_STAIE 0x0000004d | 372 | #define EVENT_HOSTWAKE_STAIE 0x0000004d |
326 | 373 | ||
327 | #define EVENT_ID_MASK 0xffff | 374 | #define EVENT_ID_MASK 0xffff |
@@ -1103,6 +1150,101 @@ struct host_cmd_ds_802_11_eeprom_access { | |||
1103 | u8 value; | 1150 | u8 value; |
1104 | } __packed; | 1151 | } __packed; |
1105 | 1152 | ||
1153 | struct host_cmd_tlv { | ||
1154 | __le16 type; | ||
1155 | __le16 len; | ||
1156 | } __packed; | ||
1157 | |||
1158 | struct mwifiex_assoc_event { | ||
1159 | u8 sta_addr[ETH_ALEN]; | ||
1160 | __le16 type; | ||
1161 | __le16 len; | ||
1162 | __le16 frame_control; | ||
1163 | __le16 cap_info; | ||
1164 | __le16 listen_interval; | ||
1165 | u8 data[0]; | ||
1166 | } __packed; | ||
1167 | |||
1168 | struct host_cmd_ds_sys_config { | ||
1169 | __le16 action; | ||
1170 | u8 tlv[0]; | ||
1171 | }; | ||
1172 | |||
1173 | struct host_cmd_tlv_akmp { | ||
1174 | struct host_cmd_tlv tlv; | ||
1175 | __le16 key_mgmt; | ||
1176 | __le16 key_mgmt_operation; | ||
1177 | } __packed; | ||
1178 | |||
1179 | struct host_cmd_tlv_pwk_cipher { | ||
1180 | struct host_cmd_tlv tlv; | ||
1181 | __le16 proto; | ||
1182 | u8 cipher; | ||
1183 | u8 reserved; | ||
1184 | } __packed; | ||
1185 | |||
1186 | struct host_cmd_tlv_gwk_cipher { | ||
1187 | struct host_cmd_tlv tlv; | ||
1188 | u8 cipher; | ||
1189 | u8 reserved; | ||
1190 | } __packed; | ||
1191 | |||
1192 | struct host_cmd_tlv_passphrase { | ||
1193 | struct host_cmd_tlv tlv; | ||
1194 | u8 passphrase[0]; | ||
1195 | } __packed; | ||
1196 | |||
1197 | struct host_cmd_tlv_auth_type { | ||
1198 | struct host_cmd_tlv tlv; | ||
1199 | u8 auth_type; | ||
1200 | } __packed; | ||
1201 | |||
1202 | struct host_cmd_tlv_encrypt_protocol { | ||
1203 | struct host_cmd_tlv tlv; | ||
1204 | __le16 proto; | ||
1205 | } __packed; | ||
1206 | |||
1207 | struct host_cmd_tlv_ssid { | ||
1208 | struct host_cmd_tlv tlv; | ||
1209 | u8 ssid[0]; | ||
1210 | } __packed; | ||
1211 | |||
1212 | struct host_cmd_tlv_beacon_period { | ||
1213 | struct host_cmd_tlv tlv; | ||
1214 | __le16 period; | ||
1215 | } __packed; | ||
1216 | |||
1217 | struct host_cmd_tlv_dtim_period { | ||
1218 | struct host_cmd_tlv tlv; | ||
1219 | u8 period; | ||
1220 | } __packed; | ||
1221 | |||
1222 | struct host_cmd_tlv_frag_threshold { | ||
1223 | struct host_cmd_tlv tlv; | ||
1224 | __le16 frag_thr; | ||
1225 | } __packed; | ||
1226 | |||
1227 | struct host_cmd_tlv_rts_threshold { | ||
1228 | struct host_cmd_tlv tlv; | ||
1229 | __le16 rts_thr; | ||
1230 | } __packed; | ||
1231 | |||
1232 | struct host_cmd_tlv_retry_limit { | ||
1233 | struct host_cmd_tlv tlv; | ||
1234 | u8 limit; | ||
1235 | } __packed; | ||
1236 | |||
1237 | struct host_cmd_tlv_mac_addr { | ||
1238 | struct host_cmd_tlv tlv; | ||
1239 | u8 mac_addr[ETH_ALEN]; | ||
1240 | } __packed; | ||
1241 | |||
1242 | struct host_cmd_tlv_channel_band { | ||
1243 | struct host_cmd_tlv tlv; | ||
1244 | u8 band_config; | ||
1245 | u8 channel; | ||
1246 | } __packed; | ||
1247 | |||
1106 | struct host_cmd_ds_802_11_rf_channel { | 1248 | struct host_cmd_ds_802_11_rf_channel { |
1107 | __le16 action; | 1249 | __le16 action; |
1108 | __le16 current_channel; | 1250 | __le16 current_channel; |
@@ -1167,6 +1309,20 @@ struct host_cmd_ds_802_11_subsc_evt { | |||
1167 | __le16 events; | 1309 | __le16 events; |
1168 | } __packed; | 1310 | } __packed; |
1169 | 1311 | ||
1312 | struct mwifiex_ie { | ||
1313 | __le16 ie_index; | ||
1314 | __le16 mgmt_subtype_mask; | ||
1315 | __le16 ie_length; | ||
1316 | u8 ie_buffer[IEEE_MAX_IE_SIZE]; | ||
1317 | } __packed; | ||
1318 | |||
1319 | #define MAX_MGMT_IE_INDEX 16 | ||
1320 | struct mwifiex_ie_list { | ||
1321 | __le16 type; | ||
1322 | __le16 len; | ||
1323 | struct mwifiex_ie ie_list[MAX_MGMT_IE_INDEX]; | ||
1324 | } __packed; | ||
1325 | |||
1170 | struct host_cmd_ds_command { | 1326 | struct host_cmd_ds_command { |
1171 | __le16 command; | 1327 | __le16 command; |
1172 | __le16 size; | 1328 | __le16 size; |
@@ -1217,6 +1373,7 @@ struct host_cmd_ds_command { | |||
1217 | struct host_cmd_ds_pcie_details pcie_host_spec; | 1373 | struct host_cmd_ds_pcie_details pcie_host_spec; |
1218 | struct host_cmd_ds_802_11_eeprom_access eeprom; | 1374 | struct host_cmd_ds_802_11_eeprom_access eeprom; |
1219 | struct host_cmd_ds_802_11_subsc_evt subsc_evt; | 1375 | struct host_cmd_ds_802_11_subsc_evt subsc_evt; |
1376 | struct host_cmd_ds_sys_config uap_sys_config; | ||
1220 | } params; | 1377 | } params; |
1221 | } __packed; | 1378 | } __packed; |
1222 | 1379 | ||
diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c new file mode 100644 index 000000000000..ceb82cd749cc --- /dev/null +++ b/drivers/net/wireless/mwifiex/ie.c | |||
@@ -0,0 +1,396 @@ | |||
1 | /* | ||
2 | * Marvell Wireless LAN device driver: management IE handling- setting and | ||
3 | * deleting IE. | ||
4 | * | ||
5 | * Copyright (C) 2012, Marvell International Ltd. | ||
6 | * | ||
7 | * This software file (the "File") is distributed by Marvell International | ||
8 | * Ltd. under the terms of the GNU General Public License Version 2, June 1991 | ||
9 | * (the "License"). You may use, redistribute and/or modify this File in | ||
10 | * accordance with the terms and conditions of the License, a copy of which | ||
11 | * is available by writing to the Free Software Foundation, Inc., | ||
12 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the | ||
13 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. | ||
14 | * | ||
15 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE | ||
16 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | ||
17 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about | ||
18 | * this warranty disclaimer. | ||
19 | */ | ||
20 | |||
21 | #include "main.h" | ||
22 | |||
23 | /* This function checks if current IE index is used by any on other interface. | ||
24 | * Return: -1: yes, current IE index is used by someone else. | ||
25 | * 0: no, current IE index is NOT used by other interface. | ||
26 | */ | ||
27 | static int | ||
28 | mwifiex_ie_index_used_by_other_intf(struct mwifiex_private *priv, u16 idx) | ||
29 | { | ||
30 | int i; | ||
31 | struct mwifiex_adapter *adapter = priv->adapter; | ||
32 | struct mwifiex_ie *ie; | ||
33 | |||
34 | for (i = 0; i < adapter->priv_num; i++) { | ||
35 | if (adapter->priv[i] != priv) { | ||
36 | ie = &adapter->priv[i]->mgmt_ie[idx]; | ||
37 | if (ie->mgmt_subtype_mask && ie->ie_length) | ||
38 | return -1; | ||
39 | } | ||
40 | } | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | /* Get unused IE index. This index will be used for setting new IE */ | ||
46 | static int | ||
47 | mwifiex_ie_get_autoidx(struct mwifiex_private *priv, u16 subtype_mask, | ||
48 | struct mwifiex_ie *ie, u16 *index) | ||
49 | { | ||
50 | u16 mask, len, i; | ||
51 | |||
52 | for (i = 0; i < priv->adapter->max_mgmt_ie_index; i++) { | ||
53 | mask = le16_to_cpu(priv->mgmt_ie[i].mgmt_subtype_mask); | ||
54 | len = le16_to_cpu(priv->mgmt_ie[i].ie_length) + | ||
55 | le16_to_cpu(ie->ie_length); | ||
56 | |||
57 | if (mask == MWIFIEX_AUTO_IDX_MASK) | ||
58 | continue; | ||
59 | |||
60 | if (mask == subtype_mask) { | ||
61 | if (len > IEEE_MAX_IE_SIZE) | ||
62 | continue; | ||
63 | |||
64 | *index = i; | ||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | if (!priv->mgmt_ie[i].ie_length) { | ||
69 | if (mwifiex_ie_index_used_by_other_intf(priv, i)) | ||
70 | continue; | ||
71 | |||
72 | *index = i; | ||
73 | return 0; | ||
74 | } | ||
75 | } | ||
76 | |||
77 | return -1; | ||
78 | } | ||
79 | |||
80 | /* This function prepares IE data buffer for command to be sent to FW */ | ||
81 | static int | ||
82 | mwifiex_update_autoindex_ies(struct mwifiex_private *priv, | ||
83 | struct mwifiex_ie_list *ie_list) | ||
84 | { | ||
85 | u16 travel_len, index, mask; | ||
86 | s16 input_len; | ||
87 | struct mwifiex_ie *ie; | ||
88 | u8 *tmp; | ||
89 | |||
90 | input_len = le16_to_cpu(ie_list->len); | ||
91 | travel_len = sizeof(struct host_cmd_tlv); | ||
92 | |||
93 | ie_list->len = 0; | ||
94 | |||
95 | while (input_len > 0) { | ||
96 | ie = (struct mwifiex_ie *)(((u8 *)ie_list) + travel_len); | ||
97 | input_len -= le16_to_cpu(ie->ie_length) + MWIFIEX_IE_HDR_SIZE; | ||
98 | travel_len += le16_to_cpu(ie->ie_length) + MWIFIEX_IE_HDR_SIZE; | ||
99 | |||
100 | index = le16_to_cpu(ie->ie_index); | ||
101 | mask = le16_to_cpu(ie->mgmt_subtype_mask); | ||
102 | |||
103 | if (index == MWIFIEX_AUTO_IDX_MASK) { | ||
104 | /* automatic addition */ | ||
105 | if (mwifiex_ie_get_autoidx(priv, mask, ie, &index)) | ||
106 | return -1; | ||
107 | if (index == MWIFIEX_AUTO_IDX_MASK) | ||
108 | return -1; | ||
109 | |||
110 | tmp = (u8 *)&priv->mgmt_ie[index].ie_buffer; | ||
111 | tmp += le16_to_cpu(priv->mgmt_ie[index].ie_length); | ||
112 | memcpy(tmp, &ie->ie_buffer, le16_to_cpu(ie->ie_length)); | ||
113 | le16_add_cpu(&priv->mgmt_ie[index].ie_length, | ||
114 | le16_to_cpu(ie->ie_length)); | ||
115 | priv->mgmt_ie[index].ie_index = cpu_to_le16(index); | ||
116 | priv->mgmt_ie[index].mgmt_subtype_mask = | ||
117 | cpu_to_le16(mask); | ||
118 | |||
119 | ie->ie_index = cpu_to_le16(index); | ||
120 | ie->ie_length = priv->mgmt_ie[index].ie_length; | ||
121 | memcpy(&ie->ie_buffer, &priv->mgmt_ie[index].ie_buffer, | ||
122 | le16_to_cpu(priv->mgmt_ie[index].ie_length)); | ||
123 | } else { | ||
124 | if (mask != MWIFIEX_DELETE_MASK) | ||
125 | return -1; | ||
126 | /* | ||
127 | * Check if this index is being used on any | ||
128 | * other interface. | ||
129 | */ | ||
130 | if (mwifiex_ie_index_used_by_other_intf(priv, index)) | ||
131 | return -1; | ||
132 | |||
133 | ie->ie_length = 0; | ||
134 | memcpy(&priv->mgmt_ie[index], ie, | ||
135 | sizeof(struct mwifiex_ie)); | ||
136 | } | ||
137 | |||
138 | le16_add_cpu(&ie_list->len, | ||
139 | le16_to_cpu(priv->mgmt_ie[index].ie_length) + | ||
140 | MWIFIEX_IE_HDR_SIZE); | ||
141 | } | ||
142 | |||
143 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) | ||
144 | return mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG, | ||
145 | HostCmd_ACT_GEN_SET, | ||
146 | UAP_CUSTOM_IE_I, ie_list); | ||
147 | |||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | /* Copy individual custom IEs for beacon, probe response and assoc response | ||
152 | * and prepare single structure for IE setting. | ||
153 | * This function also updates allocated IE indices from driver. | ||
154 | */ | ||
155 | static int | ||
156 | mwifiex_update_uap_custom_ie(struct mwifiex_private *priv, | ||
157 | struct mwifiex_ie *beacon_ie, u16 *beacon_idx, | ||
158 | struct mwifiex_ie *pr_ie, u16 *probe_idx, | ||
159 | struct mwifiex_ie *ar_ie, u16 *assoc_idx) | ||
160 | { | ||
161 | struct mwifiex_ie_list *ap_custom_ie; | ||
162 | u8 *pos; | ||
163 | u16 len; | ||
164 | int ret; | ||
165 | |||
166 | ap_custom_ie = kzalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
167 | if (!ap_custom_ie) | ||
168 | return -ENOMEM; | ||
169 | |||
170 | ap_custom_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE); | ||
171 | pos = (u8 *)ap_custom_ie->ie_list; | ||
172 | |||
173 | if (beacon_ie) { | ||
174 | len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE + | ||
175 | le16_to_cpu(beacon_ie->ie_length); | ||
176 | memcpy(pos, beacon_ie, len); | ||
177 | pos += len; | ||
178 | le16_add_cpu(&ap_custom_ie->len, len); | ||
179 | } | ||
180 | if (pr_ie) { | ||
181 | len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE + | ||
182 | le16_to_cpu(pr_ie->ie_length); | ||
183 | memcpy(pos, pr_ie, len); | ||
184 | pos += len; | ||
185 | le16_add_cpu(&ap_custom_ie->len, len); | ||
186 | } | ||
187 | if (ar_ie) { | ||
188 | len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE + | ||
189 | le16_to_cpu(ar_ie->ie_length); | ||
190 | memcpy(pos, ar_ie, len); | ||
191 | pos += len; | ||
192 | le16_add_cpu(&ap_custom_ie->len, len); | ||
193 | } | ||
194 | |||
195 | ret = mwifiex_update_autoindex_ies(priv, ap_custom_ie); | ||
196 | |||
197 | pos = (u8 *)(&ap_custom_ie->ie_list[0].ie_index); | ||
198 | if (beacon_ie && *beacon_idx == MWIFIEX_AUTO_IDX_MASK) { | ||
199 | /* save beacon ie index after auto-indexing */ | ||
200 | *beacon_idx = le16_to_cpu(ap_custom_ie->ie_list[0].ie_index); | ||
201 | len = sizeof(*beacon_ie) - IEEE_MAX_IE_SIZE + | ||
202 | le16_to_cpu(beacon_ie->ie_length); | ||
203 | pos += len; | ||
204 | } | ||
205 | if (pr_ie && le16_to_cpu(pr_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK) { | ||
206 | /* save probe resp ie index after auto-indexing */ | ||
207 | *probe_idx = *((u16 *)pos); | ||
208 | len = sizeof(*pr_ie) - IEEE_MAX_IE_SIZE + | ||
209 | le16_to_cpu(pr_ie->ie_length); | ||
210 | pos += len; | ||
211 | } | ||
212 | if (ar_ie && le16_to_cpu(ar_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK) | ||
213 | /* save assoc resp ie index after auto-indexing */ | ||
214 | *assoc_idx = *((u16 *)pos); | ||
215 | |||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | /* This function parses different IEs- Tail IEs, beacon IEs, probe response IEs, | ||
220 | * association response IEs from cfg80211_ap_settings function and sets these IE | ||
221 | * to FW. | ||
222 | */ | ||
223 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | ||
224 | struct cfg80211_ap_settings *params) | ||
225 | { | ||
226 | struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL; | ||
227 | struct mwifiex_ie *ar_ie = NULL, *rsn_ie = NULL; | ||
228 | struct ieee_types_header *ie = NULL; | ||
229 | u16 beacon_idx = MWIFIEX_AUTO_IDX_MASK, pr_idx = MWIFIEX_AUTO_IDX_MASK; | ||
230 | u16 ar_idx = MWIFIEX_AUTO_IDX_MASK, rsn_idx = MWIFIEX_AUTO_IDX_MASK; | ||
231 | u16 mask; | ||
232 | int ret = 0; | ||
233 | |||
234 | if (params->beacon.tail && params->beacon.tail_len) { | ||
235 | ie = (void *)cfg80211_find_ie(WLAN_EID_RSN, params->beacon.tail, | ||
236 | params->beacon.tail_len); | ||
237 | if (ie) { | ||
238 | rsn_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
239 | if (!rsn_ie) | ||
240 | return -ENOMEM; | ||
241 | |||
242 | rsn_ie->ie_index = cpu_to_le16(rsn_idx); | ||
243 | mask = MGMT_MASK_BEACON | MGMT_MASK_PROBE_RESP | | ||
244 | MGMT_MASK_ASSOC_RESP; | ||
245 | rsn_ie->mgmt_subtype_mask = cpu_to_le16(mask); | ||
246 | rsn_ie->ie_length = cpu_to_le16(ie->len + 2); | ||
247 | memcpy(rsn_ie->ie_buffer, ie, ie->len + 2); | ||
248 | |||
249 | if (mwifiex_update_uap_custom_ie(priv, rsn_ie, &rsn_idx, | ||
250 | NULL, NULL, | ||
251 | NULL, NULL)) { | ||
252 | ret = -1; | ||
253 | goto done; | ||
254 | } | ||
255 | |||
256 | priv->rsn_idx = rsn_idx; | ||
257 | } | ||
258 | } | ||
259 | |||
260 | if (params->beacon.beacon_ies && params->beacon.beacon_ies_len) { | ||
261 | beacon_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
262 | if (!beacon_ie) { | ||
263 | ret = -ENOMEM; | ||
264 | goto done; | ||
265 | } | ||
266 | |||
267 | beacon_ie->ie_index = cpu_to_le16(beacon_idx); | ||
268 | beacon_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON); | ||
269 | beacon_ie->ie_length = | ||
270 | cpu_to_le16(params->beacon.beacon_ies_len); | ||
271 | memcpy(beacon_ie->ie_buffer, params->beacon.beacon_ies, | ||
272 | params->beacon.beacon_ies_len); | ||
273 | } | ||
274 | |||
275 | if (params->beacon.proberesp_ies && params->beacon.proberesp_ies_len) { | ||
276 | pr_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
277 | if (!pr_ie) { | ||
278 | ret = -ENOMEM; | ||
279 | goto done; | ||
280 | } | ||
281 | |||
282 | pr_ie->ie_index = cpu_to_le16(pr_idx); | ||
283 | pr_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_PROBE_RESP); | ||
284 | pr_ie->ie_length = | ||
285 | cpu_to_le16(params->beacon.proberesp_ies_len); | ||
286 | memcpy(pr_ie->ie_buffer, params->beacon.proberesp_ies, | ||
287 | params->beacon.proberesp_ies_len); | ||
288 | } | ||
289 | |||
290 | if (params->beacon.assocresp_ies && params->beacon.assocresp_ies_len) { | ||
291 | ar_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
292 | if (!ar_ie) { | ||
293 | ret = -ENOMEM; | ||
294 | goto done; | ||
295 | } | ||
296 | |||
297 | ar_ie->ie_index = cpu_to_le16(ar_idx); | ||
298 | mask = MGMT_MASK_ASSOC_RESP | MGMT_MASK_REASSOC_RESP; | ||
299 | ar_ie->mgmt_subtype_mask = cpu_to_le16(mask); | ||
300 | ar_ie->ie_length = | ||
301 | cpu_to_le16(params->beacon.assocresp_ies_len); | ||
302 | memcpy(ar_ie->ie_buffer, params->beacon.assocresp_ies, | ||
303 | params->beacon.assocresp_ies_len); | ||
304 | } | ||
305 | |||
306 | if (beacon_ie || pr_ie || ar_ie) { | ||
307 | ret = mwifiex_update_uap_custom_ie(priv, beacon_ie, | ||
308 | &beacon_idx, pr_ie, | ||
309 | &pr_idx, ar_ie, &ar_idx); | ||
310 | if (ret) | ||
311 | goto done; | ||
312 | } | ||
313 | |||
314 | priv->beacon_idx = beacon_idx; | ||
315 | priv->proberesp_idx = pr_idx; | ||
316 | priv->assocresp_idx = ar_idx; | ||
317 | |||
318 | done: | ||
319 | kfree(beacon_ie); | ||
320 | kfree(pr_ie); | ||
321 | kfree(ar_ie); | ||
322 | kfree(rsn_ie); | ||
323 | |||
324 | return ret; | ||
325 | } | ||
326 | |||
327 | /* This function removes management IE set */ | ||
328 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv) | ||
329 | { | ||
330 | struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL; | ||
331 | struct mwifiex_ie *ar_ie = NULL, *rsn_ie = NULL; | ||
332 | int ret = 0; | ||
333 | |||
334 | if (priv->rsn_idx != MWIFIEX_AUTO_IDX_MASK) { | ||
335 | rsn_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
336 | if (!rsn_ie) | ||
337 | return -ENOMEM; | ||
338 | |||
339 | rsn_ie->ie_index = cpu_to_le16(priv->rsn_idx); | ||
340 | rsn_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK); | ||
341 | rsn_ie->ie_length = 0; | ||
342 | if (mwifiex_update_uap_custom_ie(priv, rsn_ie, &priv->rsn_idx, | ||
343 | NULL, &priv->proberesp_idx, | ||
344 | NULL, &priv->assocresp_idx)) { | ||
345 | ret = -1; | ||
346 | goto done; | ||
347 | } | ||
348 | |||
349 | priv->rsn_idx = MWIFIEX_AUTO_IDX_MASK; | ||
350 | } | ||
351 | |||
352 | if (priv->beacon_idx != MWIFIEX_AUTO_IDX_MASK) { | ||
353 | beacon_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
354 | if (!beacon_ie) { | ||
355 | ret = -ENOMEM; | ||
356 | goto done; | ||
357 | } | ||
358 | beacon_ie->ie_index = cpu_to_le16(priv->beacon_idx); | ||
359 | beacon_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK); | ||
360 | beacon_ie->ie_length = 0; | ||
361 | } | ||
362 | if (priv->proberesp_idx != MWIFIEX_AUTO_IDX_MASK) { | ||
363 | pr_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
364 | if (!pr_ie) { | ||
365 | ret = -ENOMEM; | ||
366 | goto done; | ||
367 | } | ||
368 | pr_ie->ie_index = cpu_to_le16(priv->proberesp_idx); | ||
369 | pr_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK); | ||
370 | pr_ie->ie_length = 0; | ||
371 | } | ||
372 | if (priv->assocresp_idx != MWIFIEX_AUTO_IDX_MASK) { | ||
373 | ar_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); | ||
374 | if (!ar_ie) { | ||
375 | ret = -ENOMEM; | ||
376 | goto done; | ||
377 | } | ||
378 | ar_ie->ie_index = cpu_to_le16(priv->assocresp_idx); | ||
379 | ar_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK); | ||
380 | ar_ie->ie_length = 0; | ||
381 | } | ||
382 | |||
383 | if (beacon_ie || pr_ie || ar_ie) | ||
384 | ret = mwifiex_update_uap_custom_ie(priv, | ||
385 | beacon_ie, &priv->beacon_idx, | ||
386 | pr_ie, &priv->proberesp_idx, | ||
387 | ar_ie, &priv->assocresp_idx); | ||
388 | |||
389 | done: | ||
390 | kfree(beacon_ie); | ||
391 | kfree(pr_ie); | ||
392 | kfree(ar_ie); | ||
393 | kfree(rsn_ie); | ||
394 | |||
395 | return ret; | ||
396 | } | ||
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index d440c3eb640b..c1cb004db913 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -279,6 +279,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) | |||
279 | memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); | 279 | memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); |
280 | adapter->arp_filter_size = 0; | 280 | adapter->arp_filter_size = 0; |
281 | adapter->channel_type = NL80211_CHAN_HT20; | 281 | adapter->channel_type = NL80211_CHAN_HT20; |
282 | adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX; | ||
282 | } | 283 | } |
283 | 284 | ||
284 | /* | 285 | /* |
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index f0f95524e96b..e6be6ee75951 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h | |||
@@ -62,6 +62,36 @@ enum { | |||
62 | BAND_AN = 16, | 62 | BAND_AN = 16, |
63 | }; | 63 | }; |
64 | 64 | ||
65 | #define MWIFIEX_WPA_PASSHPHRASE_LEN 64 | ||
66 | struct wpa_param { | ||
67 | u8 pairwise_cipher_wpa; | ||
68 | u8 pairwise_cipher_wpa2; | ||
69 | u8 group_cipher; | ||
70 | u32 length; | ||
71 | u8 passphrase[MWIFIEX_WPA_PASSHPHRASE_LEN]; | ||
72 | }; | ||
73 | |||
74 | #define KEY_MGMT_ON_HOST 0x03 | ||
75 | #define MWIFIEX_AUTH_MODE_AUTO 0xFF | ||
76 | #define BAND_CONFIG_MANUAL 0x00 | ||
77 | struct mwifiex_uap_bss_param { | ||
78 | u8 channel; | ||
79 | u8 band_cfg; | ||
80 | u16 rts_threshold; | ||
81 | u16 frag_threshold; | ||
82 | u8 retry_limit; | ||
83 | struct mwifiex_802_11_ssid ssid; | ||
84 | u8 bcast_ssid_ctl; | ||
85 | u8 radio_ctl; | ||
86 | u8 dtim_period; | ||
87 | u16 beacon_period; | ||
88 | u16 auth_mode; | ||
89 | u16 protocol; | ||
90 | u16 key_mgmt; | ||
91 | u16 key_mgmt_operation; | ||
92 | struct wpa_param wpa_cfg; | ||
93 | }; | ||
94 | |||
65 | enum { | 95 | enum { |
66 | ADHOC_IDLE, | 96 | ADHOC_IDLE, |
67 | ADHOC_STARTED, | 97 | ADHOC_STARTED, |
@@ -269,6 +299,8 @@ struct mwifiex_ds_read_eeprom { | |||
269 | 299 | ||
270 | #define IEEE_MAX_IE_SIZE 256 | 300 | #define IEEE_MAX_IE_SIZE 256 |
271 | 301 | ||
302 | #define MWIFIEX_IE_HDR_SIZE (sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE) | ||
303 | |||
272 | struct mwifiex_ds_misc_gen_ie { | 304 | struct mwifiex_ds_misc_gen_ie { |
273 | u32 type; | 305 | u32 type; |
274 | u32 len; | 306 | u32 len; |
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 8a390982463e..d6b4fb04011f 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c | |||
@@ -1374,22 +1374,28 @@ static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac) | |||
1374 | * | 1374 | * |
1375 | * In case of infra made, it sends deauthentication request, and | 1375 | * In case of infra made, it sends deauthentication request, and |
1376 | * in case of ad-hoc mode, a stop network request is sent to the firmware. | 1376 | * in case of ad-hoc mode, a stop network request is sent to the firmware. |
1377 | * In AP mode, a command to stop bss is sent to firmware. | ||
1377 | */ | 1378 | */ |
1378 | int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac) | 1379 | int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac) |
1379 | { | 1380 | { |
1380 | int ret = 0; | 1381 | if (!priv->media_connected) |
1382 | return 0; | ||
1381 | 1383 | ||
1382 | if (priv->media_connected) { | 1384 | switch (priv->bss_mode) { |
1383 | if (priv->bss_mode == NL80211_IFTYPE_STATION) { | 1385 | case NL80211_IFTYPE_STATION: |
1384 | ret = mwifiex_deauthenticate_infra(priv, mac); | 1386 | return mwifiex_deauthenticate_infra(priv, mac); |
1385 | } else if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { | 1387 | case NL80211_IFTYPE_ADHOC: |
1386 | ret = mwifiex_send_cmd_sync(priv, | 1388 | return mwifiex_send_cmd_sync(priv, |
1387 | HostCmd_CMD_802_11_AD_HOC_STOP, | 1389 | HostCmd_CMD_802_11_AD_HOC_STOP, |
1388 | HostCmd_ACT_GEN_SET, 0, NULL); | 1390 | HostCmd_ACT_GEN_SET, 0, NULL); |
1389 | } | 1391 | case NL80211_IFTYPE_AP: |
1392 | return mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, | ||
1393 | HostCmd_ACT_GEN_SET, 0, NULL); | ||
1394 | default: | ||
1395 | break; | ||
1390 | } | 1396 | } |
1391 | 1397 | ||
1392 | return ret; | 1398 | return 0; |
1393 | } | 1399 | } |
1394 | EXPORT_SYMBOL_GPL(mwifiex_deauthenticate); | 1400 | EXPORT_SYMBOL_GPL(mwifiex_deauthenticate); |
1395 | 1401 | ||
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index be0f0e583f75..3192855c31c0 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -64,17 +64,17 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, | |||
64 | 64 | ||
65 | adapter->priv_num = 0; | 65 | adapter->priv_num = 0; |
66 | 66 | ||
67 | /* Allocate memory for private structure */ | 67 | for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) { |
68 | adapter->priv[0] = kzalloc(sizeof(struct mwifiex_private), GFP_KERNEL); | 68 | /* Allocate memory for private structure */ |
69 | if (!adapter->priv[0]) { | 69 | adapter->priv[i] = |
70 | dev_err(adapter->dev, | 70 | kzalloc(sizeof(struct mwifiex_private), GFP_KERNEL); |
71 | "%s: failed to alloc priv[0]\n", __func__); | 71 | if (!adapter->priv[i]) |
72 | goto error; | 72 | goto error; |
73 | } | ||
74 | |||
75 | adapter->priv_num++; | ||
76 | 73 | ||
77 | adapter->priv[0]->adapter = adapter; | 74 | adapter->priv[i]->adapter = adapter; |
75 | adapter->priv[i]->bss_priority = i; | ||
76 | adapter->priv_num++; | ||
77 | } | ||
78 | mwifiex_init_lock_list(adapter); | 78 | mwifiex_init_lock_list(adapter); |
79 | 79 | ||
80 | init_timer(&adapter->cmd_timer); | 80 | init_timer(&adapter->cmd_timer); |
@@ -349,19 +349,26 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) | |||
349 | if (adapter->hw_status != MWIFIEX_HW_STATUS_READY) | 349 | if (adapter->hw_status != MWIFIEX_HW_STATUS_READY) |
350 | goto done; | 350 | goto done; |
351 | 351 | ||
352 | priv = adapter->priv[0]; | 352 | priv = adapter->priv[MWIFIEX_BSS_ROLE_STA]; |
353 | if (mwifiex_register_cfg80211(priv) != 0) { | 353 | if (mwifiex_register_cfg80211(adapter)) { |
354 | dev_err(adapter->dev, "cannot register with cfg80211\n"); | 354 | dev_err(adapter->dev, "cannot register with cfg80211\n"); |
355 | goto err_init_fw; | 355 | goto err_init_fw; |
356 | } | 356 | } |
357 | 357 | ||
358 | rtnl_lock(); | 358 | rtnl_lock(); |
359 | /* Create station interface by default */ | 359 | /* Create station interface by default */ |
360 | if (!mwifiex_add_virtual_intf(priv->wdev->wiphy, "mlan%d", | 360 | if (!mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", |
361 | NL80211_IFTYPE_STATION, NULL, NULL)) { | 361 | NL80211_IFTYPE_STATION, NULL, NULL)) { |
362 | dev_err(adapter->dev, "cannot create default STA interface\n"); | 362 | dev_err(adapter->dev, "cannot create default STA interface\n"); |
363 | goto err_add_intf; | 363 | goto err_add_intf; |
364 | } | 364 | } |
365 | |||
366 | /* Create AP interface by default */ | ||
367 | if (!mwifiex_add_virtual_intf(adapter->wiphy, "uap%d", | ||
368 | NL80211_IFTYPE_AP, NULL, NULL)) { | ||
369 | dev_err(adapter->dev, "cannot create default AP interface\n"); | ||
370 | goto err_add_intf; | ||
371 | } | ||
365 | rtnl_unlock(); | 372 | rtnl_unlock(); |
366 | 373 | ||
367 | mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); | 374 | mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); |
@@ -369,7 +376,7 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) | |||
369 | goto done; | 376 | goto done; |
370 | 377 | ||
371 | err_add_intf: | 378 | err_add_intf: |
372 | mwifiex_del_virtual_intf(priv->wdev->wiphy, priv->netdev); | 379 | mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev); |
373 | rtnl_unlock(); | 380 | rtnl_unlock(); |
374 | err_init_fw: | 381 | err_init_fw: |
375 | pr_debug("info: %s: unregister device\n", __func__); | 382 | pr_debug("info: %s: unregister device\n", __func__); |
@@ -633,6 +640,12 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv, | |||
633 | priv->current_key_index = 0; | 640 | priv->current_key_index = 0; |
634 | priv->media_connected = false; | 641 | priv->media_connected = false; |
635 | memset(&priv->nick_name, 0, sizeof(priv->nick_name)); | 642 | memset(&priv->nick_name, 0, sizeof(priv->nick_name)); |
643 | memset(priv->mgmt_ie, 0, | ||
644 | sizeof(struct mwifiex_ie) * MAX_MGMT_IE_INDEX); | ||
645 | priv->beacon_idx = MWIFIEX_AUTO_IDX_MASK; | ||
646 | priv->proberesp_idx = MWIFIEX_AUTO_IDX_MASK; | ||
647 | priv->assocresp_idx = MWIFIEX_AUTO_IDX_MASK; | ||
648 | priv->rsn_idx = MWIFIEX_AUTO_IDX_MASK; | ||
636 | priv->num_tx_timeout = 0; | 649 | priv->num_tx_timeout = 0; |
637 | memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); | 650 | memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); |
638 | } | 651 | } |
@@ -830,19 +843,21 @@ int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) | |||
830 | 843 | ||
831 | rtnl_lock(); | 844 | rtnl_lock(); |
832 | if (priv->wdev && priv->netdev) | 845 | if (priv->wdev && priv->netdev) |
833 | mwifiex_del_virtual_intf(priv->wdev->wiphy, | 846 | mwifiex_del_virtual_intf(adapter->wiphy, priv->netdev); |
834 | priv->netdev); | ||
835 | rtnl_unlock(); | 847 | rtnl_unlock(); |
836 | } | 848 | } |
837 | 849 | ||
838 | priv = adapter->priv[0]; | 850 | priv = adapter->priv[0]; |
839 | if (!priv) | 851 | if (!priv || !priv->wdev) |
840 | goto exit_remove; | 852 | goto exit_remove; |
841 | 853 | ||
842 | if (priv->wdev) { | 854 | wiphy_unregister(priv->wdev->wiphy); |
843 | wiphy_unregister(priv->wdev->wiphy); | 855 | wiphy_free(priv->wdev->wiphy); |
844 | wiphy_free(priv->wdev->wiphy); | 856 | |
845 | kfree(priv->wdev); | 857 | for (i = 0; i < adapter->priv_num; i++) { |
858 | priv = adapter->priv[i]; | ||
859 | if (priv) | ||
860 | kfree(priv->wdev); | ||
846 | } | 861 | } |
847 | 862 | ||
848 | mwifiex_terminate_workqueue(adapter); | 863 | mwifiex_terminate_workqueue(adapter); |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 324ad390cacd..bd3b0bf94b9e 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -116,6 +116,7 @@ enum { | |||
116 | #define MAX_FREQUENCY_BAND_BG 2484 | 116 | #define MAX_FREQUENCY_BAND_BG 2484 |
117 | 117 | ||
118 | #define MWIFIEX_EVENT_HEADER_LEN 4 | 118 | #define MWIFIEX_EVENT_HEADER_LEN 4 |
119 | #define MWIFIEX_UAP_EVENT_EXTRA_HEADER 2 | ||
119 | 120 | ||
120 | #define MWIFIEX_TYPE_LEN 4 | 121 | #define MWIFIEX_TYPE_LEN 4 |
121 | #define MWIFIEX_USB_TYPE_CMD 0xF00DFACE | 122 | #define MWIFIEX_USB_TYPE_CMD 0xF00DFACE |
@@ -370,6 +371,7 @@ struct mwifiex_private { | |||
370 | u8 bss_role; | 371 | u8 bss_role; |
371 | u8 bss_priority; | 372 | u8 bss_priority; |
372 | u8 bss_num; | 373 | u8 bss_num; |
374 | u8 bss_started; | ||
373 | u8 frame_type; | 375 | u8 frame_type; |
374 | u8 curr_addr[ETH_ALEN]; | 376 | u8 curr_addr[ETH_ALEN]; |
375 | u8 media_connected; | 377 | u8 media_connected; |
@@ -470,12 +472,16 @@ struct mwifiex_private { | |||
470 | struct cfg80211_scan_request *scan_request; | 472 | struct cfg80211_scan_request *scan_request; |
471 | struct mwifiex_user_scan_cfg *user_scan_cfg; | 473 | struct mwifiex_user_scan_cfg *user_scan_cfg; |
472 | u8 cfg_bssid[6]; | 474 | u8 cfg_bssid[6]; |
473 | u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; | ||
474 | struct wps wps; | 475 | struct wps wps; |
475 | u8 scan_block; | 476 | u8 scan_block; |
476 | s32 cqm_rssi_thold; | 477 | s32 cqm_rssi_thold; |
477 | u32 cqm_rssi_hyst; | 478 | u32 cqm_rssi_hyst; |
478 | u8 subsc_evt_rssi_state; | 479 | u8 subsc_evt_rssi_state; |
480 | struct mwifiex_ie mgmt_ie[MAX_MGMT_IE_INDEX]; | ||
481 | u16 beacon_idx; | ||
482 | u16 proberesp_idx; | ||
483 | u16 assocresp_idx; | ||
484 | u16 rsn_idx; | ||
479 | }; | 485 | }; |
480 | 486 | ||
481 | enum mwifiex_ba_status { | 487 | enum mwifiex_ba_status { |
@@ -571,6 +577,7 @@ struct mwifiex_adapter { | |||
571 | char fw_name[32]; | 577 | char fw_name[32]; |
572 | int winner; | 578 | int winner; |
573 | struct device *dev; | 579 | struct device *dev; |
580 | struct wiphy *wiphy; | ||
574 | bool surprise_removed; | 581 | bool surprise_removed; |
575 | u32 fw_release_number; | 582 | u32 fw_release_number; |
576 | u16 init_wait_q_woken; | 583 | u16 init_wait_q_woken; |
@@ -677,6 +684,8 @@ struct mwifiex_adapter { | |||
677 | struct cmd_ctrl_node *cmd_queued; | 684 | struct cmd_ctrl_node *cmd_queued; |
678 | spinlock_t queue_lock; /* lock for tx queues */ | 685 | spinlock_t queue_lock; /* lock for tx queues */ |
679 | struct completion fw_load; | 686 | struct completion fw_load; |
687 | u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; | ||
688 | u16 max_mgmt_ie_index; | ||
680 | }; | 689 | }; |
681 | 690 | ||
682 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); | 691 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); |
@@ -760,6 +769,9 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, | |||
760 | int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no, | 769 | int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no, |
761 | u16 cmd_action, u32 cmd_oid, | 770 | u16 cmd_action, u32 cmd_oid, |
762 | void *data_buf, void *cmd_buf); | 771 | void *data_buf, void *cmd_buf); |
772 | int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | ||
773 | u16 cmd_action, u32 cmd_oid, | ||
774 | void *data_buf, void *cmd_buf); | ||
763 | int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no, | 775 | int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no, |
764 | struct host_cmd_ds_command *resp); | 776 | struct host_cmd_ds_command *resp); |
765 | int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *, | 777 | int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *, |
@@ -820,6 +832,9 @@ int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, | |||
820 | int is_command_pending(struct mwifiex_adapter *adapter); | 832 | int is_command_pending(struct mwifiex_adapter *adapter); |
821 | void mwifiex_init_priv_params(struct mwifiex_private *priv, | 833 | void mwifiex_init_priv_params(struct mwifiex_private *priv, |
822 | struct net_device *dev); | 834 | struct net_device *dev); |
835 | int mwifiex_set_secure_params(struct mwifiex_private *priv, | ||
836 | struct mwifiex_uap_bss_param *bss_config, | ||
837 | struct cfg80211_ap_settings *params); | ||
823 | 838 | ||
824 | /* | 839 | /* |
825 | * This function checks if the queuing is RA based or not. | 840 | * This function checks if the queuing is RA based or not. |
@@ -933,7 +948,8 @@ int mwifiex_set_radio(struct mwifiex_private *priv, u8 option); | |||
933 | int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel); | 948 | int mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, u16 channel); |
934 | 949 | ||
935 | int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, | 950 | int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, |
936 | int key_len, u8 key_index, int disable); | 951 | int key_len, u8 key_index, const u8 *mac_addr, |
952 | int disable); | ||
937 | 953 | ||
938 | int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len); | 954 | int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len); |
939 | 955 | ||
@@ -969,6 +985,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, | |||
969 | 985 | ||
970 | int mwifiex_main_process(struct mwifiex_adapter *); | 986 | int mwifiex_main_process(struct mwifiex_adapter *); |
971 | 987 | ||
988 | int mwifiex_uap_set_channel(struct mwifiex_private *priv, int channel); | ||
972 | int mwifiex_bss_set_channel(struct mwifiex_private *, | 989 | int mwifiex_bss_set_channel(struct mwifiex_private *, |
973 | struct mwifiex_chan_freq_power *cfp); | 990 | struct mwifiex_chan_freq_power *cfp); |
974 | int mwifiex_get_bss_info(struct mwifiex_private *, | 991 | int mwifiex_get_bss_info(struct mwifiex_private *, |
@@ -986,6 +1003,11 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
986 | u32 *flags, struct vif_params *params); | 1003 | u32 *flags, struct vif_params *params); |
987 | int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev); | 1004 | int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev); |
988 | 1005 | ||
1006 | void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config); | ||
1007 | |||
1008 | int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, | ||
1009 | struct cfg80211_ap_settings *params); | ||
1010 | int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); | ||
989 | u8 *mwifiex_11d_code_2_region(u8 code); | 1011 | u8 *mwifiex_11d_code_2_region(u8 code); |
990 | 1012 | ||
991 | #ifdef CONFIG_DEBUG_FS | 1013 | #ifdef CONFIG_DEBUG_FS |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 87ed2a1f6cd9..40e025da6bc2 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -498,7 +498,8 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, | |||
498 | { | 498 | { |
499 | struct host_cmd_ds_802_11_key_material *key_material = | 499 | struct host_cmd_ds_802_11_key_material *key_material = |
500 | &cmd->params.key_material; | 500 | &cmd->params.key_material; |
501 | u16 key_param_len = 0; | 501 | struct host_cmd_tlv_mac_addr *tlv_mac; |
502 | u16 key_param_len = 0, cmd_size; | ||
502 | int ret = 0; | 503 | int ret = 0; |
503 | const u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | 504 | const u8 bc_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
504 | 505 | ||
@@ -614,11 +615,26 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, | |||
614 | cpu_to_le16((u16) enc_key->key_len + | 615 | cpu_to_le16((u16) enc_key->key_len + |
615 | KEYPARAMSET_FIXED_LEN); | 616 | KEYPARAMSET_FIXED_LEN); |
616 | 617 | ||
617 | key_param_len = (u16) (enc_key->key_len + KEYPARAMSET_FIXED_LEN) | 618 | key_param_len = (u16)(enc_key->key_len + KEYPARAMSET_FIXED_LEN) |
618 | + sizeof(struct mwifiex_ie_types_header); | 619 | + sizeof(struct mwifiex_ie_types_header); |
619 | 620 | ||
620 | cmd->size = cpu_to_le16(sizeof(key_material->action) + S_DS_GEN | 621 | cmd->size = cpu_to_le16(sizeof(key_material->action) + S_DS_GEN |
621 | + key_param_len); | 622 | + key_param_len); |
623 | |||
624 | if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) { | ||
625 | tlv_mac = (void *)((u8 *)&key_material->key_param_set + | ||
626 | key_param_len); | ||
627 | tlv_mac->tlv.type = cpu_to_le16(TLV_TYPE_STA_MAC_ADDR); | ||
628 | tlv_mac->tlv.len = cpu_to_le16(ETH_ALEN); | ||
629 | memcpy(tlv_mac->mac_addr, enc_key->mac_addr, ETH_ALEN); | ||
630 | cmd_size = key_param_len + S_DS_GEN + | ||
631 | sizeof(key_material->action) + | ||
632 | sizeof(struct host_cmd_tlv_mac_addr); | ||
633 | } else { | ||
634 | cmd_size = key_param_len + S_DS_GEN + | ||
635 | sizeof(key_material->action); | ||
636 | } | ||
637 | cmd->size = cpu_to_le16(cmd_size); | ||
622 | } | 638 | } |
623 | 639 | ||
624 | return ret; | 640 | return ret; |
@@ -1248,13 +1264,15 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
1248 | if (ret) | 1264 | if (ret) |
1249 | return -1; | 1265 | return -1; |
1250 | 1266 | ||
1251 | /* Enable IEEE PS by default */ | 1267 | if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { |
1252 | priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; | 1268 | /* Enable IEEE PS by default */ |
1253 | ret = mwifiex_send_cmd_async(priv, | 1269 | priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; |
1254 | HostCmd_CMD_802_11_PS_MODE_ENH, | 1270 | ret = mwifiex_send_cmd_async( |
1255 | EN_AUTO_PS, BITMAP_STA_PS, NULL); | 1271 | priv, HostCmd_CMD_802_11_PS_MODE_ENH, |
1256 | if (ret) | 1272 | EN_AUTO_PS, BITMAP_STA_PS, NULL); |
1257 | return -1; | 1273 | if (ret) |
1274 | return -1; | ||
1275 | } | ||
1258 | } | 1276 | } |
1259 | 1277 | ||
1260 | /* get tx rate */ | 1278 | /* get tx rate */ |
@@ -1270,12 +1288,14 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
1270 | if (ret) | 1288 | if (ret) |
1271 | return -1; | 1289 | return -1; |
1272 | 1290 | ||
1273 | /* set ibss coalescing_status */ | 1291 | if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) { |
1274 | ret = mwifiex_send_cmd_async(priv, | 1292 | /* set ibss coalescing_status */ |
1275 | HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, | 1293 | ret = mwifiex_send_cmd_async( |
1276 | HostCmd_ACT_GEN_SET, 0, &enable); | 1294 | priv, HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, |
1277 | if (ret) | 1295 | HostCmd_ACT_GEN_SET, 0, &enable); |
1278 | return -1; | 1296 | if (ret) |
1297 | return -1; | ||
1298 | } | ||
1279 | 1299 | ||
1280 | memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl)); | 1300 | memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl)); |
1281 | amsdu_aggr_ctrl.enable = true; | 1301 | amsdu_aggr_ctrl.enable = true; |
@@ -1293,7 +1313,8 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
1293 | if (ret) | 1313 | if (ret) |
1294 | return -1; | 1314 | return -1; |
1295 | 1315 | ||
1296 | if (first_sta && (priv->adapter->iface_type != MWIFIEX_USB)) { | 1316 | if (first_sta && priv->adapter->iface_type != MWIFIEX_USB && |
1317 | priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { | ||
1297 | /* Enable auto deep sleep */ | 1318 | /* Enable auto deep sleep */ |
1298 | auto_ds.auto_ds = DEEP_SLEEP_ON; | 1319 | auto_ds.auto_ds = DEEP_SLEEP_ON; |
1299 | auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME; | 1320 | auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME; |
@@ -1305,12 +1326,16 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | |||
1305 | return -1; | 1326 | return -1; |
1306 | } | 1327 | } |
1307 | 1328 | ||
1308 | /* Send cmd to FW to enable/disable 11D function */ | 1329 | if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { |
1309 | state_11d = ENABLE_11D; | 1330 | /* Send cmd to FW to enable/disable 11D function */ |
1310 | ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SNMP_MIB, | 1331 | state_11d = ENABLE_11D; |
1311 | HostCmd_ACT_GEN_SET, DOT11D_I, &state_11d); | 1332 | ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SNMP_MIB, |
1312 | if (ret) | 1333 | HostCmd_ACT_GEN_SET, DOT11D_I, |
1313 | dev_err(priv->adapter->dev, "11D: failed to enable 11D\n"); | 1334 | &state_11d); |
1335 | if (ret) | ||
1336 | dev_err(priv->adapter->dev, | ||
1337 | "11D: failed to enable 11D\n"); | ||
1338 | } | ||
1314 | 1339 | ||
1315 | /* Send cmd to FW to configure 11n specific configuration | 1340 | /* Send cmd to FW to configure 11n specific configuration |
1316 | * (Short GI, Channel BW, Green field support etc.) for transmit | 1341 | * (Short GI, Channel BW, Green field support etc.) for transmit |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 3aa54243dea9..a79ed9bd9695 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -944,6 +944,14 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
944 | case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: | 944 | case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: |
945 | ret = mwifiex_ret_subsc_evt(priv, resp, data_buf); | 945 | ret = mwifiex_ret_subsc_evt(priv, resp, data_buf); |
946 | break; | 946 | break; |
947 | case HostCmd_CMD_UAP_SYS_CONFIG: | ||
948 | break; | ||
949 | case HostCmd_CMD_UAP_BSS_START: | ||
950 | priv->bss_started = 1; | ||
951 | break; | ||
952 | case HostCmd_CMD_UAP_BSS_STOP: | ||
953 | priv->bss_started = 0; | ||
954 | break; | ||
947 | default: | 955 | default: |
948 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", | 956 | dev_err(adapter->dev, "CMD_RESP: unknown cmd response %#x\n", |
949 | resp->command); | 957 | resp->command); |
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index f6bbb9307f86..4ace5a3dcd23 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c | |||
@@ -184,8 +184,10 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv) | |||
184 | int mwifiex_process_sta_event(struct mwifiex_private *priv) | 184 | int mwifiex_process_sta_event(struct mwifiex_private *priv) |
185 | { | 185 | { |
186 | struct mwifiex_adapter *adapter = priv->adapter; | 186 | struct mwifiex_adapter *adapter = priv->adapter; |
187 | int ret = 0; | 187 | int len, ret = 0; |
188 | u32 eventcause = adapter->event_cause; | 188 | u32 eventcause = adapter->event_cause; |
189 | struct station_info sinfo; | ||
190 | struct mwifiex_assoc_event *event; | ||
189 | 191 | ||
190 | switch (eventcause) { | 192 | switch (eventcause) { |
191 | case EVENT_DUMMY_HOST_WAKEUP_SIGNAL: | 193 | case EVENT_DUMMY_HOST_WAKEUP_SIGNAL: |
@@ -402,6 +404,53 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) | |||
402 | case EVENT_HOSTWAKE_STAIE: | 404 | case EVENT_HOSTWAKE_STAIE: |
403 | dev_dbg(adapter->dev, "event: HOSTWAKE_STAIE %d\n", eventcause); | 405 | dev_dbg(adapter->dev, "event: HOSTWAKE_STAIE %d\n", eventcause); |
404 | break; | 406 | break; |
407 | |||
408 | case EVENT_UAP_STA_ASSOC: | ||
409 | skb_pull(adapter->event_skb, MWIFIEX_UAP_EVENT_EXTRA_HEADER); | ||
410 | memset(&sinfo, 0, sizeof(sinfo)); | ||
411 | event = (struct mwifiex_assoc_event *)adapter->event_skb->data; | ||
412 | if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) { | ||
413 | len = -1; | ||
414 | |||
415 | if (ieee80211_is_assoc_req(event->frame_control)) | ||
416 | len = 0; | ||
417 | else if (ieee80211_is_reassoc_req(event->frame_control)) | ||
418 | /* There will be ETH_ALEN bytes of | ||
419 | * current_ap_addr before the re-assoc ies. | ||
420 | */ | ||
421 | len = ETH_ALEN; | ||
422 | |||
423 | if (len != -1) { | ||
424 | sinfo.filled = STATION_INFO_ASSOC_REQ_IES; | ||
425 | sinfo.assoc_req_ies = (u8 *)&event->data[len]; | ||
426 | len = (u8 *)sinfo.assoc_req_ies - | ||
427 | (u8 *)&event->frame_control; | ||
428 | sinfo.assoc_req_ies_len = | ||
429 | le16_to_cpu(event->len) - (u16)len; | ||
430 | } | ||
431 | } | ||
432 | cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo, | ||
433 | GFP_KERNEL); | ||
434 | break; | ||
435 | case EVENT_UAP_STA_DEAUTH: | ||
436 | skb_pull(adapter->event_skb, MWIFIEX_UAP_EVENT_EXTRA_HEADER); | ||
437 | cfg80211_del_sta(priv->netdev, adapter->event_skb->data, | ||
438 | GFP_KERNEL); | ||
439 | break; | ||
440 | case EVENT_UAP_BSS_IDLE: | ||
441 | priv->media_connected = false; | ||
442 | break; | ||
443 | case EVENT_UAP_BSS_ACTIVE: | ||
444 | priv->media_connected = true; | ||
445 | break; | ||
446 | case EVENT_UAP_BSS_START: | ||
447 | dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause); | ||
448 | memcpy(priv->netdev->dev_addr, adapter->event_body+2, ETH_ALEN); | ||
449 | break; | ||
450 | case EVENT_UAP_MIC_COUNTERMEASURES: | ||
451 | /* For future development */ | ||
452 | dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause); | ||
453 | break; | ||
405 | default: | 454 | default: |
406 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", | 455 | dev_dbg(adapter->dev, "event: unknown event id: %#x\n", |
407 | eventcause); | 456 | eventcause); |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 58970e0f7d13..106c449477b2 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -462,7 +462,7 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv, | |||
462 | 462 | ||
463 | info->bss_chan = bss_desc->channel; | 463 | info->bss_chan = bss_desc->channel; |
464 | 464 | ||
465 | memcpy(info->country_code, priv->country_code, | 465 | memcpy(info->country_code, adapter->country_code, |
466 | IEEE80211_COUNTRY_STRING_LEN); | 466 | IEEE80211_COUNTRY_STRING_LEN); |
467 | 467 | ||
468 | info->media_connected = priv->media_connected; | 468 | info->media_connected = priv->media_connected; |
@@ -1219,7 +1219,8 @@ mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version, | |||
1219 | * with requisite parameters and calls the IOCTL handler. | 1219 | * with requisite parameters and calls the IOCTL handler. |
1220 | */ | 1220 | */ |
1221 | int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, | 1221 | int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, |
1222 | int key_len, u8 key_index, int disable) | 1222 | int key_len, u8 key_index, |
1223 | const u8 *mac_addr, int disable) | ||
1223 | { | 1224 | { |
1224 | struct mwifiex_ds_encrypt_key encrypt_key; | 1225 | struct mwifiex_ds_encrypt_key encrypt_key; |
1225 | 1226 | ||
@@ -1229,8 +1230,12 @@ int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key, | |||
1229 | encrypt_key.key_index = key_index; | 1230 | encrypt_key.key_index = key_index; |
1230 | if (key_len) | 1231 | if (key_len) |
1231 | memcpy(encrypt_key.key_material, key, key_len); | 1232 | memcpy(encrypt_key.key_material, key, key_len); |
1233 | if (mac_addr) | ||
1234 | memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); | ||
1232 | } else { | 1235 | } else { |
1233 | encrypt_key.key_disable = true; | 1236 | encrypt_key.key_disable = true; |
1237 | if (mac_addr) | ||
1238 | memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); | ||
1234 | } | 1239 | } |
1235 | 1240 | ||
1236 | return mwifiex_sec_ioctl_encrypt_key(priv, &encrypt_key); | 1241 | return mwifiex_sec_ioctl_encrypt_key(priv, &encrypt_key); |
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c new file mode 100644 index 000000000000..76dfbc42a732 --- /dev/null +++ b/drivers/net/wireless/mwifiex/uap_cmd.c | |||
@@ -0,0 +1,432 @@ | |||
1 | /* | ||
2 | * Marvell Wireless LAN device driver: AP specific command handling | ||
3 | * | ||
4 | * Copyright (C) 2012, Marvell International Ltd. | ||
5 | * | ||
6 | * This software file (the "File") is distributed by Marvell International | ||
7 | * Ltd. under the terms of the GNU General Public License Version 2, June 1991 | ||
8 | * (the "License"). You may use, redistribute and/or modify this File in | ||
9 | * accordance with the terms and conditions of the License, a copy of which | ||
10 | * is available by writing to the Free Software Foundation, Inc., | ||
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the | ||
12 | * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. | ||
13 | * | ||
14 | * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE | ||
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE | ||
16 | * ARE EXPRESSLY DISCLAIMED. The License provides additional details about | ||
17 | * this warranty disclaimer. | ||
18 | */ | ||
19 | |||
20 | #include "main.h" | ||
21 | |||
22 | /* This function parses security related parameters from cfg80211_ap_settings | ||
23 | * and sets into FW understandable bss_config structure. | ||
24 | */ | ||
25 | int mwifiex_set_secure_params(struct mwifiex_private *priv, | ||
26 | struct mwifiex_uap_bss_param *bss_config, | ||
27 | struct cfg80211_ap_settings *params) { | ||
28 | int i; | ||
29 | |||
30 | switch (params->auth_type) { | ||
31 | case NL80211_AUTHTYPE_OPEN_SYSTEM: | ||
32 | bss_config->auth_mode = WLAN_AUTH_OPEN; | ||
33 | break; | ||
34 | case NL80211_AUTHTYPE_SHARED_KEY: | ||
35 | bss_config->auth_mode = WLAN_AUTH_SHARED_KEY; | ||
36 | break; | ||
37 | case NL80211_AUTHTYPE_NETWORK_EAP: | ||
38 | bss_config->auth_mode = WLAN_AUTH_LEAP; | ||
39 | break; | ||
40 | default: | ||
41 | bss_config->auth_mode = MWIFIEX_AUTH_MODE_AUTO; | ||
42 | break; | ||
43 | } | ||
44 | |||
45 | bss_config->key_mgmt_operation |= KEY_MGMT_ON_HOST; | ||
46 | |||
47 | for (i = 0; i < params->crypto.n_akm_suites; i++) { | ||
48 | switch (params->crypto.akm_suites[i]) { | ||
49 | case WLAN_AKM_SUITE_8021X: | ||
50 | if (params->crypto.wpa_versions & | ||
51 | NL80211_WPA_VERSION_1) { | ||
52 | bss_config->protocol = PROTOCOL_WPA; | ||
53 | bss_config->key_mgmt = KEY_MGMT_EAP; | ||
54 | } | ||
55 | if (params->crypto.wpa_versions & | ||
56 | NL80211_WPA_VERSION_2) { | ||
57 | bss_config->protocol = PROTOCOL_WPA2; | ||
58 | bss_config->key_mgmt = KEY_MGMT_EAP; | ||
59 | } | ||
60 | break; | ||
61 | case WLAN_AKM_SUITE_PSK: | ||
62 | if (params->crypto.wpa_versions & | ||
63 | NL80211_WPA_VERSION_1) { | ||
64 | bss_config->protocol = PROTOCOL_WPA; | ||
65 | bss_config->key_mgmt = KEY_MGMT_PSK; | ||
66 | } | ||
67 | if (params->crypto.wpa_versions & | ||
68 | NL80211_WPA_VERSION_2) { | ||
69 | bss_config->protocol = PROTOCOL_WPA2; | ||
70 | bss_config->key_mgmt = KEY_MGMT_PSK; | ||
71 | } | ||
72 | break; | ||
73 | default: | ||
74 | break; | ||
75 | } | ||
76 | } | ||
77 | for (i = 0; i < params->crypto.n_ciphers_pairwise; i++) { | ||
78 | switch (params->crypto.ciphers_pairwise[i]) { | ||
79 | case WLAN_CIPHER_SUITE_WEP40: | ||
80 | case WLAN_CIPHER_SUITE_WEP104: | ||
81 | break; | ||
82 | case WLAN_CIPHER_SUITE_TKIP: | ||
83 | bss_config->wpa_cfg.pairwise_cipher_wpa = CIPHER_TKIP; | ||
84 | break; | ||
85 | case WLAN_CIPHER_SUITE_CCMP: | ||
86 | bss_config->wpa_cfg.pairwise_cipher_wpa2 = | ||
87 | CIPHER_AES_CCMP; | ||
88 | default: | ||
89 | break; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | switch (params->crypto.cipher_group) { | ||
94 | case WLAN_CIPHER_SUITE_WEP40: | ||
95 | case WLAN_CIPHER_SUITE_WEP104: | ||
96 | break; | ||
97 | case WLAN_CIPHER_SUITE_TKIP: | ||
98 | bss_config->wpa_cfg.group_cipher = CIPHER_TKIP; | ||
99 | break; | ||
100 | case WLAN_CIPHER_SUITE_CCMP: | ||
101 | bss_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP; | ||
102 | break; | ||
103 | default: | ||
104 | break; | ||
105 | } | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | /* This function initializes some of mwifiex_uap_bss_param variables. | ||
111 | * This helps FW in ignoring invalid values. These values may or may not | ||
112 | * be get updated to valid ones at later stage. | ||
113 | */ | ||
114 | void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config) | ||
115 | { | ||
116 | config->bcast_ssid_ctl = 0x7F; | ||
117 | config->radio_ctl = 0x7F; | ||
118 | config->dtim_period = 0x7F; | ||
119 | config->beacon_period = 0x7FFF; | ||
120 | config->auth_mode = 0x7F; | ||
121 | config->rts_threshold = 0x7FFF; | ||
122 | config->frag_threshold = 0x7FFF; | ||
123 | config->retry_limit = 0x7F; | ||
124 | } | ||
125 | |||
126 | /* This function parses BSS related parameters from structure | ||
127 | * and prepares TLVs. These TLVs are appended to command buffer. | ||
128 | */ | ||
129 | static int | ||
130 | mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) | ||
131 | { | ||
132 | struct host_cmd_tlv_dtim_period *dtim_period; | ||
133 | struct host_cmd_tlv_beacon_period *beacon_period; | ||
134 | struct host_cmd_tlv_ssid *ssid; | ||
135 | struct host_cmd_tlv_channel_band *chan_band; | ||
136 | struct host_cmd_tlv_frag_threshold *frag_threshold; | ||
137 | struct host_cmd_tlv_rts_threshold *rts_threshold; | ||
138 | struct host_cmd_tlv_retry_limit *retry_limit; | ||
139 | struct host_cmd_tlv_pwk_cipher *pwk_cipher; | ||
140 | struct host_cmd_tlv_gwk_cipher *gwk_cipher; | ||
141 | struct host_cmd_tlv_encrypt_protocol *encrypt_protocol; | ||
142 | struct host_cmd_tlv_auth_type *auth_type; | ||
143 | struct host_cmd_tlv_passphrase *passphrase; | ||
144 | struct host_cmd_tlv_akmp *tlv_akmp; | ||
145 | struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; | ||
146 | u16 cmd_size = *param_size; | ||
147 | |||
148 | if (bss_cfg->ssid.ssid_len) { | ||
149 | ssid = (struct host_cmd_tlv_ssid *)tlv; | ||
150 | ssid->tlv.type = cpu_to_le16(TLV_TYPE_UAP_SSID); | ||
151 | ssid->tlv.len = cpu_to_le16((u16)bss_cfg->ssid.ssid_len); | ||
152 | memcpy(ssid->ssid, bss_cfg->ssid.ssid, bss_cfg->ssid.ssid_len); | ||
153 | cmd_size += sizeof(struct host_cmd_tlv) + | ||
154 | bss_cfg->ssid.ssid_len; | ||
155 | tlv += sizeof(struct host_cmd_tlv) + bss_cfg->ssid.ssid_len; | ||
156 | } | ||
157 | if (bss_cfg->channel && bss_cfg->channel <= MAX_CHANNEL_BAND_BG) { | ||
158 | chan_band = (struct host_cmd_tlv_channel_band *)tlv; | ||
159 | chan_band->tlv.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST); | ||
160 | chan_band->tlv.len = | ||
161 | cpu_to_le16(sizeof(struct host_cmd_tlv_channel_band) - | ||
162 | sizeof(struct host_cmd_tlv)); | ||
163 | chan_band->band_config = bss_cfg->band_cfg; | ||
164 | chan_band->channel = bss_cfg->channel; | ||
165 | cmd_size += sizeof(struct host_cmd_tlv_channel_band); | ||
166 | tlv += sizeof(struct host_cmd_tlv_channel_band); | ||
167 | } | ||
168 | if (bss_cfg->beacon_period >= MIN_BEACON_PERIOD && | ||
169 | bss_cfg->beacon_period <= MAX_BEACON_PERIOD) { | ||
170 | beacon_period = (struct host_cmd_tlv_beacon_period *)tlv; | ||
171 | beacon_period->tlv.type = | ||
172 | cpu_to_le16(TLV_TYPE_UAP_BEACON_PERIOD); | ||
173 | beacon_period->tlv.len = | ||
174 | cpu_to_le16(sizeof(struct host_cmd_tlv_beacon_period) - | ||
175 | sizeof(struct host_cmd_tlv)); | ||
176 | beacon_period->period = cpu_to_le16(bss_cfg->beacon_period); | ||
177 | cmd_size += sizeof(struct host_cmd_tlv_beacon_period); | ||
178 | tlv += sizeof(struct host_cmd_tlv_beacon_period); | ||
179 | } | ||
180 | if (bss_cfg->dtim_period >= MIN_DTIM_PERIOD && | ||
181 | bss_cfg->dtim_period <= MAX_DTIM_PERIOD) { | ||
182 | dtim_period = (struct host_cmd_tlv_dtim_period *)tlv; | ||
183 | dtim_period->tlv.type = cpu_to_le16(TLV_TYPE_UAP_DTIM_PERIOD); | ||
184 | dtim_period->tlv.len = | ||
185 | cpu_to_le16(sizeof(struct host_cmd_tlv_dtim_period) - | ||
186 | sizeof(struct host_cmd_tlv)); | ||
187 | dtim_period->period = bss_cfg->dtim_period; | ||
188 | cmd_size += sizeof(struct host_cmd_tlv_dtim_period); | ||
189 | tlv += sizeof(struct host_cmd_tlv_dtim_period); | ||
190 | } | ||
191 | if (bss_cfg->rts_threshold <= MWIFIEX_RTS_MAX_VALUE) { | ||
192 | rts_threshold = (struct host_cmd_tlv_rts_threshold *)tlv; | ||
193 | rts_threshold->tlv.type = | ||
194 | cpu_to_le16(TLV_TYPE_UAP_RTS_THRESHOLD); | ||
195 | rts_threshold->tlv.len = | ||
196 | cpu_to_le16(sizeof(struct host_cmd_tlv_rts_threshold) - | ||
197 | sizeof(struct host_cmd_tlv)); | ||
198 | rts_threshold->rts_thr = cpu_to_le16(bss_cfg->rts_threshold); | ||
199 | cmd_size += sizeof(struct host_cmd_tlv_frag_threshold); | ||
200 | tlv += sizeof(struct host_cmd_tlv_frag_threshold); | ||
201 | } | ||
202 | if ((bss_cfg->frag_threshold >= MWIFIEX_FRAG_MIN_VALUE) && | ||
203 | (bss_cfg->frag_threshold <= MWIFIEX_FRAG_MAX_VALUE)) { | ||
204 | frag_threshold = (struct host_cmd_tlv_frag_threshold *)tlv; | ||
205 | frag_threshold->tlv.type = | ||
206 | cpu_to_le16(TLV_TYPE_UAP_FRAG_THRESHOLD); | ||
207 | frag_threshold->tlv.len = | ||
208 | cpu_to_le16(sizeof(struct host_cmd_tlv_frag_threshold) - | ||
209 | sizeof(struct host_cmd_tlv)); | ||
210 | frag_threshold->frag_thr = cpu_to_le16(bss_cfg->frag_threshold); | ||
211 | cmd_size += sizeof(struct host_cmd_tlv_frag_threshold); | ||
212 | tlv += sizeof(struct host_cmd_tlv_frag_threshold); | ||
213 | } | ||
214 | if (bss_cfg->retry_limit <= MWIFIEX_RETRY_LIMIT) { | ||
215 | retry_limit = (struct host_cmd_tlv_retry_limit *)tlv; | ||
216 | retry_limit->tlv.type = cpu_to_le16(TLV_TYPE_UAP_RETRY_LIMIT); | ||
217 | retry_limit->tlv.len = | ||
218 | cpu_to_le16(sizeof(struct host_cmd_tlv_retry_limit) - | ||
219 | sizeof(struct host_cmd_tlv)); | ||
220 | retry_limit->limit = (u8)bss_cfg->retry_limit; | ||
221 | cmd_size += sizeof(struct host_cmd_tlv_retry_limit); | ||
222 | tlv += sizeof(struct host_cmd_tlv_retry_limit); | ||
223 | } | ||
224 | if ((bss_cfg->protocol & PROTOCOL_WPA) || | ||
225 | (bss_cfg->protocol & PROTOCOL_WPA2) || | ||
226 | (bss_cfg->protocol & PROTOCOL_EAP)) { | ||
227 | tlv_akmp = (struct host_cmd_tlv_akmp *)tlv; | ||
228 | tlv_akmp->tlv.type = cpu_to_le16(TLV_TYPE_UAP_AKMP); | ||
229 | tlv_akmp->tlv.len = | ||
230 | cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) - | ||
231 | sizeof(struct host_cmd_tlv)); | ||
232 | tlv_akmp->key_mgmt_operation = | ||
233 | cpu_to_le16(bss_cfg->key_mgmt_operation); | ||
234 | tlv_akmp->key_mgmt = cpu_to_le16(bss_cfg->key_mgmt); | ||
235 | cmd_size += sizeof(struct host_cmd_tlv_akmp); | ||
236 | tlv += sizeof(struct host_cmd_tlv_akmp); | ||
237 | |||
238 | if (bss_cfg->wpa_cfg.pairwise_cipher_wpa & | ||
239 | VALID_CIPHER_BITMAP) { | ||
240 | pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv; | ||
241 | pwk_cipher->tlv.type = | ||
242 | cpu_to_le16(TLV_TYPE_PWK_CIPHER); | ||
243 | pwk_cipher->tlv.len = cpu_to_le16( | ||
244 | sizeof(struct host_cmd_tlv_pwk_cipher) - | ||
245 | sizeof(struct host_cmd_tlv)); | ||
246 | pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA); | ||
247 | pwk_cipher->cipher = | ||
248 | bss_cfg->wpa_cfg.pairwise_cipher_wpa; | ||
249 | cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher); | ||
250 | tlv += sizeof(struct host_cmd_tlv_pwk_cipher); | ||
251 | } | ||
252 | if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 & | ||
253 | VALID_CIPHER_BITMAP) { | ||
254 | pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv; | ||
255 | pwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER); | ||
256 | pwk_cipher->tlv.len = cpu_to_le16( | ||
257 | sizeof(struct host_cmd_tlv_pwk_cipher) - | ||
258 | sizeof(struct host_cmd_tlv)); | ||
259 | pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA2); | ||
260 | pwk_cipher->cipher = | ||
261 | bss_cfg->wpa_cfg.pairwise_cipher_wpa2; | ||
262 | cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher); | ||
263 | tlv += sizeof(struct host_cmd_tlv_pwk_cipher); | ||
264 | } | ||
265 | if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) { | ||
266 | gwk_cipher = (struct host_cmd_tlv_gwk_cipher *)tlv; | ||
267 | gwk_cipher->tlv.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER); | ||
268 | gwk_cipher->tlv.len = cpu_to_le16( | ||
269 | sizeof(struct host_cmd_tlv_gwk_cipher) - | ||
270 | sizeof(struct host_cmd_tlv)); | ||
271 | gwk_cipher->cipher = bss_cfg->wpa_cfg.group_cipher; | ||
272 | cmd_size += sizeof(struct host_cmd_tlv_gwk_cipher); | ||
273 | tlv += sizeof(struct host_cmd_tlv_gwk_cipher); | ||
274 | } | ||
275 | if (bss_cfg->wpa_cfg.length) { | ||
276 | passphrase = (struct host_cmd_tlv_passphrase *)tlv; | ||
277 | passphrase->tlv.type = | ||
278 | cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE); | ||
279 | passphrase->tlv.len = | ||
280 | cpu_to_le16(bss_cfg->wpa_cfg.length); | ||
281 | memcpy(passphrase->passphrase, | ||
282 | bss_cfg->wpa_cfg.passphrase, | ||
283 | bss_cfg->wpa_cfg.length); | ||
284 | cmd_size += sizeof(struct host_cmd_tlv) + | ||
285 | bss_cfg->wpa_cfg.length; | ||
286 | tlv += sizeof(struct host_cmd_tlv) + | ||
287 | bss_cfg->wpa_cfg.length; | ||
288 | } | ||
289 | } | ||
290 | if ((bss_cfg->auth_mode <= WLAN_AUTH_SHARED_KEY) || | ||
291 | (bss_cfg->auth_mode == MWIFIEX_AUTH_MODE_AUTO)) { | ||
292 | auth_type = (struct host_cmd_tlv_auth_type *)tlv; | ||
293 | auth_type->tlv.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); | ||
294 | auth_type->tlv.len = | ||
295 | cpu_to_le16(sizeof(struct host_cmd_tlv_auth_type) - | ||
296 | sizeof(struct host_cmd_tlv)); | ||
297 | auth_type->auth_type = (u8)bss_cfg->auth_mode; | ||
298 | cmd_size += sizeof(struct host_cmd_tlv_auth_type); | ||
299 | tlv += sizeof(struct host_cmd_tlv_auth_type); | ||
300 | } | ||
301 | if (bss_cfg->protocol) { | ||
302 | encrypt_protocol = (struct host_cmd_tlv_encrypt_protocol *)tlv; | ||
303 | encrypt_protocol->tlv.type = | ||
304 | cpu_to_le16(TLV_TYPE_UAP_ENCRY_PROTOCOL); | ||
305 | encrypt_protocol->tlv.len = | ||
306 | cpu_to_le16(sizeof(struct host_cmd_tlv_encrypt_protocol) | ||
307 | - sizeof(struct host_cmd_tlv)); | ||
308 | encrypt_protocol->proto = cpu_to_le16(bss_cfg->protocol); | ||
309 | cmd_size += sizeof(struct host_cmd_tlv_encrypt_protocol); | ||
310 | tlv += sizeof(struct host_cmd_tlv_encrypt_protocol); | ||
311 | } | ||
312 | |||
313 | *param_size = cmd_size; | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | /* This function parses custom IEs from IE list and prepares command buffer */ | ||
319 | static int mwifiex_uap_custom_ie_prepare(u8 *tlv, void *cmd_buf, u16 *ie_size) | ||
320 | { | ||
321 | struct mwifiex_ie_list *ap_ie = cmd_buf; | ||
322 | struct host_cmd_tlv *tlv_ie = (struct host_cmd_tlv *)tlv; | ||
323 | |||
324 | if (!ap_ie || !ap_ie->len || !ap_ie->ie_list) | ||
325 | return -1; | ||
326 | |||
327 | *ie_size += le16_to_cpu(ap_ie->len) + sizeof(struct host_cmd_tlv); | ||
328 | |||
329 | tlv_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE); | ||
330 | tlv_ie->len = ap_ie->len; | ||
331 | tlv += sizeof(struct host_cmd_tlv); | ||
332 | |||
333 | memcpy(tlv, ap_ie->ie_list, le16_to_cpu(ap_ie->len)); | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | /* Parse AP config structure and prepare TLV based command structure | ||
339 | * to be sent to FW for uAP configuration | ||
340 | */ | ||
341 | static int | ||
342 | mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, u16 cmd_action, | ||
343 | u32 type, void *cmd_buf) | ||
344 | { | ||
345 | u8 *tlv; | ||
346 | u16 cmd_size, param_size, ie_size; | ||
347 | struct host_cmd_ds_sys_config *sys_cfg; | ||
348 | |||
349 | cmd->command = cpu_to_le16(HostCmd_CMD_UAP_SYS_CONFIG); | ||
350 | cmd_size = (u16)(sizeof(struct host_cmd_ds_sys_config) + S_DS_GEN); | ||
351 | sys_cfg = (struct host_cmd_ds_sys_config *)&cmd->params.uap_sys_config; | ||
352 | sys_cfg->action = cpu_to_le16(cmd_action); | ||
353 | tlv = sys_cfg->tlv; | ||
354 | |||
355 | switch (type) { | ||
356 | case UAP_BSS_PARAMS_I: | ||
357 | param_size = cmd_size; | ||
358 | if (mwifiex_uap_bss_param_prepare(tlv, cmd_buf, ¶m_size)) | ||
359 | return -1; | ||
360 | cmd->size = cpu_to_le16(param_size); | ||
361 | break; | ||
362 | case UAP_CUSTOM_IE_I: | ||
363 | ie_size = cmd_size; | ||
364 | if (mwifiex_uap_custom_ie_prepare(tlv, cmd_buf, &ie_size)) | ||
365 | return -1; | ||
366 | cmd->size = cpu_to_le16(ie_size); | ||
367 | break; | ||
368 | default: | ||
369 | return -1; | ||
370 | } | ||
371 | |||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | /* This function prepares the AP specific commands before sending them | ||
376 | * to the firmware. | ||
377 | * This is a generic function which calls specific command preparation | ||
378 | * routines based upon the command number. | ||
379 | */ | ||
380 | int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no, | ||
381 | u16 cmd_action, u32 type, | ||
382 | void *data_buf, void *cmd_buf) | ||
383 | { | ||
384 | struct host_cmd_ds_command *cmd = cmd_buf; | ||
385 | |||
386 | switch (cmd_no) { | ||
387 | case HostCmd_CMD_UAP_SYS_CONFIG: | ||
388 | if (mwifiex_cmd_uap_sys_config(cmd, cmd_action, type, data_buf)) | ||
389 | return -1; | ||
390 | break; | ||
391 | case HostCmd_CMD_UAP_BSS_START: | ||
392 | case HostCmd_CMD_UAP_BSS_STOP: | ||
393 | cmd->command = cpu_to_le16(cmd_no); | ||
394 | cmd->size = cpu_to_le16(S_DS_GEN); | ||
395 | break; | ||
396 | default: | ||
397 | dev_err(priv->adapter->dev, | ||
398 | "PREP_CMD: unknown cmd %#x\n", cmd_no); | ||
399 | return -1; | ||
400 | } | ||
401 | |||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | /* This function sets the RF channel for AP. | ||
406 | * | ||
407 | * This function populates channel information in AP config structure | ||
408 | * and sends command to configure channel information in AP. | ||
409 | */ | ||
410 | int mwifiex_uap_set_channel(struct mwifiex_private *priv, int channel) | ||
411 | { | ||
412 | struct mwifiex_uap_bss_param *bss_cfg; | ||
413 | struct wiphy *wiphy = priv->wdev->wiphy; | ||
414 | |||
415 | bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL); | ||
416 | if (!bss_cfg) | ||
417 | return -ENOMEM; | ||
418 | |||
419 | bss_cfg->band_cfg = BAND_CONFIG_MANUAL; | ||
420 | bss_cfg->channel = channel; | ||
421 | |||
422 | if (mwifiex_send_cmd_async(priv, HostCmd_CMD_UAP_SYS_CONFIG, | ||
423 | HostCmd_ACT_GEN_SET, | ||
424 | UAP_BSS_PARAMS_I, bss_cfg)) { | ||
425 | wiphy_err(wiphy, "Failed to set the uAP channel\n"); | ||
426 | kfree(bss_cfg); | ||
427 | return -1; | ||
428 | } | ||
429 | |||
430 | kfree(bss_cfg); | ||
431 | return 0; | ||
432 | } | ||
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 429a1dee2d26..f3fc65515857 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
@@ -885,6 +885,10 @@ mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, | |||
885 | tid_ptr = &(priv_tmp)->wmm. | 885 | tid_ptr = &(priv_tmp)->wmm. |
886 | tid_tbl_ptr[tos_to_tid[i]]; | 886 | tid_tbl_ptr[tos_to_tid[i]]; |
887 | 887 | ||
888 | /* For non-STA ra_list_curr may be NULL */ | ||
889 | if (!tid_ptr->ra_list_curr) | ||
890 | continue; | ||
891 | |||
888 | spin_lock_irqsave(&tid_ptr->tid_tbl_lock, | 892 | spin_lock_irqsave(&tid_ptr->tid_tbl_lock, |
889 | flags); | 893 | flags); |
890 | is_list_empty = | 894 | is_list_empty = |
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index c5404eb82b2f..2e9e6af21362 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c | |||
@@ -505,9 +505,6 @@ static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev, | |||
505 | 505 | ||
506 | static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev); | 506 | static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev); |
507 | 507 | ||
508 | static int rndis_set_channel(struct wiphy *wiphy, struct net_device *dev, | ||
509 | struct ieee80211_channel *chan, enum nl80211_channel_type channel_type); | ||
510 | |||
511 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, | 508 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, |
512 | u8 key_index, bool pairwise, const u8 *mac_addr, | 509 | u8 key_index, bool pairwise, const u8 *mac_addr, |
513 | struct key_params *params); | 510 | struct key_params *params); |
@@ -549,7 +546,6 @@ static const struct cfg80211_ops rndis_config_ops = { | |||
549 | .disconnect = rndis_disconnect, | 546 | .disconnect = rndis_disconnect, |
550 | .join_ibss = rndis_join_ibss, | 547 | .join_ibss = rndis_join_ibss, |
551 | .leave_ibss = rndis_leave_ibss, | 548 | .leave_ibss = rndis_leave_ibss, |
552 | .set_channel = rndis_set_channel, | ||
553 | .add_key = rndis_add_key, | 549 | .add_key = rndis_add_key, |
554 | .del_key = rndis_del_key, | 550 | .del_key = rndis_del_key, |
555 | .set_default_key = rndis_set_default_key, | 551 | .set_default_key = rndis_set_default_key, |
@@ -2398,16 +2394,6 @@ static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev) | |||
2398 | return deauthenticate(usbdev); | 2394 | return deauthenticate(usbdev); |
2399 | } | 2395 | } |
2400 | 2396 | ||
2401 | static int rndis_set_channel(struct wiphy *wiphy, struct net_device *netdev, | ||
2402 | struct ieee80211_channel *chan, enum nl80211_channel_type channel_type) | ||
2403 | { | ||
2404 | struct rndis_wlan_private *priv = wiphy_priv(wiphy); | ||
2405 | struct usbnet *usbdev = priv->usbdev; | ||
2406 | |||
2407 | return set_channel(usbdev, | ||
2408 | ieee80211_frequency_to_channel(chan->center_freq)); | ||
2409 | } | ||
2410 | |||
2411 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, | 2397 | static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, |
2412 | u8 key_index, bool pairwise, const u8 *mac_addr, | 2398 | u8 key_index, bool pairwise, const u8 *mac_addr, |
2413 | struct key_params *params) | 2399 | struct key_params *params) |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 931331d95217..cad25bfebd7a 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -1192,6 +1192,7 @@ static DEFINE_PCI_DEVICE_TABLE(rt2800pci_device_table) = { | |||
1192 | { PCI_DEVICE(0x1814, 0x5390) }, | 1192 | { PCI_DEVICE(0x1814, 0x5390) }, |
1193 | { PCI_DEVICE(0x1814, 0x5392) }, | 1193 | { PCI_DEVICE(0x1814, 0x5392) }, |
1194 | { PCI_DEVICE(0x1814, 0x539a) }, | 1194 | { PCI_DEVICE(0x1814, 0x539a) }, |
1195 | { PCI_DEVICE(0x1814, 0x539b) }, | ||
1195 | { PCI_DEVICE(0x1814, 0x539f) }, | 1196 | { PCI_DEVICE(0x1814, 0x539f) }, |
1196 | #endif | 1197 | #endif |
1197 | { 0, } | 1198 | { 0, } |
diff --git a/drivers/net/wireless/ti/wl12xx/Kconfig b/drivers/net/wireless/ti/wl12xx/Kconfig index 5b92329122c4..c2183594655a 100644 --- a/drivers/net/wireless/ti/wl12xx/Kconfig +++ b/drivers/net/wireless/ti/wl12xx/Kconfig | |||
@@ -1,5 +1,6 @@ | |||
1 | config WL12XX | 1 | config WL12XX |
2 | tristate "TI wl12xx support" | 2 | tristate "TI wl12xx support" |
3 | depends on MAC80211 | ||
3 | select WLCORE | 4 | select WLCORE |
4 | ---help--- | 5 | ---help--- |
5 | This module adds support for wireless adapters based on TI wl1271, | 6 | This module adds support for wireless adapters based on TI wl1271, |
diff --git a/drivers/net/wireless/ti/wlcore/Kconfig b/drivers/net/wireless/ti/wlcore/Kconfig index 9d04c38938bc..54156b0b5c2d 100644 --- a/drivers/net/wireless/ti/wlcore/Kconfig +++ b/drivers/net/wireless/ti/wlcore/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config WLCORE | 1 | config WLCORE |
2 | tristate "TI wlcore support" | 2 | tristate "TI wlcore support" |
3 | depends on WL_TI && GENERIC_HARDIRQS | 3 | depends on WL_TI && GENERIC_HARDIRQS && MAC80211 |
4 | depends on INET | 4 | depends on INET |
5 | select FW_LOADER | 5 | select FW_LOADER |
6 | ---help--- | 6 | ---help--- |
diff --git a/drivers/net/wireless/ti/wlcore/acx.c b/drivers/net/wireless/ti/wlcore/acx.c index 5912541a925e..509aa881d790 100644 --- a/drivers/net/wireless/ti/wlcore/acx.c +++ b/drivers/net/wireless/ti/wlcore/acx.c | |||
@@ -1714,3 +1714,83 @@ out: | |||
1714 | return ret; | 1714 | return ret; |
1715 | 1715 | ||
1716 | } | 1716 | } |
1717 | |||
1718 | /* Set the global behaviour of RX filters - On/Off + default action */ | ||
1719 | int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable, | ||
1720 | enum rx_filter_action action) | ||
1721 | { | ||
1722 | struct acx_default_rx_filter *acx; | ||
1723 | int ret; | ||
1724 | |||
1725 | wl1271_debug(DEBUG_ACX, "acx default rx filter en: %d act: %d", | ||
1726 | enable, action); | ||
1727 | |||
1728 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1729 | if (!acx) | ||
1730 | return -ENOMEM; | ||
1731 | |||
1732 | acx->enable = enable; | ||
1733 | acx->default_action = action; | ||
1734 | |||
1735 | ret = wl1271_cmd_configure(wl, ACX_ENABLE_RX_DATA_FILTER, acx, | ||
1736 | sizeof(*acx)); | ||
1737 | if (ret < 0) { | ||
1738 | wl1271_warning("acx default rx filter enable failed: %d", ret); | ||
1739 | goto out; | ||
1740 | } | ||
1741 | |||
1742 | out: | ||
1743 | kfree(acx); | ||
1744 | return ret; | ||
1745 | } | ||
1746 | |||
1747 | /* Configure or disable a specific RX filter pattern */ | ||
1748 | int wl1271_acx_set_rx_filter(struct wl1271 *wl, u8 index, bool enable, | ||
1749 | struct wl12xx_rx_filter *filter) | ||
1750 | { | ||
1751 | struct acx_rx_filter_cfg *acx; | ||
1752 | int fields_size = 0; | ||
1753 | int acx_size; | ||
1754 | int ret; | ||
1755 | |||
1756 | WARN_ON(enable && !filter); | ||
1757 | WARN_ON(index >= WL1271_MAX_RX_FILTERS); | ||
1758 | |||
1759 | wl1271_debug(DEBUG_ACX, | ||
1760 | "acx set rx filter idx: %d enable: %d filter: %p", | ||
1761 | index, enable, filter); | ||
1762 | |||
1763 | if (enable) { | ||
1764 | fields_size = wl1271_rx_filter_get_fields_size(filter); | ||
1765 | |||
1766 | wl1271_debug(DEBUG_ACX, "act: %d num_fields: %d field_size: %d", | ||
1767 | filter->action, filter->num_fields, fields_size); | ||
1768 | } | ||
1769 | |||
1770 | acx_size = ALIGN(sizeof(*acx) + fields_size, 4); | ||
1771 | acx = kzalloc(acx_size, GFP_KERNEL); | ||
1772 | |||
1773 | if (!acx) | ||
1774 | return -ENOMEM; | ||
1775 | |||
1776 | acx->enable = enable; | ||
1777 | acx->index = index; | ||
1778 | |||
1779 | if (enable) { | ||
1780 | acx->num_fields = filter->num_fields; | ||
1781 | acx->action = filter->action; | ||
1782 | wl1271_rx_filter_flatten_fields(filter, acx->fields); | ||
1783 | } | ||
1784 | |||
1785 | wl1271_dump(DEBUG_ACX, "RX_FILTER: ", acx, acx_size); | ||
1786 | |||
1787 | ret = wl1271_cmd_configure(wl, ACX_SET_RX_DATA_FILTER, acx, acx_size); | ||
1788 | if (ret < 0) { | ||
1789 | wl1271_warning("setting rx filter failed: %d", ret); | ||
1790 | goto out; | ||
1791 | } | ||
1792 | |||
1793 | out: | ||
1794 | kfree(acx); | ||
1795 | return ret; | ||
1796 | } | ||
diff --git a/drivers/net/wireless/ti/wlcore/acx.h b/drivers/net/wireless/ti/wlcore/acx.h index b2f88831b7a9..8106b2ebfe60 100644 --- a/drivers/net/wireless/ti/wlcore/acx.h +++ b/drivers/net/wireless/ti/wlcore/acx.h | |||
@@ -1147,6 +1147,32 @@ struct wl12xx_acx_config_hangover { | |||
1147 | u8 padding[2]; | 1147 | u8 padding[2]; |
1148 | } __packed; | 1148 | } __packed; |
1149 | 1149 | ||
1150 | |||
1151 | struct acx_default_rx_filter { | ||
1152 | struct acx_header header; | ||
1153 | u8 enable; | ||
1154 | |||
1155 | /* action of type FILTER_XXX */ | ||
1156 | u8 default_action; | ||
1157 | |||
1158 | u8 pad[2]; | ||
1159 | } __packed; | ||
1160 | |||
1161 | |||
1162 | struct acx_rx_filter_cfg { | ||
1163 | struct acx_header header; | ||
1164 | |||
1165 | u8 enable; | ||
1166 | |||
1167 | /* 0 - WL1271_MAX_RX_FILTERS-1 */ | ||
1168 | u8 index; | ||
1169 | |||
1170 | u8 action; | ||
1171 | |||
1172 | u8 num_fields; | ||
1173 | u8 fields[0]; | ||
1174 | } __packed; | ||
1175 | |||
1150 | enum { | 1176 | enum { |
1151 | ACX_WAKE_UP_CONDITIONS = 0x0000, | 1177 | ACX_WAKE_UP_CONDITIONS = 0x0000, |
1152 | ACX_MEM_CFG = 0x0001, | 1178 | ACX_MEM_CFG = 0x0001, |
@@ -1304,5 +1330,9 @@ int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); | |||
1304 | int wl1271_acx_fm_coex(struct wl1271 *wl); | 1330 | int wl1271_acx_fm_coex(struct wl1271 *wl); |
1305 | int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl); | 1331 | int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl); |
1306 | int wl12xx_acx_config_hangover(struct wl1271 *wl); | 1332 | int wl12xx_acx_config_hangover(struct wl1271 *wl); |
1333 | int wl1271_acx_default_rx_filter_enable(struct wl1271 *wl, bool enable, | ||
1334 | enum rx_filter_action action); | ||
1335 | int wl1271_acx_set_rx_filter(struct wl1271 *wl, u8 index, bool enable, | ||
1336 | struct wl12xx_rx_filter *filter); | ||
1307 | 1337 | ||
1308 | #endif /* __WL1271_ACX_H__ */ | 1338 | #endif /* __WL1271_ACX_H__ */ |
diff --git a/drivers/net/wireless/ti/wlcore/boot.c b/drivers/net/wireless/ti/wlcore/boot.c index 3a2207db5405..9b98230f84ce 100644 --- a/drivers/net/wireless/ti/wlcore/boot.c +++ b/drivers/net/wireless/ti/wlcore/boot.c | |||
@@ -72,7 +72,7 @@ static int wlcore_boot_fw_version(struct wl1271 *wl) | |||
72 | struct wl1271_static_data *static_data; | 72 | struct wl1271_static_data *static_data; |
73 | int ret; | 73 | int ret; |
74 | 74 | ||
75 | static_data = kmalloc(sizeof(*static_data), GFP_DMA); | 75 | static_data = kmalloc(sizeof(*static_data), GFP_KERNEL | GFP_DMA); |
76 | if (!static_data) { | 76 | if (!static_data) { |
77 | wl1271_error("Couldn't allocate memory for static data!"); | 77 | wl1271_error("Couldn't allocate memory for static data!"); |
78 | return -ENOMEM; | 78 | return -ENOMEM; |
@@ -413,6 +413,7 @@ int wlcore_boot_run_firmware(struct wl1271 *wl) | |||
413 | 413 | ||
414 | /* unmask required mbox events */ | 414 | /* unmask required mbox events */ |
415 | wl->event_mask = BSS_LOSE_EVENT_ID | | 415 | wl->event_mask = BSS_LOSE_EVENT_ID | |
416 | REGAINED_BSS_EVENT_ID | | ||
416 | SCAN_COMPLETE_EVENT_ID | | 417 | SCAN_COMPLETE_EVENT_ID | |
417 | ROLE_STOP_COMPLETE_EVENT_ID | | 418 | ROLE_STOP_COMPLETE_EVENT_ID | |
418 | RSSI_SNR_TRIGGER_0_EVENT_ID | | 419 | RSSI_SNR_TRIGGER_0_EVENT_ID | |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 5c4716c6f040..5b128a971449 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c | |||
@@ -123,7 +123,9 @@ static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask) | |||
123 | unsigned long timeout; | 123 | unsigned long timeout; |
124 | int ret = 0; | 124 | int ret = 0; |
125 | 125 | ||
126 | events_vector = kmalloc(sizeof(*events_vector), GFP_DMA); | 126 | events_vector = kmalloc(sizeof(*events_vector), GFP_KERNEL | GFP_DMA); |
127 | if (!events_vector) | ||
128 | return -ENOMEM; | ||
127 | 129 | ||
128 | timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); | 130 | timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); |
129 | 131 | ||
@@ -1034,7 +1036,7 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
1034 | skb_reserve(skb, sizeof(*hdr) + WL1271_EXTRA_SPACE_MAX); | 1036 | skb_reserve(skb, sizeof(*hdr) + WL1271_EXTRA_SPACE_MAX); |
1035 | 1037 | ||
1036 | tmpl = (struct wl12xx_arp_rsp_template *)skb_put(skb, sizeof(*tmpl)); | 1038 | tmpl = (struct wl12xx_arp_rsp_template *)skb_put(skb, sizeof(*tmpl)); |
1037 | memset(tmpl, 0, sizeof(tmpl)); | 1039 | memset(tmpl, 0, sizeof(*tmpl)); |
1038 | 1040 | ||
1039 | /* llc layer */ | 1041 | /* llc layer */ |
1040 | memcpy(tmpl->llc_hdr, rfc1042_header, sizeof(rfc1042_header)); | 1042 | memcpy(tmpl->llc_hdr, rfc1042_header, sizeof(rfc1042_header)); |
@@ -1083,7 +1085,7 @@ int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, struct wl12xx_vif *wlvif) | |||
1083 | 1085 | ||
1084 | /* mac80211 header */ | 1086 | /* mac80211 header */ |
1085 | hdr = (struct ieee80211_hdr_3addr *)skb_push(skb, sizeof(*hdr)); | 1087 | hdr = (struct ieee80211_hdr_3addr *)skb_push(skb, sizeof(*hdr)); |
1086 | memset(hdr, 0, sizeof(hdr)); | 1088 | memset(hdr, 0, sizeof(*hdr)); |
1087 | fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS; | 1089 | fc = IEEE80211_FTYPE_DATA | IEEE80211_FCTL_TODS; |
1088 | if (wlvif->sta.qos) | 1090 | if (wlvif->sta.qos) |
1089 | fc |= IEEE80211_STYPE_QOS_DATA; | 1091 | fc |= IEEE80211_STYPE_QOS_DATA; |
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c index 292632ddf890..28e2a633c3be 100644 --- a/drivers/net/wireless/ti/wlcore/event.c +++ b/drivers/net/wireless/ti/wlcore/event.c | |||
@@ -103,7 +103,6 @@ static int wl1271_event_process(struct wl1271 *wl) | |||
103 | struct ieee80211_vif *vif; | 103 | struct ieee80211_vif *vif; |
104 | struct wl12xx_vif *wlvif; | 104 | struct wl12xx_vif *wlvif; |
105 | u32 vector; | 105 | u32 vector; |
106 | bool beacon_loss = false; | ||
107 | bool disconnect_sta = false; | 106 | bool disconnect_sta = false; |
108 | unsigned long sta_bitmap = 0; | 107 | unsigned long sta_bitmap = 0; |
109 | 108 | ||
@@ -141,20 +140,23 @@ static int wl1271_event_process(struct wl1271 *wl) | |||
141 | mbox->soft_gemini_sense_info); | 140 | mbox->soft_gemini_sense_info); |
142 | 141 | ||
143 | /* | 142 | /* |
144 | * The BSS_LOSE_EVENT_ID is only needed while psm (and hence beacon | 143 | * We are HW_MONITOR device. On beacon loss - queue |
145 | * filtering) is enabled. Without PSM, the stack will receive all | 144 | * connection loss work. Cancel it on REGAINED event. |
146 | * beacons and can detect beacon loss by itself. | ||
147 | * | ||
148 | * As there's possibility that the driver disables PSM before receiving | ||
149 | * BSS_LOSE_EVENT, beacon loss has to be reported to the stack. | ||
150 | * | ||
151 | */ | 145 | */ |
152 | if (vector & BSS_LOSE_EVENT_ID) { | 146 | if (vector & BSS_LOSE_EVENT_ID) { |
153 | /* TODO: check for multi-role */ | 147 | /* TODO: check for multi-role */ |
148 | int delay = wl->conf.conn.synch_fail_thold * | ||
149 | wl->conf.conn.bss_lose_timeout; | ||
154 | wl1271_info("Beacon loss detected."); | 150 | wl1271_info("Beacon loss detected."); |
151 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
152 | ieee80211_queue_delayed_work(wl->hw, &wl->connection_loss_work, | ||
153 | msecs_to_jiffies(delay)); | ||
154 | } | ||
155 | 155 | ||
156 | /* indicate to the stack, that beacons have been lost */ | 156 | if (vector & REGAINED_BSS_EVENT_ID) { |
157 | beacon_loss = true; | 157 | /* TODO: check for multi-role */ |
158 | wl1271_info("Beacon regained."); | ||
159 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
158 | } | 160 | } |
159 | 161 | ||
160 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { | 162 | if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) { |
@@ -257,13 +259,6 @@ static int wl1271_event_process(struct wl1271 *wl) | |||
257 | rcu_read_unlock(); | 259 | rcu_read_unlock(); |
258 | } | 260 | } |
259 | } | 261 | } |
260 | |||
261 | if (beacon_loss) | ||
262 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
263 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
264 | ieee80211_connection_loss(vif); | ||
265 | } | ||
266 | |||
267 | return 0; | 262 | return 0; |
268 | } | 263 | } |
269 | 264 | ||
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 2b0f987660c6..acef93390d3d 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -1120,6 +1120,7 @@ int wl1271_plt_stop(struct wl1271 *wl) | |||
1120 | cancel_work_sync(&wl->recovery_work); | 1120 | cancel_work_sync(&wl->recovery_work); |
1121 | cancel_delayed_work_sync(&wl->elp_work); | 1121 | cancel_delayed_work_sync(&wl->elp_work); |
1122 | cancel_delayed_work_sync(&wl->tx_watchdog_work); | 1122 | cancel_delayed_work_sync(&wl->tx_watchdog_work); |
1123 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
1123 | 1124 | ||
1124 | mutex_lock(&wl->mutex); | 1125 | mutex_lock(&wl->mutex); |
1125 | wl1271_power_off(wl); | 1126 | wl1271_power_off(wl); |
@@ -1261,8 +1262,270 @@ static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl) | |||
1261 | 1262 | ||
1262 | 1263 | ||
1263 | #ifdef CONFIG_PM | 1264 | #ifdef CONFIG_PM |
1265 | static int | ||
1266 | wl1271_validate_wowlan_pattern(struct cfg80211_wowlan_trig_pkt_pattern *p) | ||
1267 | { | ||
1268 | int num_fields = 0, in_field = 0, fields_size = 0; | ||
1269 | int i, pattern_len = 0; | ||
1270 | |||
1271 | if (!p->mask) { | ||
1272 | wl1271_warning("No mask in WoWLAN pattern"); | ||
1273 | return -EINVAL; | ||
1274 | } | ||
1275 | |||
1276 | /* | ||
1277 | * The pattern is broken up into segments of bytes at different offsets | ||
1278 | * that need to be checked by the FW filter. Each segment is called | ||
1279 | * a field in the FW API. We verify that the total number of fields | ||
1280 | * required for this pattern won't exceed FW limits (8) | ||
1281 | * as well as the total fields buffer won't exceed the FW limit. | ||
1282 | * Note that if there's a pattern which crosses Ethernet/IP header | ||
1283 | * boundary a new field is required. | ||
1284 | */ | ||
1285 | for (i = 0; i < p->pattern_len; i++) { | ||
1286 | if (test_bit(i, (unsigned long *)p->mask)) { | ||
1287 | if (!in_field) { | ||
1288 | in_field = 1; | ||
1289 | pattern_len = 1; | ||
1290 | } else { | ||
1291 | if (i == WL1271_RX_FILTER_ETH_HEADER_SIZE) { | ||
1292 | num_fields++; | ||
1293 | fields_size += pattern_len + | ||
1294 | RX_FILTER_FIELD_OVERHEAD; | ||
1295 | pattern_len = 1; | ||
1296 | } else | ||
1297 | pattern_len++; | ||
1298 | } | ||
1299 | } else { | ||
1300 | if (in_field) { | ||
1301 | in_field = 0; | ||
1302 | fields_size += pattern_len + | ||
1303 | RX_FILTER_FIELD_OVERHEAD; | ||
1304 | num_fields++; | ||
1305 | } | ||
1306 | } | ||
1307 | } | ||
1308 | |||
1309 | if (in_field) { | ||
1310 | fields_size += pattern_len + RX_FILTER_FIELD_OVERHEAD; | ||
1311 | num_fields++; | ||
1312 | } | ||
1313 | |||
1314 | if (num_fields > WL1271_RX_FILTER_MAX_FIELDS) { | ||
1315 | wl1271_warning("RX Filter too complex. Too many segments"); | ||
1316 | return -EINVAL; | ||
1317 | } | ||
1318 | |||
1319 | if (fields_size > WL1271_RX_FILTER_MAX_FIELDS_SIZE) { | ||
1320 | wl1271_warning("RX filter pattern is too big"); | ||
1321 | return -E2BIG; | ||
1322 | } | ||
1323 | |||
1324 | return 0; | ||
1325 | } | ||
1326 | |||
1327 | struct wl12xx_rx_filter *wl1271_rx_filter_alloc(void) | ||
1328 | { | ||
1329 | return kzalloc(sizeof(struct wl12xx_rx_filter), GFP_KERNEL); | ||
1330 | } | ||
1331 | |||
1332 | void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter) | ||
1333 | { | ||
1334 | int i; | ||
1335 | |||
1336 | if (filter == NULL) | ||
1337 | return; | ||
1338 | |||
1339 | for (i = 0; i < filter->num_fields; i++) | ||
1340 | kfree(filter->fields[i].pattern); | ||
1341 | |||
1342 | kfree(filter); | ||
1343 | } | ||
1344 | |||
1345 | int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter, | ||
1346 | u16 offset, u8 flags, | ||
1347 | u8 *pattern, u8 len) | ||
1348 | { | ||
1349 | struct wl12xx_rx_filter_field *field; | ||
1350 | |||
1351 | if (filter->num_fields == WL1271_RX_FILTER_MAX_FIELDS) { | ||
1352 | wl1271_warning("Max fields per RX filter. can't alloc another"); | ||
1353 | return -EINVAL; | ||
1354 | } | ||
1355 | |||
1356 | field = &filter->fields[filter->num_fields]; | ||
1357 | |||
1358 | field->pattern = kzalloc(len, GFP_KERNEL); | ||
1359 | if (!field->pattern) { | ||
1360 | wl1271_warning("Failed to allocate RX filter pattern"); | ||
1361 | return -ENOMEM; | ||
1362 | } | ||
1363 | |||
1364 | filter->num_fields++; | ||
1365 | |||
1366 | field->offset = cpu_to_le16(offset); | ||
1367 | field->flags = flags; | ||
1368 | field->len = len; | ||
1369 | memcpy(field->pattern, pattern, len); | ||
1370 | |||
1371 | return 0; | ||
1372 | } | ||
1373 | |||
1374 | int wl1271_rx_filter_get_fields_size(struct wl12xx_rx_filter *filter) | ||
1375 | { | ||
1376 | int i, fields_size = 0; | ||
1377 | |||
1378 | for (i = 0; i < filter->num_fields; i++) | ||
1379 | fields_size += filter->fields[i].len + | ||
1380 | sizeof(struct wl12xx_rx_filter_field) - | ||
1381 | sizeof(u8 *); | ||
1382 | |||
1383 | return fields_size; | ||
1384 | } | ||
1385 | |||
1386 | void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter, | ||
1387 | u8 *buf) | ||
1388 | { | ||
1389 | int i; | ||
1390 | struct wl12xx_rx_filter_field *field; | ||
1391 | |||
1392 | for (i = 0; i < filter->num_fields; i++) { | ||
1393 | field = (struct wl12xx_rx_filter_field *)buf; | ||
1394 | |||
1395 | field->offset = filter->fields[i].offset; | ||
1396 | field->flags = filter->fields[i].flags; | ||
1397 | field->len = filter->fields[i].len; | ||
1398 | |||
1399 | memcpy(&field->pattern, filter->fields[i].pattern, field->len); | ||
1400 | buf += sizeof(struct wl12xx_rx_filter_field) - | ||
1401 | sizeof(u8 *) + field->len; | ||
1402 | } | ||
1403 | } | ||
1404 | |||
1405 | /* | ||
1406 | * Allocates an RX filter returned through f | ||
1407 | * which needs to be freed using rx_filter_free() | ||
1408 | */ | ||
1409 | static int wl1271_convert_wowlan_pattern_to_rx_filter( | ||
1410 | struct cfg80211_wowlan_trig_pkt_pattern *p, | ||
1411 | struct wl12xx_rx_filter **f) | ||
1412 | { | ||
1413 | int i, j, ret = 0; | ||
1414 | struct wl12xx_rx_filter *filter; | ||
1415 | u16 offset; | ||
1416 | u8 flags, len; | ||
1417 | |||
1418 | filter = wl1271_rx_filter_alloc(); | ||
1419 | if (!filter) { | ||
1420 | wl1271_warning("Failed to alloc rx filter"); | ||
1421 | ret = -ENOMEM; | ||
1422 | goto err; | ||
1423 | } | ||
1424 | |||
1425 | i = 0; | ||
1426 | while (i < p->pattern_len) { | ||
1427 | if (!test_bit(i, (unsigned long *)p->mask)) { | ||
1428 | i++; | ||
1429 | continue; | ||
1430 | } | ||
1431 | |||
1432 | for (j = i; j < p->pattern_len; j++) { | ||
1433 | if (!test_bit(j, (unsigned long *)p->mask)) | ||
1434 | break; | ||
1435 | |||
1436 | if (i < WL1271_RX_FILTER_ETH_HEADER_SIZE && | ||
1437 | j >= WL1271_RX_FILTER_ETH_HEADER_SIZE) | ||
1438 | break; | ||
1439 | } | ||
1440 | |||
1441 | if (i < WL1271_RX_FILTER_ETH_HEADER_SIZE) { | ||
1442 | offset = i; | ||
1443 | flags = WL1271_RX_FILTER_FLAG_ETHERNET_HEADER; | ||
1444 | } else { | ||
1445 | offset = i - WL1271_RX_FILTER_ETH_HEADER_SIZE; | ||
1446 | flags = WL1271_RX_FILTER_FLAG_IP_HEADER; | ||
1447 | } | ||
1448 | |||
1449 | len = j - i; | ||
1450 | |||
1451 | ret = wl1271_rx_filter_alloc_field(filter, | ||
1452 | offset, | ||
1453 | flags, | ||
1454 | &p->pattern[i], len); | ||
1455 | if (ret) | ||
1456 | goto err; | ||
1457 | |||
1458 | i = j; | ||
1459 | } | ||
1460 | |||
1461 | filter->action = FILTER_SIGNAL; | ||
1462 | |||
1463 | *f = filter; | ||
1464 | return 0; | ||
1465 | |||
1466 | err: | ||
1467 | wl1271_rx_filter_free(filter); | ||
1468 | *f = NULL; | ||
1469 | |||
1470 | return ret; | ||
1471 | } | ||
1472 | |||
1473 | static int wl1271_configure_wowlan(struct wl1271 *wl, | ||
1474 | struct cfg80211_wowlan *wow) | ||
1475 | { | ||
1476 | int i, ret; | ||
1477 | |||
1478 | if (!wow || wow->any || !wow->n_patterns) { | ||
1479 | wl1271_acx_default_rx_filter_enable(wl, 0, FILTER_SIGNAL); | ||
1480 | wl1271_rx_filter_clear_all(wl); | ||
1481 | return 0; | ||
1482 | } | ||
1483 | |||
1484 | if (WARN_ON(wow->n_patterns > WL1271_MAX_RX_FILTERS)) | ||
1485 | return -EINVAL; | ||
1486 | |||
1487 | /* Validate all incoming patterns before clearing current FW state */ | ||
1488 | for (i = 0; i < wow->n_patterns; i++) { | ||
1489 | ret = wl1271_validate_wowlan_pattern(&wow->patterns[i]); | ||
1490 | if (ret) { | ||
1491 | wl1271_warning("Bad wowlan pattern %d", i); | ||
1492 | return ret; | ||
1493 | } | ||
1494 | } | ||
1495 | |||
1496 | wl1271_acx_default_rx_filter_enable(wl, 0, FILTER_SIGNAL); | ||
1497 | wl1271_rx_filter_clear_all(wl); | ||
1498 | |||
1499 | /* Translate WoWLAN patterns into filters */ | ||
1500 | for (i = 0; i < wow->n_patterns; i++) { | ||
1501 | struct cfg80211_wowlan_trig_pkt_pattern *p; | ||
1502 | struct wl12xx_rx_filter *filter = NULL; | ||
1503 | |||
1504 | p = &wow->patterns[i]; | ||
1505 | |||
1506 | ret = wl1271_convert_wowlan_pattern_to_rx_filter(p, &filter); | ||
1507 | if (ret) { | ||
1508 | wl1271_warning("Failed to create an RX filter from " | ||
1509 | "wowlan pattern %d", i); | ||
1510 | goto out; | ||
1511 | } | ||
1512 | |||
1513 | ret = wl1271_rx_filter_enable(wl, i, 1, filter); | ||
1514 | |||
1515 | wl1271_rx_filter_free(filter); | ||
1516 | if (ret) | ||
1517 | goto out; | ||
1518 | } | ||
1519 | |||
1520 | ret = wl1271_acx_default_rx_filter_enable(wl, 1, FILTER_DROP); | ||
1521 | |||
1522 | out: | ||
1523 | return ret; | ||
1524 | } | ||
1525 | |||
1264 | static int wl1271_configure_suspend_sta(struct wl1271 *wl, | 1526 | static int wl1271_configure_suspend_sta(struct wl1271 *wl, |
1265 | struct wl12xx_vif *wlvif) | 1527 | struct wl12xx_vif *wlvif, |
1528 | struct cfg80211_wowlan *wow) | ||
1266 | { | 1529 | { |
1267 | int ret = 0; | 1530 | int ret = 0; |
1268 | 1531 | ||
@@ -1273,6 +1536,7 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, | |||
1273 | if (ret < 0) | 1536 | if (ret < 0) |
1274 | goto out; | 1537 | goto out; |
1275 | 1538 | ||
1539 | wl1271_configure_wowlan(wl, wow); | ||
1276 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, | 1540 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, |
1277 | wl->conf.conn.suspend_wake_up_event, | 1541 | wl->conf.conn.suspend_wake_up_event, |
1278 | wl->conf.conn.suspend_listen_interval); | 1542 | wl->conf.conn.suspend_listen_interval); |
@@ -1308,10 +1572,11 @@ out: | |||
1308 | } | 1572 | } |
1309 | 1573 | ||
1310 | static int wl1271_configure_suspend(struct wl1271 *wl, | 1574 | static int wl1271_configure_suspend(struct wl1271 *wl, |
1311 | struct wl12xx_vif *wlvif) | 1575 | struct wl12xx_vif *wlvif, |
1576 | struct cfg80211_wowlan *wow) | ||
1312 | { | 1577 | { |
1313 | if (wlvif->bss_type == BSS_TYPE_STA_BSS) | 1578 | if (wlvif->bss_type == BSS_TYPE_STA_BSS) |
1314 | return wl1271_configure_suspend_sta(wl, wlvif); | 1579 | return wl1271_configure_suspend_sta(wl, wlvif, wow); |
1315 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) | 1580 | if (wlvif->bss_type == BSS_TYPE_AP_BSS) |
1316 | return wl1271_configure_suspend_ap(wl, wlvif); | 1581 | return wl1271_configure_suspend_ap(wl, wlvif); |
1317 | return 0; | 1582 | return 0; |
@@ -1332,6 +1597,8 @@ static void wl1271_configure_resume(struct wl1271 *wl, | |||
1332 | return; | 1597 | return; |
1333 | 1598 | ||
1334 | if (is_sta) { | 1599 | if (is_sta) { |
1600 | wl1271_configure_wowlan(wl, NULL); | ||
1601 | |||
1335 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, | 1602 | ret = wl1271_acx_wake_up_conditions(wl, wlvif, |
1336 | wl->conf.conn.wake_up_event, | 1603 | wl->conf.conn.wake_up_event, |
1337 | wl->conf.conn.listen_interval); | 1604 | wl->conf.conn.listen_interval); |
@@ -1355,15 +1622,16 @@ static int wl1271_op_suspend(struct ieee80211_hw *hw, | |||
1355 | int ret; | 1622 | int ret; |
1356 | 1623 | ||
1357 | wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); | 1624 | wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); |
1358 | WARN_ON(!wow || !wow->any); | 1625 | WARN_ON(!wow); |
1359 | 1626 | ||
1360 | wl1271_tx_flush(wl); | 1627 | wl1271_tx_flush(wl); |
1361 | 1628 | ||
1362 | mutex_lock(&wl->mutex); | 1629 | mutex_lock(&wl->mutex); |
1363 | wl->wow_enabled = true; | 1630 | wl->wow_enabled = true; |
1364 | wl12xx_for_each_wlvif(wl, wlvif) { | 1631 | wl12xx_for_each_wlvif(wl, wlvif) { |
1365 | ret = wl1271_configure_suspend(wl, wlvif); | 1632 | ret = wl1271_configure_suspend(wl, wlvif, wow); |
1366 | if (ret < 0) { | 1633 | if (ret < 0) { |
1634 | mutex_unlock(&wl->mutex); | ||
1367 | wl1271_warning("couldn't prepare device to suspend"); | 1635 | wl1271_warning("couldn't prepare device to suspend"); |
1368 | return ret; | 1636 | return ret; |
1369 | } | 1637 | } |
@@ -1487,6 +1755,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw) | |||
1487 | cancel_work_sync(&wl->tx_work); | 1755 | cancel_work_sync(&wl->tx_work); |
1488 | cancel_delayed_work_sync(&wl->elp_work); | 1756 | cancel_delayed_work_sync(&wl->elp_work); |
1489 | cancel_delayed_work_sync(&wl->tx_watchdog_work); | 1757 | cancel_delayed_work_sync(&wl->tx_watchdog_work); |
1758 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
1490 | 1759 | ||
1491 | /* let's notify MAC80211 about the remaining pending TX frames */ | 1760 | /* let's notify MAC80211 about the remaining pending TX frames */ |
1492 | wl12xx_tx_reset(wl, true); | 1761 | wl12xx_tx_reset(wl, true); |
@@ -3439,6 +3708,9 @@ sta_not_found: | |||
3439 | do_join = true; | 3708 | do_join = true; |
3440 | set_assoc = true; | 3709 | set_assoc = true; |
3441 | 3710 | ||
3711 | /* Cancel connection_loss_work */ | ||
3712 | cancel_delayed_work_sync(&wl->connection_loss_work); | ||
3713 | |||
3442 | /* | 3714 | /* |
3443 | * use basic rates from AP, and determine lowest rate | 3715 | * use basic rates from AP, and determine lowest rate |
3444 | * to use with control frames. | 3716 | * to use with control frames. |
@@ -4549,6 +4821,34 @@ static struct bin_attribute fwlog_attr = { | |||
4549 | .read = wl1271_sysfs_read_fwlog, | 4821 | .read = wl1271_sysfs_read_fwlog, |
4550 | }; | 4822 | }; |
4551 | 4823 | ||
4824 | static void wl1271_connection_loss_work(struct work_struct *work) | ||
4825 | { | ||
4826 | struct delayed_work *dwork; | ||
4827 | struct wl1271 *wl; | ||
4828 | struct ieee80211_vif *vif; | ||
4829 | struct wl12xx_vif *wlvif; | ||
4830 | |||
4831 | dwork = container_of(work, struct delayed_work, work); | ||
4832 | wl = container_of(dwork, struct wl1271, connection_loss_work); | ||
4833 | |||
4834 | wl1271_info("Connection loss work."); | ||
4835 | |||
4836 | mutex_lock(&wl->mutex); | ||
4837 | |||
4838 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
4839 | goto out; | ||
4840 | |||
4841 | /* Call mac80211 connection loss */ | ||
4842 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
4843 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
4844 | goto out; | ||
4845 | vif = wl12xx_wlvif_to_vif(wlvif); | ||
4846 | ieee80211_connection_loss(vif); | ||
4847 | } | ||
4848 | out: | ||
4849 | mutex_unlock(&wl->mutex); | ||
4850 | } | ||
4851 | |||
4552 | static void wl12xx_derive_mac_addresses(struct wl1271 *wl, | 4852 | static void wl12xx_derive_mac_addresses(struct wl1271 *wl, |
4553 | u32 oui, u32 nic, int n) | 4853 | u32 oui, u32 nic, int n) |
4554 | { | 4854 | { |
@@ -4804,6 +5104,8 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size) | |||
4804 | INIT_WORK(&wl->recovery_work, wl1271_recovery_work); | 5104 | INIT_WORK(&wl->recovery_work, wl1271_recovery_work); |
4805 | INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); | 5105 | INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work); |
4806 | INIT_DELAYED_WORK(&wl->tx_watchdog_work, wl12xx_tx_watchdog_work); | 5106 | INIT_DELAYED_WORK(&wl->tx_watchdog_work, wl12xx_tx_watchdog_work); |
5107 | INIT_DELAYED_WORK(&wl->connection_loss_work, | ||
5108 | wl1271_connection_loss_work); | ||
4807 | 5109 | ||
4808 | wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); | 5110 | wl->freezable_wq = create_freezable_workqueue("wl12xx_wq"); |
4809 | if (!wl->freezable_wq) { | 5111 | if (!wl->freezable_wq) { |
@@ -4861,7 +5163,7 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size) | |||
4861 | goto err_dummy_packet; | 5163 | goto err_dummy_packet; |
4862 | } | 5164 | } |
4863 | 5165 | ||
4864 | wl->mbox = kmalloc(sizeof(*wl->mbox), GFP_DMA); | 5166 | wl->mbox = kmalloc(sizeof(*wl->mbox), GFP_KERNEL | GFP_DMA); |
4865 | if (!wl->mbox) { | 5167 | if (!wl->mbox) { |
4866 | ret = -ENOMEM; | 5168 | ret = -ENOMEM; |
4867 | goto err_fwlog; | 5169 | goto err_fwlog; |
@@ -5003,9 +5305,14 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) | |||
5003 | if (!ret) { | 5305 | if (!ret) { |
5004 | wl->irq_wake_enabled = true; | 5306 | wl->irq_wake_enabled = true; |
5005 | device_init_wakeup(wl->dev, 1); | 5307 | device_init_wakeup(wl->dev, 1); |
5006 | if (pdata->pwr_in_suspend) | 5308 | if (pdata->pwr_in_suspend) { |
5007 | wl->hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; | 5309 | wl->hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; |
5008 | 5310 | wl->hw->wiphy->wowlan.n_patterns = | |
5311 | WL1271_MAX_RX_FILTERS; | ||
5312 | wl->hw->wiphy->wowlan.pattern_min_len = 1; | ||
5313 | wl->hw->wiphy->wowlan.pattern_max_len = | ||
5314 | WL1271_RX_FILTER_MAX_PATTERN_SIZE; | ||
5315 | } | ||
5009 | } | 5316 | } |
5010 | disable_irq(wl->irq); | 5317 | disable_irq(wl->irq); |
5011 | 5318 | ||
diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c index 89bd9385e90b..1f1d9488dfb6 100644 --- a/drivers/net/wireless/ti/wlcore/rx.c +++ b/drivers/net/wireless/ti/wlcore/rx.c | |||
@@ -278,3 +278,39 @@ void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status) | |||
278 | 278 | ||
279 | wl12xx_rearm_rx_streaming(wl, active_hlids); | 279 | wl12xx_rearm_rx_streaming(wl, active_hlids); |
280 | } | 280 | } |
281 | |||
282 | int wl1271_rx_filter_enable(struct wl1271 *wl, | ||
283 | int index, bool enable, | ||
284 | struct wl12xx_rx_filter *filter) | ||
285 | { | ||
286 | int ret; | ||
287 | |||
288 | if (wl->rx_filter_enabled[index] == enable) { | ||
289 | wl1271_warning("Request to enable an already " | ||
290 | "enabled rx filter %d", index); | ||
291 | return 0; | ||
292 | } | ||
293 | |||
294 | ret = wl1271_acx_set_rx_filter(wl, index, enable, filter); | ||
295 | |||
296 | if (ret) { | ||
297 | wl1271_error("Failed to %s rx data filter %d (err=%d)", | ||
298 | enable ? "enable" : "disable", index, ret); | ||
299 | return ret; | ||
300 | } | ||
301 | |||
302 | wl->rx_filter_enabled[index] = enable; | ||
303 | |||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | void wl1271_rx_filter_clear_all(struct wl1271 *wl) | ||
308 | { | ||
309 | int i; | ||
310 | |||
311 | for (i = 0; i < WL1271_MAX_RX_FILTERS; i++) { | ||
312 | if (!wl->rx_filter_enabled[i]) | ||
313 | continue; | ||
314 | wl1271_rx_filter_enable(wl, i, 0, NULL); | ||
315 | } | ||
316 | } | ||
diff --git a/drivers/net/wireless/ti/wlcore/rx.h b/drivers/net/wireless/ti/wlcore/rx.h index 6e129e2a8546..e9a162a864ca 100644 --- a/drivers/net/wireless/ti/wlcore/rx.h +++ b/drivers/net/wireless/ti/wlcore/rx.h | |||
@@ -138,5 +138,9 @@ struct wl1271_rx_descriptor { | |||
138 | 138 | ||
139 | void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status); | 139 | void wl12xx_rx(struct wl1271 *wl, struct wl_fw_status *status); |
140 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); | 140 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); |
141 | int wl1271_rx_filter_enable(struct wl1271 *wl, | ||
142 | int index, bool enable, | ||
143 | struct wl12xx_rx_filter *filter); | ||
144 | void wl1271_rx_filter_clear_all(struct wl1271 *wl); | ||
141 | 145 | ||
142 | #endif | 146 | #endif |
diff --git a/drivers/net/wireless/ti/wlcore/wl12xx.h b/drivers/net/wireless/ti/wlcore/wl12xx.h index a9b220c43e54..f12bdf745180 100644 --- a/drivers/net/wireless/ti/wlcore/wl12xx.h +++ b/drivers/net/wireless/ti/wlcore/wl12xx.h | |||
@@ -279,6 +279,39 @@ struct wl1271_link { | |||
279 | u8 ba_bitmap; | 279 | u8 ba_bitmap; |
280 | }; | 280 | }; |
281 | 281 | ||
282 | #define WL1271_MAX_RX_FILTERS 5 | ||
283 | #define WL1271_RX_FILTER_MAX_FIELDS 8 | ||
284 | |||
285 | #define WL1271_RX_FILTER_ETH_HEADER_SIZE 14 | ||
286 | #define WL1271_RX_FILTER_MAX_FIELDS_SIZE 95 | ||
287 | #define RX_FILTER_FIELD_OVERHEAD \ | ||
288 | (sizeof(struct wl12xx_rx_filter_field) - sizeof(u8 *)) | ||
289 | #define WL1271_RX_FILTER_MAX_PATTERN_SIZE \ | ||
290 | (WL1271_RX_FILTER_MAX_FIELDS_SIZE - RX_FILTER_FIELD_OVERHEAD) | ||
291 | |||
292 | #define WL1271_RX_FILTER_FLAG_MASK BIT(0) | ||
293 | #define WL1271_RX_FILTER_FLAG_IP_HEADER 0 | ||
294 | #define WL1271_RX_FILTER_FLAG_ETHERNET_HEADER BIT(1) | ||
295 | |||
296 | enum rx_filter_action { | ||
297 | FILTER_DROP = 0, | ||
298 | FILTER_SIGNAL = 1, | ||
299 | FILTER_FW_HANDLE = 2 | ||
300 | }; | ||
301 | |||
302 | struct wl12xx_rx_filter_field { | ||
303 | __le16 offset; | ||
304 | u8 len; | ||
305 | u8 flags; | ||
306 | u8 *pattern; | ||
307 | } __packed; | ||
308 | |||
309 | struct wl12xx_rx_filter { | ||
310 | u8 action; | ||
311 | int num_fields; | ||
312 | struct wl12xx_rx_filter_field fields[WL1271_RX_FILTER_MAX_FIELDS]; | ||
313 | }; | ||
314 | |||
282 | struct wl1271_station { | 315 | struct wl1271_station { |
283 | u8 hlid; | 316 | u8 hlid; |
284 | }; | 317 | }; |
@@ -439,6 +472,14 @@ int wl1271_plt_stop(struct wl1271 *wl); | |||
439 | int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif); | 472 | int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif); |
440 | void wl12xx_queue_recovery_work(struct wl1271 *wl); | 473 | void wl12xx_queue_recovery_work(struct wl1271 *wl); |
441 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); | 474 | size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen); |
475 | int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter, | ||
476 | u16 offset, u8 flags, | ||
477 | u8 *pattern, u8 len); | ||
478 | void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter); | ||
479 | struct wl12xx_rx_filter *wl1271_rx_filter_alloc(void); | ||
480 | int wl1271_rx_filter_get_fields_size(struct wl12xx_rx_filter *filter); | ||
481 | void wl1271_rx_filter_flatten_fields(struct wl12xx_rx_filter *filter, | ||
482 | u8 *buf); | ||
442 | 483 | ||
443 | #define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */ | 484 | #define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */ |
444 | 485 | ||
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 39f9fadfebd9..0b3f0b586f4b 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h | |||
@@ -243,6 +243,9 @@ struct wl1271 { | |||
243 | struct wl1271_scan scan; | 243 | struct wl1271_scan scan; |
244 | struct delayed_work scan_complete_work; | 244 | struct delayed_work scan_complete_work; |
245 | 245 | ||
246 | /* Connection loss work */ | ||
247 | struct delayed_work connection_loss_work; | ||
248 | |||
246 | bool sched_scanning; | 249 | bool sched_scanning; |
247 | 250 | ||
248 | /* The current band */ | 251 | /* The current band */ |
@@ -349,6 +352,9 @@ struct wl1271 { | |||
349 | 352 | ||
350 | /* size of the private FW status data */ | 353 | /* size of the private FW status data */ |
351 | size_t fw_status_priv_len; | 354 | size_t fw_status_priv_len; |
355 | |||
356 | /* RX Data filter rule state - enabled/disabled */ | ||
357 | bool rx_filter_enabled[WL1271_MAX_RX_FILTERS]; | ||
352 | }; | 358 | }; |
353 | 359 | ||
354 | int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); | 360 | int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); |
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 0ebbb1906c30..2027afe405fe 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c | |||
@@ -1962,9 +1962,6 @@ static int __init netif_init(void) | |||
1962 | if (!xen_domain()) | 1962 | if (!xen_domain()) |
1963 | return -ENODEV; | 1963 | return -ENODEV; |
1964 | 1964 | ||
1965 | if (xen_initial_domain()) | ||
1966 | return 0; | ||
1967 | |||
1968 | if (xen_hvm_domain() && !xen_platform_pci_unplug) | 1965 | if (xen_hvm_domain() && !xen_platform_pci_unplug) |
1969 | return -ENODEV; | 1966 | return -ENODEV; |
1970 | 1967 | ||
@@ -1977,9 +1974,6 @@ module_init(netif_init); | |||
1977 | 1974 | ||
1978 | static void __exit netif_exit(void) | 1975 | static void __exit netif_exit(void) |
1979 | { | 1976 | { |
1980 | if (xen_initial_domain()) | ||
1981 | return; | ||
1982 | |||
1983 | xenbus_unregister_driver(&netfront_driver); | 1977 | xenbus_unregister_driver(&netfront_driver); |
1984 | } | 1978 | } |
1985 | module_exit(netif_exit); | 1979 | module_exit(netif_exit); |
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig index 5af959274d4e..3b20b73ee649 100644 --- a/drivers/nfc/Kconfig +++ b/drivers/nfc/Kconfig | |||
@@ -17,6 +17,19 @@ config PN544_NFC | |||
17 | To compile this driver as a module, choose m here. The module will | 17 | To compile this driver as a module, choose m here. The module will |
18 | be called pn544. | 18 | be called pn544. |
19 | 19 | ||
20 | config PN544_HCI_NFC | ||
21 | tristate "HCI PN544 NFC driver" | ||
22 | depends on I2C && NFC_SHDLC | ||
23 | select CRC_CCITT | ||
24 | default n | ||
25 | ---help--- | ||
26 | NXP PN544 i2c driver. | ||
27 | This is a driver based on the SHDLC and HCI NFC kernel layers and | ||
28 | will thus not work with NXP libnfc library. | ||
29 | |||
30 | To compile this driver as a module, choose m here. The module will | ||
31 | be called pn544_hci. | ||
32 | |||
20 | config NFC_PN533 | 33 | config NFC_PN533 |
21 | tristate "NXP PN533 USB driver" | 34 | tristate "NXP PN533 USB driver" |
22 | depends on USB | 35 | depends on USB |
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile index ab99e8572f02..473e44cef612 100644 --- a/drivers/nfc/Makefile +++ b/drivers/nfc/Makefile | |||
@@ -3,6 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_PN544_NFC) += pn544.o | 5 | obj-$(CONFIG_PN544_NFC) += pn544.o |
6 | obj-$(CONFIG_PN544_HCI_NFC) += pn544_hci.o | ||
6 | obj-$(CONFIG_NFC_PN533) += pn533.o | 7 | obj-$(CONFIG_NFC_PN533) += pn533.o |
7 | obj-$(CONFIG_NFC_WILINK) += nfcwilink.o | 8 | obj-$(CONFIG_NFC_WILINK) += nfcwilink.o |
8 | 9 | ||
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index e6ec16d92e65..19110f0eb15f 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c | |||
@@ -394,9 +394,6 @@ static void pn533_wq_cmd_complete(struct work_struct *work) | |||
394 | struct pn533_frame *in_frame; | 394 | struct pn533_frame *in_frame; |
395 | int rc; | 395 | int rc; |
396 | 396 | ||
397 | if (dev == NULL) | ||
398 | return; | ||
399 | |||
400 | in_frame = dev->wq_in_frame; | 397 | in_frame = dev->wq_in_frame; |
401 | 398 | ||
402 | if (dev->wq_in_error) | 399 | if (dev->wq_in_error) |
@@ -1194,8 +1191,8 @@ static int pn533_activate_target_nfcdep(struct pn533 *dev) | |||
1194 | return rc; | 1191 | return rc; |
1195 | } | 1192 | } |
1196 | 1193 | ||
1197 | static int pn533_activate_target(struct nfc_dev *nfc_dev, u32 target_idx, | 1194 | static int pn533_activate_target(struct nfc_dev *nfc_dev, |
1198 | u32 protocol) | 1195 | struct nfc_target *target, u32 protocol) |
1199 | { | 1196 | { |
1200 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 1197 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
1201 | int rc; | 1198 | int rc; |
@@ -1243,7 +1240,8 @@ static int pn533_activate_target(struct nfc_dev *nfc_dev, u32 target_idx, | |||
1243 | return 0; | 1240 | return 0; |
1244 | } | 1241 | } |
1245 | 1242 | ||
1246 | static void pn533_deactivate_target(struct nfc_dev *nfc_dev, u32 target_idx) | 1243 | static void pn533_deactivate_target(struct nfc_dev *nfc_dev, |
1244 | struct nfc_target *target) | ||
1247 | { | 1245 | { |
1248 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 1246 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
1249 | u8 tg; | 1247 | u8 tg; |
@@ -1351,7 +1349,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, | |||
1351 | return 0; | 1349 | return 0; |
1352 | } | 1350 | } |
1353 | 1351 | ||
1354 | static int pn533_dep_link_up(struct nfc_dev *nfc_dev, int target_idx, | 1352 | static int pn533_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, |
1355 | u8 comm_mode, u8* gb, size_t gb_len) | 1353 | u8 comm_mode, u8* gb, size_t gb_len) |
1356 | { | 1354 | { |
1357 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 1355 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
@@ -1552,10 +1550,9 @@ error: | |||
1552 | return 0; | 1550 | return 0; |
1553 | } | 1551 | } |
1554 | 1552 | ||
1555 | static int pn533_data_exchange(struct nfc_dev *nfc_dev, u32 target_idx, | 1553 | static int pn533_data_exchange(struct nfc_dev *nfc_dev, |
1556 | struct sk_buff *skb, | 1554 | struct nfc_target *target, struct sk_buff *skb, |
1557 | data_exchange_cb_t cb, | 1555 | data_exchange_cb_t cb, void *cb_context) |
1558 | void *cb_context) | ||
1559 | { | 1556 | { |
1560 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); | 1557 | struct pn533 *dev = nfc_get_drvdata(nfc_dev); |
1561 | struct pn533_frame *out_frame, *in_frame; | 1558 | struct pn533_frame *out_frame, *in_frame; |
diff --git a/drivers/nfc/pn544_hci.c b/drivers/nfc/pn544_hci.c new file mode 100644 index 000000000000..46f4a9f9f5e4 --- /dev/null +++ b/drivers/nfc/pn544_hci.c | |||
@@ -0,0 +1,947 @@ | |||
1 | /* | ||
2 | * HCI based Driver for NXP PN544 NFC Chip | ||
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/delay.h> | ||
24 | #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 | |||
30 | #include <linux/nfc.h> | ||
31 | #include <net/nfc/hci.h> | ||
32 | #include <net/nfc/shdlc.h> | ||
33 | |||
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" | ||
39 | |||
40 | /* Timing restrictions (ms) */ | ||
41 | #define PN544_HCI_RESETVEN_TIME 30 | ||
42 | |||
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 | #define HCI_MODE 0 | ||
51 | #define FW_MODE 1 | ||
52 | |||
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 | enum pn544_state { | ||
63 | PN544_ST_COLD, | ||
64 | PN544_ST_FW_READY, | ||
65 | PN544_ST_READY, | ||
66 | }; | ||
67 | |||
68 | #define FULL_VERSION_LEN 11 | ||
69 | |||
70 | /* Proprietary commands */ | ||
71 | #define PN544_WRITE 0x3f | ||
72 | |||
73 | /* Proprietary gates, events, commands and registers */ | ||
74 | |||
75 | /* NFC_HCI_RF_READER_A_GATE additional registers and commands */ | ||
76 | #define PN544_RF_READER_A_AUTO_ACTIVATION 0x10 | ||
77 | #define PN544_RF_READER_A_CMD_CONTINUE_ACTIVATION 0x12 | ||
78 | #define PN544_MIFARE_CMD 0x21 | ||
79 | |||
80 | /* Commands that apply to all RF readers */ | ||
81 | #define PN544_RF_READER_CMD_PRESENCE_CHECK 0x30 | ||
82 | #define PN544_RF_READER_CMD_ACTIVATE_NEXT 0x32 | ||
83 | |||
84 | /* NFC_HCI_ID_MGMT_GATE additional registers */ | ||
85 | #define PN544_ID_MGMT_FULL_VERSION_SW 0x10 | ||
86 | |||
87 | #define PN544_RF_READER_ISO15693_GATE 0x12 | ||
88 | |||
89 | #define PN544_RF_READER_F_GATE 0x14 | ||
90 | #define PN544_FELICA_ID 0x04 | ||
91 | #define PN544_FELICA_RAW 0x20 | ||
92 | |||
93 | #define PN544_RF_READER_JEWEL_GATE 0x15 | ||
94 | #define PN544_JEWEL_RAW_CMD 0x23 | ||
95 | |||
96 | #define PN544_RF_READER_NFCIP1_INITIATOR_GATE 0x30 | ||
97 | #define PN544_RF_READER_NFCIP1_TARGET_GATE 0x31 | ||
98 | |||
99 | #define PN544_SYS_MGMT_GATE 0x90 | ||
100 | #define PN544_SYS_MGMT_INFO_NOTIFICATION 0x02 | ||
101 | |||
102 | #define PN544_POLLING_LOOP_MGMT_GATE 0x94 | ||
103 | #define PN544_PL_RDPHASES 0x06 | ||
104 | #define PN544_PL_EMULATION 0x07 | ||
105 | #define PN544_PL_NFCT_DEACTIVATED 0x09 | ||
106 | |||
107 | #define PN544_SWP_MGMT_GATE 0xA0 | ||
108 | |||
109 | #define PN544_NFC_WI_MGMT_GATE 0xA1 | ||
110 | |||
111 | static u8 pn544_custom_gates[] = { | ||
112 | PN544_SYS_MGMT_GATE, | ||
113 | PN544_SWP_MGMT_GATE, | ||
114 | PN544_POLLING_LOOP_MGMT_GATE, | ||
115 | PN544_NFC_WI_MGMT_GATE, | ||
116 | PN544_RF_READER_F_GATE, | ||
117 | PN544_RF_READER_JEWEL_GATE, | ||
118 | PN544_RF_READER_ISO15693_GATE, | ||
119 | PN544_RF_READER_NFCIP1_INITIATOR_GATE, | ||
120 | PN544_RF_READER_NFCIP1_TARGET_GATE | ||
121 | }; | ||
122 | |||
123 | /* Largest headroom needed for outgoing custom commands */ | ||
124 | #define PN544_CMDS_HEADROOM 2 | ||
125 | |||
126 | struct pn544_hci_info { | ||
127 | struct i2c_client *i2c_dev; | ||
128 | struct nfc_shdlc *shdlc; | ||
129 | |||
130 | enum pn544_state state; | ||
131 | |||
132 | struct mutex info_lock; | ||
133 | |||
134 | unsigned int gpio_en; | ||
135 | unsigned int gpio_irq; | ||
136 | unsigned int gpio_fw; | ||
137 | unsigned int en_polarity; | ||
138 | |||
139 | int hard_fault; /* | ||
140 | * < 0 if hardware error occured (e.g. i2c err) | ||
141 | * and prevents normal operation. | ||
142 | */ | ||
143 | }; | ||
144 | |||
145 | static void pn544_hci_platform_init(struct pn544_hci_info *info) | ||
146 | { | ||
147 | int polarity, retry, ret; | ||
148 | char rset_cmd[] = { 0x05, 0xF9, 0x04, 0x00, 0xC3, 0xE5 }; | ||
149 | int count = sizeof(rset_cmd); | ||
150 | |||
151 | pr_info(DRIVER_DESC ": %s\n", __func__); | ||
152 | dev_info(&info->i2c_dev->dev, "Detecting nfc_en polarity\n"); | ||
153 | |||
154 | /* Disable fw download */ | ||
155 | gpio_set_value(info->gpio_fw, 0); | ||
156 | |||
157 | for (polarity = 0; polarity < 2; polarity++) { | ||
158 | info->en_polarity = polarity; | ||
159 | retry = 3; | ||
160 | while (retry--) { | ||
161 | /* power off */ | ||
162 | gpio_set_value(info->gpio_en, !info->en_polarity); | ||
163 | usleep_range(10000, 15000); | ||
164 | |||
165 | /* power on */ | ||
166 | gpio_set_value(info->gpio_en, info->en_polarity); | ||
167 | usleep_range(10000, 15000); | ||
168 | |||
169 | /* send reset */ | ||
170 | dev_dbg(&info->i2c_dev->dev, "Sending reset cmd\n"); | ||
171 | ret = i2c_master_send(info->i2c_dev, rset_cmd, count); | ||
172 | if (ret == count) { | ||
173 | dev_info(&info->i2c_dev->dev, | ||
174 | "nfc_en polarity : active %s\n", | ||
175 | (polarity == 0 ? "low" : "high")); | ||
176 | goto out; | ||
177 | } | ||
178 | } | ||
179 | } | ||
180 | |||
181 | dev_err(&info->i2c_dev->dev, | ||
182 | "Could not detect nfc_en polarity, fallback to active high\n"); | ||
183 | |||
184 | out: | ||
185 | gpio_set_value(info->gpio_en, !info->en_polarity); | ||
186 | } | ||
187 | |||
188 | static int pn544_hci_enable(struct pn544_hci_info *info, int mode) | ||
189 | { | ||
190 | pr_info(DRIVER_DESC ": %s\n", __func__); | ||
191 | |||
192 | gpio_set_value(info->gpio_fw, 0); | ||
193 | gpio_set_value(info->gpio_en, info->en_polarity); | ||
194 | usleep_range(10000, 15000); | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static void pn544_hci_disable(struct pn544_hci_info *info) | ||
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 | gpio_set_value(info->gpio_en, info->en_polarity); | ||
208 | usleep_range(10000, 15000); | ||
209 | |||
210 | gpio_set_value(info->gpio_en, !info->en_polarity); | ||
211 | usleep_range(10000, 15000); | ||
212 | } | ||
213 | |||
214 | static int pn544_hci_i2c_write(struct i2c_client *client, u8 *buf, int len) | ||
215 | { | ||
216 | int r; | ||
217 | |||
218 | usleep_range(3000, 6000); | ||
219 | |||
220 | r = i2c_master_send(client, buf, len); | ||
221 | |||
222 | if (r == -EREMOTEIO) { /* Retry, chip was in standby */ | ||
223 | usleep_range(6000, 10000); | ||
224 | r = i2c_master_send(client, buf, len); | ||
225 | } | ||
226 | |||
227 | if (r >= 0 && r != len) | ||
228 | r = -EREMOTEIO; | ||
229 | |||
230 | return r; | ||
231 | } | ||
232 | |||
233 | static int check_crc(u8 *buf, int buflen) | ||
234 | { | ||
235 | u8 len; | ||
236 | u16 crc; | ||
237 | |||
238 | len = buf[0] + 1; | ||
239 | crc = crc_ccitt(0xffff, buf, len - 2); | ||
240 | crc = ~crc; | ||
241 | |||
242 | if (buf[len - 2] != (crc & 0xff) || buf[len - 1] != (crc >> 8)) { | ||
243 | pr_err(PN544_HCI_DRIVER_NAME ": CRC error 0x%x != 0x%x 0x%x\n", | ||
244 | crc, buf[len - 1], buf[len - 2]); | ||
245 | |||
246 | pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__); | ||
247 | print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE, | ||
248 | 16, 2, buf, buflen, false); | ||
249 | return -EPERM; | ||
250 | } | ||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | /* | ||
255 | * Reads an shdlc frame and returns it in a newly allocated sk_buff. Guarantees | ||
256 | * that i2c bus will be flushed and that next read will start on a new frame. | ||
257 | * returned skb contains only LLC header and payload. | ||
258 | * returns: | ||
259 | * -EREMOTEIO : i2c read error (fatal) | ||
260 | * -EBADMSG : frame was incorrect and discarded | ||
261 | * -ENOMEM : cannot allocate skb, frame dropped | ||
262 | */ | ||
263 | static int pn544_hci_i2c_read(struct i2c_client *client, struct sk_buff **skb) | ||
264 | { | ||
265 | int r; | ||
266 | u8 len; | ||
267 | u8 tmp[PN544_HCI_LLC_MAX_SIZE - 1]; | ||
268 | |||
269 | r = i2c_master_recv(client, &len, 1); | ||
270 | if (r != 1) { | ||
271 | dev_err(&client->dev, "cannot read len byte\n"); | ||
272 | return -EREMOTEIO; | ||
273 | } | ||
274 | |||
275 | if ((len < (PN544_HCI_LLC_MIN_SIZE - 1)) || | ||
276 | (len > (PN544_HCI_LLC_MAX_SIZE - 1))) { | ||
277 | dev_err(&client->dev, "invalid len byte\n"); | ||
278 | r = -EBADMSG; | ||
279 | goto flush; | ||
280 | } | ||
281 | |||
282 | *skb = alloc_skb(1 + len, GFP_KERNEL); | ||
283 | if (*skb == NULL) { | ||
284 | r = -ENOMEM; | ||
285 | goto flush; | ||
286 | } | ||
287 | |||
288 | *skb_put(*skb, 1) = len; | ||
289 | |||
290 | r = i2c_master_recv(client, skb_put(*skb, len), len); | ||
291 | if (r != len) { | ||
292 | kfree_skb(*skb); | ||
293 | return -EREMOTEIO; | ||
294 | } | ||
295 | |||
296 | r = check_crc((*skb)->data, (*skb)->len); | ||
297 | if (r != 0) { | ||
298 | kfree_skb(*skb); | ||
299 | r = -EBADMSG; | ||
300 | goto flush; | ||
301 | } | ||
302 | |||
303 | skb_pull(*skb, 1); | ||
304 | skb_trim(*skb, (*skb)->len - 2); | ||
305 | |||
306 | usleep_range(3000, 6000); | ||
307 | |||
308 | return 0; | ||
309 | |||
310 | flush: | ||
311 | if (i2c_master_recv(client, tmp, sizeof(tmp)) < 0) | ||
312 | r = -EREMOTEIO; | ||
313 | |||
314 | usleep_range(3000, 6000); | ||
315 | |||
316 | return r; | ||
317 | } | ||
318 | |||
319 | /* | ||
320 | * Reads an shdlc frame from the chip. This is not as straightforward as it | ||
321 | * seems. There are cases where we could loose the frame start synchronization. | ||
322 | * The frame format is len-data-crc, and corruption can occur anywhere while | ||
323 | * transiting on i2c bus, such that we could read an invalid len. | ||
324 | * In order to recover synchronization with the next frame, we must be sure | ||
325 | * to read the real amount of data without using the len byte. We do this by | ||
326 | * assuming the following: | ||
327 | * - the chip will always present only one single complete frame on the bus | ||
328 | * before triggering the interrupt | ||
329 | * - the chip will not present a new frame until we have completely read | ||
330 | * the previous one (or until we have handled the interrupt). | ||
331 | * The tricky case is when we read a corrupted len that is less than the real | ||
332 | * len. We must detect this here in order to determine that we need to flush | ||
333 | * the bus. This is the reason why we check the crc here. | ||
334 | */ | ||
335 | static irqreturn_t pn544_hci_irq_thread_fn(int irq, void *dev_id) | ||
336 | { | ||
337 | struct pn544_hci_info *info = dev_id; | ||
338 | struct i2c_client *client = info->i2c_dev; | ||
339 | struct sk_buff *skb = NULL; | ||
340 | int r; | ||
341 | |||
342 | BUG_ON(!info); | ||
343 | BUG_ON(irq != info->i2c_dev->irq); | ||
344 | |||
345 | dev_dbg(&client->dev, "IRQ\n"); | ||
346 | |||
347 | if (info->hard_fault != 0) | ||
348 | return IRQ_HANDLED; | ||
349 | |||
350 | r = pn544_hci_i2c_read(client, &skb); | ||
351 | if (r == -EREMOTEIO) { | ||
352 | info->hard_fault = r; | ||
353 | |||
354 | nfc_shdlc_recv_frame(info->shdlc, NULL); | ||
355 | |||
356 | return IRQ_HANDLED; | ||
357 | } else if ((r == -ENOMEM) || (r == -EBADMSG)) { | ||
358 | return IRQ_HANDLED; | ||
359 | } | ||
360 | |||
361 | nfc_shdlc_recv_frame(info->shdlc, skb); | ||
362 | |||
363 | return IRQ_HANDLED; | ||
364 | } | ||
365 | |||
366 | static int pn544_hci_open(struct nfc_shdlc *shdlc) | ||
367 | { | ||
368 | struct pn544_hci_info *info = nfc_shdlc_get_clientdata(shdlc); | ||
369 | int r = 0; | ||
370 | |||
371 | mutex_lock(&info->info_lock); | ||
372 | |||
373 | if (info->state != PN544_ST_COLD) { | ||
374 | r = -EBUSY; | ||
375 | goto out; | ||
376 | } | ||
377 | |||
378 | r = pn544_hci_enable(info, HCI_MODE); | ||
379 | |||
380 | out: | ||
381 | mutex_unlock(&info->info_lock); | ||
382 | return r; | ||
383 | } | ||
384 | |||
385 | static void pn544_hci_close(struct nfc_shdlc *shdlc) | ||
386 | { | ||
387 | struct pn544_hci_info *info = nfc_shdlc_get_clientdata(shdlc); | ||
388 | |||
389 | mutex_lock(&info->info_lock); | ||
390 | |||
391 | if (info->state == PN544_ST_COLD) | ||
392 | goto out; | ||
393 | |||
394 | pn544_hci_disable(info); | ||
395 | |||
396 | out: | ||
397 | mutex_unlock(&info->info_lock); | ||
398 | } | ||
399 | |||
400 | static int pn544_hci_ready(struct nfc_shdlc *shdlc) | ||
401 | { | ||
402 | struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc); | ||
403 | struct sk_buff *skb; | ||
404 | static struct hw_config { | ||
405 | u8 adr[2]; | ||
406 | u8 value; | ||
407 | } hw_config[] = { | ||
408 | {{0x9f, 0x9a}, 0x00}, | ||
409 | |||
410 | {{0x98, 0x10}, 0xbc}, | ||
411 | |||
412 | {{0x9e, 0x71}, 0x00}, | ||
413 | |||
414 | {{0x98, 0x09}, 0x00}, | ||
415 | |||
416 | {{0x9e, 0xb4}, 0x00}, | ||
417 | |||
418 | {{0x9e, 0xd9}, 0xff}, | ||
419 | {{0x9e, 0xda}, 0xff}, | ||
420 | {{0x9e, 0xdb}, 0x23}, | ||
421 | {{0x9e, 0xdc}, 0x21}, | ||
422 | {{0x9e, 0xdd}, 0x22}, | ||
423 | {{0x9e, 0xde}, 0x24}, | ||
424 | |||
425 | {{0x9c, 0x01}, 0x08}, | ||
426 | |||
427 | {{0x9e, 0xaa}, 0x01}, | ||
428 | |||
429 | {{0x9b, 0xd1}, 0x0d}, | ||
430 | {{0x9b, 0xd2}, 0x24}, | ||
431 | {{0x9b, 0xd3}, 0x0a}, | ||
432 | {{0x9b, 0xd4}, 0x22}, | ||
433 | {{0x9b, 0xd5}, 0x08}, | ||
434 | {{0x9b, 0xd6}, 0x1e}, | ||
435 | {{0x9b, 0xdd}, 0x1c}, | ||
436 | |||
437 | {{0x9b, 0x84}, 0x13}, | ||
438 | {{0x99, 0x81}, 0x7f}, | ||
439 | {{0x99, 0x31}, 0x70}, | ||
440 | |||
441 | {{0x98, 0x00}, 0x3f}, | ||
442 | |||
443 | {{0x9f, 0x09}, 0x00}, | ||
444 | |||
445 | {{0x9f, 0x0a}, 0x05}, | ||
446 | |||
447 | {{0x9e, 0xd1}, 0xa1}, | ||
448 | {{0x99, 0x23}, 0x00}, | ||
449 | |||
450 | {{0x9e, 0x74}, 0x80}, | ||
451 | |||
452 | {{0x9f, 0x28}, 0x10}, | ||
453 | |||
454 | {{0x9f, 0x35}, 0x14}, | ||
455 | |||
456 | {{0x9f, 0x36}, 0x60}, | ||
457 | |||
458 | {{0x9c, 0x31}, 0x00}, | ||
459 | |||
460 | {{0x9c, 0x32}, 0xc8}, | ||
461 | |||
462 | {{0x9c, 0x19}, 0x40}, | ||
463 | |||
464 | {{0x9c, 0x1a}, 0x40}, | ||
465 | |||
466 | {{0x9c, 0x0c}, 0x00}, | ||
467 | |||
468 | {{0x9c, 0x0d}, 0x00}, | ||
469 | |||
470 | {{0x9c, 0x12}, 0x00}, | ||
471 | |||
472 | {{0x9c, 0x13}, 0x00}, | ||
473 | |||
474 | {{0x98, 0xa2}, 0x0e}, | ||
475 | |||
476 | {{0x98, 0x93}, 0x40}, | ||
477 | |||
478 | {{0x98, 0x7d}, 0x02}, | ||
479 | {{0x98, 0x7e}, 0x00}, | ||
480 | {{0x9f, 0xc8}, 0x01}, | ||
481 | }; | ||
482 | struct hw_config *p = hw_config; | ||
483 | int count = ARRAY_SIZE(hw_config); | ||
484 | struct sk_buff *res_skb; | ||
485 | u8 param[4]; | ||
486 | int r; | ||
487 | |||
488 | param[0] = 0; | ||
489 | while (count--) { | ||
490 | param[1] = p->adr[0]; | ||
491 | param[2] = p->adr[1]; | ||
492 | param[3] = p->value; | ||
493 | |||
494 | r = nfc_hci_send_cmd(hdev, PN544_SYS_MGMT_GATE, PN544_WRITE, | ||
495 | param, 4, &res_skb); | ||
496 | if (r < 0) | ||
497 | return r; | ||
498 | |||
499 | if (res_skb->len != 1) { | ||
500 | kfree_skb(res_skb); | ||
501 | return -EPROTO; | ||
502 | } | ||
503 | |||
504 | if (res_skb->data[0] != p->value) { | ||
505 | kfree_skb(res_skb); | ||
506 | return -EIO; | ||
507 | } | ||
508 | |||
509 | kfree_skb(res_skb); | ||
510 | |||
511 | p++; | ||
512 | } | ||
513 | |||
514 | param[0] = NFC_HCI_UICC_HOST_ID; | ||
515 | r = nfc_hci_set_param(hdev, NFC_HCI_ADMIN_GATE, | ||
516 | NFC_HCI_ADMIN_WHITELIST, param, 1); | ||
517 | if (r < 0) | ||
518 | return r; | ||
519 | |||
520 | param[0] = 0x3d; | ||
521 | r = nfc_hci_set_param(hdev, PN544_SYS_MGMT_GATE, | ||
522 | PN544_SYS_MGMT_INFO_NOTIFICATION, param, 1); | ||
523 | if (r < 0) | ||
524 | return r; | ||
525 | |||
526 | param[0] = 0x0; | ||
527 | r = nfc_hci_set_param(hdev, NFC_HCI_RF_READER_A_GATE, | ||
528 | PN544_RF_READER_A_AUTO_ACTIVATION, param, 1); | ||
529 | if (r < 0) | ||
530 | return r; | ||
531 | |||
532 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | ||
533 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | ||
534 | if (r < 0) | ||
535 | return r; | ||
536 | |||
537 | param[0] = 0x1; | ||
538 | r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, | ||
539 | PN544_PL_NFCT_DEACTIVATED, param, 1); | ||
540 | if (r < 0) | ||
541 | return r; | ||
542 | |||
543 | param[0] = 0x0; | ||
544 | r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, | ||
545 | PN544_PL_RDPHASES, param, 1); | ||
546 | if (r < 0) | ||
547 | return r; | ||
548 | |||
549 | r = nfc_hci_get_param(hdev, NFC_HCI_ID_MGMT_GATE, | ||
550 | PN544_ID_MGMT_FULL_VERSION_SW, &skb); | ||
551 | if (r < 0) | ||
552 | return r; | ||
553 | |||
554 | if (skb->len != FULL_VERSION_LEN) { | ||
555 | kfree_skb(skb); | ||
556 | return -EINVAL; | ||
557 | } | ||
558 | |||
559 | print_hex_dump(KERN_DEBUG, "FULL VERSION SOFTWARE INFO: ", | ||
560 | DUMP_PREFIX_NONE, 16, 1, | ||
561 | skb->data, FULL_VERSION_LEN, false); | ||
562 | |||
563 | kfree_skb(skb); | ||
564 | |||
565 | return 0; | ||
566 | } | ||
567 | |||
568 | static int pn544_hci_xmit(struct nfc_shdlc *shdlc, struct sk_buff *skb) | ||
569 | { | ||
570 | struct pn544_hci_info *info = nfc_shdlc_get_clientdata(shdlc); | ||
571 | struct i2c_client *client = info->i2c_dev; | ||
572 | |||
573 | if (info->hard_fault != 0) | ||
574 | return info->hard_fault; | ||
575 | |||
576 | return pn544_hci_i2c_write(client, skb->data, skb->len); | ||
577 | } | ||
578 | |||
579 | static int pn544_hci_start_poll(struct nfc_shdlc *shdlc, u32 protocols) | ||
580 | { | ||
581 | struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc); | ||
582 | u8 phases = 0; | ||
583 | int r; | ||
584 | u8 duration[2]; | ||
585 | u8 activated; | ||
586 | |||
587 | pr_info(DRIVER_DESC ": %s protocols = %d\n", __func__, protocols); | ||
588 | |||
589 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | ||
590 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | ||
591 | if (r < 0) | ||
592 | return r; | ||
593 | |||
594 | duration[0] = 0x18; | ||
595 | duration[1] = 0x6a; | ||
596 | r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, | ||
597 | PN544_PL_EMULATION, duration, 2); | ||
598 | if (r < 0) | ||
599 | return r; | ||
600 | |||
601 | activated = 0; | ||
602 | r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, | ||
603 | PN544_PL_NFCT_DEACTIVATED, &activated, 1); | ||
604 | if (r < 0) | ||
605 | return r; | ||
606 | |||
607 | if (protocols & (NFC_PROTO_ISO14443_MASK | NFC_PROTO_MIFARE_MASK | | ||
608 | NFC_PROTO_JEWEL_MASK)) | ||
609 | phases |= 1; /* Type A */ | ||
610 | if (protocols & NFC_PROTO_FELICA_MASK) { | ||
611 | phases |= (1 << 2); /* Type F 212 */ | ||
612 | phases |= (1 << 3); /* Type F 424 */ | ||
613 | } | ||
614 | |||
615 | phases |= (1 << 5); /* NFC active */ | ||
616 | |||
617 | r = nfc_hci_set_param(hdev, PN544_POLLING_LOOP_MGMT_GATE, | ||
618 | PN544_PL_RDPHASES, &phases, 1); | ||
619 | if (r < 0) | ||
620 | return r; | ||
621 | |||
622 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | ||
623 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); | ||
624 | if (r < 0) | ||
625 | nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | ||
626 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | ||
627 | |||
628 | return r; | ||
629 | } | ||
630 | |||
631 | static int pn544_hci_target_from_gate(struct nfc_shdlc *shdlc, u8 gate, | ||
632 | struct nfc_target *target) | ||
633 | { | ||
634 | switch (gate) { | ||
635 | case PN544_RF_READER_F_GATE: | ||
636 | target->supported_protocols = NFC_PROTO_FELICA_MASK; | ||
637 | break; | ||
638 | case PN544_RF_READER_JEWEL_GATE: | ||
639 | target->supported_protocols = NFC_PROTO_JEWEL_MASK; | ||
640 | target->sens_res = 0x0c00; | ||
641 | break; | ||
642 | default: | ||
643 | return -EPROTO; | ||
644 | } | ||
645 | |||
646 | return 0; | ||
647 | } | ||
648 | |||
649 | static int pn544_hci_complete_target_discovered(struct nfc_shdlc *shdlc, | ||
650 | u8 gate, | ||
651 | struct nfc_target *target) | ||
652 | { | ||
653 | struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc); | ||
654 | struct sk_buff *uid_skb; | ||
655 | int r = 0; | ||
656 | |||
657 | if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) { | ||
658 | if (target->nfcid1_len != 4 && target->nfcid1_len != 7 && | ||
659 | target->nfcid1_len != 10) | ||
660 | return -EPROTO; | ||
661 | |||
662 | r = nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE, | ||
663 | PN544_RF_READER_CMD_ACTIVATE_NEXT, | ||
664 | target->nfcid1, target->nfcid1_len, NULL); | ||
665 | } else if (target->supported_protocols & NFC_PROTO_FELICA_MASK) { | ||
666 | r = nfc_hci_get_param(hdev, PN544_RF_READER_F_GATE, | ||
667 | PN544_FELICA_ID, &uid_skb); | ||
668 | if (r < 0) | ||
669 | return r; | ||
670 | |||
671 | if (uid_skb->len != 8) { | ||
672 | kfree_skb(uid_skb); | ||
673 | return -EPROTO; | ||
674 | } | ||
675 | |||
676 | r = nfc_hci_send_cmd(hdev, PN544_RF_READER_F_GATE, | ||
677 | PN544_RF_READER_CMD_ACTIVATE_NEXT, | ||
678 | uid_skb->data, uid_skb->len, NULL); | ||
679 | kfree_skb(uid_skb); | ||
680 | } else if (target->supported_protocols & NFC_PROTO_ISO14443_MASK) { | ||
681 | /* | ||
682 | * TODO: maybe other ISO 14443 require some kind of continue | ||
683 | * activation, but for now we've seen only this one below. | ||
684 | */ | ||
685 | if (target->sens_res == 0x4403) /* Type 4 Mifare DESFire */ | ||
686 | r = nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE, | ||
687 | PN544_RF_READER_A_CMD_CONTINUE_ACTIVATION, | ||
688 | NULL, 0, NULL); | ||
689 | } | ||
690 | |||
691 | return r; | ||
692 | } | ||
693 | |||
694 | #define MIFARE_CMD_AUTH_KEY_A 0x60 | ||
695 | #define MIFARE_CMD_AUTH_KEY_B 0x61 | ||
696 | #define MIFARE_CMD_HEADER 2 | ||
697 | #define MIFARE_UID_LEN 4 | ||
698 | #define MIFARE_KEY_LEN 6 | ||
699 | #define MIFARE_CMD_LEN 12 | ||
700 | /* | ||
701 | * Returns: | ||
702 | * <= 0: driver handled the data exchange | ||
703 | * 1: driver doesn't especially handle, please do standard processing | ||
704 | */ | ||
705 | static int pn544_hci_data_exchange(struct nfc_shdlc *shdlc, | ||
706 | struct nfc_target *target, | ||
707 | struct sk_buff *skb, | ||
708 | struct sk_buff **res_skb) | ||
709 | { | ||
710 | struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc); | ||
711 | int r; | ||
712 | |||
713 | pr_info(DRIVER_DESC ": %s for gate=%d\n", __func__, | ||
714 | target->hci_reader_gate); | ||
715 | |||
716 | switch (target->hci_reader_gate) { | ||
717 | case NFC_HCI_RF_READER_A_GATE: | ||
718 | if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) { | ||
719 | /* | ||
720 | * It seems that pn544 is inverting key and UID for | ||
721 | * MIFARE authentication commands. | ||
722 | */ | ||
723 | if (skb->len == MIFARE_CMD_LEN && | ||
724 | (skb->data[0] == MIFARE_CMD_AUTH_KEY_A || | ||
725 | skb->data[0] == MIFARE_CMD_AUTH_KEY_B)) { | ||
726 | u8 uid[MIFARE_UID_LEN]; | ||
727 | u8 *data = skb->data + MIFARE_CMD_HEADER; | ||
728 | |||
729 | memcpy(uid, data + MIFARE_KEY_LEN, | ||
730 | MIFARE_UID_LEN); | ||
731 | memmove(data + MIFARE_UID_LEN, data, | ||
732 | MIFARE_KEY_LEN); | ||
733 | memcpy(data, uid, MIFARE_UID_LEN); | ||
734 | } | ||
735 | |||
736 | return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | ||
737 | PN544_MIFARE_CMD, | ||
738 | skb->data, skb->len, res_skb); | ||
739 | } else | ||
740 | return 1; | ||
741 | case PN544_RF_READER_F_GATE: | ||
742 | *skb_push(skb, 1) = 0; | ||
743 | *skb_push(skb, 1) = 0; | ||
744 | |||
745 | r = nfc_hci_send_cmd(hdev, target->hci_reader_gate, | ||
746 | PN544_FELICA_RAW, | ||
747 | skb->data, skb->len, res_skb); | ||
748 | if (r == 0) | ||
749 | skb_pull(*res_skb, 1); | ||
750 | return r; | ||
751 | case PN544_RF_READER_JEWEL_GATE: | ||
752 | return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | ||
753 | PN544_JEWEL_RAW_CMD, | ||
754 | skb->data, skb->len, res_skb); | ||
755 | default: | ||
756 | return 1; | ||
757 | } | ||
758 | } | ||
759 | |||
760 | static int pn544_hci_check_presence(struct nfc_shdlc *shdlc, | ||
761 | struct nfc_target *target) | ||
762 | { | ||
763 | struct nfc_hci_dev *hdev = nfc_shdlc_get_hci_dev(shdlc); | ||
764 | |||
765 | return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | ||
766 | PN544_RF_READER_CMD_PRESENCE_CHECK, | ||
767 | NULL, 0, NULL); | ||
768 | } | ||
769 | |||
770 | static struct nfc_shdlc_ops pn544_shdlc_ops = { | ||
771 | .open = pn544_hci_open, | ||
772 | .close = pn544_hci_close, | ||
773 | .hci_ready = pn544_hci_ready, | ||
774 | .xmit = pn544_hci_xmit, | ||
775 | .start_poll = pn544_hci_start_poll, | ||
776 | .target_from_gate = pn544_hci_target_from_gate, | ||
777 | .complete_target_discovered = pn544_hci_complete_target_discovered, | ||
778 | .data_exchange = pn544_hci_data_exchange, | ||
779 | .check_presence = pn544_hci_check_presence, | ||
780 | }; | ||
781 | |||
782 | static int __devinit pn544_hci_probe(struct i2c_client *client, | ||
783 | const struct i2c_device_id *id) | ||
784 | { | ||
785 | struct pn544_hci_info *info; | ||
786 | struct pn544_nfc_platform_data *pdata; | ||
787 | int r = 0; | ||
788 | u32 protocols; | ||
789 | struct nfc_hci_init_data init_data; | ||
790 | |||
791 | dev_dbg(&client->dev, "%s\n", __func__); | ||
792 | dev_dbg(&client->dev, "IRQ: %d\n", client->irq); | ||
793 | |||
794 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
795 | dev_err(&client->dev, "Need I2C_FUNC_I2C\n"); | ||
796 | return -ENODEV; | ||
797 | } | ||
798 | |||
799 | info = kzalloc(sizeof(struct pn544_hci_info), GFP_KERNEL); | ||
800 | if (!info) { | ||
801 | dev_err(&client->dev, | ||
802 | "Cannot allocate memory for pn544_hci_info.\n"); | ||
803 | r = -ENOMEM; | ||
804 | goto err_info_alloc; | ||
805 | } | ||
806 | |||
807 | info->i2c_dev = client; | ||
808 | info->state = PN544_ST_COLD; | ||
809 | mutex_init(&info->info_lock); | ||
810 | i2c_set_clientdata(client, info); | ||
811 | |||
812 | pdata = client->dev.platform_data; | ||
813 | if (pdata == NULL) { | ||
814 | dev_err(&client->dev, "No platform data\n"); | ||
815 | r = -EINVAL; | ||
816 | goto err_pdata; | ||
817 | } | ||
818 | |||
819 | if (pdata->request_resources == NULL) { | ||
820 | dev_err(&client->dev, "request_resources() missing\n"); | ||
821 | r = -EINVAL; | ||
822 | goto err_pdata; | ||
823 | } | ||
824 | |||
825 | r = pdata->request_resources(client); | ||
826 | if (r) { | ||
827 | dev_err(&client->dev, "Cannot get platform resources\n"); | ||
828 | goto err_pdata; | ||
829 | } | ||
830 | |||
831 | info->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE); | ||
832 | info->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET); | ||
833 | info->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ); | ||
834 | |||
835 | pn544_hci_platform_init(info); | ||
836 | |||
837 | r = request_threaded_irq(client->irq, NULL, pn544_hci_irq_thread_fn, | ||
838 | IRQF_TRIGGER_RISING, PN544_HCI_DRIVER_NAME, | ||
839 | info); | ||
840 | if (r < 0) { | ||
841 | dev_err(&client->dev, "Unable to register IRQ handler\n"); | ||
842 | goto err_rti; | ||
843 | } | ||
844 | |||
845 | init_data.gate_count = ARRAY_SIZE(pn544_custom_gates); | ||
846 | |||
847 | memcpy(init_data.gates, pn544_custom_gates, | ||
848 | ARRAY_SIZE(pn544_custom_gates)); | ||
849 | |||
850 | /* | ||
851 | * TODO: Session id must include the driver name + some bus addr | ||
852 | * persistent info to discriminate 2 identical chips | ||
853 | */ | ||
854 | strcpy(init_data.session_id, "ID544HCI"); | ||
855 | |||
856 | protocols = NFC_PROTO_JEWEL_MASK | | ||
857 | NFC_PROTO_MIFARE_MASK | | ||
858 | NFC_PROTO_FELICA_MASK | | ||
859 | NFC_PROTO_ISO14443_MASK | | ||
860 | NFC_PROTO_NFC_DEP_MASK; | ||
861 | |||
862 | info->shdlc = nfc_shdlc_allocate(&pn544_shdlc_ops, | ||
863 | &init_data, protocols, | ||
864 | PN544_CMDS_HEADROOM, 0, | ||
865 | PN544_HCI_LLC_MAX_PAYLOAD, | ||
866 | dev_name(&client->dev)); | ||
867 | if (!info->shdlc) { | ||
868 | dev_err(&client->dev, "Cannot allocate nfc shdlc.\n"); | ||
869 | r = -ENOMEM; | ||
870 | goto err_allocshdlc; | ||
871 | } | ||
872 | |||
873 | nfc_shdlc_set_clientdata(info->shdlc, info); | ||
874 | |||
875 | return 0; | ||
876 | |||
877 | err_allocshdlc: | ||
878 | free_irq(client->irq, info); | ||
879 | |||
880 | err_rti: | ||
881 | if (pdata->free_resources != NULL) | ||
882 | pdata->free_resources(); | ||
883 | |||
884 | err_pdata: | ||
885 | kfree(info); | ||
886 | |||
887 | err_info_alloc: | ||
888 | return r; | ||
889 | } | ||
890 | |||
891 | static __devexit int pn544_hci_remove(struct i2c_client *client) | ||
892 | { | ||
893 | struct pn544_hci_info *info = i2c_get_clientdata(client); | ||
894 | struct pn544_nfc_platform_data *pdata = client->dev.platform_data; | ||
895 | |||
896 | dev_dbg(&client->dev, "%s\n", __func__); | ||
897 | |||
898 | nfc_shdlc_free(info->shdlc); | ||
899 | |||
900 | if (info->state != PN544_ST_COLD) { | ||
901 | if (pdata->disable) | ||
902 | pdata->disable(); | ||
903 | } | ||
904 | |||
905 | free_irq(client->irq, info); | ||
906 | if (pdata->free_resources) | ||
907 | pdata->free_resources(); | ||
908 | |||
909 | kfree(info); | ||
910 | |||
911 | return 0; | ||
912 | } | ||
913 | |||
914 | static struct i2c_driver pn544_hci_driver = { | ||
915 | .driver = { | ||
916 | .name = PN544_HCI_DRIVER_NAME, | ||
917 | }, | ||
918 | .probe = pn544_hci_probe, | ||
919 | .id_table = pn544_hci_id_table, | ||
920 | .remove = __devexit_p(pn544_hci_remove), | ||
921 | }; | ||
922 | |||
923 | static int __init pn544_hci_init(void) | ||
924 | { | ||
925 | int r; | ||
926 | |||
927 | pr_debug(DRIVER_DESC ": %s\n", __func__); | ||
928 | |||
929 | r = i2c_add_driver(&pn544_hci_driver); | ||
930 | if (r) { | ||
931 | pr_err(PN544_HCI_DRIVER_NAME ": driver registration failed\n"); | ||
932 | return r; | ||
933 | } | ||
934 | |||
935 | return 0; | ||
936 | } | ||
937 | |||
938 | static void __exit pn544_hci_exit(void) | ||
939 | { | ||
940 | i2c_del_driver(&pn544_hci_driver); | ||
941 | } | ||
942 | |||
943 | module_init(pn544_hci_init); | ||
944 | module_exit(pn544_hci_exit); | ||
945 | |||
946 | MODULE_LICENSE("GPL"); | ||
947 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c index bad7ba517a1c..f551e5376147 100644 --- a/drivers/ssb/b43_pci_bridge.c +++ b/drivers/ssb/b43_pci_bridge.c | |||
@@ -29,6 +29,8 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = { | |||
29 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) }, | 29 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) }, |
30 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) }, | 30 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) }, |
31 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) }, | 31 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) }, |
32 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4322) }, | ||
33 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43222) }, | ||
32 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) }, | 34 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4324) }, |
33 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) }, | 35 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4325) }, |
34 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) }, | 36 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4328) }, |
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c index ed4124469a3a..e9d94968f394 100644 --- a/drivers/ssb/pci.c +++ b/drivers/ssb/pci.c | |||
@@ -178,6 +178,18 @@ err_pci: | |||
178 | #define SPEX(_outvar, _offset, _mask, _shift) \ | 178 | #define SPEX(_outvar, _offset, _mask, _shift) \ |
179 | SPEX16(_outvar, _offset, _mask, _shift) | 179 | SPEX16(_outvar, _offset, _mask, _shift) |
180 | 180 | ||
181 | #define SPEX_ARRAY8(_field, _offset, _mask, _shift) \ | ||
182 | do { \ | ||
183 | SPEX(_field[0], _offset + 0, _mask, _shift); \ | ||
184 | SPEX(_field[1], _offset + 2, _mask, _shift); \ | ||
185 | SPEX(_field[2], _offset + 4, _mask, _shift); \ | ||
186 | SPEX(_field[3], _offset + 6, _mask, _shift); \ | ||
187 | SPEX(_field[4], _offset + 8, _mask, _shift); \ | ||
188 | SPEX(_field[5], _offset + 10, _mask, _shift); \ | ||
189 | SPEX(_field[6], _offset + 12, _mask, _shift); \ | ||
190 | SPEX(_field[7], _offset + 14, _mask, _shift); \ | ||
191 | } while (0) | ||
192 | |||
181 | 193 | ||
182 | static inline u8 ssb_crc8(u8 crc, u8 data) | 194 | static inline u8 ssb_crc8(u8 crc, u8 data) |
183 | { | 195 | { |
@@ -360,8 +372,9 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
360 | SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14); | 372 | SPEX(et0mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET0M, 14); |
361 | SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15); | 373 | SPEX(et1mdcport, SSB_SPROM1_ETHPHY, SSB_SPROM1_ETHPHY_ET1M, 15); |
362 | SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0); | 374 | SPEX(board_rev, SSB_SPROM1_BINF, SSB_SPROM1_BINF_BREV, 0); |
363 | SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, | 375 | if (out->revision == 1) |
364 | SSB_SPROM1_BINF_CCODE_SHIFT); | 376 | SPEX(country_code, SSB_SPROM1_BINF, SSB_SPROM1_BINF_CCODE, |
377 | SSB_SPROM1_BINF_CCODE_SHIFT); | ||
365 | SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA, | 378 | SPEX(ant_available_a, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTA, |
366 | SSB_SPROM1_BINF_ANTA_SHIFT); | 379 | SSB_SPROM1_BINF_ANTA_SHIFT); |
367 | SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG, | 380 | SPEX(ant_available_bg, SSB_SPROM1_BINF, SSB_SPROM1_BINF_ANTBG, |
@@ -387,6 +400,8 @@ static void sprom_extract_r123(struct ssb_sprom *out, const u16 *in) | |||
387 | SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); | 400 | SPEX(boardflags_lo, SSB_SPROM1_BFLLO, 0xFFFF, 0); |
388 | if (out->revision >= 2) | 401 | if (out->revision >= 2) |
389 | SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); | 402 | SPEX(boardflags_hi, SSB_SPROM2_BFLHI, 0xFFFF, 0); |
403 | SPEX(alpha2[0], SSB_SPROM1_CCODE, 0xff00, 8); | ||
404 | SPEX(alpha2[1], SSB_SPROM1_CCODE, 0x00ff, 0); | ||
390 | 405 | ||
391 | /* Extract the antenna gain values. */ | 406 | /* Extract the antenna gain values. */ |
392 | out->antenna_gain.a0 = r123_extract_antgain(out->revision, in, | 407 | out->antenna_gain.a0 = r123_extract_antgain(out->revision, in, |
@@ -455,14 +470,17 @@ static void sprom_extract_r45(struct ssb_sprom *out, const u16 *in) | |||
455 | SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); | 470 | SPEX(et0phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET0A, 0); |
456 | SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, | 471 | SPEX(et1phyaddr, SSB_SPROM4_ETHPHY, SSB_SPROM4_ETHPHY_ET1A, |
457 | SSB_SPROM4_ETHPHY_ET1A_SHIFT); | 472 | SSB_SPROM4_ETHPHY_ET1A_SHIFT); |
473 | SPEX(board_rev, SSB_SPROM4_BOARDREV, 0xFFFF, 0); | ||
458 | if (out->revision == 4) { | 474 | if (out->revision == 4) { |
459 | SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0); | 475 | SPEX(alpha2[0], SSB_SPROM4_CCODE, 0xff00, 8); |
476 | SPEX(alpha2[1], SSB_SPROM4_CCODE, 0x00ff, 0); | ||
460 | SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0); | 477 | SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0); |
461 | SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0); | 478 | SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0); |
462 | SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0); | 479 | SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0); |
463 | SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0); | 480 | SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0); |
464 | } else { | 481 | } else { |
465 | SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0); | 482 | SPEX(alpha2[0], SSB_SPROM5_CCODE, 0xff00, 8); |
483 | SPEX(alpha2[1], SSB_SPROM5_CCODE, 0x00ff, 0); | ||
466 | SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0); | 484 | SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0); |
467 | SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0); | 485 | SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0); |
468 | SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0); | 486 | SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0); |
@@ -525,7 +543,9 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) | |||
525 | v = in[SPOFF(SSB_SPROM8_IL0MAC) + i]; | 543 | v = in[SPOFF(SSB_SPROM8_IL0MAC) + i]; |
526 | *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); | 544 | *(((__be16 *)out->il0mac) + i) = cpu_to_be16(v); |
527 | } | 545 | } |
528 | SPEX(country_code, SSB_SPROM8_CCODE, 0xFFFF, 0); | 546 | SPEX(board_rev, SSB_SPROM8_BOARDREV, 0xFFFF, 0); |
547 | SPEX(alpha2[0], SSB_SPROM8_CCODE, 0xff00, 8); | ||
548 | SPEX(alpha2[1], SSB_SPROM8_CCODE, 0x00ff, 0); | ||
529 | SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0); | 549 | SPEX(boardflags_lo, SSB_SPROM8_BFLLO, 0xFFFF, 0); |
530 | SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0); | 550 | SPEX(boardflags_hi, SSB_SPROM8_BFLHI, 0xFFFF, 0); |
531 | SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0); | 551 | SPEX(boardflags2_lo, SSB_SPROM8_BFL2LO, 0xFFFF, 0); |
@@ -655,6 +675,63 @@ static void sprom_extract_r8(struct ssb_sprom *out, const u16 *in) | |||
655 | SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, | 675 | SPEX(fem.ghz5.antswlut, SSB_SPROM8_FEM5G, |
656 | SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT); | 676 | SSB_SROM8_FEM_ANTSWLUT, SSB_SROM8_FEM_ANTSWLUT_SHIFT); |
657 | 677 | ||
678 | SPEX(leddc_on_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_ON, | ||
679 | SSB_SPROM8_LEDDC_ON_SHIFT); | ||
680 | SPEX(leddc_off_time, SSB_SPROM8_LEDDC, SSB_SPROM8_LEDDC_OFF, | ||
681 | SSB_SPROM8_LEDDC_OFF_SHIFT); | ||
682 | |||
683 | SPEX(txchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_TXCHAIN, | ||
684 | SSB_SPROM8_TXRXC_TXCHAIN_SHIFT); | ||
685 | SPEX(rxchain, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_RXCHAIN, | ||
686 | SSB_SPROM8_TXRXC_RXCHAIN_SHIFT); | ||
687 | SPEX(antswitch, SSB_SPROM8_TXRXC, SSB_SPROM8_TXRXC_SWITCH, | ||
688 | SSB_SPROM8_TXRXC_SWITCH_SHIFT); | ||
689 | |||
690 | SPEX(opo, SSB_SPROM8_OFDM2GPO, 0x00ff, 0); | ||
691 | |||
692 | SPEX_ARRAY8(mcs2gpo, SSB_SPROM8_2G_MCSPO, ~0, 0); | ||
693 | SPEX_ARRAY8(mcs5gpo, SSB_SPROM8_5G_MCSPO, ~0, 0); | ||
694 | SPEX_ARRAY8(mcs5glpo, SSB_SPROM8_5GL_MCSPO, ~0, 0); | ||
695 | SPEX_ARRAY8(mcs5ghpo, SSB_SPROM8_5GH_MCSPO, ~0, 0); | ||
696 | |||
697 | SPEX(rawtempsense, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_RAWTEMP, | ||
698 | SSB_SPROM8_RAWTS_RAWTEMP_SHIFT); | ||
699 | SPEX(measpower, SSB_SPROM8_RAWTS, SSB_SPROM8_RAWTS_MEASPOWER, | ||
700 | SSB_SPROM8_RAWTS_MEASPOWER_SHIFT); | ||
701 | SPEX(tempsense_slope, SSB_SPROM8_OPT_CORRX, | ||
702 | SSB_SPROM8_OPT_CORRX_TEMP_SLOPE, | ||
703 | SSB_SPROM8_OPT_CORRX_TEMP_SLOPE_SHIFT); | ||
704 | SPEX(tempcorrx, SSB_SPROM8_OPT_CORRX, SSB_SPROM8_OPT_CORRX_TEMPCORRX, | ||
705 | SSB_SPROM8_OPT_CORRX_TEMPCORRX_SHIFT); | ||
706 | SPEX(tempsense_option, SSB_SPROM8_OPT_CORRX, | ||
707 | SSB_SPROM8_OPT_CORRX_TEMP_OPTION, | ||
708 | SSB_SPROM8_OPT_CORRX_TEMP_OPTION_SHIFT); | ||
709 | SPEX(freqoffset_corr, SSB_SPROM8_HWIQ_IQSWP, | ||
710 | SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR, | ||
711 | SSB_SPROM8_HWIQ_IQSWP_FREQ_CORR_SHIFT); | ||
712 | SPEX(iqcal_swp_dis, SSB_SPROM8_HWIQ_IQSWP, | ||
713 | SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP, | ||
714 | SSB_SPROM8_HWIQ_IQSWP_IQCAL_SWP_SHIFT); | ||
715 | SPEX(hw_iqcal_en, SSB_SPROM8_HWIQ_IQSWP, SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL, | ||
716 | SSB_SPROM8_HWIQ_IQSWP_HW_IQCAL_SHIFT); | ||
717 | |||
718 | SPEX(bw40po, SSB_SPROM8_BW40PO, ~0, 0); | ||
719 | SPEX(cddpo, SSB_SPROM8_CDDPO, ~0, 0); | ||
720 | SPEX(stbcpo, SSB_SPROM8_STBCPO, ~0, 0); | ||
721 | SPEX(bwduppo, SSB_SPROM8_BWDUPPO, ~0, 0); | ||
722 | |||
723 | SPEX(tempthresh, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_TRESH, | ||
724 | SSB_SPROM8_THERMAL_TRESH_SHIFT); | ||
725 | SPEX(tempoffset, SSB_SPROM8_THERMAL, SSB_SPROM8_THERMAL_OFFSET, | ||
726 | SSB_SPROM8_THERMAL_OFFSET_SHIFT); | ||
727 | SPEX(phycal_tempdelta, SSB_SPROM8_TEMPDELTA, | ||
728 | SSB_SPROM8_TEMPDELTA_PHYCAL, | ||
729 | SSB_SPROM8_TEMPDELTA_PHYCAL_SHIFT); | ||
730 | SPEX(temps_period, SSB_SPROM8_TEMPDELTA, SSB_SPROM8_TEMPDELTA_PERIOD, | ||
731 | SSB_SPROM8_TEMPDELTA_PERIOD_SHIFT); | ||
732 | SPEX(temps_hysteresis, SSB_SPROM8_TEMPDELTA, | ||
733 | SSB_SPROM8_TEMPDELTA_HYSTERESIS, | ||
734 | SSB_SPROM8_TEMPDELTA_HYSTERESIS_SHIFT); | ||
658 | sprom_extract_r458(out, in); | 735 | sprom_extract_r458(out, in); |
659 | 736 | ||
660 | /* TODO - get remaining rev 8 stuff needed */ | 737 | /* TODO - get remaining rev 8 stuff needed */ |
@@ -784,7 +861,6 @@ static void ssb_pci_get_boardinfo(struct ssb_bus *bus, | |||
784 | { | 861 | { |
785 | bi->vendor = bus->host_pci->subsystem_vendor; | 862 | bi->vendor = bus->host_pci->subsystem_vendor; |
786 | bi->type = bus->host_pci->subsystem_device; | 863 | bi->type = bus->host_pci->subsystem_device; |
787 | bi->rev = bus->host_pci->revision; | ||
788 | } | 864 | } |
789 | 865 | ||
790 | int ssb_pci_get_invariants(struct ssb_bus *bus, | 866 | int ssb_pci_get_invariants(struct ssb_bus *bus, |