diff options
author | Johannes Berg <johannes.berg@intel.com> | 2012-10-30 04:09:48 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2012-10-30 04:09:48 -0400 |
commit | 6fb47de9cf1be4710fb9f364c500ff216fb47b34 (patch) | |
tree | e638cd1de972e7120dff9200efe71ce1b4ca3805 | |
parent | 1041638f2bba0f1de75e66086d50fb1251d64dcf (diff) | |
parent | ab3d59d265e772e734c36fe738809cb1a910f566 (diff) |
Merge remote-tracking branch 'wireless-next/master' into mac80211-next
175 files changed, 8252 insertions, 2951 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index e73060fe0788..568ea9373091 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -7477,6 +7477,12 @@ S: Maintained | |||
7477 | F: Documentation/usb/acm.txt | 7477 | F: Documentation/usb/acm.txt |
7478 | F: drivers/usb/class/cdc-acm.* | 7478 | F: drivers/usb/class/cdc-acm.* |
7479 | 7479 | ||
7480 | USB AR5523 WIRELESS DRIVER | ||
7481 | M: Pontus Fuchs <pontus.fuchs@gmail.com> | ||
7482 | L: linux-wireless@vger.kernel.org | ||
7483 | S: Maintained | ||
7484 | F: drivers/net/wireless/ath/ar5523/ | ||
7485 | |||
7480 | USB ATTACHED SCSI | 7486 | USB ATTACHED SCSI |
7481 | M: Matthew Wilcox <willy@linux.intel.com> | 7487 | M: Matthew Wilcox <willy@linux.intel.com> |
7482 | M: Sarah Sharp <sarah.a.sharp@linux.intel.com> | 7488 | M: Sarah Sharp <sarah.a.sharp@linux.intel.com> |
diff --git a/arch/mips/bcm47xx/nvram.c b/arch/mips/bcm47xx/nvram.c index d43ceff5be47..48a4c70b3842 100644 --- a/arch/mips/bcm47xx/nvram.c +++ b/arch/mips/bcm47xx/nvram.c | |||
@@ -43,8 +43,8 @@ static void early_nvram_init(void) | |||
43 | #ifdef CONFIG_BCM47XX_SSB | 43 | #ifdef CONFIG_BCM47XX_SSB |
44 | case BCM47XX_BUS_TYPE_SSB: | 44 | case BCM47XX_BUS_TYPE_SSB: |
45 | mcore_ssb = &bcm47xx_bus.ssb.mipscore; | 45 | mcore_ssb = &bcm47xx_bus.ssb.mipscore; |
46 | base = mcore_ssb->flash_window; | 46 | base = mcore_ssb->pflash.window; |
47 | lim = mcore_ssb->flash_window_size; | 47 | lim = mcore_ssb->pflash.window_size; |
48 | break; | 48 | break; |
49 | #endif | 49 | #endif |
50 | #ifdef CONFIG_BCM47XX_BCMA | 50 | #ifdef CONFIG_BCM47XX_BCMA |
diff --git a/arch/mips/bcm47xx/wgt634u.c b/arch/mips/bcm47xx/wgt634u.c index e9f9ec8d443b..e80d585731aa 100644 --- a/arch/mips/bcm47xx/wgt634u.c +++ b/arch/mips/bcm47xx/wgt634u.c | |||
@@ -156,10 +156,10 @@ static int __init wgt634u_init(void) | |||
156 | SSB_CHIPCO_IRQ_GPIO); | 156 | SSB_CHIPCO_IRQ_GPIO); |
157 | } | 157 | } |
158 | 158 | ||
159 | wgt634u_flash_data.width = mcore->flash_buswidth; | 159 | wgt634u_flash_data.width = mcore->pflash.buswidth; |
160 | wgt634u_flash_resource.start = mcore->flash_window; | 160 | wgt634u_flash_resource.start = mcore->pflash.window; |
161 | wgt634u_flash_resource.end = mcore->flash_window | 161 | wgt634u_flash_resource.end = mcore->pflash.window |
162 | + mcore->flash_window_size | 162 | + mcore->pflash.window_size |
163 | - 1; | 163 | - 1; |
164 | return platform_add_devices(wgt634u_devices, | 164 | return platform_add_devices(wgt634u_devices, |
165 | ARRAY_SIZE(wgt634u_devices)); | 165 | ARRAY_SIZE(wgt634u_devices)); |
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c index a4c3ebcc4c86..ffd74e51f02d 100644 --- a/drivers/bcma/driver_chipcommon.c +++ b/drivers/bcma/driver_chipcommon.c | |||
@@ -22,12 +22,9 @@ static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, | |||
22 | return value; | 22 | return value; |
23 | } | 23 | } |
24 | 24 | ||
25 | void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) | 25 | void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc) |
26 | { | 26 | { |
27 | u32 leddc_on = 10; | 27 | if (cc->early_setup_done) |
28 | u32 leddc_off = 90; | ||
29 | |||
30 | if (cc->setup_done) | ||
31 | return; | 28 | return; |
32 | 29 | ||
33 | if (cc->core->id.rev >= 11) | 30 | if (cc->core->id.rev >= 11) |
@@ -36,6 +33,22 @@ void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) | |||
36 | if (cc->core->id.rev >= 35) | 33 | if (cc->core->id.rev >= 35) |
37 | cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT); | 34 | cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT); |
38 | 35 | ||
36 | if (cc->capabilities & BCMA_CC_CAP_PMU) | ||
37 | bcma_pmu_early_init(cc); | ||
38 | |||
39 | cc->early_setup_done = true; | ||
40 | } | ||
41 | |||
42 | void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) | ||
43 | { | ||
44 | u32 leddc_on = 10; | ||
45 | u32 leddc_off = 90; | ||
46 | |||
47 | if (cc->setup_done) | ||
48 | return; | ||
49 | |||
50 | bcma_core_chipcommon_early_init(cc); | ||
51 | |||
39 | if (cc->core->id.rev >= 20) { | 52 | if (cc->core->id.rev >= 20) { |
40 | bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0); | 53 | bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0); |
41 | bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0); | 54 | bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0); |
diff --git a/drivers/bcma/driver_chipcommon_nflash.c b/drivers/bcma/driver_chipcommon_nflash.c index 9042781edec3..dbda91e4dff5 100644 --- a/drivers/bcma/driver_chipcommon_nflash.c +++ b/drivers/bcma/driver_chipcommon_nflash.c | |||
@@ -32,6 +32,9 @@ int bcma_nflash_init(struct bcma_drv_cc *cc) | |||
32 | } | 32 | } |
33 | 33 | ||
34 | cc->nflash.present = true; | 34 | cc->nflash.present = true; |
35 | if (cc->core->id.rev == 38 && | ||
36 | (cc->status & BCMA_CC_CHIPST_5357_NAND_BOOT)) | ||
37 | cc->nflash.boot = true; | ||
35 | 38 | ||
36 | /* Prepare platform device, but don't register it yet. It's too early, | 39 | /* Prepare platform device, but don't register it yet. It's too early, |
37 | * malloc (required by device_private_init) is not available yet. */ | 40 | * malloc (required by device_private_init) is not available yet. */ |
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index 201faf106b3f..a63ddd9c70eb 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c | |||
@@ -144,7 +144,7 @@ static void bcma_pmu_workarounds(struct bcma_drv_cc *cc) | |||
144 | } | 144 | } |
145 | } | 145 | } |
146 | 146 | ||
147 | void bcma_pmu_init(struct bcma_drv_cc *cc) | 147 | void bcma_pmu_early_init(struct bcma_drv_cc *cc) |
148 | { | 148 | { |
149 | u32 pmucap; | 149 | u32 pmucap; |
150 | 150 | ||
@@ -153,7 +153,10 @@ void bcma_pmu_init(struct bcma_drv_cc *cc) | |||
153 | 153 | ||
154 | bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n", | 154 | bcma_debug(cc->core->bus, "Found rev %u PMU (capabilities 0x%08X)\n", |
155 | cc->pmu.rev, pmucap); | 155 | cc->pmu.rev, pmucap); |
156 | } | ||
156 | 157 | ||
158 | void bcma_pmu_init(struct bcma_drv_cc *cc) | ||
159 | { | ||
157 | if (cc->pmu.rev == 1) | 160 | if (cc->pmu.rev == 1) |
158 | bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, | 161 | bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, |
159 | ~BCMA_CC_PMU_CTL_NOILPONW); | 162 | ~BCMA_CC_PMU_CTL_NOILPONW); |
diff --git a/drivers/bcma/driver_chipcommon_sflash.c b/drivers/bcma/driver_chipcommon_sflash.c index 2c4eec2ca5a0..63e688393825 100644 --- a/drivers/bcma/driver_chipcommon_sflash.c +++ b/drivers/bcma/driver_chipcommon_sflash.c | |||
@@ -12,7 +12,7 @@ | |||
12 | 12 | ||
13 | static struct resource bcma_sflash_resource = { | 13 | static struct resource bcma_sflash_resource = { |
14 | .name = "bcma_sflash", | 14 | .name = "bcma_sflash", |
15 | .start = BCMA_SFLASH, | 15 | .start = BCMA_SOC_FLASH2, |
16 | .end = 0, | 16 | .end = 0, |
17 | .flags = IORESOURCE_MEM | IORESOURCE_READONLY, | 17 | .flags = IORESOURCE_MEM | IORESOURCE_READONLY, |
18 | }; | 18 | }; |
@@ -31,15 +31,42 @@ struct bcma_sflash_tbl_e { | |||
31 | }; | 31 | }; |
32 | 32 | ||
33 | static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { | 33 | static struct bcma_sflash_tbl_e bcma_sflash_st_tbl[] = { |
34 | { "", 0x14, 0x10000, 32, }, | 34 | { "M25P20", 0x11, 0x10000, 4, }, |
35 | { "M25P40", 0x12, 0x10000, 8, }, | ||
36 | |||
37 | { "M25P16", 0x14, 0x10000, 32, }, | ||
38 | { "M25P32", 0x14, 0x10000, 64, }, | ||
39 | { "M25P64", 0x16, 0x10000, 128, }, | ||
40 | { "M25FL128", 0x17, 0x10000, 256, }, | ||
35 | { 0 }, | 41 | { 0 }, |
36 | }; | 42 | }; |
37 | 43 | ||
38 | static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { | 44 | static struct bcma_sflash_tbl_e bcma_sflash_sst_tbl[] = { |
45 | { "SST25WF512", 1, 0x1000, 16, }, | ||
46 | { "SST25VF512", 0x48, 0x1000, 16, }, | ||
47 | { "SST25WF010", 2, 0x1000, 32, }, | ||
48 | { "SST25VF010", 0x49, 0x1000, 32, }, | ||
49 | { "SST25WF020", 3, 0x1000, 64, }, | ||
50 | { "SST25VF020", 0x43, 0x1000, 64, }, | ||
51 | { "SST25WF040", 4, 0x1000, 128, }, | ||
52 | { "SST25VF040", 0x44, 0x1000, 128, }, | ||
53 | { "SST25VF040B", 0x8d, 0x1000, 128, }, | ||
54 | { "SST25WF080", 5, 0x1000, 256, }, | ||
55 | { "SST25VF080B", 0x8e, 0x1000, 256, }, | ||
56 | { "SST25VF016", 0x41, 0x1000, 512, }, | ||
57 | { "SST25VF032", 0x4a, 0x1000, 1024, }, | ||
58 | { "SST25VF064", 0x4b, 0x1000, 2048, }, | ||
39 | { 0 }, | 59 | { 0 }, |
40 | }; | 60 | }; |
41 | 61 | ||
42 | static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { | 62 | static struct bcma_sflash_tbl_e bcma_sflash_at_tbl[] = { |
63 | { "AT45DB011", 0xc, 256, 512, }, | ||
64 | { "AT45DB021", 0x14, 256, 1024, }, | ||
65 | { "AT45DB041", 0x1c, 256, 2048, }, | ||
66 | { "AT45DB081", 0x24, 256, 4096, }, | ||
67 | { "AT45DB161", 0x2c, 512, 4096, }, | ||
68 | { "AT45DB321", 0x34, 512, 8192, }, | ||
69 | { "AT45DB642", 0x3c, 1024, 8192, }, | ||
43 | { 0 }, | 70 | { 0 }, |
44 | }; | 71 | }; |
45 | 72 | ||
@@ -84,6 +111,8 @@ int bcma_sflash_init(struct bcma_drv_cc *cc) | |||
84 | break; | 111 | break; |
85 | } | 112 | } |
86 | break; | 113 | break; |
114 | case 0x13: | ||
115 | return -ENOTSUPP; | ||
87 | default: | 116 | default: |
88 | for (e = bcma_sflash_st_tbl; e->name; e++) { | 117 | for (e = bcma_sflash_st_tbl; e->name; e++) { |
89 | if (e->id == id) | 118 | if (e->id == id) |
@@ -116,7 +145,7 @@ int bcma_sflash_init(struct bcma_drv_cc *cc) | |||
116 | return -ENOTSUPP; | 145 | return -ENOTSUPP; |
117 | } | 146 | } |
118 | 147 | ||
119 | sflash->window = BCMA_SFLASH; | 148 | sflash->window = BCMA_SOC_FLASH2; |
120 | sflash->blocksize = e->blocksize; | 149 | sflash->blocksize = e->blocksize; |
121 | sflash->numblocks = e->numblocks; | 150 | sflash->numblocks = e->numblocks; |
122 | sflash->size = sflash->blocksize * sflash->numblocks; | 151 | sflash->size = sflash->blocksize * sflash->numblocks; |
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c index cc65b45b4368..170822ea51c7 100644 --- a/drivers/bcma/driver_mips.c +++ b/drivers/bcma/driver_mips.c | |||
@@ -181,47 +181,66 @@ EXPORT_SYMBOL(bcma_cpu_clock); | |||
181 | static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) | 181 | static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore) |
182 | { | 182 | { |
183 | struct bcma_bus *bus = mcore->core->bus; | 183 | struct bcma_bus *bus = mcore->core->bus; |
184 | struct bcma_drv_cc *cc = &bus->drv_cc; | ||
184 | 185 | ||
185 | switch (bus->drv_cc.capabilities & BCMA_CC_CAP_FLASHT) { | 186 | switch (cc->capabilities & BCMA_CC_CAP_FLASHT) { |
186 | case BCMA_CC_FLASHT_STSER: | 187 | case BCMA_CC_FLASHT_STSER: |
187 | case BCMA_CC_FLASHT_ATSER: | 188 | case BCMA_CC_FLASHT_ATSER: |
188 | bcma_debug(bus, "Found serial flash\n"); | 189 | bcma_debug(bus, "Found serial flash\n"); |
189 | bcma_sflash_init(&bus->drv_cc); | 190 | bcma_sflash_init(cc); |
190 | break; | 191 | break; |
191 | case BCMA_CC_FLASHT_PARA: | 192 | case BCMA_CC_FLASHT_PARA: |
192 | bcma_debug(bus, "Found parallel flash\n"); | 193 | bcma_debug(bus, "Found parallel flash\n"); |
193 | bus->drv_cc.pflash.window = 0x1c000000; | 194 | cc->pflash.present = true; |
194 | bus->drv_cc.pflash.window_size = 0x02000000; | 195 | cc->pflash.window = BCMA_SOC_FLASH2; |
196 | cc->pflash.window_size = BCMA_SOC_FLASH2_SZ; | ||
195 | 197 | ||
196 | if ((bcma_read32(bus->drv_cc.core, BCMA_CC_FLASH_CFG) & | 198 | if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) & |
197 | BCMA_CC_FLASH_CFG_DS) == 0) | 199 | BCMA_CC_FLASH_CFG_DS) == 0) |
198 | bus->drv_cc.pflash.buswidth = 1; | 200 | cc->pflash.buswidth = 1; |
199 | else | 201 | else |
200 | bus->drv_cc.pflash.buswidth = 2; | 202 | cc->pflash.buswidth = 2; |
201 | break; | 203 | break; |
202 | default: | 204 | default: |
203 | bcma_err(bus, "Flash type not supported\n"); | 205 | bcma_err(bus, "Flash type not supported\n"); |
204 | } | 206 | } |
205 | 207 | ||
206 | if (bus->drv_cc.core->id.rev == 38 || | 208 | if (cc->core->id.rev == 38 || |
207 | bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) { | 209 | bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) { |
208 | if (bus->drv_cc.capabilities & BCMA_CC_CAP_NFLASH) { | 210 | if (cc->capabilities & BCMA_CC_CAP_NFLASH) { |
209 | bcma_debug(bus, "Found NAND flash\n"); | 211 | bcma_debug(bus, "Found NAND flash\n"); |
210 | bcma_nflash_init(&bus->drv_cc); | 212 | bcma_nflash_init(cc); |
211 | } | 213 | } |
212 | } | 214 | } |
213 | } | 215 | } |
214 | 216 | ||
217 | void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) | ||
218 | { | ||
219 | struct bcma_bus *bus = mcore->core->bus; | ||
220 | |||
221 | if (mcore->early_setup_done) | ||
222 | return; | ||
223 | |||
224 | bcma_chipco_serial_init(&bus->drv_cc); | ||
225 | bcma_core_mips_flash_detect(mcore); | ||
226 | |||
227 | mcore->early_setup_done = true; | ||
228 | } | ||
229 | |||
215 | void bcma_core_mips_init(struct bcma_drv_mips *mcore) | 230 | void bcma_core_mips_init(struct bcma_drv_mips *mcore) |
216 | { | 231 | { |
217 | struct bcma_bus *bus; | 232 | struct bcma_bus *bus; |
218 | struct bcma_device *core; | 233 | struct bcma_device *core; |
219 | bus = mcore->core->bus; | 234 | bus = mcore->core->bus; |
220 | 235 | ||
236 | if (mcore->setup_done) | ||
237 | return; | ||
238 | |||
221 | bcma_info(bus, "Initializing MIPS core...\n"); | 239 | bcma_info(bus, "Initializing MIPS core...\n"); |
222 | 240 | ||
223 | if (!mcore->setup_done) | 241 | bcma_core_mips_early_init(mcore); |
224 | mcore->assigned_irqs = 1; | 242 | |
243 | mcore->assigned_irqs = 1; | ||
225 | 244 | ||
226 | /* Assign IRQs to all cores on the bus */ | 245 | /* Assign IRQs to all cores on the bus */ |
227 | list_for_each_entry(core, &bus->cores, list) { | 246 | list_for_each_entry(core, &bus->cores, list) { |
@@ -256,10 +275,5 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore) | |||
256 | bcma_info(bus, "IRQ reconfiguration done\n"); | 275 | bcma_info(bus, "IRQ reconfiguration done\n"); |
257 | bcma_core_mips_dump_irq(bus); | 276 | bcma_core_mips_dump_irq(bus); |
258 | 277 | ||
259 | if (mcore->setup_done) | ||
260 | return; | ||
261 | |||
262 | bcma_chipco_serial_init(&bus->drv_cc); | ||
263 | bcma_core_mips_flash_detect(mcore); | ||
264 | mcore->setup_done = true; | 278 | mcore->setup_done = true; |
265 | } | 279 | } |
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c index 9baf886e82df..e56449506695 100644 --- a/drivers/bcma/driver_pci_host.c +++ b/drivers/bcma/driver_pci_host.c | |||
@@ -35,11 +35,6 @@ bool __devinit bcma_core_pci_is_in_hostmode(struct bcma_drv_pci *pc) | |||
35 | chipid_top != 0x5300) | 35 | chipid_top != 0x5300) |
36 | return false; | 36 | return false; |
37 | 37 | ||
38 | if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) { | ||
39 | bcma_info(bus, "This PCI core is disabled and not working\n"); | ||
40 | return false; | ||
41 | } | ||
42 | |||
43 | bcma_core_enable(pc->core, 0); | 38 | bcma_core_enable(pc->core, 0); |
44 | 39 | ||
45 | return !mips_busprobe32(tmp, pc->core->io_addr); | 40 | return !mips_busprobe32(tmp, pc->core->io_addr); |
@@ -396,6 +391,11 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) | |||
396 | 391 | ||
397 | bcma_info(bus, "PCIEcore in host mode found\n"); | 392 | bcma_info(bus, "PCIEcore in host mode found\n"); |
398 | 393 | ||
394 | if (bus->sprom.boardflags_lo & BCMA_CORE_PCI_BFL_NOPCI) { | ||
395 | bcma_info(bus, "This PCIE core is disabled and not working\n"); | ||
396 | return; | ||
397 | } | ||
398 | |||
399 | pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL); | 399 | pc_host = kzalloc(sizeof(*pc_host), GFP_KERNEL); |
400 | if (!pc_host) { | 400 | if (!pc_host) { |
401 | bcma_err(bus, "can not allocate memory"); | 401 | bcma_err(bus, "can not allocate memory"); |
@@ -452,6 +452,8 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) | |||
452 | pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; | 452 | pc_host->mem_resource.start = BCMA_SOC_PCI_MEM; |
453 | pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + | 453 | pc_host->mem_resource.end = BCMA_SOC_PCI_MEM + |
454 | BCMA_SOC_PCI_MEM_SZ - 1; | 454 | BCMA_SOC_PCI_MEM_SZ - 1; |
455 | pc_host->io_resource.start = 0x100; | ||
456 | pc_host->io_resource.end = 0x47F; | ||
455 | pci_membase_1G = BCMA_SOC_PCIE_DMA_H32; | 457 | pci_membase_1G = BCMA_SOC_PCIE_DMA_H32; |
456 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, | 458 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, |
457 | tmp | BCMA_SOC_PCI_MEM); | 459 | tmp | BCMA_SOC_PCI_MEM); |
@@ -459,6 +461,8 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) | |||
459 | pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM; | 461 | pc_host->mem_resource.start = BCMA_SOC_PCI1_MEM; |
460 | pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM + | 462 | pc_host->mem_resource.end = BCMA_SOC_PCI1_MEM + |
461 | BCMA_SOC_PCI_MEM_SZ - 1; | 463 | BCMA_SOC_PCI_MEM_SZ - 1; |
464 | pc_host->io_resource.start = 0x480; | ||
465 | pc_host->io_resource.end = 0x7FF; | ||
462 | pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32; | 466 | pci_membase_1G = BCMA_SOC_PCIE1_DMA_H32; |
463 | pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG; | 467 | pc_host->host_cfg_addr = BCMA_SOC_PCI1_CFG; |
464 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, | 468 | pcicore_write32(pc, BCMA_CORE_PCI_SBTOPCI0, |
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c index b6b4b5ebd4c2..98fdc3e014e7 100644 --- a/drivers/bcma/host_pci.c +++ b/drivers/bcma/host_pci.c | |||
@@ -238,7 +238,7 @@ static void __devexit bcma_host_pci_remove(struct pci_dev *dev) | |||
238 | pci_set_drvdata(dev, NULL); | 238 | pci_set_drvdata(dev, NULL); |
239 | } | 239 | } |
240 | 240 | ||
241 | #ifdef CONFIG_PM | 241 | #ifdef CONFIG_PM_SLEEP |
242 | static int bcma_host_pci_suspend(struct device *dev) | 242 | static int bcma_host_pci_suspend(struct device *dev) |
243 | { | 243 | { |
244 | struct pci_dev *pdev = to_pci_dev(dev); | 244 | struct pci_dev *pdev = to_pci_dev(dev); |
@@ -261,11 +261,11 @@ static SIMPLE_DEV_PM_OPS(bcma_pm_ops, bcma_host_pci_suspend, | |||
261 | bcma_host_pci_resume); | 261 | bcma_host_pci_resume); |
262 | #define BCMA_PM_OPS (&bcma_pm_ops) | 262 | #define BCMA_PM_OPS (&bcma_pm_ops) |
263 | 263 | ||
264 | #else /* CONFIG_PM */ | 264 | #else /* CONFIG_PM_SLEEP */ |
265 | 265 | ||
266 | #define BCMA_PM_OPS NULL | 266 | #define BCMA_PM_OPS NULL |
267 | 267 | ||
268 | #endif /* CONFIG_PM */ | 268 | #endif /* CONFIG_PM_SLEEP */ |
269 | 269 | ||
270 | static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { | 270 | static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { |
271 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, | 271 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) }, |
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 432aeeedfd5e..a9718893000b 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c | |||
@@ -81,6 +81,18 @@ struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid) | |||
81 | } | 81 | } |
82 | EXPORT_SYMBOL_GPL(bcma_find_core); | 82 | EXPORT_SYMBOL_GPL(bcma_find_core); |
83 | 83 | ||
84 | static struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid, | ||
85 | u8 unit) | ||
86 | { | ||
87 | struct bcma_device *core; | ||
88 | |||
89 | list_for_each_entry(core, &bus->cores, list) { | ||
90 | if (core->id.id == coreid && core->core_unit == unit) | ||
91 | return core; | ||
92 | } | ||
93 | return NULL; | ||
94 | } | ||
95 | |||
84 | static void bcma_release_core_dev(struct device *dev) | 96 | static void bcma_release_core_dev(struct device *dev) |
85 | { | 97 | { |
86 | struct bcma_device *core = container_of(dev, struct bcma_device, dev); | 98 | struct bcma_device *core = container_of(dev, struct bcma_device, dev); |
@@ -158,9 +170,10 @@ static int bcma_register_cores(struct bcma_bus *bus) | |||
158 | 170 | ||
159 | static void bcma_unregister_cores(struct bcma_bus *bus) | 171 | static void bcma_unregister_cores(struct bcma_bus *bus) |
160 | { | 172 | { |
161 | struct bcma_device *core; | 173 | struct bcma_device *core, *tmp; |
162 | 174 | ||
163 | list_for_each_entry(core, &bus->cores, list) { | 175 | list_for_each_entry_safe(core, tmp, &bus->cores, list) { |
176 | list_del(&core->list); | ||
164 | if (core->dev_registered) | 177 | if (core->dev_registered) |
165 | device_unregister(&core->dev); | 178 | device_unregister(&core->dev); |
166 | } | 179 | } |
@@ -182,6 +195,20 @@ int __devinit bcma_bus_register(struct bcma_bus *bus) | |||
182 | return -1; | 195 | return -1; |
183 | } | 196 | } |
184 | 197 | ||
198 | /* Early init CC core */ | ||
199 | core = bcma_find_core(bus, bcma_cc_core_id(bus)); | ||
200 | if (core) { | ||
201 | bus->drv_cc.core = core; | ||
202 | bcma_core_chipcommon_early_init(&bus->drv_cc); | ||
203 | } | ||
204 | |||
205 | /* Try to get SPROM */ | ||
206 | err = bcma_sprom_get(bus); | ||
207 | if (err == -ENOENT) { | ||
208 | bcma_err(bus, "No SPROM available\n"); | ||
209 | } else if (err) | ||
210 | bcma_err(bus, "Failed to get SPROM: %d\n", err); | ||
211 | |||
185 | /* Init CC core */ | 212 | /* Init CC core */ |
186 | core = bcma_find_core(bus, bcma_cc_core_id(bus)); | 213 | core = bcma_find_core(bus, bcma_cc_core_id(bus)); |
187 | if (core) { | 214 | if (core) { |
@@ -197,10 +224,17 @@ int __devinit bcma_bus_register(struct bcma_bus *bus) | |||
197 | } | 224 | } |
198 | 225 | ||
199 | /* Init PCIE core */ | 226 | /* Init PCIE core */ |
200 | core = bcma_find_core(bus, BCMA_CORE_PCIE); | 227 | core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 0); |
228 | if (core) { | ||
229 | bus->drv_pci[0].core = core; | ||
230 | bcma_core_pci_init(&bus->drv_pci[0]); | ||
231 | } | ||
232 | |||
233 | /* Init PCIE core */ | ||
234 | core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 1); | ||
201 | if (core) { | 235 | if (core) { |
202 | bus->drv_pci.core = core; | 236 | bus->drv_pci[1].core = core; |
203 | bcma_core_pci_init(&bus->drv_pci); | 237 | bcma_core_pci_init(&bus->drv_pci[1]); |
204 | } | 238 | } |
205 | 239 | ||
206 | /* Init GBIT MAC COMMON core */ | 240 | /* Init GBIT MAC COMMON core */ |
@@ -210,13 +244,6 @@ int __devinit bcma_bus_register(struct bcma_bus *bus) | |||
210 | bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn); | 244 | bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn); |
211 | } | 245 | } |
212 | 246 | ||
213 | /* Try to get SPROM */ | ||
214 | err = bcma_sprom_get(bus); | ||
215 | if (err == -ENOENT) { | ||
216 | bcma_err(bus, "No SPROM available\n"); | ||
217 | } else if (err) | ||
218 | bcma_err(bus, "Failed to get SPROM: %d\n", err); | ||
219 | |||
220 | /* Register found cores */ | 247 | /* Register found cores */ |
221 | bcma_register_cores(bus); | 248 | bcma_register_cores(bus); |
222 | 249 | ||
@@ -274,18 +301,18 @@ int __init bcma_bus_early_register(struct bcma_bus *bus, | |||
274 | return -1; | 301 | return -1; |
275 | } | 302 | } |
276 | 303 | ||
277 | /* Init CC core */ | 304 | /* Early init CC core */ |
278 | core = bcma_find_core(bus, bcma_cc_core_id(bus)); | 305 | core = bcma_find_core(bus, bcma_cc_core_id(bus)); |
279 | if (core) { | 306 | if (core) { |
280 | bus->drv_cc.core = core; | 307 | bus->drv_cc.core = core; |
281 | bcma_core_chipcommon_init(&bus->drv_cc); | 308 | bcma_core_chipcommon_early_init(&bus->drv_cc); |
282 | } | 309 | } |
283 | 310 | ||
284 | /* Init MIPS core */ | 311 | /* Early init MIPS core */ |
285 | core = bcma_find_core(bus, BCMA_CORE_MIPS_74K); | 312 | core = bcma_find_core(bus, BCMA_CORE_MIPS_74K); |
286 | if (core) { | 313 | if (core) { |
287 | bus->drv_mips.core = core; | 314 | bus->drv_mips.core = core; |
288 | bcma_core_mips_init(&bus->drv_mips); | 315 | bcma_core_mips_early_init(&bus->drv_mips); |
289 | } | 316 | } |
290 | 317 | ||
291 | bcma_info(bus, "Early bus registered\n"); | 318 | bcma_info(bus, "Early bus registered\n"); |
diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index 0d546b64be34..4adf9ef9a113 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c | |||
@@ -595,8 +595,11 @@ int bcma_sprom_get(struct bcma_bus *bus) | |||
595 | bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); | 595 | bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); |
596 | 596 | ||
597 | err = bcma_sprom_valid(sprom); | 597 | err = bcma_sprom_valid(sprom); |
598 | if (err) | 598 | if (err) { |
599 | bcma_warn(bus, "invalid sprom read from the PCIe card, try to use fallback sprom\n"); | ||
600 | err = bcma_fill_sprom_with_fallback(bus, &bus->sprom); | ||
599 | goto out; | 601 | goto out; |
602 | } | ||
600 | 603 | ||
601 | bcma_sprom_extract_r8(bus, sprom); | 604 | bcma_sprom_extract_r8(bus, sprom); |
602 | 605 | ||
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 3f4bfc814dc7..9959d4cb23dc 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c | |||
@@ -492,7 +492,7 @@ done: | |||
492 | static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) | 492 | static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) |
493 | { | 493 | { |
494 | u16 buf_len = 0; | 494 | u16 buf_len = 0; |
495 | int ret, buf_block_len, blksz; | 495 | int ret, num_blocks, blksz; |
496 | struct sk_buff *skb = NULL; | 496 | struct sk_buff *skb = NULL; |
497 | u32 type; | 497 | u32 type; |
498 | u8 *payload = NULL; | 498 | u8 *payload = NULL; |
@@ -514,18 +514,17 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) | |||
514 | } | 514 | } |
515 | 515 | ||
516 | blksz = SDIO_BLOCK_SIZE; | 516 | blksz = SDIO_BLOCK_SIZE; |
517 | buf_block_len = (buf_len + blksz - 1) / blksz; | 517 | num_blocks = DIV_ROUND_UP(buf_len, blksz); |
518 | 518 | ||
519 | if (buf_len <= SDIO_HEADER_LEN | 519 | if (buf_len <= SDIO_HEADER_LEN |
520 | || (buf_block_len * blksz) > ALLOC_BUF_SIZE) { | 520 | || (num_blocks * blksz) > ALLOC_BUF_SIZE) { |
521 | BT_ERR("invalid packet length: %d", buf_len); | 521 | BT_ERR("invalid packet length: %d", buf_len); |
522 | ret = -EINVAL; | 522 | ret = -EINVAL; |
523 | goto exit; | 523 | goto exit; |
524 | } | 524 | } |
525 | 525 | ||
526 | /* Allocate buffer */ | 526 | /* Allocate buffer */ |
527 | skb = bt_skb_alloc(buf_block_len * blksz + BTSDIO_DMA_ALIGN, | 527 | skb = bt_skb_alloc(num_blocks * blksz + BTSDIO_DMA_ALIGN, GFP_ATOMIC); |
528 | GFP_ATOMIC); | ||
529 | if (skb == NULL) { | 528 | if (skb == NULL) { |
530 | BT_ERR("No free skb"); | 529 | BT_ERR("No free skb"); |
531 | goto exit; | 530 | goto exit; |
@@ -541,7 +540,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) | |||
541 | payload = skb->data; | 540 | payload = skb->data; |
542 | 541 | ||
543 | ret = sdio_readsb(card->func, payload, card->ioport, | 542 | ret = sdio_readsb(card->func, payload, card->ioport, |
544 | buf_block_len * blksz); | 543 | num_blocks * blksz); |
545 | if (ret < 0) { | 544 | if (ret < 0) { |
546 | BT_ERR("readsb failed: %d", ret); | 545 | BT_ERR("readsb failed: %d", ret); |
547 | ret = -EIO; | 546 | ret = -EIO; |
@@ -553,7 +552,16 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) | |||
553 | */ | 552 | */ |
554 | 553 | ||
555 | buf_len = payload[0]; | 554 | buf_len = payload[0]; |
556 | buf_len |= (u16) payload[1] << 8; | 555 | buf_len |= payload[1] << 8; |
556 | buf_len |= payload[2] << 16; | ||
557 | |||
558 | if (buf_len > blksz * num_blocks) { | ||
559 | BT_ERR("Skip incorrect packet: hdrlen %d buffer %d", | ||
560 | buf_len, blksz * num_blocks); | ||
561 | ret = -EIO; | ||
562 | goto exit; | ||
563 | } | ||
564 | |||
557 | type = payload[3]; | 565 | type = payload[3]; |
558 | 566 | ||
559 | switch (type) { | 567 | switch (type) { |
@@ -589,8 +597,7 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) | |||
589 | 597 | ||
590 | default: | 598 | default: |
591 | BT_ERR("Unknown packet type:%d", type); | 599 | BT_ERR("Unknown packet type:%d", type); |
592 | print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, payload, | 600 | BT_ERR("hex: %*ph", blksz * num_blocks, payload); |
593 | blksz * buf_block_len); | ||
594 | 601 | ||
595 | kfree_skb(skb); | 602 | kfree_skb(skb); |
596 | skb = NULL; | 603 | skb = NULL; |
@@ -849,8 +856,7 @@ static int btmrvl_sdio_host_to_card(struct btmrvl_private *priv, | |||
849 | if (ret < 0) { | 856 | if (ret < 0) { |
850 | i++; | 857 | i++; |
851 | BT_ERR("i=%d writesb failed: %d", i, ret); | 858 | BT_ERR("i=%d writesb failed: %d", i, ret); |
852 | print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, | 859 | BT_ERR("hex: %*ph", nb, payload); |
853 | payload, nb); | ||
854 | ret = -EIO; | 860 | ret = -EIO; |
855 | if (i > MAX_WRITE_IOMEM_RETRY) | 861 | if (i > MAX_WRITE_IOMEM_RETRY) |
856 | goto exit; | 862 | goto exit; |
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index 09602241901b..c25dcf192fec 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig | |||
@@ -26,5 +26,6 @@ source "drivers/net/wireless/ath/ath5k/Kconfig" | |||
26 | source "drivers/net/wireless/ath/ath9k/Kconfig" | 26 | source "drivers/net/wireless/ath/ath9k/Kconfig" |
27 | source "drivers/net/wireless/ath/carl9170/Kconfig" | 27 | source "drivers/net/wireless/ath/carl9170/Kconfig" |
28 | source "drivers/net/wireless/ath/ath6kl/Kconfig" | 28 | source "drivers/net/wireless/ath/ath6kl/Kconfig" |
29 | source "drivers/net/wireless/ath/ar5523/Kconfig" | ||
29 | 30 | ||
30 | endif | 31 | endif |
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile index d716b748e574..1e18621326dc 100644 --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile | |||
@@ -2,6 +2,7 @@ obj-$(CONFIG_ATH5K) += ath5k/ | |||
2 | obj-$(CONFIG_ATH9K_HW) += ath9k/ | 2 | obj-$(CONFIG_ATH9K_HW) += ath9k/ |
3 | obj-$(CONFIG_CARL9170) += carl9170/ | 3 | obj-$(CONFIG_CARL9170) += carl9170/ |
4 | obj-$(CONFIG_ATH6KL) += ath6kl/ | 4 | obj-$(CONFIG_ATH6KL) += ath6kl/ |
5 | obj-$(CONFIG_AR5523) += ar5523/ | ||
5 | 6 | ||
6 | obj-$(CONFIG_ATH_COMMON) += ath.o | 7 | obj-$(CONFIG_ATH_COMMON) += ath.o |
7 | 8 | ||
diff --git a/drivers/net/wireless/ath/ar5523/Kconfig b/drivers/net/wireless/ath/ar5523/Kconfig new file mode 100644 index 000000000000..11d99ee8de51 --- /dev/null +++ b/drivers/net/wireless/ath/ar5523/Kconfig | |||
@@ -0,0 +1,7 @@ | |||
1 | config AR5523 | ||
2 | tristate "Atheros AR5523 wireless driver support" | ||
3 | depends on MAC80211 && USB | ||
4 | select FW_LOADER | ||
5 | ---help--- | ||
6 | This module add support for AR5523 based USB dongles such as D-Link | ||
7 | DWL-G132, Netgear WPN111 and many more. | ||
diff --git a/drivers/net/wireless/ath/ar5523/Makefile b/drivers/net/wireless/ath/ar5523/Makefile new file mode 100644 index 000000000000..ebf7f3bf0a33 --- /dev/null +++ b/drivers/net/wireless/ath/ar5523/Makefile | |||
@@ -0,0 +1 @@ | |||
obj-$(CONFIG_AR5523) := ar5523.o | |||
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c new file mode 100644 index 000000000000..f782b6e502bf --- /dev/null +++ b/drivers/net/wireless/ath/ar5523/ar5523.c | |||
@@ -0,0 +1,1806 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr> | ||
3 | * Copyright (c) 2006 Sam Leffler, Errno Consulting | ||
4 | * Copyright (c) 2007 Christoph Hellwig <hch@lst.de> | ||
5 | * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org> | ||
6 | * Copyright (c) 2012 Pontus Fuchs <pontus.fuchs@gmail.com> | ||
7 | * | ||
8 | * Permission to use, copy, modify, and/or distribute this software for any | ||
9 | * purpose with or without fee is hereby granted, provided that the above | ||
10 | * copyright notice and this permission notice appear in all copies. | ||
11 | * | ||
12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
13 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
14 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
15 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
16 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
17 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
18 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | * This driver is based on the uath driver written by Damien Bergamini for | ||
23 | * OpenBSD, who did black-box analysis of the Windows binary driver to find | ||
24 | * out how the hardware works. It contains a lot magic numbers because of | ||
25 | * that and only has minimal functionality. | ||
26 | */ | ||
27 | #include <linux/compiler.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/kernel.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/list.h> | ||
32 | #include <linux/completion.h> | ||
33 | #include <linux/firmware.h> | ||
34 | #include <linux/skbuff.h> | ||
35 | #include <linux/usb.h> | ||
36 | #include <net/mac80211.h> | ||
37 | |||
38 | #include "ar5523.h" | ||
39 | #include "ar5523_hw.h" | ||
40 | |||
41 | /* | ||
42 | * Various supported device vendors/products. | ||
43 | * UB51: AR5005UG 802.11b/g, UB52: AR5005UX 802.11a/b/g | ||
44 | */ | ||
45 | |||
46 | static int ar5523_submit_rx_cmd(struct ar5523 *ar); | ||
47 | static void ar5523_data_tx_pkt_put(struct ar5523 *ar); | ||
48 | |||
49 | static void ar5523_read_reply(struct ar5523 *ar, struct ar5523_cmd_hdr *hdr, | ||
50 | struct ar5523_tx_cmd *cmd) | ||
51 | { | ||
52 | int dlen, olen; | ||
53 | u32 *rp; | ||
54 | |||
55 | dlen = hdr->len - sizeof(*hdr); | ||
56 | |||
57 | if (dlen < 0) { | ||
58 | WARN_ON(1); | ||
59 | goto out; | ||
60 | } | ||
61 | |||
62 | ar5523_dbg(ar, "Code = %d len = %d\n", hdr->code & 0xff, dlen); | ||
63 | |||
64 | rp = (u32 *)(hdr + 1); | ||
65 | if (dlen >= sizeof(u32)) { | ||
66 | olen = be32_to_cpu(rp[0]); | ||
67 | dlen -= sizeof(u32); | ||
68 | if (olen == 0) { | ||
69 | /* convention is 0 =>'s one word */ | ||
70 | olen = sizeof(u32); | ||
71 | } | ||
72 | } else | ||
73 | olen = 0; | ||
74 | |||
75 | if (cmd->odata) { | ||
76 | if (cmd->olen < olen) { | ||
77 | ar5523_err(ar, "olen to small %d < %d\n", | ||
78 | cmd->olen, olen); | ||
79 | cmd->olen = 0; | ||
80 | cmd->res = -EOVERFLOW; | ||
81 | } else { | ||
82 | cmd->olen = olen; | ||
83 | memcpy(cmd->odata, &rp[1], olen); | ||
84 | cmd->res = 0; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | out: | ||
89 | complete(&cmd->done); | ||
90 | } | ||
91 | |||
92 | static void ar5523_cmd_rx_cb(struct urb *urb) | ||
93 | { | ||
94 | struct ar5523 *ar = urb->context; | ||
95 | struct ar5523_tx_cmd *cmd = &ar->tx_cmd; | ||
96 | struct ar5523_cmd_hdr *hdr = ar->rx_cmd_buf; | ||
97 | int dlen; | ||
98 | |||
99 | if (urb->status) { | ||
100 | if (urb->status != -ESHUTDOWN) | ||
101 | ar5523_err(ar, "RX USB error %d.\n", urb->status); | ||
102 | goto skip; | ||
103 | } | ||
104 | |||
105 | if (urb->actual_length < sizeof(struct ar5523_cmd_hdr)) { | ||
106 | ar5523_err(ar, "RX USB to short.\n"); | ||
107 | goto skip; | ||
108 | } | ||
109 | |||
110 | ar5523_dbg(ar, "%s code %02x priv %d\n", __func__, | ||
111 | be32_to_cpu(hdr->code) & 0xff, hdr->priv); | ||
112 | |||
113 | hdr->code = be32_to_cpu(hdr->code); | ||
114 | hdr->len = be32_to_cpu(hdr->len); | ||
115 | |||
116 | switch (hdr->code & 0xff) { | ||
117 | default: | ||
118 | /* reply to a read command */ | ||
119 | if (hdr->priv != AR5523_CMD_ID) { | ||
120 | ar5523_err(ar, "Unexpected command id: %02x\n", | ||
121 | hdr->code & 0xff); | ||
122 | goto skip; | ||
123 | } | ||
124 | ar5523_read_reply(ar, hdr, cmd); | ||
125 | break; | ||
126 | |||
127 | case WDCMSG_DEVICE_AVAIL: | ||
128 | ar5523_dbg(ar, "WDCMSG_DEVICE_AVAIL\n"); | ||
129 | cmd->res = 0; | ||
130 | cmd->olen = 0; | ||
131 | complete(&cmd->done); | ||
132 | break; | ||
133 | |||
134 | case WDCMSG_SEND_COMPLETE: | ||
135 | ar5523_dbg(ar, "WDCMSG_SEND_COMPLETE: %d pending\n", | ||
136 | atomic_read(&ar->tx_nr_pending)); | ||
137 | if (!test_bit(AR5523_HW_UP, &ar->flags)) | ||
138 | ar5523_dbg(ar, "Unexpected WDCMSG_SEND_COMPLETE\n"); | ||
139 | else { | ||
140 | mod_timer(&ar->tx_wd_timer, | ||
141 | jiffies + AR5523_TX_WD_TIMEOUT); | ||
142 | ar5523_data_tx_pkt_put(ar); | ||
143 | |||
144 | } | ||
145 | break; | ||
146 | |||
147 | case WDCMSG_TARGET_START: | ||
148 | /* This command returns a bogus id so it needs special | ||
149 | handling */ | ||
150 | dlen = hdr->len - sizeof(*hdr); | ||
151 | if (dlen != (int)sizeof(u32)) { | ||
152 | ar5523_err(ar, "Invalid reply to WDCMSG_TARGET_START"); | ||
153 | return; | ||
154 | } | ||
155 | memcpy(cmd->odata, hdr + 1, sizeof(u32)); | ||
156 | cmd->olen = sizeof(u32); | ||
157 | cmd->res = 0; | ||
158 | complete(&cmd->done); | ||
159 | break; | ||
160 | |||
161 | case WDCMSG_STATS_UPDATE: | ||
162 | ar5523_dbg(ar, "WDCMSG_STATS_UPDATE\n"); | ||
163 | break; | ||
164 | } | ||
165 | |||
166 | skip: | ||
167 | ar5523_submit_rx_cmd(ar); | ||
168 | } | ||
169 | |||
170 | static int ar5523_alloc_rx_cmd(struct ar5523 *ar) | ||
171 | { | ||
172 | ar->rx_cmd_urb = usb_alloc_urb(0, GFP_KERNEL); | ||
173 | if (!ar->rx_cmd_urb) | ||
174 | return -ENOMEM; | ||
175 | |||
176 | ar->rx_cmd_buf = usb_alloc_coherent(ar->dev, AR5523_MAX_RXCMDSZ, | ||
177 | GFP_KERNEL, | ||
178 | &ar->rx_cmd_urb->transfer_dma); | ||
179 | if (!ar->rx_cmd_buf) { | ||
180 | usb_free_urb(ar->rx_cmd_urb); | ||
181 | return -ENOMEM; | ||
182 | } | ||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | static void ar5523_cancel_rx_cmd(struct ar5523 *ar) | ||
187 | { | ||
188 | usb_kill_urb(ar->rx_cmd_urb); | ||
189 | } | ||
190 | |||
191 | static void ar5523_free_rx_cmd(struct ar5523 *ar) | ||
192 | { | ||
193 | usb_free_coherent(ar->dev, AR5523_MAX_RXCMDSZ, | ||
194 | ar->rx_cmd_buf, ar->rx_cmd_urb->transfer_dma); | ||
195 | usb_free_urb(ar->rx_cmd_urb); | ||
196 | } | ||
197 | |||
198 | static int ar5523_submit_rx_cmd(struct ar5523 *ar) | ||
199 | { | ||
200 | int error; | ||
201 | |||
202 | usb_fill_bulk_urb(ar->rx_cmd_urb, ar->dev, | ||
203 | ar5523_cmd_rx_pipe(ar->dev), ar->rx_cmd_buf, | ||
204 | AR5523_MAX_RXCMDSZ, ar5523_cmd_rx_cb, ar); | ||
205 | ar->rx_cmd_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
206 | |||
207 | error = usb_submit_urb(ar->rx_cmd_urb, GFP_ATOMIC); | ||
208 | if (error) { | ||
209 | if (error != -ENODEV) | ||
210 | ar5523_err(ar, "error %d when submitting rx urb\n", | ||
211 | error); | ||
212 | return error; | ||
213 | } | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | /* | ||
218 | * Command submitted cb | ||
219 | */ | ||
220 | static void ar5523_cmd_tx_cb(struct urb *urb) | ||
221 | { | ||
222 | struct ar5523_tx_cmd *cmd = urb->context; | ||
223 | struct ar5523 *ar = cmd->ar; | ||
224 | |||
225 | if (urb->status) { | ||
226 | ar5523_err(ar, "Failed to TX command. Status = %d\n", | ||
227 | urb->status); | ||
228 | cmd->res = urb->status; | ||
229 | complete(&cmd->done); | ||
230 | return; | ||
231 | } | ||
232 | |||
233 | if (!(cmd->flags & AR5523_CMD_FLAG_READ)) { | ||
234 | cmd->res = 0; | ||
235 | complete(&cmd->done); | ||
236 | } | ||
237 | } | ||
238 | |||
239 | static int ar5523_cmd(struct ar5523 *ar, u32 code, const void *idata, | ||
240 | int ilen, void *odata, int olen, int flags) | ||
241 | { | ||
242 | struct ar5523_cmd_hdr *hdr; | ||
243 | struct ar5523_tx_cmd *cmd = &ar->tx_cmd; | ||
244 | int xferlen, error; | ||
245 | |||
246 | /* always bulk-out a multiple of 4 bytes */ | ||
247 | xferlen = (sizeof(struct ar5523_cmd_hdr) + ilen + 3) & ~3; | ||
248 | |||
249 | hdr = (struct ar5523_cmd_hdr *)cmd->buf_tx; | ||
250 | memset(hdr, 0, sizeof(struct ar5523_cmd_hdr)); | ||
251 | hdr->len = cpu_to_be32(xferlen); | ||
252 | hdr->code = cpu_to_be32(code); | ||
253 | hdr->priv = AR5523_CMD_ID; | ||
254 | |||
255 | if (flags & AR5523_CMD_FLAG_MAGIC) | ||
256 | hdr->magic = cpu_to_be32(1 << 24); | ||
257 | memcpy(hdr + 1, idata, ilen); | ||
258 | |||
259 | cmd->odata = odata; | ||
260 | cmd->olen = olen; | ||
261 | cmd->flags = flags; | ||
262 | |||
263 | ar5523_dbg(ar, "do cmd %02x\n", code); | ||
264 | |||
265 | usb_fill_bulk_urb(cmd->urb_tx, ar->dev, ar5523_cmd_tx_pipe(ar->dev), | ||
266 | cmd->buf_tx, xferlen, ar5523_cmd_tx_cb, cmd); | ||
267 | cmd->urb_tx->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | ||
268 | |||
269 | error = usb_submit_urb(cmd->urb_tx, GFP_KERNEL); | ||
270 | if (error) { | ||
271 | ar5523_err(ar, "could not send command 0x%x, error=%d\n", | ||
272 | code, error); | ||
273 | return error; | ||
274 | } | ||
275 | |||
276 | if (!wait_for_completion_timeout(&cmd->done, 2 * HZ)) { | ||
277 | cmd->odata = NULL; | ||
278 | ar5523_err(ar, "timeout waiting for command %02x reply\n", | ||
279 | code); | ||
280 | cmd->res = -ETIMEDOUT; | ||
281 | } | ||
282 | return cmd->res; | ||
283 | } | ||
284 | |||
285 | static int ar5523_cmd_write(struct ar5523 *ar, u32 code, const void *data, | ||
286 | int len, int flags) | ||
287 | { | ||
288 | flags &= ~AR5523_CMD_FLAG_READ; | ||
289 | return ar5523_cmd(ar, code, data, len, NULL, 0, flags); | ||
290 | } | ||
291 | |||
292 | static int ar5523_cmd_read(struct ar5523 *ar, u32 code, const void *idata, | ||
293 | int ilen, void *odata, int olen, int flags) | ||
294 | { | ||
295 | flags |= AR5523_CMD_FLAG_READ; | ||
296 | return ar5523_cmd(ar, code, idata, ilen, odata, olen, flags); | ||
297 | } | ||
298 | |||
299 | static int ar5523_config(struct ar5523 *ar, u32 reg, u32 val) | ||
300 | { | ||
301 | struct ar5523_write_mac write; | ||
302 | int error; | ||
303 | |||
304 | write.reg = cpu_to_be32(reg); | ||
305 | write.len = cpu_to_be32(0); /* 0 = single write */ | ||
306 | *(u32 *)write.data = cpu_to_be32(val); | ||
307 | |||
308 | error = ar5523_cmd_write(ar, WDCMSG_TARGET_SET_CONFIG, &write, | ||
309 | 3 * sizeof(u32), 0); | ||
310 | if (error != 0) | ||
311 | ar5523_err(ar, "could not write register 0x%02x\n", reg); | ||
312 | return error; | ||
313 | } | ||
314 | |||
315 | static int ar5523_config_multi(struct ar5523 *ar, u32 reg, const void *data, | ||
316 | int len) | ||
317 | { | ||
318 | struct ar5523_write_mac write; | ||
319 | int error; | ||
320 | |||
321 | write.reg = cpu_to_be32(reg); | ||
322 | write.len = cpu_to_be32(len); | ||
323 | memcpy(write.data, data, len); | ||
324 | |||
325 | /* properly handle the case where len is zero (reset) */ | ||
326 | error = ar5523_cmd_write(ar, WDCMSG_TARGET_SET_CONFIG, &write, | ||
327 | (len == 0) ? sizeof(u32) : 2 * sizeof(u32) + len, 0); | ||
328 | if (error != 0) | ||
329 | ar5523_err(ar, "could not write %d bytes to register 0x%02x\n", | ||
330 | len, reg); | ||
331 | return error; | ||
332 | } | ||
333 | |||
334 | static int ar5523_get_status(struct ar5523 *ar, u32 which, void *odata, | ||
335 | int olen) | ||
336 | { | ||
337 | int error; | ||
338 | |||
339 | which = cpu_to_be32(which); | ||
340 | error = ar5523_cmd_read(ar, WDCMSG_TARGET_GET_STATUS, | ||
341 | &which, sizeof(which), odata, olen, AR5523_CMD_FLAG_MAGIC); | ||
342 | if (error != 0) | ||
343 | ar5523_err(ar, "could not read EEPROM offset 0x%02x\n", | ||
344 | be32_to_cpu(which)); | ||
345 | return error; | ||
346 | } | ||
347 | |||
348 | static int ar5523_get_capability(struct ar5523 *ar, u32 cap, u32 *val) | ||
349 | { | ||
350 | int error; | ||
351 | |||
352 | cap = cpu_to_be32(cap); | ||
353 | error = ar5523_cmd_read(ar, WDCMSG_TARGET_GET_CAPABILITY, | ||
354 | &cap, sizeof(cap), val, sizeof(u32), AR5523_CMD_FLAG_MAGIC); | ||
355 | if (error != 0) { | ||
356 | ar5523_err(ar, "could not read capability %u\n", | ||
357 | be32_to_cpu(cap)); | ||
358 | return error; | ||
359 | } | ||
360 | *val = be32_to_cpu(*val); | ||
361 | return error; | ||
362 | } | ||
363 | |||
364 | static int ar5523_get_devcap(struct ar5523 *ar) | ||
365 | { | ||
366 | #define GETCAP(x) do { \ | ||
367 | error = ar5523_get_capability(ar, x, &cap); \ | ||
368 | if (error != 0) \ | ||
369 | return error; \ | ||
370 | ar5523_info(ar, "Cap: " \ | ||
371 | "%s=0x%08x\n", #x, cap); \ | ||
372 | } while (0) | ||
373 | int error; | ||
374 | u32 cap; | ||
375 | |||
376 | /* collect device capabilities */ | ||
377 | GETCAP(CAP_TARGET_VERSION); | ||
378 | GETCAP(CAP_TARGET_REVISION); | ||
379 | GETCAP(CAP_MAC_VERSION); | ||
380 | GETCAP(CAP_MAC_REVISION); | ||
381 | GETCAP(CAP_PHY_REVISION); | ||
382 | GETCAP(CAP_ANALOG_5GHz_REVISION); | ||
383 | GETCAP(CAP_ANALOG_2GHz_REVISION); | ||
384 | |||
385 | GETCAP(CAP_REG_DOMAIN); | ||
386 | GETCAP(CAP_REG_CAP_BITS); | ||
387 | GETCAP(CAP_WIRELESS_MODES); | ||
388 | GETCAP(CAP_CHAN_SPREAD_SUPPORT); | ||
389 | GETCAP(CAP_COMPRESS_SUPPORT); | ||
390 | GETCAP(CAP_BURST_SUPPORT); | ||
391 | GETCAP(CAP_FAST_FRAMES_SUPPORT); | ||
392 | GETCAP(CAP_CHAP_TUNING_SUPPORT); | ||
393 | GETCAP(CAP_TURBOG_SUPPORT); | ||
394 | GETCAP(CAP_TURBO_PRIME_SUPPORT); | ||
395 | GETCAP(CAP_DEVICE_TYPE); | ||
396 | GETCAP(CAP_WME_SUPPORT); | ||
397 | GETCAP(CAP_TOTAL_QUEUES); | ||
398 | GETCAP(CAP_CONNECTION_ID_MAX); | ||
399 | |||
400 | GETCAP(CAP_LOW_5GHZ_CHAN); | ||
401 | GETCAP(CAP_HIGH_5GHZ_CHAN); | ||
402 | GETCAP(CAP_LOW_2GHZ_CHAN); | ||
403 | GETCAP(CAP_HIGH_2GHZ_CHAN); | ||
404 | GETCAP(CAP_TWICE_ANTENNAGAIN_5G); | ||
405 | GETCAP(CAP_TWICE_ANTENNAGAIN_2G); | ||
406 | |||
407 | GETCAP(CAP_CIPHER_AES_CCM); | ||
408 | GETCAP(CAP_CIPHER_TKIP); | ||
409 | GETCAP(CAP_MIC_TKIP); | ||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | static int ar5523_set_ledsteady(struct ar5523 *ar, int lednum, int ledmode) | ||
414 | { | ||
415 | struct ar5523_cmd_ledsteady led; | ||
416 | |||
417 | led.lednum = cpu_to_be32(lednum); | ||
418 | led.ledmode = cpu_to_be32(ledmode); | ||
419 | |||
420 | ar5523_dbg(ar, "set %s led %s (steady)\n", | ||
421 | (lednum == UATH_LED_LINK) ? "link" : "activity", | ||
422 | ledmode ? "on" : "off"); | ||
423 | return ar5523_cmd_write(ar, WDCMSG_SET_LED_STEADY, &led, sizeof(led), | ||
424 | 0); | ||
425 | } | ||
426 | |||
427 | static int ar5523_set_rxfilter(struct ar5523 *ar, u32 bits, u32 op) | ||
428 | { | ||
429 | struct ar5523_cmd_rx_filter rxfilter; | ||
430 | |||
431 | rxfilter.bits = cpu_to_be32(bits); | ||
432 | rxfilter.op = cpu_to_be32(op); | ||
433 | |||
434 | ar5523_dbg(ar, "setting Rx filter=0x%x flags=0x%x\n", bits, op); | ||
435 | return ar5523_cmd_write(ar, WDCMSG_RX_FILTER, &rxfilter, | ||
436 | sizeof(rxfilter), 0); | ||
437 | } | ||
438 | |||
439 | static int ar5523_reset_tx_queues(struct ar5523 *ar) | ||
440 | { | ||
441 | __be32 qid = cpu_to_be32(0); | ||
442 | |||
443 | ar5523_dbg(ar, "resetting Tx queue\n"); | ||
444 | return ar5523_cmd_write(ar, WDCMSG_RELEASE_TX_QUEUE, | ||
445 | &qid, sizeof(qid), 0); | ||
446 | } | ||
447 | |||
448 | static int ar5523_set_chan(struct ar5523 *ar) | ||
449 | { | ||
450 | struct ieee80211_conf *conf = &ar->hw->conf; | ||
451 | |||
452 | struct ar5523_cmd_reset reset; | ||
453 | |||
454 | memset(&reset, 0, sizeof(reset)); | ||
455 | reset.flags |= cpu_to_be32(UATH_CHAN_2GHZ); | ||
456 | reset.flags |= cpu_to_be32(UATH_CHAN_OFDM); | ||
457 | reset.freq = cpu_to_be32(conf->channel->center_freq); | ||
458 | reset.maxrdpower = cpu_to_be32(50); /* XXX */ | ||
459 | reset.channelchange = cpu_to_be32(1); | ||
460 | reset.keeprccontent = cpu_to_be32(0); | ||
461 | |||
462 | ar5523_dbg(ar, "set chan flags 0x%x freq %d\n", | ||
463 | be32_to_cpu(reset.flags), | ||
464 | conf->channel->center_freq); | ||
465 | return ar5523_cmd_write(ar, WDCMSG_RESET, &reset, sizeof(reset), 0); | ||
466 | } | ||
467 | |||
468 | static int ar5523_queue_init(struct ar5523 *ar) | ||
469 | { | ||
470 | struct ar5523_cmd_txq_setup qinfo; | ||
471 | |||
472 | ar5523_dbg(ar, "setting up Tx queue\n"); | ||
473 | qinfo.qid = cpu_to_be32(0); | ||
474 | qinfo.len = cpu_to_be32(sizeof(qinfo.attr)); | ||
475 | qinfo.attr.priority = cpu_to_be32(0); /* XXX */ | ||
476 | qinfo.attr.aifs = cpu_to_be32(3); | ||
477 | qinfo.attr.logcwmin = cpu_to_be32(4); | ||
478 | qinfo.attr.logcwmax = cpu_to_be32(10); | ||
479 | qinfo.attr.bursttime = cpu_to_be32(0); | ||
480 | qinfo.attr.mode = cpu_to_be32(0); | ||
481 | qinfo.attr.qflags = cpu_to_be32(1); /* XXX? */ | ||
482 | return ar5523_cmd_write(ar, WDCMSG_SETUP_TX_QUEUE, &qinfo, | ||
483 | sizeof(qinfo), 0); | ||
484 | } | ||
485 | |||
486 | static int ar5523_switch_chan(struct ar5523 *ar) | ||
487 | { | ||
488 | int error; | ||
489 | |||
490 | error = ar5523_set_chan(ar); | ||
491 | if (error) { | ||
492 | ar5523_err(ar, "could not set chan, error %d\n", error); | ||
493 | goto out_err; | ||
494 | } | ||
495 | |||
496 | /* reset Tx rings */ | ||
497 | error = ar5523_reset_tx_queues(ar); | ||
498 | if (error) { | ||
499 | ar5523_err(ar, "could not reset Tx queues, error %d\n", | ||
500 | error); | ||
501 | goto out_err; | ||
502 | } | ||
503 | /* set Tx rings WME properties */ | ||
504 | error = ar5523_queue_init(ar); | ||
505 | if (error) | ||
506 | ar5523_err(ar, "could not init wme, error %d\n", error); | ||
507 | |||
508 | out_err: | ||
509 | return error; | ||
510 | } | ||
511 | |||
512 | static void ar5523_rx_data_put(struct ar5523 *ar, | ||
513 | struct ar5523_rx_data *data) | ||
514 | { | ||
515 | unsigned long flags; | ||
516 | spin_lock_irqsave(&ar->rx_data_list_lock, flags); | ||
517 | list_move(&data->list, &ar->rx_data_free); | ||
518 | spin_unlock_irqrestore(&ar->rx_data_list_lock, flags); | ||
519 | } | ||
520 | |||
521 | static void ar5523_data_rx_cb(struct urb *urb) | ||
522 | { | ||
523 | struct ar5523_rx_data *data = urb->context; | ||
524 | struct ar5523 *ar = data->ar; | ||
525 | struct ar5523_rx_desc *desc; | ||
526 | struct ar5523_chunk *chunk; | ||
527 | struct ieee80211_hw *hw = ar->hw; | ||
528 | struct ieee80211_rx_status *rx_status; | ||
529 | u32 rxlen; | ||
530 | int usblen = urb->actual_length; | ||
531 | int hdrlen, pad; | ||
532 | |||
533 | ar5523_dbg(ar, "%s\n", __func__); | ||
534 | /* sync/async unlink faults aren't errors */ | ||
535 | if (urb->status) { | ||
536 | if (urb->status != -ESHUTDOWN) | ||
537 | ar5523_err(ar, "%s: USB err: %d\n", __func__, | ||
538 | urb->status); | ||
539 | goto skip; | ||
540 | } | ||
541 | |||
542 | if (usblen < AR5523_MIN_RXBUFSZ) { | ||
543 | ar5523_err(ar, "RX: wrong xfer size (usblen=%d)\n", usblen); | ||
544 | goto skip; | ||
545 | } | ||
546 | |||
547 | chunk = (struct ar5523_chunk *) data->skb->data; | ||
548 | |||
549 | if (((chunk->flags & UATH_CFLAGS_FINAL) == 0) || | ||
550 | chunk->seqnum != 0) { | ||
551 | ar5523_dbg(ar, "RX: No final flag. s: %d f: %02x l: %d\n", | ||
552 | chunk->seqnum, chunk->flags, | ||
553 | be16_to_cpu(chunk->length)); | ||
554 | goto skip; | ||
555 | } | ||
556 | |||
557 | /* Rx descriptor is located at the end, 32-bit aligned */ | ||
558 | desc = (struct ar5523_rx_desc *) | ||
559 | (data->skb->data + usblen - sizeof(struct ar5523_rx_desc)); | ||
560 | |||
561 | rxlen = be32_to_cpu(desc->len); | ||
562 | if (rxlen > ar->rxbufsz) { | ||
563 | ar5523_dbg(ar, "RX: Bad descriptor (len=%d)\n", | ||
564 | be32_to_cpu(desc->len)); | ||
565 | goto skip; | ||
566 | } | ||
567 | |||
568 | if (!rxlen) { | ||
569 | ar5523_dbg(ar, "RX: rxlen is 0\n"); | ||
570 | goto skip; | ||
571 | } | ||
572 | |||
573 | if (be32_to_cpu(desc->status) != 0) { | ||
574 | ar5523_dbg(ar, "Bad RX status (0x%x len = %d). Skip\n", | ||
575 | be32_to_cpu(desc->status), be32_to_cpu(desc->len)); | ||
576 | goto skip; | ||
577 | } | ||
578 | |||
579 | skb_reserve(data->skb, sizeof(*chunk)); | ||
580 | skb_put(data->skb, rxlen - sizeof(struct ar5523_rx_desc)); | ||
581 | |||
582 | hdrlen = ieee80211_get_hdrlen_from_skb(data->skb); | ||
583 | if (!IS_ALIGNED(hdrlen, 4)) { | ||
584 | ar5523_dbg(ar, "eek, alignment workaround activated\n"); | ||
585 | pad = ALIGN(hdrlen, 4) - hdrlen; | ||
586 | memmove(data->skb->data + pad, data->skb->data, hdrlen); | ||
587 | skb_pull(data->skb, pad); | ||
588 | skb_put(data->skb, pad); | ||
589 | } | ||
590 | |||
591 | rx_status = IEEE80211_SKB_RXCB(data->skb); | ||
592 | memset(rx_status, 0, sizeof(*rx_status)); | ||
593 | rx_status->freq = be32_to_cpu(desc->channel); | ||
594 | rx_status->band = hw->conf.channel->band; | ||
595 | rx_status->signal = -95 + be32_to_cpu(desc->rssi); | ||
596 | |||
597 | ieee80211_rx_irqsafe(hw, data->skb); | ||
598 | data->skb = NULL; | ||
599 | |||
600 | skip: | ||
601 | if (data->skb) { | ||
602 | dev_kfree_skb_irq(data->skb); | ||
603 | data->skb = NULL; | ||
604 | } | ||
605 | |||
606 | ar5523_rx_data_put(ar, data); | ||
607 | if (atomic_inc_return(&ar->rx_data_free_cnt) >= | ||
608 | AR5523_RX_DATA_REFILL_COUNT && | ||
609 | test_bit(AR5523_HW_UP, &ar->flags)) | ||
610 | queue_work(ar->wq, &ar->rx_refill_work); | ||
611 | } | ||
612 | |||
613 | static void ar5523_rx_refill_work(struct work_struct *work) | ||
614 | { | ||
615 | struct ar5523 *ar = container_of(work, struct ar5523, rx_refill_work); | ||
616 | struct ar5523_rx_data *data; | ||
617 | unsigned long flags; | ||
618 | int error; | ||
619 | |||
620 | ar5523_dbg(ar, "%s\n", __func__); | ||
621 | do { | ||
622 | spin_lock_irqsave(&ar->rx_data_list_lock, flags); | ||
623 | |||
624 | if (!list_empty(&ar->rx_data_free)) | ||
625 | data = (struct ar5523_rx_data *) ar->rx_data_free.next; | ||
626 | else | ||
627 | data = NULL; | ||
628 | spin_unlock_irqrestore(&ar->rx_data_list_lock, flags); | ||
629 | |||
630 | if (!data) | ||
631 | goto done; | ||
632 | |||
633 | data->skb = alloc_skb(ar->rxbufsz, GFP_KERNEL); | ||
634 | if (!data->skb) { | ||
635 | ar5523_err(ar, "could not allocate rx skbuff\n"); | ||
636 | return; | ||
637 | } | ||
638 | |||
639 | usb_fill_bulk_urb(data->urb, ar->dev, | ||
640 | ar5523_data_rx_pipe(ar->dev), data->skb->data, | ||
641 | ar->rxbufsz, ar5523_data_rx_cb, data); | ||
642 | |||
643 | spin_lock_irqsave(&ar->rx_data_list_lock, flags); | ||
644 | list_move(&data->list, &ar->rx_data_used); | ||
645 | spin_unlock_irqrestore(&ar->rx_data_list_lock, flags); | ||
646 | atomic_dec(&ar->rx_data_free_cnt); | ||
647 | |||
648 | error = usb_submit_urb(data->urb, GFP_KERNEL); | ||
649 | if (error) { | ||
650 | kfree_skb(data->skb); | ||
651 | if (error != -ENODEV) | ||
652 | ar5523_err(ar, "Err sending rx data urb %d\n", | ||
653 | error); | ||
654 | ar5523_rx_data_put(ar, data); | ||
655 | atomic_inc(&ar->rx_data_free_cnt); | ||
656 | return; | ||
657 | } | ||
658 | |||
659 | } while (true); | ||
660 | done: | ||
661 | return; | ||
662 | } | ||
663 | |||
664 | static void ar5523_cancel_rx_bufs(struct ar5523 *ar) | ||
665 | { | ||
666 | struct ar5523_rx_data *data; | ||
667 | unsigned long flags; | ||
668 | |||
669 | do { | ||
670 | spin_lock_irqsave(&ar->rx_data_list_lock, flags); | ||
671 | if (!list_empty(&ar->rx_data_used)) | ||
672 | data = (struct ar5523_rx_data *) ar->rx_data_used.next; | ||
673 | else | ||
674 | data = NULL; | ||
675 | spin_unlock_irqrestore(&ar->rx_data_list_lock, flags); | ||
676 | |||
677 | if (!data) | ||
678 | break; | ||
679 | |||
680 | usb_kill_urb(data->urb); | ||
681 | list_move(&data->list, &ar->rx_data_free); | ||
682 | atomic_inc(&ar->rx_data_free_cnt); | ||
683 | } while (data); | ||
684 | } | ||
685 | |||
686 | static void ar5523_free_rx_bufs(struct ar5523 *ar) | ||
687 | { | ||
688 | struct ar5523_rx_data *data; | ||
689 | |||
690 | ar5523_cancel_rx_bufs(ar); | ||
691 | while (!list_empty(&ar->rx_data_free)) { | ||
692 | data = (struct ar5523_rx_data *) ar->rx_data_free.next; | ||
693 | list_del(&data->list); | ||
694 | usb_free_urb(data->urb); | ||
695 | } | ||
696 | } | ||
697 | |||
698 | static int ar5523_alloc_rx_bufs(struct ar5523 *ar) | ||
699 | { | ||
700 | int i; | ||
701 | |||
702 | for (i = 0; i < AR5523_RX_DATA_COUNT; i++) { | ||
703 | struct ar5523_rx_data *data = &ar->rx_data[i]; | ||
704 | |||
705 | data->ar = ar; | ||
706 | data->urb = usb_alloc_urb(0, GFP_KERNEL); | ||
707 | if (!data->urb) { | ||
708 | ar5523_err(ar, "could not allocate rx data urb\n"); | ||
709 | goto err; | ||
710 | } | ||
711 | list_add_tail(&data->list, &ar->rx_data_free); | ||
712 | atomic_inc(&ar->rx_data_free_cnt); | ||
713 | } | ||
714 | return 0; | ||
715 | |||
716 | err: | ||
717 | ar5523_free_rx_bufs(ar); | ||
718 | return -ENOMEM; | ||
719 | } | ||
720 | |||
721 | static void ar5523_data_tx_pkt_put(struct ar5523 *ar) | ||
722 | { | ||
723 | atomic_dec(&ar->tx_nr_total); | ||
724 | if (!atomic_dec_return(&ar->tx_nr_pending)) { | ||
725 | del_timer(&ar->tx_wd_timer); | ||
726 | wake_up(&ar->tx_flush_waitq); | ||
727 | } | ||
728 | |||
729 | if (atomic_read(&ar->tx_nr_total) < AR5523_TX_DATA_RESTART_COUNT) { | ||
730 | ar5523_dbg(ar, "restart tx queue\n"); | ||
731 | ieee80211_wake_queues(ar->hw); | ||
732 | } | ||
733 | } | ||
734 | |||
735 | static void ar5523_data_tx_cb(struct urb *urb) | ||
736 | { | ||
737 | struct sk_buff *skb = urb->context; | ||
738 | struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb); | ||
739 | struct ar5523_tx_data *data = (struct ar5523_tx_data *) | ||
740 | txi->driver_data; | ||
741 | struct ar5523 *ar = data->ar; | ||
742 | unsigned long flags; | ||
743 | |||
744 | ar5523_dbg(ar, "data tx urb completed: %d\n", urb->status); | ||
745 | |||
746 | spin_lock_irqsave(&ar->tx_data_list_lock, flags); | ||
747 | list_del(&data->list); | ||
748 | spin_unlock_irqrestore(&ar->tx_data_list_lock, flags); | ||
749 | |||
750 | if (urb->status) { | ||
751 | ar5523_dbg(ar, "%s: urb status: %d\n", __func__, urb->status); | ||
752 | ar5523_data_tx_pkt_put(ar); | ||
753 | ieee80211_free_txskb(ar->hw, skb); | ||
754 | } else { | ||
755 | skb_pull(skb, sizeof(struct ar5523_tx_desc) + sizeof(__be32)); | ||
756 | ieee80211_tx_status_irqsafe(ar->hw, skb); | ||
757 | } | ||
758 | usb_free_urb(urb); | ||
759 | } | ||
760 | |||
761 | static void ar5523_tx(struct ieee80211_hw *hw, | ||
762 | struct ieee80211_tx_control *control, | ||
763 | struct sk_buff *skb) | ||
764 | { | ||
765 | struct ieee80211_tx_info *txi = IEEE80211_SKB_CB(skb); | ||
766 | struct ar5523_tx_data *data = (struct ar5523_tx_data *) | ||
767 | txi->driver_data; | ||
768 | struct ar5523 *ar = hw->priv; | ||
769 | unsigned long flags; | ||
770 | |||
771 | ar5523_dbg(ar, "tx called\n"); | ||
772 | if (atomic_inc_return(&ar->tx_nr_total) >= AR5523_TX_DATA_COUNT) { | ||
773 | ar5523_dbg(ar, "tx queue full\n"); | ||
774 | ar5523_dbg(ar, "stop queues (tot %d pend %d)\n", | ||
775 | atomic_read(&ar->tx_nr_total), | ||
776 | atomic_read(&ar->tx_nr_pending)); | ||
777 | ieee80211_stop_queues(hw); | ||
778 | } | ||
779 | |||
780 | data->skb = skb; | ||
781 | |||
782 | spin_lock_irqsave(&ar->tx_data_list_lock, flags); | ||
783 | list_add_tail(&data->list, &ar->tx_queue_pending); | ||
784 | spin_unlock_irqrestore(&ar->tx_data_list_lock, flags); | ||
785 | |||
786 | ieee80211_queue_work(ar->hw, &ar->tx_work); | ||
787 | } | ||
788 | |||
789 | static void ar5523_tx_work_locked(struct ar5523 *ar) | ||
790 | { | ||
791 | struct ar5523_tx_data *data; | ||
792 | struct ar5523_tx_desc *desc; | ||
793 | struct ar5523_chunk *chunk; | ||
794 | struct ieee80211_tx_info *txi; | ||
795 | struct urb *urb; | ||
796 | struct sk_buff *skb; | ||
797 | int error = 0, paylen; | ||
798 | u32 txqid; | ||
799 | unsigned long flags; | ||
800 | |||
801 | BUILD_BUG_ON(sizeof(struct ar5523_tx_data) > | ||
802 | IEEE80211_TX_INFO_DRIVER_DATA_SIZE); | ||
803 | |||
804 | ar5523_dbg(ar, "%s\n", __func__); | ||
805 | do { | ||
806 | spin_lock_irqsave(&ar->tx_data_list_lock, flags); | ||
807 | if (!list_empty(&ar->tx_queue_pending)) { | ||
808 | data = (struct ar5523_tx_data *) | ||
809 | ar->tx_queue_pending.next; | ||
810 | list_del(&data->list); | ||
811 | } else | ||
812 | data = NULL; | ||
813 | spin_unlock_irqrestore(&ar->tx_data_list_lock, flags); | ||
814 | |||
815 | if (!data) | ||
816 | break; | ||
817 | |||
818 | skb = data->skb; | ||
819 | txqid = 0; | ||
820 | txi = IEEE80211_SKB_CB(skb); | ||
821 | paylen = skb->len; | ||
822 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
823 | if (!urb) { | ||
824 | ar5523_err(ar, "Failed to allocate TX urb\n"); | ||
825 | ieee80211_free_txskb(ar->hw, skb); | ||
826 | continue; | ||
827 | } | ||
828 | |||
829 | data->ar = ar; | ||
830 | data->urb = urb; | ||
831 | |||
832 | desc = (struct ar5523_tx_desc *)skb_push(skb, sizeof(*desc)); | ||
833 | chunk = (struct ar5523_chunk *)skb_push(skb, sizeof(*chunk)); | ||
834 | |||
835 | chunk->seqnum = 0; | ||
836 | chunk->flags = UATH_CFLAGS_FINAL; | ||
837 | chunk->length = cpu_to_be16(skb->len); | ||
838 | |||
839 | desc->msglen = cpu_to_be32(skb->len); | ||
840 | desc->msgid = AR5523_DATA_ID; | ||
841 | desc->buflen = cpu_to_be32(paylen); | ||
842 | desc->type = cpu_to_be32(WDCMSG_SEND); | ||
843 | desc->flags = cpu_to_be32(UATH_TX_NOTIFY); | ||
844 | |||
845 | if (test_bit(AR5523_CONNECTED, &ar->flags)) | ||
846 | desc->connid = cpu_to_be32(AR5523_ID_BSS); | ||
847 | else | ||
848 | desc->connid = cpu_to_be32(AR5523_ID_BROADCAST); | ||
849 | |||
850 | if (txi->flags & IEEE80211_TX_CTL_USE_MINRATE) | ||
851 | txqid |= UATH_TXQID_MINRATE; | ||
852 | |||
853 | desc->txqid = cpu_to_be32(txqid); | ||
854 | |||
855 | urb->transfer_flags = URB_ZERO_PACKET; | ||
856 | usb_fill_bulk_urb(urb, ar->dev, ar5523_data_tx_pipe(ar->dev), | ||
857 | skb->data, skb->len, ar5523_data_tx_cb, skb); | ||
858 | |||
859 | spin_lock_irqsave(&ar->tx_data_list_lock, flags); | ||
860 | list_add_tail(&data->list, &ar->tx_queue_submitted); | ||
861 | spin_unlock_irqrestore(&ar->tx_data_list_lock, flags); | ||
862 | mod_timer(&ar->tx_wd_timer, jiffies + AR5523_TX_WD_TIMEOUT); | ||
863 | atomic_inc(&ar->tx_nr_pending); | ||
864 | |||
865 | ar5523_dbg(ar, "TX Frame (%d pending)\n", | ||
866 | atomic_read(&ar->tx_nr_pending)); | ||
867 | error = usb_submit_urb(urb, GFP_KERNEL); | ||
868 | if (error) { | ||
869 | ar5523_err(ar, "error %d when submitting tx urb\n", | ||
870 | error); | ||
871 | spin_lock_irqsave(&ar->tx_data_list_lock, flags); | ||
872 | list_del(&data->list); | ||
873 | spin_unlock_irqrestore(&ar->tx_data_list_lock, flags); | ||
874 | atomic_dec(&ar->tx_nr_pending); | ||
875 | ar5523_data_tx_pkt_put(ar); | ||
876 | usb_free_urb(urb); | ||
877 | ieee80211_free_txskb(ar->hw, skb); | ||
878 | } | ||
879 | } while (true); | ||
880 | } | ||
881 | |||
882 | static void ar5523_tx_work(struct work_struct *work) | ||
883 | { | ||
884 | struct ar5523 *ar = container_of(work, struct ar5523, tx_work); | ||
885 | |||
886 | ar5523_dbg(ar, "%s\n", __func__); | ||
887 | mutex_lock(&ar->mutex); | ||
888 | ar5523_tx_work_locked(ar); | ||
889 | mutex_unlock(&ar->mutex); | ||
890 | } | ||
891 | |||
892 | static void ar5523_tx_wd_timer(unsigned long arg) | ||
893 | { | ||
894 | struct ar5523 *ar = (struct ar5523 *) arg; | ||
895 | |||
896 | ar5523_dbg(ar, "TX watchdog timer triggered\n"); | ||
897 | ieee80211_queue_work(ar->hw, &ar->tx_wd_work); | ||
898 | } | ||
899 | |||
900 | static void ar5523_tx_wd_work(struct work_struct *work) | ||
901 | { | ||
902 | struct ar5523 *ar = container_of(work, struct ar5523, tx_wd_work); | ||
903 | |||
904 | /* Occasionally the TX queues stop responding. The only way to | ||
905 | * recover seems to be to reset the dongle. | ||
906 | */ | ||
907 | |||
908 | mutex_lock(&ar->mutex); | ||
909 | ar5523_err(ar, "TX queue stuck (tot %d pend %d)\n", | ||
910 | atomic_read(&ar->tx_nr_total), | ||
911 | atomic_read(&ar->tx_nr_pending)); | ||
912 | |||
913 | ar5523_err(ar, "Will restart dongle.\n"); | ||
914 | ar5523_cmd_write(ar, WDCMSG_TARGET_RESET, NULL, 0, 0); | ||
915 | mutex_unlock(&ar->mutex); | ||
916 | } | ||
917 | |||
918 | static void ar5523_flush_tx(struct ar5523 *ar) | ||
919 | { | ||
920 | ar5523_tx_work_locked(ar); | ||
921 | |||
922 | /* Don't waste time trying to flush if USB is disconnected */ | ||
923 | if (test_bit(AR5523_USB_DISCONNECTED, &ar->flags)) | ||
924 | return; | ||
925 | if (!wait_event_timeout(ar->tx_flush_waitq, | ||
926 | !atomic_read(&ar->tx_nr_pending), AR5523_FLUSH_TIMEOUT)) | ||
927 | ar5523_err(ar, "flush timeout (tot %d pend %d)\n", | ||
928 | atomic_read(&ar->tx_nr_total), | ||
929 | atomic_read(&ar->tx_nr_pending)); | ||
930 | } | ||
931 | |||
932 | static void ar5523_free_tx_cmd(struct ar5523 *ar) | ||
933 | { | ||
934 | struct ar5523_tx_cmd *cmd = &ar->tx_cmd; | ||
935 | |||
936 | usb_free_coherent(ar->dev, AR5523_MAX_RXCMDSZ, cmd->buf_tx, | ||
937 | cmd->urb_tx->transfer_dma); | ||
938 | usb_free_urb(cmd->urb_tx); | ||
939 | } | ||
940 | |||
941 | static int ar5523_alloc_tx_cmd(struct ar5523 *ar) | ||
942 | { | ||
943 | struct ar5523_tx_cmd *cmd = &ar->tx_cmd; | ||
944 | |||
945 | cmd->ar = ar; | ||
946 | init_completion(&cmd->done); | ||
947 | |||
948 | cmd->urb_tx = usb_alloc_urb(0, GFP_KERNEL); | ||
949 | if (!cmd->urb_tx) { | ||
950 | ar5523_err(ar, "could not allocate urb\n"); | ||
951 | return -ENOMEM; | ||
952 | } | ||
953 | cmd->buf_tx = usb_alloc_coherent(ar->dev, AR5523_MAX_TXCMDSZ, | ||
954 | GFP_KERNEL, | ||
955 | &cmd->urb_tx->transfer_dma); | ||
956 | if (!cmd->buf_tx) { | ||
957 | usb_free_urb(cmd->urb_tx); | ||
958 | return -ENOMEM; | ||
959 | } | ||
960 | return 0; | ||
961 | } | ||
962 | |||
963 | /* | ||
964 | * This function is called periodically (every second) when associated to | ||
965 | * query device statistics. | ||
966 | */ | ||
967 | static void ar5523_stat_work(struct work_struct *work) | ||
968 | { | ||
969 | struct ar5523 *ar = container_of(work, struct ar5523, stat_work.work); | ||
970 | int error; | ||
971 | |||
972 | ar5523_dbg(ar, "%s\n", __func__); | ||
973 | mutex_lock(&ar->mutex); | ||
974 | |||
975 | /* | ||
976 | * Send request for statistics asynchronously once a second. This | ||
977 | * seems to be important. Throughput is a lot better if this is done. | ||
978 | */ | ||
979 | error = ar5523_cmd_write(ar, WDCMSG_TARGET_GET_STATS, NULL, 0, 0); | ||
980 | if (error) | ||
981 | ar5523_err(ar, "could not query stats, error %d\n", error); | ||
982 | mutex_unlock(&ar->mutex); | ||
983 | ieee80211_queue_delayed_work(ar->hw, &ar->stat_work, HZ); | ||
984 | } | ||
985 | |||
986 | /* | ||
987 | * Interface routines to the mac80211 stack. | ||
988 | */ | ||
989 | static int ar5523_start(struct ieee80211_hw *hw) | ||
990 | { | ||
991 | struct ar5523 *ar = hw->priv; | ||
992 | int error; | ||
993 | __be32 val; | ||
994 | |||
995 | ar5523_dbg(ar, "start called\n"); | ||
996 | |||
997 | mutex_lock(&ar->mutex); | ||
998 | val = cpu_to_be32(0); | ||
999 | ar5523_cmd_write(ar, WDCMSG_BIND, &val, sizeof(val), 0); | ||
1000 | |||
1001 | /* set MAC address */ | ||
1002 | ar5523_config_multi(ar, CFG_MAC_ADDR, &ar->hw->wiphy->perm_addr, | ||
1003 | ETH_ALEN); | ||
1004 | |||
1005 | /* XXX honor net80211 state */ | ||
1006 | ar5523_config(ar, CFG_RATE_CONTROL_ENABLE, 0x00000001); | ||
1007 | ar5523_config(ar, CFG_DIVERSITY_CTL, 0x00000001); | ||
1008 | ar5523_config(ar, CFG_ABOLT, 0x0000003f); | ||
1009 | ar5523_config(ar, CFG_WME_ENABLED, 0x00000000); | ||
1010 | |||
1011 | ar5523_config(ar, CFG_SERVICE_TYPE, 1); | ||
1012 | ar5523_config(ar, CFG_TP_SCALE, 0x00000000); | ||
1013 | ar5523_config(ar, CFG_TPC_HALF_DBM5, 0x0000003c); | ||
1014 | ar5523_config(ar, CFG_TPC_HALF_DBM2, 0x0000003c); | ||
1015 | ar5523_config(ar, CFG_OVERRD_TX_POWER, 0x00000000); | ||
1016 | ar5523_config(ar, CFG_GMODE_PROTECTION, 0x00000000); | ||
1017 | ar5523_config(ar, CFG_GMODE_PROTECT_RATE_INDEX, 0x00000003); | ||
1018 | ar5523_config(ar, CFG_PROTECTION_TYPE, 0x00000000); | ||
1019 | ar5523_config(ar, CFG_MODE_CTS, 0x00000002); | ||
1020 | |||
1021 | error = ar5523_cmd_read(ar, WDCMSG_TARGET_START, NULL, 0, | ||
1022 | &val, sizeof(val), AR5523_CMD_FLAG_MAGIC); | ||
1023 | if (error) { | ||
1024 | ar5523_dbg(ar, "could not start target, error %d\n", error); | ||
1025 | goto err; | ||
1026 | } | ||
1027 | ar5523_dbg(ar, "WDCMSG_TARGET_START returns handle: 0x%x\n", | ||
1028 | be32_to_cpu(val)); | ||
1029 | |||
1030 | ar5523_switch_chan(ar); | ||
1031 | |||
1032 | val = cpu_to_be32(TARGET_DEVICE_AWAKE); | ||
1033 | ar5523_cmd_write(ar, WDCMSG_SET_PWR_MODE, &val, sizeof(val), 0); | ||
1034 | /* XXX? check */ | ||
1035 | ar5523_cmd_write(ar, WDCMSG_RESET_KEY_CACHE, NULL, 0, 0); | ||
1036 | |||
1037 | set_bit(AR5523_HW_UP, &ar->flags); | ||
1038 | queue_work(ar->wq, &ar->rx_refill_work); | ||
1039 | |||
1040 | /* enable Rx */ | ||
1041 | ar5523_set_rxfilter(ar, 0, UATH_FILTER_OP_INIT); | ||
1042 | ar5523_set_rxfilter(ar, | ||
1043 | UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST | | ||
1044 | UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON, | ||
1045 | UATH_FILTER_OP_SET); | ||
1046 | |||
1047 | ar5523_set_ledsteady(ar, UATH_LED_ACTIVITY, UATH_LED_ON); | ||
1048 | ar5523_dbg(ar, "start OK\n"); | ||
1049 | |||
1050 | err: | ||
1051 | mutex_unlock(&ar->mutex); | ||
1052 | return error; | ||
1053 | } | ||
1054 | |||
1055 | static void ar5523_stop(struct ieee80211_hw *hw) | ||
1056 | { | ||
1057 | struct ar5523 *ar = hw->priv; | ||
1058 | |||
1059 | ar5523_dbg(ar, "stop called\n"); | ||
1060 | |||
1061 | cancel_delayed_work_sync(&ar->stat_work); | ||
1062 | mutex_lock(&ar->mutex); | ||
1063 | clear_bit(AR5523_HW_UP, &ar->flags); | ||
1064 | |||
1065 | ar5523_set_ledsteady(ar, UATH_LED_LINK, UATH_LED_OFF); | ||
1066 | ar5523_set_ledsteady(ar, UATH_LED_ACTIVITY, UATH_LED_OFF); | ||
1067 | |||
1068 | ar5523_cmd_write(ar, WDCMSG_TARGET_STOP, NULL, 0, 0); | ||
1069 | |||
1070 | del_timer_sync(&ar->tx_wd_timer); | ||
1071 | cancel_work_sync(&ar->tx_wd_work); | ||
1072 | cancel_work_sync(&ar->rx_refill_work); | ||
1073 | ar5523_cancel_rx_bufs(ar); | ||
1074 | mutex_unlock(&ar->mutex); | ||
1075 | } | ||
1076 | |||
1077 | static int ar5523_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | ||
1078 | { | ||
1079 | struct ar5523 *ar = hw->priv; | ||
1080 | int ret; | ||
1081 | |||
1082 | ar5523_dbg(ar, "set_rts_threshold called\n"); | ||
1083 | mutex_lock(&ar->mutex); | ||
1084 | |||
1085 | ret = ar5523_config(ar, CFG_USER_RTS_THRESHOLD, value); | ||
1086 | |||
1087 | mutex_unlock(&ar->mutex); | ||
1088 | return ret; | ||
1089 | } | ||
1090 | |||
1091 | static void ar5523_flush(struct ieee80211_hw *hw, bool drop) | ||
1092 | { | ||
1093 | struct ar5523 *ar = hw->priv; | ||
1094 | |||
1095 | ar5523_dbg(ar, "flush called\n"); | ||
1096 | ar5523_flush_tx(ar); | ||
1097 | } | ||
1098 | |||
1099 | static int ar5523_add_interface(struct ieee80211_hw *hw, | ||
1100 | struct ieee80211_vif *vif) | ||
1101 | { | ||
1102 | struct ar5523 *ar = hw->priv; | ||
1103 | |||
1104 | ar5523_dbg(ar, "add interface called\n"); | ||
1105 | |||
1106 | if (ar->vif) { | ||
1107 | ar5523_dbg(ar, "invalid add_interface\n"); | ||
1108 | return -EOPNOTSUPP; | ||
1109 | } | ||
1110 | |||
1111 | switch (vif->type) { | ||
1112 | case NL80211_IFTYPE_STATION: | ||
1113 | ar->vif = vif; | ||
1114 | break; | ||
1115 | default: | ||
1116 | return -EOPNOTSUPP; | ||
1117 | } | ||
1118 | return 0; | ||
1119 | } | ||
1120 | |||
1121 | static void ar5523_remove_interface(struct ieee80211_hw *hw, | ||
1122 | struct ieee80211_vif *vif) | ||
1123 | { | ||
1124 | struct ar5523 *ar = hw->priv; | ||
1125 | |||
1126 | ar5523_dbg(ar, "remove interface called\n"); | ||
1127 | ar->vif = NULL; | ||
1128 | } | ||
1129 | |||
1130 | static int ar5523_hwconfig(struct ieee80211_hw *hw, u32 changed) | ||
1131 | { | ||
1132 | struct ar5523 *ar = hw->priv; | ||
1133 | |||
1134 | ar5523_dbg(ar, "config called\n"); | ||
1135 | mutex_lock(&ar->mutex); | ||
1136 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | ||
1137 | ar5523_dbg(ar, "Do channel switch\n"); | ||
1138 | ar5523_flush_tx(ar); | ||
1139 | ar5523_switch_chan(ar); | ||
1140 | } | ||
1141 | mutex_unlock(&ar->mutex); | ||
1142 | return 0; | ||
1143 | } | ||
1144 | |||
1145 | static int ar5523_get_wlan_mode(struct ar5523 *ar, | ||
1146 | struct ieee80211_bss_conf *bss_conf) | ||
1147 | { | ||
1148 | struct ieee80211_supported_band *band; | ||
1149 | int bit; | ||
1150 | struct ieee80211_sta *sta; | ||
1151 | u32 sta_rate_set; | ||
1152 | |||
1153 | band = ar->hw->wiphy->bands[ar->hw->conf.channel->band]; | ||
1154 | sta = ieee80211_find_sta(ar->vif, bss_conf->bssid); | ||
1155 | if (!sta) { | ||
1156 | ar5523_info(ar, "STA not found!\n"); | ||
1157 | return WLAN_MODE_11b; | ||
1158 | } | ||
1159 | sta_rate_set = sta->supp_rates[ar->hw->conf.channel->band]; | ||
1160 | |||
1161 | for (bit = 0; bit < band->n_bitrates; bit++) { | ||
1162 | if (sta_rate_set & 1) { | ||
1163 | int rate = band->bitrates[bit].bitrate; | ||
1164 | switch (rate) { | ||
1165 | case 60: | ||
1166 | case 90: | ||
1167 | case 120: | ||
1168 | case 180: | ||
1169 | case 240: | ||
1170 | case 360: | ||
1171 | case 480: | ||
1172 | case 540: | ||
1173 | return WLAN_MODE_11g; | ||
1174 | } | ||
1175 | } | ||
1176 | sta_rate_set >>= 1; | ||
1177 | } | ||
1178 | return WLAN_MODE_11b; | ||
1179 | } | ||
1180 | |||
1181 | static void ar5523_create_rateset(struct ar5523 *ar, | ||
1182 | struct ieee80211_bss_conf *bss_conf, | ||
1183 | struct ar5523_cmd_rateset *rs, | ||
1184 | bool basic) | ||
1185 | { | ||
1186 | struct ieee80211_supported_band *band; | ||
1187 | struct ieee80211_sta *sta; | ||
1188 | int bit, i = 0; | ||
1189 | u32 sta_rate_set, basic_rate_set; | ||
1190 | |||
1191 | sta = ieee80211_find_sta(ar->vif, bss_conf->bssid); | ||
1192 | basic_rate_set = bss_conf->basic_rates; | ||
1193 | if (!sta) { | ||
1194 | ar5523_info(ar, "STA not found. Cannot set rates\n"); | ||
1195 | sta_rate_set = bss_conf->basic_rates; | ||
1196 | } | ||
1197 | sta_rate_set = sta->supp_rates[ar->hw->conf.channel->band]; | ||
1198 | |||
1199 | ar5523_dbg(ar, "sta rate_set = %08x\n", sta_rate_set); | ||
1200 | |||
1201 | band = ar->hw->wiphy->bands[ar->hw->conf.channel->band]; | ||
1202 | for (bit = 0; bit < band->n_bitrates; bit++) { | ||
1203 | BUG_ON(i >= AR5523_MAX_NRATES); | ||
1204 | ar5523_dbg(ar, "Considering rate %d : %d\n", | ||
1205 | band->bitrates[bit].hw_value, sta_rate_set & 1); | ||
1206 | if (sta_rate_set & 1) { | ||
1207 | rs->set[i] = band->bitrates[bit].hw_value; | ||
1208 | if (basic_rate_set & 1 && basic) | ||
1209 | rs->set[i] |= 0x80; | ||
1210 | i++; | ||
1211 | } | ||
1212 | sta_rate_set >>= 1; | ||
1213 | basic_rate_set >>= 1; | ||
1214 | } | ||
1215 | |||
1216 | rs->length = i; | ||
1217 | } | ||
1218 | |||
1219 | static int ar5523_set_basic_rates(struct ar5523 *ar, | ||
1220 | struct ieee80211_bss_conf *bss) | ||
1221 | { | ||
1222 | struct ar5523_cmd_rates rates; | ||
1223 | |||
1224 | memset(&rates, 0, sizeof(rates)); | ||
1225 | rates.connid = cpu_to_be32(2); /* XXX */ | ||
1226 | rates.size = cpu_to_be32(sizeof(struct ar5523_cmd_rateset)); | ||
1227 | ar5523_create_rateset(ar, bss, &rates.rateset, true); | ||
1228 | |||
1229 | return ar5523_cmd_write(ar, WDCMSG_SET_BASIC_RATE, &rates, | ||
1230 | sizeof(rates), 0); | ||
1231 | } | ||
1232 | |||
1233 | static int ar5523_create_connection(struct ar5523 *ar, | ||
1234 | struct ieee80211_vif *vif, | ||
1235 | struct ieee80211_bss_conf *bss) | ||
1236 | { | ||
1237 | struct ar5523_cmd_create_connection create; | ||
1238 | int wlan_mode; | ||
1239 | |||
1240 | memset(&create, 0, sizeof(create)); | ||
1241 | create.connid = cpu_to_be32(2); | ||
1242 | create.bssid = cpu_to_be32(0); | ||
1243 | /* XXX packed or not? */ | ||
1244 | create.size = cpu_to_be32(sizeof(struct ar5523_cmd_rateset)); | ||
1245 | |||
1246 | ar5523_create_rateset(ar, bss, &create.connattr.rateset, false); | ||
1247 | |||
1248 | wlan_mode = ar5523_get_wlan_mode(ar, bss); | ||
1249 | create.connattr.wlanmode = cpu_to_be32(wlan_mode); | ||
1250 | |||
1251 | return ar5523_cmd_write(ar, WDCMSG_CREATE_CONNECTION, &create, | ||
1252 | sizeof(create), 0); | ||
1253 | } | ||
1254 | |||
1255 | static int ar5523_write_associd(struct ar5523 *ar, | ||
1256 | struct ieee80211_bss_conf *bss) | ||
1257 | { | ||
1258 | struct ar5523_cmd_set_associd associd; | ||
1259 | |||
1260 | memset(&associd, 0, sizeof(associd)); | ||
1261 | associd.defaultrateix = cpu_to_be32(0); /* XXX */ | ||
1262 | associd.associd = cpu_to_be32(bss->aid); | ||
1263 | associd.timoffset = cpu_to_be32(0x3b); /* XXX */ | ||
1264 | memcpy(associd.bssid, bss->bssid, ETH_ALEN); | ||
1265 | return ar5523_cmd_write(ar, WDCMSG_WRITE_ASSOCID, &associd, | ||
1266 | sizeof(associd), 0); | ||
1267 | } | ||
1268 | |||
1269 | static void ar5523_bss_info_changed(struct ieee80211_hw *hw, | ||
1270 | struct ieee80211_vif *vif, | ||
1271 | struct ieee80211_bss_conf *bss, | ||
1272 | u32 changed) | ||
1273 | { | ||
1274 | struct ar5523 *ar = hw->priv; | ||
1275 | int error; | ||
1276 | |||
1277 | ar5523_dbg(ar, "bss_info_changed called\n"); | ||
1278 | mutex_lock(&ar->mutex); | ||
1279 | |||
1280 | if (!(changed & BSS_CHANGED_ASSOC)) | ||
1281 | goto out_unlock; | ||
1282 | |||
1283 | if (bss->assoc) { | ||
1284 | error = ar5523_create_connection(ar, vif, bss); | ||
1285 | if (error) { | ||
1286 | ar5523_err(ar, "could not create connection\n"); | ||
1287 | goto out_unlock; | ||
1288 | } | ||
1289 | |||
1290 | error = ar5523_set_basic_rates(ar, bss); | ||
1291 | if (error) { | ||
1292 | ar5523_err(ar, "could not set negotiated rate set\n"); | ||
1293 | goto out_unlock; | ||
1294 | } | ||
1295 | |||
1296 | error = ar5523_write_associd(ar, bss); | ||
1297 | if (error) { | ||
1298 | ar5523_err(ar, "could not set association\n"); | ||
1299 | goto out_unlock; | ||
1300 | } | ||
1301 | |||
1302 | /* turn link LED on */ | ||
1303 | ar5523_set_ledsteady(ar, UATH_LED_LINK, UATH_LED_ON); | ||
1304 | set_bit(AR5523_CONNECTED, &ar->flags); | ||
1305 | ieee80211_queue_delayed_work(hw, &ar->stat_work, HZ); | ||
1306 | |||
1307 | } else { | ||
1308 | cancel_delayed_work(&ar->stat_work); | ||
1309 | clear_bit(AR5523_CONNECTED, &ar->flags); | ||
1310 | ar5523_set_ledsteady(ar, UATH_LED_LINK, UATH_LED_OFF); | ||
1311 | } | ||
1312 | |||
1313 | out_unlock: | ||
1314 | mutex_unlock(&ar->mutex); | ||
1315 | |||
1316 | } | ||
1317 | |||
1318 | #define AR5523_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \ | ||
1319 | FIF_ALLMULTI | \ | ||
1320 | FIF_FCSFAIL | \ | ||
1321 | FIF_OTHER_BSS) | ||
1322 | |||
1323 | static void ar5523_configure_filter(struct ieee80211_hw *hw, | ||
1324 | unsigned int changed_flags, | ||
1325 | unsigned int *total_flags, | ||
1326 | u64 multicast) | ||
1327 | { | ||
1328 | struct ar5523 *ar = hw->priv; | ||
1329 | u32 filter = 0; | ||
1330 | |||
1331 | ar5523_dbg(ar, "configure_filter called\n"); | ||
1332 | mutex_lock(&ar->mutex); | ||
1333 | ar5523_flush_tx(ar); | ||
1334 | |||
1335 | *total_flags &= AR5523_SUPPORTED_FILTERS; | ||
1336 | |||
1337 | /* The filters seems strange. UATH_FILTER_RX_BCAST and | ||
1338 | * UATH_FILTER_RX_MCAST does not result in those frames being RXed. | ||
1339 | * The only way I have found to get [mb]cast frames seems to be | ||
1340 | * to set UATH_FILTER_RX_PROM. */ | ||
1341 | filter |= UATH_FILTER_RX_UCAST | UATH_FILTER_RX_MCAST | | ||
1342 | UATH_FILTER_RX_BCAST | UATH_FILTER_RX_BEACON | | ||
1343 | UATH_FILTER_RX_PROM; | ||
1344 | |||
1345 | ar5523_set_rxfilter(ar, 0, UATH_FILTER_OP_INIT); | ||
1346 | ar5523_set_rxfilter(ar, filter, UATH_FILTER_OP_SET); | ||
1347 | |||
1348 | mutex_unlock(&ar->mutex); | ||
1349 | } | ||
1350 | |||
1351 | static const struct ieee80211_ops ar5523_ops = { | ||
1352 | .start = ar5523_start, | ||
1353 | .stop = ar5523_stop, | ||
1354 | .tx = ar5523_tx, | ||
1355 | .set_rts_threshold = ar5523_set_rts_threshold, | ||
1356 | .add_interface = ar5523_add_interface, | ||
1357 | .remove_interface = ar5523_remove_interface, | ||
1358 | .config = ar5523_hwconfig, | ||
1359 | .bss_info_changed = ar5523_bss_info_changed, | ||
1360 | .configure_filter = ar5523_configure_filter, | ||
1361 | .flush = ar5523_flush, | ||
1362 | }; | ||
1363 | |||
1364 | static int ar5523_host_available(struct ar5523 *ar) | ||
1365 | { | ||
1366 | struct ar5523_cmd_host_available setup; | ||
1367 | |||
1368 | /* inform target the host is available */ | ||
1369 | setup.sw_ver_major = cpu_to_be32(ATH_SW_VER_MAJOR); | ||
1370 | setup.sw_ver_minor = cpu_to_be32(ATH_SW_VER_MINOR); | ||
1371 | setup.sw_ver_patch = cpu_to_be32(ATH_SW_VER_PATCH); | ||
1372 | setup.sw_ver_build = cpu_to_be32(ATH_SW_VER_BUILD); | ||
1373 | return ar5523_cmd_read(ar, WDCMSG_HOST_AVAILABLE, | ||
1374 | &setup, sizeof(setup), NULL, 0, 0); | ||
1375 | } | ||
1376 | |||
1377 | static int ar5523_get_devstatus(struct ar5523 *ar) | ||
1378 | { | ||
1379 | u8 macaddr[ETH_ALEN]; | ||
1380 | int error; | ||
1381 | |||
1382 | /* retrieve MAC address */ | ||
1383 | error = ar5523_get_status(ar, ST_MAC_ADDR, macaddr, ETH_ALEN); | ||
1384 | if (error) { | ||
1385 | ar5523_err(ar, "could not read MAC address\n"); | ||
1386 | return error; | ||
1387 | } | ||
1388 | |||
1389 | SET_IEEE80211_PERM_ADDR(ar->hw, macaddr); | ||
1390 | |||
1391 | error = ar5523_get_status(ar, ST_SERIAL_NUMBER, | ||
1392 | &ar->serial[0], sizeof(ar->serial)); | ||
1393 | if (error) { | ||
1394 | ar5523_err(ar, "could not read device serial number\n"); | ||
1395 | return error; | ||
1396 | } | ||
1397 | return 0; | ||
1398 | } | ||
1399 | |||
1400 | #define AR5523_SANE_RXBUFSZ 2000 | ||
1401 | |||
1402 | static int ar5523_get_max_rxsz(struct ar5523 *ar) | ||
1403 | { | ||
1404 | int error; | ||
1405 | __be32 rxsize; | ||
1406 | |||
1407 | /* Get max rx size */ | ||
1408 | error = ar5523_get_status(ar, ST_WDC_TRANSPORT_CHUNK_SIZE, &rxsize, | ||
1409 | sizeof(rxsize)); | ||
1410 | if (error != 0) { | ||
1411 | ar5523_err(ar, "could not read max RX size\n"); | ||
1412 | return error; | ||
1413 | } | ||
1414 | |||
1415 | ar->rxbufsz = be32_to_cpu(rxsize); | ||
1416 | |||
1417 | if (!ar->rxbufsz || ar->rxbufsz > AR5523_SANE_RXBUFSZ) { | ||
1418 | ar5523_err(ar, "Bad rxbufsz from device. Using %d instead\n", | ||
1419 | AR5523_SANE_RXBUFSZ); | ||
1420 | ar->rxbufsz = AR5523_SANE_RXBUFSZ; | ||
1421 | } | ||
1422 | |||
1423 | ar5523_dbg(ar, "Max RX buf size: %d\n", ar->rxbufsz); | ||
1424 | return 0; | ||
1425 | } | ||
1426 | |||
1427 | /* | ||
1428 | * This is copied from rtl818x, but we should probably move this | ||
1429 | * to common code as in OpenBSD. | ||
1430 | */ | ||
1431 | static const struct ieee80211_rate ar5523_rates[] = { | ||
1432 | { .bitrate = 10, .hw_value = 2, }, | ||
1433 | { .bitrate = 20, .hw_value = 4 }, | ||
1434 | { .bitrate = 55, .hw_value = 11, }, | ||
1435 | { .bitrate = 110, .hw_value = 22, }, | ||
1436 | { .bitrate = 60, .hw_value = 12, }, | ||
1437 | { .bitrate = 90, .hw_value = 18, }, | ||
1438 | { .bitrate = 120, .hw_value = 24, }, | ||
1439 | { .bitrate = 180, .hw_value = 36, }, | ||
1440 | { .bitrate = 240, .hw_value = 48, }, | ||
1441 | { .bitrate = 360, .hw_value = 72, }, | ||
1442 | { .bitrate = 480, .hw_value = 96, }, | ||
1443 | { .bitrate = 540, .hw_value = 108, }, | ||
1444 | }; | ||
1445 | |||
1446 | static const struct ieee80211_channel ar5523_channels[] = { | ||
1447 | { .center_freq = 2412 }, | ||
1448 | { .center_freq = 2417 }, | ||
1449 | { .center_freq = 2422 }, | ||
1450 | { .center_freq = 2427 }, | ||
1451 | { .center_freq = 2432 }, | ||
1452 | { .center_freq = 2437 }, | ||
1453 | { .center_freq = 2442 }, | ||
1454 | { .center_freq = 2447 }, | ||
1455 | { .center_freq = 2452 }, | ||
1456 | { .center_freq = 2457 }, | ||
1457 | { .center_freq = 2462 }, | ||
1458 | { .center_freq = 2467 }, | ||
1459 | { .center_freq = 2472 }, | ||
1460 | { .center_freq = 2484 }, | ||
1461 | }; | ||
1462 | |||
1463 | static int ar5523_init_modes(struct ar5523 *ar) | ||
1464 | { | ||
1465 | BUILD_BUG_ON(sizeof(ar->channels) != sizeof(ar5523_channels)); | ||
1466 | BUILD_BUG_ON(sizeof(ar->rates) != sizeof(ar5523_rates)); | ||
1467 | |||
1468 | memcpy(ar->channels, ar5523_channels, sizeof(ar5523_channels)); | ||
1469 | memcpy(ar->rates, ar5523_rates, sizeof(ar5523_rates)); | ||
1470 | |||
1471 | ar->band.band = IEEE80211_BAND_2GHZ; | ||
1472 | ar->band.channels = ar->channels; | ||
1473 | ar->band.n_channels = ARRAY_SIZE(ar5523_channels); | ||
1474 | ar->band.bitrates = ar->rates; | ||
1475 | ar->band.n_bitrates = ARRAY_SIZE(ar5523_rates); | ||
1476 | ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar->band; | ||
1477 | return 0; | ||
1478 | } | ||
1479 | |||
1480 | /* | ||
1481 | * Load the MIPS R4000 microcode into the device. Once the image is loaded, | ||
1482 | * the device will detach itself from the bus and reattach later with a new | ||
1483 | * product Id (a la ezusb). | ||
1484 | */ | ||
1485 | static int ar5523_load_firmware(struct usb_device *dev) | ||
1486 | { | ||
1487 | struct ar5523_fwblock *txblock, *rxblock; | ||
1488 | const struct firmware *fw; | ||
1489 | void *fwbuf; | ||
1490 | int len, offset; | ||
1491 | int foolen; /* XXX(hch): handle short transfers */ | ||
1492 | int error = -ENXIO; | ||
1493 | |||
1494 | if (request_firmware(&fw, AR5523_FIRMWARE_FILE, &dev->dev)) { | ||
1495 | dev_err(&dev->dev, "no firmware found: %s\n", | ||
1496 | AR5523_FIRMWARE_FILE); | ||
1497 | return -ENOENT; | ||
1498 | } | ||
1499 | |||
1500 | txblock = kmalloc(sizeof(*txblock), GFP_KERNEL); | ||
1501 | if (!txblock) | ||
1502 | goto out; | ||
1503 | |||
1504 | rxblock = kmalloc(sizeof(*rxblock), GFP_KERNEL); | ||
1505 | if (!rxblock) | ||
1506 | goto out_free_txblock; | ||
1507 | |||
1508 | fwbuf = kmalloc(AR5523_MAX_FWBLOCK_SIZE, GFP_KERNEL); | ||
1509 | if (!fwbuf) | ||
1510 | goto out_free_rxblock; | ||
1511 | |||
1512 | memset(txblock, 0, sizeof(struct ar5523_fwblock)); | ||
1513 | txblock->flags = cpu_to_be32(AR5523_WRITE_BLOCK); | ||
1514 | txblock->total = cpu_to_be32(fw->size); | ||
1515 | |||
1516 | offset = 0; | ||
1517 | len = fw->size; | ||
1518 | while (len > 0) { | ||
1519 | int mlen = min(len, AR5523_MAX_FWBLOCK_SIZE); | ||
1520 | |||
1521 | txblock->remain = cpu_to_be32(len - mlen); | ||
1522 | txblock->len = cpu_to_be32(mlen); | ||
1523 | |||
1524 | /* send firmware block meta-data */ | ||
1525 | error = usb_bulk_msg(dev, ar5523_cmd_tx_pipe(dev), | ||
1526 | txblock, sizeof(*txblock), &foolen, | ||
1527 | AR5523_CMD_TIMEOUT); | ||
1528 | if (error) { | ||
1529 | dev_err(&dev->dev, | ||
1530 | "could not send firmware block info\n"); | ||
1531 | goto out_free_fwbuf; | ||
1532 | } | ||
1533 | |||
1534 | /* send firmware block data */ | ||
1535 | memcpy(fwbuf, fw->data + offset, mlen); | ||
1536 | error = usb_bulk_msg(dev, ar5523_data_tx_pipe(dev), | ||
1537 | fwbuf, mlen, &foolen, | ||
1538 | AR5523_DATA_TIMEOUT); | ||
1539 | if (error) { | ||
1540 | dev_err(&dev->dev, | ||
1541 | "could not send firmware block data\n"); | ||
1542 | goto out_free_fwbuf; | ||
1543 | } | ||
1544 | |||
1545 | /* wait for ack from firmware */ | ||
1546 | error = usb_bulk_msg(dev, ar5523_cmd_rx_pipe(dev), | ||
1547 | rxblock, sizeof(*rxblock), &foolen, | ||
1548 | AR5523_CMD_TIMEOUT); | ||
1549 | if (error) { | ||
1550 | dev_err(&dev->dev, | ||
1551 | "could not read firmware answer\n"); | ||
1552 | goto out_free_fwbuf; | ||
1553 | } | ||
1554 | |||
1555 | len -= mlen; | ||
1556 | offset += mlen; | ||
1557 | } | ||
1558 | |||
1559 | /* | ||
1560 | * Set the error to -ENXIO to make sure we continue probing for | ||
1561 | * a driver. | ||
1562 | */ | ||
1563 | error = -ENXIO; | ||
1564 | |||
1565 | out_free_fwbuf: | ||
1566 | kfree(fwbuf); | ||
1567 | out_free_rxblock: | ||
1568 | kfree(rxblock); | ||
1569 | out_free_txblock: | ||
1570 | kfree(txblock); | ||
1571 | out: | ||
1572 | release_firmware(fw); | ||
1573 | return error; | ||
1574 | } | ||
1575 | |||
1576 | static int ar5523_probe(struct usb_interface *intf, | ||
1577 | const struct usb_device_id *id) | ||
1578 | { | ||
1579 | struct usb_device *dev = interface_to_usbdev(intf); | ||
1580 | struct ieee80211_hw *hw; | ||
1581 | struct ar5523 *ar; | ||
1582 | int error = -ENOMEM; | ||
1583 | |||
1584 | /* | ||
1585 | * Load firmware if the device requires it. This will return | ||
1586 | * -ENXIO on success and we'll get called back afer the usb | ||
1587 | * id changes to indicate that the firmware is present. | ||
1588 | */ | ||
1589 | if (id->driver_info & AR5523_FLAG_PRE_FIRMWARE) | ||
1590 | return ar5523_load_firmware(dev); | ||
1591 | |||
1592 | |||
1593 | hw = ieee80211_alloc_hw(sizeof(*ar), &ar5523_ops); | ||
1594 | if (!hw) | ||
1595 | goto out; | ||
1596 | SET_IEEE80211_DEV(hw, &intf->dev); | ||
1597 | |||
1598 | ar = hw->priv; | ||
1599 | ar->hw = hw; | ||
1600 | ar->dev = dev; | ||
1601 | mutex_init(&ar->mutex); | ||
1602 | |||
1603 | INIT_DELAYED_WORK(&ar->stat_work, ar5523_stat_work); | ||
1604 | init_timer(&ar->tx_wd_timer); | ||
1605 | setup_timer(&ar->tx_wd_timer, ar5523_tx_wd_timer, (unsigned long) ar); | ||
1606 | INIT_WORK(&ar->tx_wd_work, ar5523_tx_wd_work); | ||
1607 | INIT_WORK(&ar->tx_work, ar5523_tx_work); | ||
1608 | INIT_LIST_HEAD(&ar->tx_queue_pending); | ||
1609 | INIT_LIST_HEAD(&ar->tx_queue_submitted); | ||
1610 | spin_lock_init(&ar->tx_data_list_lock); | ||
1611 | atomic_set(&ar->tx_nr_total, 0); | ||
1612 | atomic_set(&ar->tx_nr_pending, 0); | ||
1613 | init_waitqueue_head(&ar->tx_flush_waitq); | ||
1614 | |||
1615 | atomic_set(&ar->rx_data_free_cnt, 0); | ||
1616 | INIT_WORK(&ar->rx_refill_work, ar5523_rx_refill_work); | ||
1617 | INIT_LIST_HEAD(&ar->rx_data_free); | ||
1618 | INIT_LIST_HEAD(&ar->rx_data_used); | ||
1619 | spin_lock_init(&ar->rx_data_list_lock); | ||
1620 | |||
1621 | ar->wq = create_singlethread_workqueue("ar5523"); | ||
1622 | if (!ar->wq) { | ||
1623 | ar5523_err(ar, "Could not create wq\n"); | ||
1624 | goto out_free_ar; | ||
1625 | } | ||
1626 | |||
1627 | error = ar5523_alloc_rx_bufs(ar); | ||
1628 | if (error) { | ||
1629 | ar5523_err(ar, "Could not allocate rx buffers\n"); | ||
1630 | goto out_free_wq; | ||
1631 | } | ||
1632 | |||
1633 | error = ar5523_alloc_rx_cmd(ar); | ||
1634 | if (error) { | ||
1635 | ar5523_err(ar, "Could not allocate rx command buffers\n"); | ||
1636 | goto out_free_rx_bufs; | ||
1637 | } | ||
1638 | |||
1639 | error = ar5523_alloc_tx_cmd(ar); | ||
1640 | if (error) { | ||
1641 | ar5523_err(ar, "Could not allocate tx command buffers\n"); | ||
1642 | goto out_free_rx_cmd; | ||
1643 | } | ||
1644 | |||
1645 | error = ar5523_submit_rx_cmd(ar); | ||
1646 | if (error) { | ||
1647 | ar5523_err(ar, "Failed to submit rx cmd\n"); | ||
1648 | goto out_free_tx_cmd; | ||
1649 | } | ||
1650 | |||
1651 | /* | ||
1652 | * We're now ready to send/receive firmware commands. | ||
1653 | */ | ||
1654 | error = ar5523_host_available(ar); | ||
1655 | if (error) { | ||
1656 | ar5523_err(ar, "could not initialize adapter\n"); | ||
1657 | goto out_cancel_rx_cmd; | ||
1658 | } | ||
1659 | |||
1660 | error = ar5523_get_max_rxsz(ar); | ||
1661 | if (error) { | ||
1662 | ar5523_err(ar, "could not get caps from adapter\n"); | ||
1663 | goto out_cancel_rx_cmd; | ||
1664 | } | ||
1665 | |||
1666 | error = ar5523_get_devcap(ar); | ||
1667 | if (error) { | ||
1668 | ar5523_err(ar, "could not get caps from adapter\n"); | ||
1669 | goto out_cancel_rx_cmd; | ||
1670 | } | ||
1671 | |||
1672 | error = ar5523_get_devstatus(ar); | ||
1673 | if (error != 0) { | ||
1674 | ar5523_err(ar, "could not get device status\n"); | ||
1675 | goto out_cancel_rx_cmd; | ||
1676 | } | ||
1677 | |||
1678 | ar5523_info(ar, "MAC/BBP AR5523, RF AR%c112\n", | ||
1679 | (id->driver_info & AR5523_FLAG_ABG) ? '5' : '2'); | ||
1680 | |||
1681 | ar->vif = NULL; | ||
1682 | hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | | ||
1683 | IEEE80211_HW_SIGNAL_DBM | | ||
1684 | IEEE80211_HW_HAS_RATE_CONTROL; | ||
1685 | hw->extra_tx_headroom = sizeof(struct ar5523_tx_desc) + | ||
1686 | sizeof(struct ar5523_chunk); | ||
1687 | hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); | ||
1688 | hw->queues = 1; | ||
1689 | |||
1690 | error = ar5523_init_modes(ar); | ||
1691 | if (error) | ||
1692 | goto out_cancel_rx_cmd; | ||
1693 | |||
1694 | usb_set_intfdata(intf, hw); | ||
1695 | |||
1696 | error = ieee80211_register_hw(hw); | ||
1697 | if (error) { | ||
1698 | ar5523_err(ar, "could not register device\n"); | ||
1699 | goto out_cancel_rx_cmd; | ||
1700 | } | ||
1701 | |||
1702 | ar5523_info(ar, "Found and initialized AR5523 device\n"); | ||
1703 | return 0; | ||
1704 | |||
1705 | out_cancel_rx_cmd: | ||
1706 | ar5523_cancel_rx_cmd(ar); | ||
1707 | out_free_tx_cmd: | ||
1708 | ar5523_free_tx_cmd(ar); | ||
1709 | out_free_rx_cmd: | ||
1710 | ar5523_free_rx_cmd(ar); | ||
1711 | out_free_rx_bufs: | ||
1712 | ar5523_free_rx_bufs(ar); | ||
1713 | out_free_wq: | ||
1714 | destroy_workqueue(ar->wq); | ||
1715 | out_free_ar: | ||
1716 | ieee80211_free_hw(hw); | ||
1717 | out: | ||
1718 | return error; | ||
1719 | } | ||
1720 | |||
1721 | static void ar5523_disconnect(struct usb_interface *intf) | ||
1722 | { | ||
1723 | struct ieee80211_hw *hw = usb_get_intfdata(intf); | ||
1724 | struct ar5523 *ar = hw->priv; | ||
1725 | |||
1726 | ar5523_dbg(ar, "detaching\n"); | ||
1727 | set_bit(AR5523_USB_DISCONNECTED, &ar->flags); | ||
1728 | |||
1729 | ieee80211_unregister_hw(hw); | ||
1730 | |||
1731 | ar5523_cancel_rx_cmd(ar); | ||
1732 | ar5523_free_tx_cmd(ar); | ||
1733 | ar5523_free_rx_cmd(ar); | ||
1734 | ar5523_free_rx_bufs(ar); | ||
1735 | |||
1736 | destroy_workqueue(ar->wq); | ||
1737 | |||
1738 | ieee80211_free_hw(hw); | ||
1739 | usb_set_intfdata(intf, NULL); | ||
1740 | } | ||
1741 | |||
1742 | #define AR5523_DEVICE_UG(vendor, device) \ | ||
1743 | { USB_DEVICE((vendor), (device)) }, \ | ||
1744 | { USB_DEVICE((vendor), (device) + 1), \ | ||
1745 | .driver_info = AR5523_FLAG_PRE_FIRMWARE } | ||
1746 | #define AR5523_DEVICE_UX(vendor, device) \ | ||
1747 | { USB_DEVICE((vendor), (device)), \ | ||
1748 | .driver_info = AR5523_FLAG_ABG }, \ | ||
1749 | { USB_DEVICE((vendor), (device) + 1), \ | ||
1750 | .driver_info = AR5523_FLAG_ABG|AR5523_FLAG_PRE_FIRMWARE } | ||
1751 | |||
1752 | static struct usb_device_id ar5523_id_table[] = { | ||
1753 | AR5523_DEVICE_UG(0x168c, 0x0001), /* Atheros / AR5523 */ | ||
1754 | AR5523_DEVICE_UG(0x0cf3, 0x0001), /* Atheros2 / AR5523_1 */ | ||
1755 | AR5523_DEVICE_UG(0x0cf3, 0x0003), /* Atheros2 / AR5523_2 */ | ||
1756 | AR5523_DEVICE_UX(0x0cf3, 0x0005), /* Atheros2 / AR5523_3 */ | ||
1757 | AR5523_DEVICE_UG(0x0d8e, 0x7801), /* Conceptronic / AR5523_1 */ | ||
1758 | AR5523_DEVICE_UX(0x0d8e, 0x7811), /* Conceptronic / AR5523_2 */ | ||
1759 | AR5523_DEVICE_UX(0x2001, 0x3a00), /* Dlink / DWLAG132 */ | ||
1760 | AR5523_DEVICE_UG(0x2001, 0x3a02), /* Dlink / DWLG132 */ | ||
1761 | AR5523_DEVICE_UX(0x2001, 0x3a04), /* Dlink / DWLAG122 */ | ||
1762 | AR5523_DEVICE_UG(0x1690, 0x0712), /* Gigaset / AR5523 */ | ||
1763 | AR5523_DEVICE_UG(0x1690, 0x0710), /* Gigaset / SMCWUSBTG */ | ||
1764 | AR5523_DEVICE_UG(0x129b, 0x160c), /* Gigaset / USB stick 108 | ||
1765 | (CyberTAN Technology) */ | ||
1766 | AR5523_DEVICE_UG(0x16ab, 0x7801), /* Globalsun / AR5523_1 */ | ||
1767 | AR5523_DEVICE_UX(0x16ab, 0x7811), /* Globalsun / AR5523_2 */ | ||
1768 | AR5523_DEVICE_UG(0x0d8e, 0x7802), /* Globalsun / AR5523_3 */ | ||
1769 | AR5523_DEVICE_UX(0x0846, 0x4300), /* Netgear / WG111U */ | ||
1770 | AR5523_DEVICE_UG(0x0846, 0x4250), /* Netgear / WG111T */ | ||
1771 | AR5523_DEVICE_UG(0x0846, 0x5f00), /* Netgear / WPN111 */ | ||
1772 | AR5523_DEVICE_UG(0x157e, 0x3006), /* Umedia / AR5523_1 */ | ||
1773 | AR5523_DEVICE_UX(0x157e, 0x3205), /* Umedia / AR5523_2 */ | ||
1774 | AR5523_DEVICE_UG(0x157e, 0x3006), /* Umedia / TEW444UBEU */ | ||
1775 | AR5523_DEVICE_UG(0x1435, 0x0826), /* Wistronneweb / AR5523_1 */ | ||
1776 | AR5523_DEVICE_UX(0x1435, 0x0828), /* Wistronneweb / AR5523_2 */ | ||
1777 | AR5523_DEVICE_UG(0x0cde, 0x0012), /* Zcom / AR5523 */ | ||
1778 | AR5523_DEVICE_UG(0x1385, 0x4250), /* Netgear3 / WG111T (2) */ | ||
1779 | AR5523_DEVICE_UG(0x1385, 0x5f00), /* Netgear / WPN111 */ | ||
1780 | AR5523_DEVICE_UG(0x1385, 0x5f02), /* Netgear / WPN111 */ | ||
1781 | { } | ||
1782 | }; | ||
1783 | MODULE_DEVICE_TABLE(usb, ar5523_id_table); | ||
1784 | |||
1785 | static struct usb_driver ar5523_driver = { | ||
1786 | .name = "ar5523", | ||
1787 | .id_table = ar5523_id_table, | ||
1788 | .probe = ar5523_probe, | ||
1789 | .disconnect = ar5523_disconnect, | ||
1790 | }; | ||
1791 | |||
1792 | static int __init ar5523_init(void) | ||
1793 | { | ||
1794 | return usb_register(&ar5523_driver); | ||
1795 | } | ||
1796 | |||
1797 | static void __exit ar5523_exit(void) | ||
1798 | { | ||
1799 | usb_deregister(&ar5523_driver); | ||
1800 | } | ||
1801 | |||
1802 | MODULE_LICENSE("Dual BSD/GPL"); | ||
1803 | MODULE_FIRMWARE(AR5523_FIRMWARE_FILE); | ||
1804 | |||
1805 | module_init(ar5523_init); | ||
1806 | module_exit(ar5523_exit); | ||
diff --git a/drivers/net/wireless/ath/ar5523/ar5523.h b/drivers/net/wireless/ath/ar5523/ar5523.h new file mode 100644 index 000000000000..6086ba3fb543 --- /dev/null +++ b/drivers/net/wireless/ath/ar5523/ar5523.h | |||
@@ -0,0 +1,152 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr> | ||
3 | * Copyright (c) 2006 Sam Leffler, Errno Consulting | ||
4 | * Copyright (c) 2007 Christoph Hellwig <hch@lst.de> | ||
5 | * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org> | ||
6 | * Copyright (c) 2012 Pontus Fuchs <pontus.fuchs@gmail.com> | ||
7 | * | ||
8 | * Permission to use, copy, modify, and/or distribute this software for any | ||
9 | * purpose with or without fee is hereby granted, provided that the above | ||
10 | * copyright notice and this permission notice appear in all copies. | ||
11 | * | ||
12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
13 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
14 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
15 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
16 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
17 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
18 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
19 | */ | ||
20 | |||
21 | #define AR5523_FLAG_PRE_FIRMWARE (1 << 0) | ||
22 | #define AR5523_FLAG_ABG (1 << 1) | ||
23 | |||
24 | #define AR5523_FIRMWARE_FILE "ar5523.bin" | ||
25 | |||
26 | #define AR5523_CMD_TX_PIPE 0x01 | ||
27 | #define AR5523_DATA_TX_PIPE 0x02 | ||
28 | #define AR5523_CMD_RX_PIPE 0x81 | ||
29 | #define AR5523_DATA_RX_PIPE 0x82 | ||
30 | |||
31 | #define ar5523_cmd_tx_pipe(dev) \ | ||
32 | usb_sndbulkpipe((dev), AR5523_CMD_TX_PIPE) | ||
33 | #define ar5523_data_tx_pipe(dev) \ | ||
34 | usb_sndbulkpipe((dev), AR5523_DATA_TX_PIPE) | ||
35 | #define ar5523_cmd_rx_pipe(dev) \ | ||
36 | usb_rcvbulkpipe((dev), AR5523_CMD_RX_PIPE) | ||
37 | #define ar5523_data_rx_pipe(dev) \ | ||
38 | usb_rcvbulkpipe((dev), AR5523_DATA_RX_PIPE) | ||
39 | |||
40 | #define AR5523_DATA_TIMEOUT 10000 | ||
41 | #define AR5523_CMD_TIMEOUT 1000 | ||
42 | |||
43 | #define AR5523_TX_DATA_COUNT 8 | ||
44 | #define AR5523_TX_DATA_RESTART_COUNT 2 | ||
45 | #define AR5523_RX_DATA_COUNT 16 | ||
46 | #define AR5523_RX_DATA_REFILL_COUNT 8 | ||
47 | |||
48 | #define AR5523_CMD_ID 1 | ||
49 | #define AR5523_DATA_ID 2 | ||
50 | |||
51 | #define AR5523_TX_WD_TIMEOUT (HZ * 2) | ||
52 | #define AR5523_FLUSH_TIMEOUT (HZ * 3) | ||
53 | |||
54 | enum AR5523_flags { | ||
55 | AR5523_HW_UP, | ||
56 | AR5523_USB_DISCONNECTED, | ||
57 | AR5523_CONNECTED | ||
58 | }; | ||
59 | |||
60 | struct ar5523_tx_cmd { | ||
61 | struct ar5523 *ar; | ||
62 | struct urb *urb_tx; | ||
63 | void *buf_tx; | ||
64 | void *odata; | ||
65 | int olen; | ||
66 | int flags; | ||
67 | int res; | ||
68 | struct completion done; | ||
69 | }; | ||
70 | |||
71 | /* This struct is placed in tx_info->driver_data. It must not be larger | ||
72 | * than IEEE80211_TX_INFO_DRIVER_DATA_SIZE. | ||
73 | */ | ||
74 | struct ar5523_tx_data { | ||
75 | struct list_head list; | ||
76 | struct ar5523 *ar; | ||
77 | struct sk_buff *skb; | ||
78 | struct urb *urb; | ||
79 | }; | ||
80 | |||
81 | struct ar5523_rx_data { | ||
82 | struct list_head list; | ||
83 | struct ar5523 *ar; | ||
84 | struct urb *urb; | ||
85 | struct sk_buff *skb; | ||
86 | }; | ||
87 | |||
88 | struct ar5523 { | ||
89 | struct usb_device *dev; | ||
90 | struct ieee80211_hw *hw; | ||
91 | |||
92 | unsigned long flags; | ||
93 | struct mutex mutex; | ||
94 | struct workqueue_struct *wq; | ||
95 | |||
96 | struct ar5523_tx_cmd tx_cmd; | ||
97 | |||
98 | struct delayed_work stat_work; | ||
99 | |||
100 | struct timer_list tx_wd_timer; | ||
101 | struct work_struct tx_wd_work; | ||
102 | struct work_struct tx_work; | ||
103 | struct list_head tx_queue_pending; | ||
104 | struct list_head tx_queue_submitted; | ||
105 | spinlock_t tx_data_list_lock; | ||
106 | wait_queue_head_t tx_flush_waitq; | ||
107 | |||
108 | /* Queued + Submitted TX frames */ | ||
109 | atomic_t tx_nr_total; | ||
110 | |||
111 | /* Submitted TX frames */ | ||
112 | atomic_t tx_nr_pending; | ||
113 | |||
114 | void *rx_cmd_buf; | ||
115 | struct urb *rx_cmd_urb; | ||
116 | |||
117 | struct ar5523_rx_data rx_data[AR5523_RX_DATA_COUNT]; | ||
118 | spinlock_t rx_data_list_lock; | ||
119 | struct list_head rx_data_free; | ||
120 | struct list_head rx_data_used; | ||
121 | atomic_t rx_data_free_cnt; | ||
122 | |||
123 | struct work_struct rx_refill_work; | ||
124 | |||
125 | int rxbufsz; | ||
126 | u8 serial[16]; | ||
127 | |||
128 | struct ieee80211_channel channels[14]; | ||
129 | struct ieee80211_rate rates[12]; | ||
130 | struct ieee80211_supported_band band; | ||
131 | struct ieee80211_vif *vif; | ||
132 | }; | ||
133 | |||
134 | /* flags for sending firmware commands */ | ||
135 | #define AR5523_CMD_FLAG_READ (1 << 1) | ||
136 | #define AR5523_CMD_FLAG_MAGIC (1 << 2) | ||
137 | |||
138 | #define ar5523_dbg(ar, format, arg...) \ | ||
139 | dev_dbg(&(ar)->dev->dev, format, ## arg) | ||
140 | |||
141 | /* On USB hot-unplug there can be a lot of URBs in flight and they'll all | ||
142 | * fail. Instead of dealing with them in every possible place just surpress | ||
143 | * any messages on USB disconnect. | ||
144 | */ | ||
145 | #define ar5523_err(ar, format, arg...) \ | ||
146 | do { \ | ||
147 | if (!test_bit(AR5523_USB_DISCONNECTED, &ar->flags)) { \ | ||
148 | dev_err(&(ar)->dev->dev, format, ## arg); \ | ||
149 | } \ | ||
150 | } while (0) | ||
151 | #define ar5523_info(ar, format, arg...) \ | ||
152 | dev_info(&(ar)->dev->dev, format, ## arg) | ||
diff --git a/drivers/net/wireless/ath/ar5523/ar5523_hw.h b/drivers/net/wireless/ath/ar5523/ar5523_hw.h new file mode 100644 index 000000000000..a0e8bf460316 --- /dev/null +++ b/drivers/net/wireless/ath/ar5523/ar5523_hw.h | |||
@@ -0,0 +1,431 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2006 Damien Bergamini <damien.bergamini@free.fr> | ||
3 | * Copyright (c) 2006 Sam Leffler, Errno Consulting | ||
4 | * Copyright (c) 2007 Christoph Hellwig <hch@lst.de> | ||
5 | * Copyright (c) 2008-2009 Weongyo Jeong <weongyo@freebsd.org> | ||
6 | * Copyright (c) 2012 Pontus Fuchs <pontus.fuchs@gmail.com> | ||
7 | * | ||
8 | * Permission to use, copy, modify, and/or distribute this software for any | ||
9 | * purpose with or without fee is hereby granted, provided that the above | ||
10 | * copyright notice and this permission notice appear in all copies. | ||
11 | * | ||
12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
13 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
14 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
15 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
16 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
17 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
18 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
19 | */ | ||
20 | |||
21 | /* all fields are big endian */ | ||
22 | struct ar5523_fwblock { | ||
23 | __be32 flags; | ||
24 | #define AR5523_WRITE_BLOCK (1 << 4) | ||
25 | |||
26 | __be32 len; | ||
27 | #define AR5523_MAX_FWBLOCK_SIZE 2048 | ||
28 | |||
29 | __be32 total; | ||
30 | __be32 remain; | ||
31 | __be32 rxtotal; | ||
32 | __be32 pad[123]; | ||
33 | } __packed; | ||
34 | |||
35 | #define AR5523_MAX_RXCMDSZ 1024 | ||
36 | #define AR5523_MAX_TXCMDSZ 1024 | ||
37 | |||
38 | struct ar5523_cmd_hdr { | ||
39 | __be32 len; | ||
40 | __be32 code; | ||
41 | /* NB: these are defined for rev 1.5 firmware; rev 1.6 is different */ | ||
42 | /* messages from Host -> Target */ | ||
43 | #define WDCMSG_HOST_AVAILABLE 0x01 | ||
44 | #define WDCMSG_BIND 0x02 | ||
45 | #define WDCMSG_TARGET_RESET 0x03 | ||
46 | #define WDCMSG_TARGET_GET_CAPABILITY 0x04 | ||
47 | #define WDCMSG_TARGET_SET_CONFIG 0x05 | ||
48 | #define WDCMSG_TARGET_GET_STATUS 0x06 | ||
49 | #define WDCMSG_TARGET_GET_STATS 0x07 | ||
50 | #define WDCMSG_TARGET_START 0x08 | ||
51 | #define WDCMSG_TARGET_STOP 0x09 | ||
52 | #define WDCMSG_TARGET_ENABLE 0x0a | ||
53 | #define WDCMSG_TARGET_DISABLE 0x0b | ||
54 | #define WDCMSG_CREATE_CONNECTION 0x0c | ||
55 | #define WDCMSG_UPDATE_CONNECT_ATTR 0x0d | ||
56 | #define WDCMSG_DELETE_CONNECT 0x0e | ||
57 | #define WDCMSG_SEND 0x0f | ||
58 | #define WDCMSG_FLUSH 0x10 | ||
59 | /* messages from Target -> Host */ | ||
60 | #define WDCMSG_STATS_UPDATE 0x11 | ||
61 | #define WDCMSG_BMISS 0x12 | ||
62 | #define WDCMSG_DEVICE_AVAIL 0x13 | ||
63 | #define WDCMSG_SEND_COMPLETE 0x14 | ||
64 | #define WDCMSG_DATA_AVAIL 0x15 | ||
65 | #define WDCMSG_SET_PWR_MODE 0x16 | ||
66 | #define WDCMSG_BMISS_ACK 0x17 | ||
67 | #define WDCMSG_SET_LED_STEADY 0x18 | ||
68 | #define WDCMSG_SET_LED_BLINK 0x19 | ||
69 | /* more messages */ | ||
70 | #define WDCMSG_SETUP_BEACON_DESC 0x1a | ||
71 | #define WDCMSG_BEACON_INIT 0x1b | ||
72 | #define WDCMSG_RESET_KEY_CACHE 0x1c | ||
73 | #define WDCMSG_RESET_KEY_CACHE_ENTRY 0x1d | ||
74 | #define WDCMSG_SET_KEY_CACHE_ENTRY 0x1e | ||
75 | #define WDCMSG_SET_DECOMP_MASK 0x1f | ||
76 | #define WDCMSG_SET_REGULATORY_DOMAIN 0x20 | ||
77 | #define WDCMSG_SET_LED_STATE 0x21 | ||
78 | #define WDCMSG_WRITE_ASSOCID 0x22 | ||
79 | #define WDCMSG_SET_STA_BEACON_TIMERS 0x23 | ||
80 | #define WDCMSG_GET_TSF 0x24 | ||
81 | #define WDCMSG_RESET_TSF 0x25 | ||
82 | #define WDCMSG_SET_ADHOC_MODE 0x26 | ||
83 | #define WDCMSG_SET_BASIC_RATE 0x27 | ||
84 | #define WDCMSG_MIB_CONTROL 0x28 | ||
85 | #define WDCMSG_GET_CHANNEL_DATA 0x29 | ||
86 | #define WDCMSG_GET_CUR_RSSI 0x2a | ||
87 | #define WDCMSG_SET_ANTENNA_SWITCH 0x2b | ||
88 | #define WDCMSG_USE_SHORT_SLOT_TIME 0x2f | ||
89 | #define WDCMSG_SET_POWER_MODE 0x30 | ||
90 | #define WDCMSG_SETUP_PSPOLL_DESC 0x31 | ||
91 | #define WDCMSG_SET_RX_MULTICAST_FILTER 0x32 | ||
92 | #define WDCMSG_RX_FILTER 0x33 | ||
93 | #define WDCMSG_PER_CALIBRATION 0x34 | ||
94 | #define WDCMSG_RESET 0x35 | ||
95 | #define WDCMSG_DISABLE 0x36 | ||
96 | #define WDCMSG_PHY_DISABLE 0x37 | ||
97 | #define WDCMSG_SET_TX_POWER_LIMIT 0x38 | ||
98 | #define WDCMSG_SET_TX_QUEUE_PARAMS 0x39 | ||
99 | #define WDCMSG_SETUP_TX_QUEUE 0x3a | ||
100 | #define WDCMSG_RELEASE_TX_QUEUE 0x3b | ||
101 | #define WDCMSG_SET_DEFAULT_KEY 0x43 | ||
102 | |||
103 | __u32 priv; /* driver private data, | ||
104 | don't care about endianess */ | ||
105 | __be32 magic; | ||
106 | __be32 reserved2[4]; | ||
107 | }; | ||
108 | |||
109 | struct ar5523_cmd_host_available { | ||
110 | __be32 sw_ver_major; | ||
111 | __be32 sw_ver_minor; | ||
112 | __be32 sw_ver_patch; | ||
113 | __be32 sw_ver_build; | ||
114 | } __packed; | ||
115 | |||
116 | #define ATH_SW_VER_MAJOR 1 | ||
117 | #define ATH_SW_VER_MINOR 5 | ||
118 | #define ATH_SW_VER_PATCH 0 | ||
119 | #define ATH_SW_VER_BUILD 9999 | ||
120 | |||
121 | struct ar5523_chunk { | ||
122 | u8 seqnum; /* sequence number for ordering */ | ||
123 | u8 flags; | ||
124 | #define UATH_CFLAGS_FINAL 0x01 /* final chunk of a msg */ | ||
125 | #define UATH_CFLAGS_RXMSG 0x02 /* chunk contains rx completion */ | ||
126 | #define UATH_CFLAGS_DEBUG 0x04 /* for debugging */ | ||
127 | __be16 length; /* chunk size in bytes */ | ||
128 | /* chunk data follows */ | ||
129 | } __packed; | ||
130 | |||
131 | /* | ||
132 | * Message format for a WDCMSG_DATA_AVAIL message from Target to Host. | ||
133 | */ | ||
134 | struct ar5523_rx_desc { | ||
135 | __be32 len; /* msg length including header */ | ||
136 | __be32 code; /* WDCMSG_DATA_AVAIL */ | ||
137 | __be32 gennum; /* generation number */ | ||
138 | __be32 status; /* start of RECEIVE_INFO */ | ||
139 | #define UATH_STATUS_OK 0 | ||
140 | #define UATH_STATUS_STOP_IN_PROGRESS 1 | ||
141 | #define UATH_STATUS_CRC_ERR 2 | ||
142 | #define UATH_STATUS_PHY_ERR 3 | ||
143 | #define UATH_STATUS_DECRYPT_CRC_ERR 4 | ||
144 | #define UATH_STATUS_DECRYPT_MIC_ERR 5 | ||
145 | #define UATH_STATUS_DECOMP_ERR 6 | ||
146 | #define UATH_STATUS_KEY_ERR 7 | ||
147 | #define UATH_STATUS_ERR 8 | ||
148 | __be32 tstamp_low; /* low-order 32-bits of rx timestamp */ | ||
149 | __be32 tstamp_high; /* high-order 32-bits of rx timestamp */ | ||
150 | __be32 framelen; /* frame length */ | ||
151 | __be32 rate; /* rx rate code */ | ||
152 | __be32 antenna; | ||
153 | __be32 rssi; | ||
154 | __be32 channel; | ||
155 | __be32 phyerror; | ||
156 | __be32 connix; /* key table ix for bss traffic */ | ||
157 | __be32 decrypterror; | ||
158 | __be32 keycachemiss; | ||
159 | __be32 pad; /* XXX? */ | ||
160 | } __packed; | ||
161 | |||
162 | struct ar5523_tx_desc { | ||
163 | __be32 msglen; | ||
164 | __be32 msgid; /* msg id (supplied by host) */ | ||
165 | __be32 type; /* opcode: WDMSG_SEND or WDCMSG_FLUSH */ | ||
166 | __be32 txqid; /* tx queue id and flags */ | ||
167 | #define UATH_TXQID_MASK 0x0f | ||
168 | #define UATH_TXQID_MINRATE 0x10 /* use min tx rate */ | ||
169 | #define UATH_TXQID_FF 0x20 /* content is fast frame */ | ||
170 | __be32 connid; /* tx connection id */ | ||
171 | #define UATH_ID_INVALID 0xffffffff /* for sending prior to connection */ | ||
172 | __be32 flags; /* non-zero if response desired */ | ||
173 | #define UATH_TX_NOTIFY (1 << 24) /* f/w will send a UATH_NOTIF_TX */ | ||
174 | __be32 buflen; /* payload length */ | ||
175 | } __packed; | ||
176 | |||
177 | |||
178 | #define AR5523_ID_BSS 2 | ||
179 | #define AR5523_ID_BROADCAST 0xffffffff | ||
180 | |||
181 | /* structure for command UATH_CMD_WRITE_MAC */ | ||
182 | struct ar5523_write_mac { | ||
183 | __be32 reg; | ||
184 | __be32 len; | ||
185 | u8 data[32]; | ||
186 | } __packed; | ||
187 | |||
188 | struct ar5523_cmd_rateset { | ||
189 | __u8 length; | ||
190 | #define AR5523_MAX_NRATES 32 | ||
191 | __u8 set[AR5523_MAX_NRATES]; | ||
192 | }; | ||
193 | |||
194 | struct ar5523_cmd_set_associd { /* AR5523_WRITE_ASSOCID */ | ||
195 | __be32 defaultrateix; | ||
196 | __be32 associd; | ||
197 | __be32 timoffset; | ||
198 | __be32 turboprime; | ||
199 | __u8 bssid[6]; | ||
200 | } __packed; | ||
201 | |||
202 | /* structure for command WDCMSG_RESET */ | ||
203 | struct ar5523_cmd_reset { | ||
204 | __be32 flags; /* channel flags */ | ||
205 | #define UATH_CHAN_TURBO 0x0100 | ||
206 | #define UATH_CHAN_CCK 0x0200 | ||
207 | #define UATH_CHAN_OFDM 0x0400 | ||
208 | #define UATH_CHAN_2GHZ 0x1000 | ||
209 | #define UATH_CHAN_5GHZ 0x2000 | ||
210 | __be32 freq; /* channel frequency */ | ||
211 | __be32 maxrdpower; | ||
212 | __be32 cfgctl; | ||
213 | __be32 twiceantennareduction; | ||
214 | __be32 channelchange; | ||
215 | __be32 keeprccontent; | ||
216 | } __packed; | ||
217 | |||
218 | /* structure for command WDCMSG_SET_BASIC_RATE */ | ||
219 | struct ar5523_cmd_rates { | ||
220 | __be32 connid; | ||
221 | __be32 keeprccontent; | ||
222 | __be32 size; | ||
223 | struct ar5523_cmd_rateset rateset; | ||
224 | } __packed; | ||
225 | |||
226 | enum { | ||
227 | WLAN_MODE_NONE = 0, | ||
228 | WLAN_MODE_11b, | ||
229 | WLAN_MODE_11a, | ||
230 | WLAN_MODE_11g, | ||
231 | WLAN_MODE_11a_TURBO, | ||
232 | WLAN_MODE_11g_TURBO, | ||
233 | WLAN_MODE_11a_TURBO_PRIME, | ||
234 | WLAN_MODE_11g_TURBO_PRIME, | ||
235 | WLAN_MODE_11a_XR, | ||
236 | WLAN_MODE_11g_XR, | ||
237 | }; | ||
238 | |||
239 | struct ar5523_cmd_connection_attr { | ||
240 | __be32 longpreambleonly; | ||
241 | struct ar5523_cmd_rateset rateset; | ||
242 | __be32 wlanmode; | ||
243 | } __packed; | ||
244 | |||
245 | /* structure for command AR5523_CREATE_CONNECTION */ | ||
246 | struct ar5523_cmd_create_connection { | ||
247 | __be32 connid; | ||
248 | __be32 bssid; | ||
249 | __be32 size; | ||
250 | struct ar5523_cmd_connection_attr connattr; | ||
251 | } __packed; | ||
252 | |||
253 | struct ar5523_cmd_ledsteady { /* WDCMSG_SET_LED_STEADY */ | ||
254 | __be32 lednum; | ||
255 | #define UATH_LED_LINK 0 | ||
256 | #define UATH_LED_ACTIVITY 1 | ||
257 | __be32 ledmode; | ||
258 | #define UATH_LED_OFF 0 | ||
259 | #define UATH_LED_ON 1 | ||
260 | } __packed; | ||
261 | |||
262 | struct ar5523_cmd_ledblink { /* WDCMSG_SET_LED_BLINK */ | ||
263 | __be32 lednum; | ||
264 | __be32 ledmode; | ||
265 | __be32 blinkrate; | ||
266 | __be32 slowmode; | ||
267 | } __packed; | ||
268 | |||
269 | struct ar5523_cmd_ledstate { /* WDCMSG_SET_LED_STATE */ | ||
270 | __be32 connected; | ||
271 | } __packed; | ||
272 | |||
273 | struct ar5523_cmd_txq_attr { | ||
274 | __be32 priority; | ||
275 | __be32 aifs; | ||
276 | __be32 logcwmin; | ||
277 | __be32 logcwmax; | ||
278 | __be32 bursttime; | ||
279 | __be32 mode; | ||
280 | __be32 qflags; | ||
281 | } __packed; | ||
282 | |||
283 | struct ar5523_cmd_txq_setup { /* WDCMSG_SETUP_TX_QUEUE */ | ||
284 | __be32 qid; | ||
285 | __be32 len; | ||
286 | struct ar5523_cmd_txq_attr attr; | ||
287 | } __packed; | ||
288 | |||
289 | struct ar5523_cmd_rx_filter { /* WDCMSG_RX_FILTER */ | ||
290 | __be32 bits; | ||
291 | #define UATH_FILTER_RX_UCAST 0x00000001 | ||
292 | #define UATH_FILTER_RX_MCAST 0x00000002 | ||
293 | #define UATH_FILTER_RX_BCAST 0x00000004 | ||
294 | #define UATH_FILTER_RX_CONTROL 0x00000008 | ||
295 | #define UATH_FILTER_RX_BEACON 0x00000010 /* beacon frames */ | ||
296 | #define UATH_FILTER_RX_PROM 0x00000020 /* promiscuous mode */ | ||
297 | #define UATH_FILTER_RX_PHY_ERR 0x00000040 /* phy errors */ | ||
298 | #define UATH_FILTER_RX_PHY_RADAR 0x00000080 /* radar phy errors */ | ||
299 | #define UATH_FILTER_RX_XR_POOL 0x00000400 /* XR group polls */ | ||
300 | #define UATH_FILTER_RX_PROBE_REQ 0x00000800 | ||
301 | __be32 op; | ||
302 | #define UATH_FILTER_OP_INIT 0x0 | ||
303 | #define UATH_FILTER_OP_SET 0x1 | ||
304 | #define UATH_FILTER_OP_CLEAR 0x2 | ||
305 | #define UATH_FILTER_OP_TEMP 0x3 | ||
306 | #define UATH_FILTER_OP_RESTORE 0x4 | ||
307 | } __packed; | ||
308 | |||
309 | enum { | ||
310 | CFG_NONE, /* Sentinal to indicate "no config" */ | ||
311 | CFG_REG_DOMAIN, /* Regulatory Domain */ | ||
312 | CFG_RATE_CONTROL_ENABLE, | ||
313 | CFG_DEF_XMIT_DATA_RATE, /* NB: if rate control is not enabled */ | ||
314 | CFG_HW_TX_RETRIES, | ||
315 | CFG_SW_TX_RETRIES, | ||
316 | CFG_SLOW_CLOCK_ENABLE, | ||
317 | CFG_COMP_PROC, | ||
318 | CFG_USER_RTS_THRESHOLD, | ||
319 | CFG_XR2NORM_RATE_THRESHOLD, | ||
320 | CFG_XRMODE_SWITCH_COUNT, | ||
321 | CFG_PROTECTION_TYPE, | ||
322 | CFG_BURST_SEQ_THRESHOLD, | ||
323 | CFG_ABOLT, | ||
324 | CFG_IQ_LOG_COUNT_MAX, | ||
325 | CFG_MODE_CTS, | ||
326 | CFG_WME_ENABLED, | ||
327 | CFG_GPRS_CBR_PERIOD, | ||
328 | CFG_SERVICE_TYPE, | ||
329 | /* MAC Address to use. Overrides EEPROM */ | ||
330 | CFG_MAC_ADDR, | ||
331 | CFG_DEBUG_EAR, | ||
332 | CFG_INIT_REGS, | ||
333 | /* An ID for use in error & debug messages */ | ||
334 | CFG_DEBUG_ID, | ||
335 | CFG_COMP_WIN_SZ, | ||
336 | CFG_DIVERSITY_CTL, | ||
337 | CFG_TP_SCALE, | ||
338 | CFG_TPC_HALF_DBM5, | ||
339 | CFG_TPC_HALF_DBM2, | ||
340 | CFG_OVERRD_TX_POWER, | ||
341 | CFG_USE_32KHZ_CLOCK, | ||
342 | CFG_GMODE_PROTECTION, | ||
343 | CFG_GMODE_PROTECT_RATE_INDEX, | ||
344 | CFG_GMODE_NON_ERP_PREAMBLE, | ||
345 | CFG_WDC_TRANSPORT_CHUNK_SIZE, | ||
346 | }; | ||
347 | |||
348 | enum { | ||
349 | /* Sentinal to indicate "no capability" */ | ||
350 | CAP_NONE, | ||
351 | CAP_ALL, /* ALL capabilities */ | ||
352 | CAP_TARGET_VERSION, | ||
353 | CAP_TARGET_REVISION, | ||
354 | CAP_MAC_VERSION, | ||
355 | CAP_MAC_REVISION, | ||
356 | CAP_PHY_REVISION, | ||
357 | CAP_ANALOG_5GHz_REVISION, | ||
358 | CAP_ANALOG_2GHz_REVISION, | ||
359 | /* Target supports WDC message debug features */ | ||
360 | CAP_DEBUG_WDCMSG_SUPPORT, | ||
361 | |||
362 | CAP_REG_DOMAIN, | ||
363 | CAP_COUNTRY_CODE, | ||
364 | CAP_REG_CAP_BITS, | ||
365 | |||
366 | CAP_WIRELESS_MODES, | ||
367 | CAP_CHAN_SPREAD_SUPPORT, | ||
368 | CAP_SLEEP_AFTER_BEACON_BROKEN, | ||
369 | CAP_COMPRESS_SUPPORT, | ||
370 | CAP_BURST_SUPPORT, | ||
371 | CAP_FAST_FRAMES_SUPPORT, | ||
372 | CAP_CHAP_TUNING_SUPPORT, | ||
373 | CAP_TURBOG_SUPPORT, | ||
374 | CAP_TURBO_PRIME_SUPPORT, | ||
375 | CAP_DEVICE_TYPE, | ||
376 | CAP_XR_SUPPORT, | ||
377 | CAP_WME_SUPPORT, | ||
378 | CAP_TOTAL_QUEUES, | ||
379 | CAP_CONNECTION_ID_MAX, /* Should absorb CAP_KEY_CACHE_SIZE */ | ||
380 | |||
381 | CAP_LOW_5GHZ_CHAN, | ||
382 | CAP_HIGH_5GHZ_CHAN, | ||
383 | CAP_LOW_2GHZ_CHAN, | ||
384 | CAP_HIGH_2GHZ_CHAN, | ||
385 | |||
386 | CAP_MIC_AES_CCM, | ||
387 | CAP_MIC_CKIP, | ||
388 | CAP_MIC_TKIP, | ||
389 | CAP_MIC_TKIP_WME, | ||
390 | CAP_CIPHER_AES_CCM, | ||
391 | CAP_CIPHER_CKIP, | ||
392 | CAP_CIPHER_TKIP, | ||
393 | |||
394 | CAP_TWICE_ANTENNAGAIN_5G, | ||
395 | CAP_TWICE_ANTENNAGAIN_2G, | ||
396 | }; | ||
397 | |||
398 | enum { | ||
399 | ST_NONE, /* Sentinal to indicate "no status" */ | ||
400 | ST_ALL, | ||
401 | ST_SERVICE_TYPE, | ||
402 | ST_WLAN_MODE, | ||
403 | ST_FREQ, | ||
404 | ST_BAND, | ||
405 | ST_LAST_RSSI, | ||
406 | ST_PS_FRAMES_DROPPED, | ||
407 | ST_CACHED_DEF_ANT, | ||
408 | ST_COUNT_OTHER_RX_ANT, | ||
409 | ST_USE_FAST_DIVERSITY, | ||
410 | ST_MAC_ADDR, | ||
411 | ST_RX_GENERATION_NUM, | ||
412 | ST_TX_QUEUE_DEPTH, | ||
413 | ST_SERIAL_NUMBER, | ||
414 | ST_WDC_TRANSPORT_CHUNK_SIZE, | ||
415 | }; | ||
416 | |||
417 | enum { | ||
418 | TARGET_DEVICE_AWAKE, | ||
419 | TARGET_DEVICE_SLEEP, | ||
420 | TARGET_DEVICE_PWRDN, | ||
421 | TARGET_DEVICE_PWRSAVE, | ||
422 | TARGET_DEVICE_SUSPEND, | ||
423 | TARGET_DEVICE_RESUME, | ||
424 | }; | ||
425 | |||
426 | /* this is in net/ieee80211.h, but that conflicts with the mac80211 headers */ | ||
427 | #define IEEE80211_2ADDR_LEN 16 | ||
428 | |||
429 | #define AR5523_MIN_RXBUFSZ \ | ||
430 | (((sizeof(__be32) + IEEE80211_2ADDR_LEN + \ | ||
431 | sizeof(struct ar5523_rx_desc)) + 3) & ~3) | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 89bf94d4d8a1..6f7cf49eff4d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h | |||
@@ -534,107 +534,107 @@ static const u32 ar9300_2p2_baseband_core[][2] = { | |||
534 | 534 | ||
535 | static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { | 535 | static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { |
536 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | 536 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ |
537 | {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, | 537 | {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, |
538 | {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, | 538 | {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, |
539 | {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, | 539 | {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, |
540 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | 540 | {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
541 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, | 541 | {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, |
542 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 542 | {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
543 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, | 543 | {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, |
544 | {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, | 544 | {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, |
545 | {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, | 545 | {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, |
546 | {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202}, | 546 | {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202}, |
547 | {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400}, | 547 | {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400}, |
548 | {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402}, | 548 | {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402}, |
549 | {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404}, | 549 | {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404}, |
550 | {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603}, | 550 | {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603}, |
551 | {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02}, | 551 | {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02}, |
552 | {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04}, | 552 | {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04}, |
553 | {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20}, | 553 | {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20}, |
554 | {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20}, | 554 | {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20}, |
555 | {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22}, | 555 | {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22}, |
556 | {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24}, | 556 | {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24}, |
557 | {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640}, | 557 | {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640}, |
558 | {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660}, | 558 | {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660}, |
559 | {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861}, | 559 | {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861}, |
560 | {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81}, | 560 | {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81}, |
561 | {0x0000a54c, 0x5a08442e, 0x5a08442e, 0x47001a83, 0x47001a83}, | 561 | {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83}, |
562 | {0x0000a550, 0x5e0a4431, 0x5e0a4431, 0x4a001c84, 0x4a001c84}, | 562 | {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84}, |
563 | {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3}, | 563 | {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3}, |
564 | {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5}, | 564 | {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5}, |
565 | {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9}, | 565 | {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9}, |
566 | {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb}, | 566 | {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb}, |
567 | {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | 567 | {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
568 | {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | 568 | {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
569 | {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | 569 | {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
570 | {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | 570 | {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
571 | {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | 571 | {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
572 | {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | 572 | {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
573 | {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, | 573 | {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec}, |
574 | {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, | 574 | {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, |
575 | {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, | 575 | {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, |
576 | {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, | 576 | {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, |
577 | {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, | 577 | {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, |
578 | {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202}, | 578 | {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202}, |
579 | {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400}, | 579 | {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400}, |
580 | {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402}, | 580 | {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402}, |
581 | {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404}, | 581 | {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404}, |
582 | {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603}, | 582 | {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603}, |
583 | {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02}, | 583 | {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02}, |
584 | {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04}, | 584 | {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04}, |
585 | {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20}, | 585 | {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20}, |
586 | {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20}, | 586 | {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20}, |
587 | {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22}, | 587 | {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22}, |
588 | {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24}, | 588 | {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24}, |
589 | {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640}, | 589 | {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640}, |
590 | {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660}, | 590 | {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660}, |
591 | {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861}, | 591 | {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861}, |
592 | {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81}, | 592 | {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81}, |
593 | {0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83}, | 593 | {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83}, |
594 | {0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84}, | 594 | {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84}, |
595 | {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3}, | 595 | {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3}, |
596 | {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5}, | 596 | {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5}, |
597 | {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9}, | 597 | {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9}, |
598 | {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb}, | 598 | {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb}, |
599 | {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, | 599 | {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
600 | {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, | 600 | {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
601 | {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, | 601 | {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
602 | {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, | 602 | {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
603 | {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, | 603 | {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
604 | {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, | 604 | {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
605 | {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, | 605 | {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec}, |
606 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 606 | {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
607 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 607 | {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
608 | {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, | 608 | {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
609 | {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, | 609 | {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
610 | {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, | 610 | {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
611 | {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000}, | 611 | {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000}, |
612 | {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501}, | 612 | {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501}, |
613 | {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501}, | 613 | {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501}, |
614 | {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03}, | 614 | {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03}, |
615 | {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, | 615 | {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04}, |
616 | {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04}, | 616 | {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04}, |
617 | {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | 617 | {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, |
618 | {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | 618 | {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, |
619 | {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | 619 | {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, |
620 | {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | 620 | {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, |
621 | {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, | 621 | {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005}, |
622 | {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, | 622 | {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, |
623 | {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, | 623 | {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, |
624 | {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, | 624 | {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, |
625 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | 625 | {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
626 | {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, | 626 | {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352}, |
627 | {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, | 627 | {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584}, |
628 | {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, | 628 | {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800}, |
629 | {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, | 629 | {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, |
630 | {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | 630 | {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, |
631 | {0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, | 631 | {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, |
632 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 632 | {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, |
633 | {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | 633 | {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, |
634 | {0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, | 634 | {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, |
635 | {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 635 | {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, |
636 | {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, | 636 | {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, |
637 | {0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, | 637 | {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, |
638 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, | 638 | {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, |
639 | }; | 639 | }; |
640 | 640 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 84b558d126ca..162401f22f8c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -276,6 +276,11 @@ static void ar9003_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) | |||
276 | offset_array[i], | 276 | offset_array[i], |
277 | REG_READ(ah, offset_array[i])); | 277 | REG_READ(ah, offset_array[i])); |
278 | 278 | ||
279 | if (AR_SREV_9565(ah) && | ||
280 | (iCoff == 63 || qCoff == 63 || | ||
281 | iCoff == -63 || qCoff == -63)) | ||
282 | return; | ||
283 | |||
279 | REG_RMW_FIELD(ah, offset_array[i], | 284 | REG_RMW_FIELD(ah, offset_array[i], |
280 | AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, | 285 | AR_PHY_RX_IQCAL_CORR_IQCORR_Q_I_COFF, |
281 | iCoff); | 286 | iCoff); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 5bbe5057ba18..c86cb6400040 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include "hw.h" | 18 | #include "hw.h" |
19 | #include "ar9003_phy.h" | 19 | #include "ar9003_phy.h" |
20 | #include "ar9003_eeprom.h" | 20 | #include "ar9003_eeprom.h" |
21 | #include "ar9003_mci.h" | ||
21 | 22 | ||
22 | #define COMP_HDR_LEN 4 | 23 | #define COMP_HDR_LEN 4 |
23 | #define COMP_CKSUM_LEN 2 | 24 | #define COMP_CKSUM_LEN 2 |
@@ -41,7 +42,6 @@ | |||
41 | static int ar9003_hw_power_interpolate(int32_t x, | 42 | static int ar9003_hw_power_interpolate(int32_t x, |
42 | int32_t *px, int32_t *py, u_int16_t np); | 43 | int32_t *px, int32_t *py, u_int16_t np); |
43 | 44 | ||
44 | |||
45 | static const struct ar9300_eeprom ar9300_default = { | 45 | static const struct ar9300_eeprom ar9300_default = { |
46 | .eepromVersion = 2, | 46 | .eepromVersion = 2, |
47 | .templateVersion = 2, | 47 | .templateVersion = 2, |
@@ -2989,7 +2989,7 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah, | |||
2989 | case EEP_PAPRD: | 2989 | case EEP_PAPRD: |
2990 | if (AR_SREV_9462(ah)) | 2990 | if (AR_SREV_9462(ah)) |
2991 | return false; | 2991 | return false; |
2992 | if (!ah->config.enable_paprd); | 2992 | if (!ah->config.enable_paprd) |
2993 | return false; | 2993 | return false; |
2994 | return !!(pBase->featureEnable & BIT(5)); | 2994 | return !!(pBase->featureEnable & BIT(5)); |
2995 | case EEP_CHAIN_MASK_REDUCE: | 2995 | case EEP_CHAIN_MASK_REDUCE: |
@@ -3601,7 +3601,7 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | |||
3601 | * 7:4 R/W SWITCH_TABLE_COM_SPDT_WLAN_IDLE | 3601 | * 7:4 R/W SWITCH_TABLE_COM_SPDT_WLAN_IDLE |
3602 | * SWITCH_TABLE_COM_SPDT_WLAN_IDLE | 3602 | * SWITCH_TABLE_COM_SPDT_WLAN_IDLE |
3603 | */ | 3603 | */ |
3604 | if (AR_SREV_9462_20_OR_LATER(ah)) { | 3604 | if (AR_SREV_9462_20(ah) || AR_SREV_9565(ah)) { |
3605 | value = ar9003_switch_com_spdt_get(ah, is2ghz); | 3605 | value = ar9003_switch_com_spdt_get(ah, is2ghz); |
3606 | REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, | 3606 | REG_RMW_FIELD(ah, AR_PHY_GLB_CONTROL, |
3607 | AR_SWITCH_TABLE_COM_SPDT_ALL, value); | 3607 | AR_SWITCH_TABLE_COM_SPDT_ALL, value); |
@@ -5037,16 +5037,28 @@ static void ar9003_hw_set_power_per_rate_table(struct ath_hw *ah, | |||
5037 | case CTL_5GHT20: | 5037 | case CTL_5GHT20: |
5038 | case CTL_2GHT20: | 5038 | case CTL_2GHT20: |
5039 | for (i = ALL_TARGET_HT20_0_8_16; | 5039 | for (i = ALL_TARGET_HT20_0_8_16; |
5040 | i <= ALL_TARGET_HT20_23; i++) | 5040 | i <= ALL_TARGET_HT20_23; i++) { |
5041 | pPwrArray[i] = (u8)min((u16)pPwrArray[i], | 5041 | pPwrArray[i] = (u8)min((u16)pPwrArray[i], |
5042 | minCtlPower); | 5042 | minCtlPower); |
5043 | if (ath9k_hw_mci_is_enabled(ah)) | ||
5044 | pPwrArray[i] = | ||
5045 | (u8)min((u16)pPwrArray[i], | ||
5046 | ar9003_mci_get_max_txpower(ah, | ||
5047 | pCtlMode[ctlMode])); | ||
5048 | } | ||
5043 | break; | 5049 | break; |
5044 | case CTL_5GHT40: | 5050 | case CTL_5GHT40: |
5045 | case CTL_2GHT40: | 5051 | case CTL_2GHT40: |
5046 | for (i = ALL_TARGET_HT40_0_8_16; | 5052 | for (i = ALL_TARGET_HT40_0_8_16; |
5047 | i <= ALL_TARGET_HT40_23; i++) | 5053 | i <= ALL_TARGET_HT40_23; i++) { |
5048 | pPwrArray[i] = (u8)min((u16)pPwrArray[i], | 5054 | pPwrArray[i] = (u8)min((u16)pPwrArray[i], |
5049 | minCtlPower); | 5055 | minCtlPower); |
5056 | if (ath9k_hw_mci_is_enabled(ah)) | ||
5057 | pPwrArray[i] = | ||
5058 | (u8)min((u16)pPwrArray[i], | ||
5059 | ar9003_mci_get_max_txpower(ah, | ||
5060 | pCtlMode[ctlMode])); | ||
5061 | } | ||
5050 | break; | 5062 | break; |
5051 | default: | 5063 | default: |
5052 | break; | 5064 | break; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 1a36fa262639..0693cd95b746 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
@@ -219,10 +219,10 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
219 | 219 | ||
220 | /* Awake -> Sleep Setting */ | 220 | /* Awake -> Sleep Setting */ |
221 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | 221 | INIT_INI_ARRAY(&ah->iniPcieSerdes, |
222 | ar9462_pciephy_pll_on_clkreq_disable_L1_2p0); | 222 | ar9462_pciephy_clkreq_disable_L1_2p0); |
223 | /* Sleep -> Awake Setting */ | 223 | /* Sleep -> Awake Setting */ |
224 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | 224 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, |
225 | ar9462_pciephy_pll_on_clkreq_disable_L1_2p0); | 225 | ar9462_pciephy_clkreq_disable_L1_2p0); |
226 | 226 | ||
227 | /* Fast clock modal settings */ | 227 | /* Fast clock modal settings */ |
228 | INIT_INI_ARRAY(&ah->iniModesFastClock, | 228 | INIT_INI_ARRAY(&ah->iniModesFastClock, |
@@ -328,9 +328,9 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
328 | ar9565_1p0_Modes_lowest_ob_db_tx_gain_table); | 328 | ar9565_1p0_Modes_lowest_ob_db_tx_gain_table); |
329 | 329 | ||
330 | INIT_INI_ARRAY(&ah->iniPcieSerdes, | 330 | INIT_INI_ARRAY(&ah->iniPcieSerdes, |
331 | ar9565_1p0_pciephy_pll_on_clkreq_disable_L1); | 331 | ar9565_1p0_pciephy_clkreq_disable_L1); |
332 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, | 332 | INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, |
333 | ar9565_1p0_pciephy_pll_on_clkreq_disable_L1); | 333 | ar9565_1p0_pciephy_clkreq_disable_L1); |
334 | 334 | ||
335 | INIT_INI_ARRAY(&ah->iniModesFastClock, | 335 | INIT_INI_ARRAY(&ah->iniModesFastClock, |
336 | ar9565_1p0_modes_fast_clock); | 336 | ar9565_1p0_modes_fast_clock); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c index 44c202ce6c66..42b4412d6794 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c | |||
@@ -750,6 +750,9 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
750 | 750 | ||
751 | mci_hw->bt_state = MCI_BT_AWAKE; | 751 | mci_hw->bt_state = MCI_BT_AWAKE; |
752 | 752 | ||
753 | REG_CLR_BIT(ah, AR_PHY_TIMING4, | ||
754 | 1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT); | ||
755 | |||
753 | if (caldata) { | 756 | if (caldata) { |
754 | caldata->done_txiqcal_once = false; | 757 | caldata->done_txiqcal_once = false; |
755 | caldata->done_txclcal_once = false; | 758 | caldata->done_txclcal_once = false; |
@@ -759,6 +762,9 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
759 | if (!ath9k_hw_init_cal(ah, chan)) | 762 | if (!ath9k_hw_init_cal(ah, chan)) |
760 | return -EIO; | 763 | return -EIO; |
761 | 764 | ||
765 | REG_SET_BIT(ah, AR_PHY_TIMING4, | ||
766 | 1 << AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT); | ||
767 | |||
762 | exit: | 768 | exit: |
763 | ar9003_mci_enable_interrupt(ah); | 769 | ar9003_mci_enable_interrupt(ah); |
764 | return 0; | 770 | return 0; |
@@ -799,6 +805,9 @@ static void ar9003_mci_osla_setup(struct ath_hw *ah, bool enable) | |||
799 | REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, | 805 | REG_RMW_FIELD(ah, AR_MCI_SCHD_TABLE_2, |
800 | AR_MCI_SCHD_TABLE_2_MEM_BASED, 1); | 806 | AR_MCI_SCHD_TABLE_2_MEM_BASED, 1); |
801 | 807 | ||
808 | if (AR_SREV_9565(ah)) | ||
809 | REG_RMW_FIELD(ah, AR_MCI_MISC, AR_MCI_MISC_HW_FIX_EN, 1); | ||
810 | |||
802 | if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) { | 811 | if (!(mci->config & ATH_MCI_CONFIG_DISABLE_AGGR_THRESH)) { |
803 | thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH); | 812 | thresh = MS(mci->config, ATH_MCI_CONFIG_AGGR_THRESH); |
804 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, | 813 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, |
@@ -818,7 +827,7 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, | |||
818 | { | 827 | { |
819 | struct ath_common *common = ath9k_hw_common(ah); | 828 | struct ath_common *common = ath9k_hw_common(ah); |
820 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | 829 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; |
821 | u32 regval; | 830 | u32 regval, i; |
822 | 831 | ||
823 | ath_dbg(common, MCI, "MCI Reset (full_sleep = %d, is_2g = %d)\n", | 832 | ath_dbg(common, MCI, "MCI Reset (full_sleep = %d, is_2g = %d)\n", |
824 | is_full_sleep, is_2g); | 833 | is_full_sleep, is_2g); |
@@ -847,11 +856,18 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, | |||
847 | SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) | | 856 | SM(1, AR_BTCOEX_CTRL_WBTIMER_EN) | |
848 | SM(1, AR_BTCOEX_CTRL_PA_SHARED) | | 857 | SM(1, AR_BTCOEX_CTRL_PA_SHARED) | |
849 | SM(1, AR_BTCOEX_CTRL_LNA_SHARED) | | 858 | SM(1, AR_BTCOEX_CTRL_LNA_SHARED) | |
850 | SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) | | ||
851 | SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK) | | ||
852 | SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) | | 859 | SM(0, AR_BTCOEX_CTRL_1_CHAIN_ACK) | |
853 | SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) | | 860 | SM(0, AR_BTCOEX_CTRL_1_CHAIN_BCN) | |
854 | SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); | 861 | SM(0, AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN); |
862 | if (AR_SREV_9565(ah)) { | ||
863 | regval |= SM(1, AR_BTCOEX_CTRL_NUM_ANTENNAS) | | ||
864 | SM(1, AR_BTCOEX_CTRL_RX_CHAIN_MASK); | ||
865 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, | ||
866 | AR_BTCOEX_CTRL2_TX_CHAIN_MASK, 0x1); | ||
867 | } else { | ||
868 | regval |= SM(2, AR_BTCOEX_CTRL_NUM_ANTENNAS) | | ||
869 | SM(3, AR_BTCOEX_CTRL_RX_CHAIN_MASK); | ||
870 | } | ||
855 | 871 | ||
856 | REG_WRITE(ah, AR_BTCOEX_CTRL, regval); | 872 | REG_WRITE(ah, AR_BTCOEX_CTRL, regval); |
857 | 873 | ||
@@ -865,9 +881,24 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, | |||
865 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3, | 881 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL3, |
866 | AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20); | 882 | AR_BTCOEX_CTRL3_CONT_INFO_TIMEOUT, 20); |
867 | 883 | ||
868 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 1); | 884 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, AR_BTCOEX_CTRL2_RX_DEWEIGHT, 0); |
869 | REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); | 885 | REG_RMW_FIELD(ah, AR_PCU_MISC, AR_PCU_BT_ANT_PREVENT_RX, 0); |
870 | 886 | ||
887 | /* Set the time out to 3.125ms (5 BT slots) */ | ||
888 | REG_RMW_FIELD(ah, AR_BTCOEX_WL_LNA, AR_BTCOEX_WL_LNA_TIMEOUT, 0x3D090); | ||
889 | |||
890 | /* concurrent tx priority */ | ||
891 | if (mci->config & ATH_MCI_CONFIG_CONCUR_TX) { | ||
892 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, | ||
893 | AR_BTCOEX_CTRL2_DESC_BASED_TXPWR_ENABLE, 0); | ||
894 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL2, | ||
895 | AR_BTCOEX_CTRL2_TXPWR_THRESH, 0x7f); | ||
896 | REG_RMW_FIELD(ah, AR_BTCOEX_CTRL, | ||
897 | AR_BTCOEX_CTRL_REDUCE_TXPWR, 0); | ||
898 | for (i = 0; i < 8; i++) | ||
899 | REG_WRITE(ah, AR_BTCOEX_MAX_TXPWR(i), 0x7f7f7f7f); | ||
900 | } | ||
901 | |||
871 | regval = MS(mci->config, ATH_MCI_CONFIG_CLK_DIV); | 902 | regval = MS(mci->config, ATH_MCI_CONFIG_CLK_DIV); |
872 | REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, regval); | 903 | REG_RMW_FIELD(ah, AR_MCI_TX_CTRL, AR_MCI_TX_CTRL_CLK_DIV, regval); |
873 | REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN); | 904 | REG_SET_BIT(ah, AR_BTCOEX_CTRL, AR_BTCOEX_CTRL_MCI_MODE_EN); |
@@ -910,6 +941,9 @@ int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, | |||
910 | mci->ready = true; | 941 | mci->ready = true; |
911 | ar9003_mci_prep_interface(ah); | 942 | ar9003_mci_prep_interface(ah); |
912 | 943 | ||
944 | if (AR_SREV_9565(ah)) | ||
945 | REG_RMW_FIELD(ah, AR_MCI_DBG_CNT_CTRL, | ||
946 | AR_MCI_DBG_CNT_CTRL_ENABLE, 0); | ||
913 | if (en_int) | 947 | if (en_int) |
914 | ar9003_mci_enable_interrupt(ah); | 948 | ar9003_mci_enable_interrupt(ah); |
915 | 949 | ||
@@ -1028,7 +1062,9 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool force) | |||
1028 | 1062 | ||
1029 | if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) | 1063 | if (!(mci->config & ATH_MCI_CONFIG_DISABLE_OSLA)) |
1030 | ar9003_mci_osla_setup(ah, true); | 1064 | ar9003_mci_osla_setup(ah, true); |
1031 | REG_WRITE(ah, AR_SELFGEN_MASK, 0x02); | 1065 | |
1066 | if (AR_SREV_9462(ah)) | ||
1067 | REG_WRITE(ah, AR_SELFGEN_MASK, 0x02); | ||
1032 | } else { | 1068 | } else { |
1033 | ar9003_mci_send_lna_take(ah, true); | 1069 | ar9003_mci_send_lna_take(ah, true); |
1034 | udelay(5); | 1070 | udelay(5); |
@@ -1170,7 +1206,7 @@ EXPORT_SYMBOL(ar9003_mci_cleanup); | |||
1170 | u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type) | 1206 | u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type) |
1171 | { | 1207 | { |
1172 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | 1208 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; |
1173 | u32 value = 0; | 1209 | u32 value = 0, tsf; |
1174 | u8 query_type; | 1210 | u8 query_type; |
1175 | 1211 | ||
1176 | switch (state_type) { | 1212 | switch (state_type) { |
@@ -1228,6 +1264,14 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type) | |||
1228 | ar9003_mci_send_coex_bt_status_query(ah, true, query_type); | 1264 | ar9003_mci_send_coex_bt_status_query(ah, true, query_type); |
1229 | break; | 1265 | break; |
1230 | case MCI_STATE_RECOVER_RX: | 1266 | case MCI_STATE_RECOVER_RX: |
1267 | tsf = ath9k_hw_gettsf32(ah); | ||
1268 | if ((tsf - mci->last_recovery) <= MCI_RECOVERY_DUR_TSF) { | ||
1269 | ath_dbg(ath9k_hw_common(ah), MCI, | ||
1270 | "(MCI) ignore Rx recovery\n"); | ||
1271 | break; | ||
1272 | } | ||
1273 | ath_dbg(ath9k_hw_common(ah), MCI, "(MCI) RECOVER RX\n"); | ||
1274 | mci->last_recovery = tsf; | ||
1231 | ar9003_mci_prep_interface(ah); | 1275 | ar9003_mci_prep_interface(ah); |
1232 | mci->query_bt = true; | 1276 | mci->query_bt = true; |
1233 | mci->need_flush_btinfo = true; | 1277 | mci->need_flush_btinfo = true; |
@@ -1426,3 +1470,17 @@ void ar9003_mci_send_wlan_channels(struct ath_hw *ah) | |||
1426 | ar9003_mci_send_coex_wlan_channels(ah, true); | 1470 | ar9003_mci_send_coex_wlan_channels(ah, true); |
1427 | } | 1471 | } |
1428 | EXPORT_SYMBOL(ar9003_mci_send_wlan_channels); | 1472 | EXPORT_SYMBOL(ar9003_mci_send_wlan_channels); |
1473 | |||
1474 | u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode) | ||
1475 | { | ||
1476 | if (!ah->btcoex_hw.mci.concur_tx) | ||
1477 | goto out; | ||
1478 | |||
1479 | if (ctlmode == CTL_2GHT20) | ||
1480 | return ATH_BTCOEX_HT20_MAX_TXPOWER; | ||
1481 | else if (ctlmode == CTL_2GHT40) | ||
1482 | return ATH_BTCOEX_HT40_MAX_TXPOWER; | ||
1483 | |||
1484 | out: | ||
1485 | return -1; | ||
1486 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.h b/drivers/net/wireless/ath/ath9k/ar9003_mci.h index 2a2d01889613..66d7ab9f920d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.h | |||
@@ -18,6 +18,7 @@ | |||
18 | #define AR9003_MCI_H | 18 | #define AR9003_MCI_H |
19 | 19 | ||
20 | #define MCI_FLAG_DISABLE_TIMESTAMP 0x00000001 /* Disable time stamp */ | 20 | #define MCI_FLAG_DISABLE_TIMESTAMP 0x00000001 /* Disable time stamp */ |
21 | #define MCI_RECOVERY_DUR_TSF (100 * 1000) /* 100 ms */ | ||
21 | 22 | ||
22 | /* Default remote BT device MCI COEX version */ | 23 | /* Default remote BT device MCI COEX version */ |
23 | #define MCI_GPM_COEX_MAJOR_VERSION_DEFAULT 3 | 24 | #define MCI_GPM_COEX_MAJOR_VERSION_DEFAULT 3 |
@@ -125,6 +126,7 @@ enum ath_mci_gpm_coex_profile_type { | |||
125 | MCI_GPM_COEX_PROFILE_HID, | 126 | MCI_GPM_COEX_PROFILE_HID, |
126 | MCI_GPM_COEX_PROFILE_BNEP, | 127 | MCI_GPM_COEX_PROFILE_BNEP, |
127 | MCI_GPM_COEX_PROFILE_VOICE, | 128 | MCI_GPM_COEX_PROFILE_VOICE, |
129 | MCI_GPM_COEX_PROFILE_A2DPVO, | ||
128 | MCI_GPM_COEX_PROFILE_MAX | 130 | MCI_GPM_COEX_PROFILE_MAX |
129 | }; | 131 | }; |
130 | 132 | ||
@@ -196,7 +198,6 @@ enum mci_state_type { | |||
196 | MCI_STATE_SEND_WLAN_COEX_VERSION, | 198 | MCI_STATE_SEND_WLAN_COEX_VERSION, |
197 | MCI_STATE_SEND_VERSION_QUERY, | 199 | MCI_STATE_SEND_VERSION_QUERY, |
198 | MCI_STATE_SEND_STATUS_QUERY, | 200 | MCI_STATE_SEND_STATUS_QUERY, |
199 | MCI_STATE_SET_CONCUR_TX_PRI, | ||
200 | MCI_STATE_RECOVER_RX, | 201 | MCI_STATE_RECOVER_RX, |
201 | MCI_STATE_NEED_FTP_STOMP, | 202 | MCI_STATE_NEED_FTP_STOMP, |
202 | MCI_STATE_DEBUG, | 203 | MCI_STATE_DEBUG, |
@@ -278,6 +279,7 @@ void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked); | |||
278 | void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah); | 279 | void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah); |
279 | void ar9003_mci_set_power_awake(struct ath_hw *ah); | 280 | void ar9003_mci_set_power_awake(struct ath_hw *ah); |
280 | void ar9003_mci_check_gpm_offset(struct ath_hw *ah); | 281 | void ar9003_mci_check_gpm_offset(struct ath_hw *ah); |
282 | u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode); | ||
281 | 283 | ||
282 | #else | 284 | #else |
283 | 285 | ||
@@ -324,6 +326,10 @@ static inline void ar9003_mci_set_power_awake(struct ath_hw *ah) | |||
324 | static inline void ar9003_mci_check_gpm_offset(struct ath_hw *ah) | 326 | static inline void ar9003_mci_check_gpm_offset(struct ath_hw *ah) |
325 | { | 327 | { |
326 | } | 328 | } |
329 | static inline u16 ar9003_mci_get_max_txpower(struct ath_hw *ah, u8 ctlmode) | ||
330 | { | ||
331 | return -1; | ||
332 | } | ||
327 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ | 333 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ |
328 | 334 | ||
329 | #endif | 335 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 9a48e3d2f231..8f585233a788 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #define AR_PHY_SPUR_REG (AR_CHAN_BASE + 0x1c) | 32 | #define AR_PHY_SPUR_REG (AR_CHAN_BASE + 0x1c) |
33 | #define AR_PHY_RX_IQCAL_CORR_B0 (AR_CHAN_BASE + 0xdc) | 33 | #define AR_PHY_RX_IQCAL_CORR_B0 (AR_CHAN_BASE + 0xdc) |
34 | #define AR_PHY_TX_IQCAL_CONTROL_3 (AR_CHAN_BASE + 0xb0) | 34 | #define AR_PHY_TX_IQCAL_CONTROL_3 (AR_CHAN_BASE + 0xb0) |
35 | #define AR_PHY_TIMING_CONTROL4_DO_GAIN_DC_IQ_CAL_SHIFT 16 | ||
35 | 36 | ||
36 | #define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 | 37 | #define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 |
37 | #define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 | 38 | #define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 |
diff --git a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h index 843e79f67ff2..0c2ac0c6dc89 100644 --- a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h | |||
@@ -768,9 +768,9 @@ static const u32 ar9565_1p0_Modes_lowest_ob_db_tx_gain_table[][5] = { | |||
768 | {0x00016054, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, | 768 | {0x00016054, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, |
769 | }; | 769 | }; |
770 | 770 | ||
771 | static const u32 ar9565_1p0_pciephy_pll_on_clkreq_disable_L1[][2] = { | 771 | static const u32 ar9565_1p0_pciephy_clkreq_disable_L1[][2] = { |
772 | /* Addr allmodes */ | 772 | /* Addr allmodes */ |
773 | {0x00018c00, 0x18212ede}, | 773 | {0x00018c00, 0x18213ede}, |
774 | {0x00018c04, 0x000801d8}, | 774 | {0x00018c04, 0x000801d8}, |
775 | {0x00018c08, 0x0003780c}, | 775 | {0x00018c08, 0x0003780c}, |
776 | }; | 776 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index dfe6a4707fd2..4e125d8904a0 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -437,6 +437,7 @@ void ath9k_set_beacon(struct ath_softc *sc); | |||
437 | #define ATH_LONG_CALINTERVAL_INT 1000 /* 1000 ms */ | 437 | #define ATH_LONG_CALINTERVAL_INT 1000 /* 1000 ms */ |
438 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ | 438 | #define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ |
439 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ | 439 | #define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ |
440 | #define ATH_ANI_MAX_SKIP_COUNT 10 | ||
440 | 441 | ||
441 | #define ATH_PAPRD_TIMEOUT 100 /* msecs */ | 442 | #define ATH_PAPRD_TIMEOUT 100 /* msecs */ |
442 | #define ATH_PLL_WORK_INTERVAL 100 | 443 | #define ATH_PLL_WORK_INTERVAL 100 |
@@ -478,6 +479,7 @@ struct ath_btcoex { | |||
478 | u32 btscan_no_stomp; /* in usec */ | 479 | u32 btscan_no_stomp; /* in usec */ |
479 | u32 duty_cycle; | 480 | u32 duty_cycle; |
480 | u32 bt_wait_time; | 481 | u32 bt_wait_time; |
482 | int rssi_count; | ||
481 | struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */ | 483 | struct ath_gen_timer *no_stomp_timer; /* Timer for no BT stomping */ |
482 | struct ath_mci_profile mci; | 484 | struct ath_mci_profile mci; |
483 | }; | 485 | }; |
@@ -492,6 +494,7 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc); | |||
492 | void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status); | 494 | void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status); |
493 | u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen); | 495 | u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen); |
494 | void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc); | 496 | void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc); |
497 | int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 len, u32 size); | ||
495 | #else | 498 | #else |
496 | static inline int ath9k_init_btcoex(struct ath_softc *sc) | 499 | static inline int ath9k_init_btcoex(struct ath_softc *sc) |
497 | { | 500 | { |
@@ -518,6 +521,11 @@ static inline u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, | |||
518 | static inline void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc) | 521 | static inline void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc) |
519 | { | 522 | { |
520 | } | 523 | } |
524 | static inline int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, | ||
525 | u32 len, u32 size) | ||
526 | { | ||
527 | return 0; | ||
528 | } | ||
521 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ | 529 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ |
522 | 530 | ||
523 | struct ath9k_wow_pattern { | 531 | struct ath9k_wow_pattern { |
@@ -642,6 +650,7 @@ enum sc_op_flags { | |||
642 | #define PS_WAIT_FOR_PSPOLL_DATA BIT(2) | 650 | #define PS_WAIT_FOR_PSPOLL_DATA BIT(2) |
643 | #define PS_WAIT_FOR_TX_ACK BIT(3) | 651 | #define PS_WAIT_FOR_TX_ACK BIT(3) |
644 | #define PS_BEACON_SYNC BIT(4) | 652 | #define PS_BEACON_SYNC BIT(4) |
653 | #define PS_WAIT_FOR_ANI BIT(5) | ||
645 | 654 | ||
646 | struct ath_rate_table; | 655 | struct ath_rate_table; |
647 | 656 | ||
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 419e9a3f2fed..c90e9bc4b026 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c | |||
@@ -195,7 +195,7 @@ void ath9k_hw_btcoex_init_mci(struct ath_hw *ah) | |||
195 | ah->btcoex_hw.mci.need_flush_btinfo = false; | 195 | ah->btcoex_hw.mci.need_flush_btinfo = false; |
196 | ah->btcoex_hw.mci.wlan_cal_seq = 0; | 196 | ah->btcoex_hw.mci.wlan_cal_seq = 0; |
197 | ah->btcoex_hw.mci.wlan_cal_done = 0; | 197 | ah->btcoex_hw.mci.wlan_cal_done = 0; |
198 | ah->btcoex_hw.mci.config = 0x2201; | 198 | ah->btcoex_hw.mci.config = (AR_SREV_9462(ah)) ? 0x2201 : 0xa4c1; |
199 | } | 199 | } |
200 | EXPORT_SYMBOL(ath9k_hw_btcoex_init_mci); | 200 | EXPORT_SYMBOL(ath9k_hw_btcoex_init_mci); |
201 | 201 | ||
@@ -218,27 +218,45 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, | |||
218 | enum ath_stomp_type stomp_type) | 218 | enum ath_stomp_type stomp_type) |
219 | { | 219 | { |
220 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; | 220 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; |
221 | struct ath9k_hw_mci *mci_hw = &ah->btcoex_hw.mci; | ||
222 | u8 txprio_shift[] = { 24, 16, 16, 0 }; /* tx priority weight */ | ||
223 | bool concur_tx = (mci_hw->concur_tx && btcoex_hw->tx_prio[stomp_type]); | ||
224 | const u32 *weight = ar9003_wlan_weights[stomp_type]; | ||
225 | int i; | ||
221 | 226 | ||
222 | if (AR_SREV_9300_20_OR_LATER(ah)) { | 227 | if (!AR_SREV_9300_20_OR_LATER(ah)) { |
223 | const u32 *weight = ar9003_wlan_weights[stomp_type]; | ||
224 | int i; | ||
225 | |||
226 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { | ||
227 | if ((stomp_type == ATH_BTCOEX_STOMP_LOW) && | ||
228 | btcoex_hw->mci.stomp_ftp) | ||
229 | stomp_type = ATH_BTCOEX_STOMP_LOW_FTP; | ||
230 | weight = mci_wlan_weights[stomp_type]; | ||
231 | } | ||
232 | |||
233 | for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) { | ||
234 | btcoex_hw->bt_weight[i] = AR9300_BT_WGHT; | ||
235 | btcoex_hw->wlan_weight[i] = weight[i]; | ||
236 | } | ||
237 | } else { | ||
238 | btcoex_hw->bt_coex_weights = | 228 | btcoex_hw->bt_coex_weights = |
239 | SM(bt_weight, AR_BTCOEX_BT_WGHT) | | 229 | SM(bt_weight, AR_BTCOEX_BT_WGHT) | |
240 | SM(wlan_weight, AR_BTCOEX_WL_WGHT); | 230 | SM(wlan_weight, AR_BTCOEX_WL_WGHT); |
231 | return; | ||
232 | } | ||
233 | |||
234 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { | ||
235 | enum ath_stomp_type stype = | ||
236 | ((stomp_type == ATH_BTCOEX_STOMP_LOW) && | ||
237 | btcoex_hw->mci.stomp_ftp) ? | ||
238 | ATH_BTCOEX_STOMP_LOW_FTP : stomp_type; | ||
239 | weight = mci_wlan_weights[stype]; | ||
241 | } | 240 | } |
241 | |||
242 | for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) { | ||
243 | btcoex_hw->bt_weight[i] = AR9300_BT_WGHT; | ||
244 | btcoex_hw->wlan_weight[i] = weight[i]; | ||
245 | if (concur_tx && i) { | ||
246 | btcoex_hw->wlan_weight[i] &= | ||
247 | ~(0xff << txprio_shift[i-1]); | ||
248 | btcoex_hw->wlan_weight[i] |= | ||
249 | (btcoex_hw->tx_prio[stomp_type] << | ||
250 | txprio_shift[i-1]); | ||
251 | } | ||
252 | } | ||
253 | /* Last WLAN weight has to be adjusted wrt tx priority */ | ||
254 | if (concur_tx) { | ||
255 | btcoex_hw->wlan_weight[i-1] &= ~(0xff << txprio_shift[i-1]); | ||
256 | btcoex_hw->wlan_weight[i-1] |= (btcoex_hw->tx_prio[stomp_type] | ||
257 | << txprio_shift[i-1]); | ||
258 | } | ||
259 | |||
242 | } | 260 | } |
243 | EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); | 261 | EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); |
244 | 262 | ||
@@ -385,3 +403,13 @@ void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, | |||
385 | } | 403 | } |
386 | } | 404 | } |
387 | EXPORT_SYMBOL(ath9k_hw_btcoex_bt_stomp); | 405 | EXPORT_SYMBOL(ath9k_hw_btcoex_bt_stomp); |
406 | |||
407 | void ath9k_hw_btcoex_set_concur_txprio(struct ath_hw *ah, u8 *stomp_txprio) | ||
408 | { | ||
409 | struct ath_btcoex_hw *btcoex = &ah->btcoex_hw; | ||
410 | int i; | ||
411 | |||
412 | for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++) | ||
413 | btcoex->tx_prio[i] = stomp_txprio[i]; | ||
414 | } | ||
415 | EXPORT_SYMBOL(ath9k_hw_btcoex_set_concur_txprio); | ||
diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index 385197ad79b0..2f84ab273d0c 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h | |||
@@ -39,6 +39,9 @@ | |||
39 | #define ATH_BTCOEX_RX_WAIT_TIME 100 | 39 | #define ATH_BTCOEX_RX_WAIT_TIME 100 |
40 | #define ATH_BTCOEX_STOMP_FTP_THRESH 5 | 40 | #define ATH_BTCOEX_STOMP_FTP_THRESH 5 |
41 | 41 | ||
42 | #define ATH_BTCOEX_HT20_MAX_TXPOWER 0x14 | ||
43 | #define ATH_BTCOEX_HT40_MAX_TXPOWER 0x10 | ||
44 | |||
42 | #define AR9300_NUM_BT_WEIGHTS 4 | 45 | #define AR9300_NUM_BT_WEIGHTS 4 |
43 | #define AR9300_NUM_WLAN_WEIGHTS 4 | 46 | #define AR9300_NUM_WLAN_WEIGHTS 4 |
44 | /* Defines the BT AR_BT_COEX_WGHT used */ | 47 | /* Defines the BT AR_BT_COEX_WGHT used */ |
@@ -84,6 +87,8 @@ struct ath9k_hw_mci { | |||
84 | u8 bt_ver_minor; | 87 | u8 bt_ver_minor; |
85 | u8 bt_state; | 88 | u8 bt_state; |
86 | u8 stomp_ftp; | 89 | u8 stomp_ftp; |
90 | bool concur_tx; | ||
91 | u32 last_recovery; | ||
87 | }; | 92 | }; |
88 | 93 | ||
89 | struct ath_btcoex_hw { | 94 | struct ath_btcoex_hw { |
@@ -98,6 +103,7 @@ struct ath_btcoex_hw { | |||
98 | u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ | 103 | u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ |
99 | u32 bt_weight[AR9300_NUM_BT_WEIGHTS]; | 104 | u32 bt_weight[AR9300_NUM_BT_WEIGHTS]; |
100 | u32 wlan_weight[AR9300_NUM_WLAN_WEIGHTS]; | 105 | u32 wlan_weight[AR9300_NUM_WLAN_WEIGHTS]; |
106 | u8 tx_prio[ATH_BTCOEX_STOMP_MAX]; | ||
101 | }; | 107 | }; |
102 | 108 | ||
103 | void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah); | 109 | void ath9k_hw_btcoex_init_scheme(struct ath_hw *ah); |
@@ -112,5 +118,6 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, | |||
112 | void ath9k_hw_btcoex_disable(struct ath_hw *ah); | 118 | void ath9k_hw_btcoex_disable(struct ath_hw *ah); |
113 | void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, | 119 | void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, |
114 | enum ath_stomp_type stomp_type); | 120 | enum ath_stomp_type stomp_type); |
121 | void ath9k_hw_btcoex_set_concur_txprio(struct ath_hw *ah, u8 *stomp_txprio); | ||
115 | 122 | ||
116 | #endif | 123 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index e5cceb077574..f3448a032e6f 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -410,6 +410,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | |||
410 | 410 | ||
411 | ah->caldata->channel = chan->channel; | 411 | ah->caldata->channel = chan->channel; |
412 | ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT; | 412 | ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT; |
413 | ah->caldata->chanmode = chan->chanmode; | ||
413 | h = ah->caldata->nfCalHist; | 414 | h = ah->caldata->nfCalHist; |
414 | default_nf = ath9k_hw_get_default_nf(ah, chan); | 415 | default_nf = ath9k_hw_get_default_nf(ah, chan); |
415 | for (i = 0; i < NUM_NF_READINGS; i++) { | 416 | for (i = 0; i < NUM_NF_READINGS; i++) { |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 6727b566d294..a8be94b2a53a 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -1586,6 +1586,35 @@ static const struct file_operations fops_samps = { | |||
1586 | 1586 | ||
1587 | #endif | 1587 | #endif |
1588 | 1588 | ||
1589 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | ||
1590 | static ssize_t read_file_btcoex(struct file *file, char __user *user_buf, | ||
1591 | size_t count, loff_t *ppos) | ||
1592 | { | ||
1593 | struct ath_softc *sc = file->private_data; | ||
1594 | u32 len = 0, size = 1500; | ||
1595 | char *buf; | ||
1596 | size_t retval; | ||
1597 | |||
1598 | buf = kzalloc(size, GFP_KERNEL); | ||
1599 | if (buf == NULL) | ||
1600 | return -ENOMEM; | ||
1601 | |||
1602 | len = ath9k_dump_btcoex(sc, buf, len, size); | ||
1603 | |||
1604 | retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
1605 | kfree(buf); | ||
1606 | |||
1607 | return retval; | ||
1608 | } | ||
1609 | |||
1610 | static const struct file_operations fops_btcoex = { | ||
1611 | .read = read_file_btcoex, | ||
1612 | .open = simple_open, | ||
1613 | .owner = THIS_MODULE, | ||
1614 | .llseek = default_llseek, | ||
1615 | }; | ||
1616 | #endif | ||
1617 | |||
1589 | int ath9k_init_debug(struct ath_hw *ah) | 1618 | int ath9k_init_debug(struct ath_hw *ah) |
1590 | { | 1619 | { |
1591 | struct ath_common *common = ath9k_hw_common(ah); | 1620 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -1658,6 +1687,9 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
1658 | sc->debug.debugfs_phy, &sc->sc_ah->gpio_val); | 1687 | sc->debug.debugfs_phy, &sc->sc_ah->gpio_val); |
1659 | debugfs_create_file("diversity", S_IRUSR | S_IWUSR, | 1688 | debugfs_create_file("diversity", S_IRUSR | S_IWUSR, |
1660 | sc->debug.debugfs_phy, sc, &fops_ant_diversity); | 1689 | sc->debug.debugfs_phy, sc, &fops_ant_diversity); |
1661 | 1690 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | |
1691 | debugfs_create_file("btcoex", S_IRUSR, sc->debug.debugfs_phy, sc, | ||
1692 | &fops_btcoex); | ||
1693 | #endif | ||
1662 | return 0; | 1694 | return 0; |
1663 | } | 1695 | } |
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index d9ed141a053e..a8ea57b9f49c 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -187,6 +187,24 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) | |||
187 | } | 187 | } |
188 | } | 188 | } |
189 | 189 | ||
190 | static void ath_mci_ftp_adjust(struct ath_softc *sc) | ||
191 | { | ||
192 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
193 | struct ath_mci_profile *mci = &btcoex->mci; | ||
194 | struct ath_hw *ah = sc->sc_ah; | ||
195 | |||
196 | if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) { | ||
197 | if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) && | ||
198 | (mci->num_pan || mci->num_other_acl)) | ||
199 | ah->btcoex_hw.mci.stomp_ftp = | ||
200 | (sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH); | ||
201 | else | ||
202 | ah->btcoex_hw.mci.stomp_ftp = false; | ||
203 | btcoex->bt_wait_time = 0; | ||
204 | sc->rx.num_pkts = 0; | ||
205 | } | ||
206 | } | ||
207 | |||
190 | /* | 208 | /* |
191 | * This is the master bt coex timer which runs for every | 209 | * This is the master bt coex timer which runs for every |
192 | * 45ms, bt traffic will be given priority during 55% of this | 210 | * 45ms, bt traffic will be given priority during 55% of this |
@@ -197,41 +215,43 @@ static void ath_btcoex_period_timer(unsigned long data) | |||
197 | struct ath_softc *sc = (struct ath_softc *) data; | 215 | struct ath_softc *sc = (struct ath_softc *) data; |
198 | struct ath_hw *ah = sc->sc_ah; | 216 | struct ath_hw *ah = sc->sc_ah; |
199 | struct ath_btcoex *btcoex = &sc->btcoex; | 217 | struct ath_btcoex *btcoex = &sc->btcoex; |
200 | struct ath_mci_profile *mci = &btcoex->mci; | 218 | enum ath_stomp_type stomp_type; |
201 | u32 timer_period; | 219 | u32 timer_period; |
202 | bool is_btscan; | ||
203 | unsigned long flags; | 220 | unsigned long flags; |
204 | 221 | ||
205 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | 222 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
206 | if (sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP) { | 223 | if (sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP) { |
224 | btcoex->bt_wait_time += btcoex->btcoex_period; | ||
207 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 225 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
208 | goto skip_hw_wakeup; | 226 | goto skip_hw_wakeup; |
209 | } | 227 | } |
210 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 228 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
211 | 229 | ||
230 | ath9k_mci_update_rssi(sc); | ||
231 | |||
212 | ath9k_ps_wakeup(sc); | 232 | ath9k_ps_wakeup(sc); |
233 | |||
213 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) | 234 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) |
214 | ath_detect_bt_priority(sc); | 235 | ath_detect_bt_priority(sc); |
215 | is_btscan = test_bit(BT_OP_SCAN, &btcoex->op_flags); | ||
216 | 236 | ||
217 | btcoex->bt_wait_time += btcoex->btcoex_period; | 237 | if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) |
218 | if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) { | 238 | ath_mci_ftp_adjust(sc); |
219 | if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) && | ||
220 | (mci->num_pan || mci->num_other_acl)) | ||
221 | ah->btcoex_hw.mci.stomp_ftp = | ||
222 | (sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH); | ||
223 | else | ||
224 | ah->btcoex_hw.mci.stomp_ftp = false; | ||
225 | btcoex->bt_wait_time = 0; | ||
226 | sc->rx.num_pkts = 0; | ||
227 | } | ||
228 | 239 | ||
229 | spin_lock_bh(&btcoex->btcoex_lock); | 240 | spin_lock_bh(&btcoex->btcoex_lock); |
230 | 241 | ||
231 | ath9k_hw_btcoex_bt_stomp(ah, is_btscan ? ATH_BTCOEX_STOMP_ALL : | 242 | stomp_type = btcoex->bt_stomp_type; |
232 | btcoex->bt_stomp_type); | 243 | timer_period = btcoex->btcoex_no_stomp; |
244 | |||
245 | if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) { | ||
246 | if (test_bit(BT_OP_SCAN, &btcoex->op_flags)) { | ||
247 | stomp_type = ATH_BTCOEX_STOMP_ALL; | ||
248 | timer_period = btcoex->btscan_no_stomp; | ||
249 | } | ||
250 | } | ||
233 | 251 | ||
252 | ath9k_hw_btcoex_bt_stomp(ah, stomp_type); | ||
234 | ath9k_hw_btcoex_enable(ah); | 253 | ath9k_hw_btcoex_enable(ah); |
254 | |||
235 | spin_unlock_bh(&btcoex->btcoex_lock); | 255 | spin_unlock_bh(&btcoex->btcoex_lock); |
236 | 256 | ||
237 | /* | 257 | /* |
@@ -243,17 +263,16 @@ static void ath_btcoex_period_timer(unsigned long data) | |||
243 | if (btcoex->hw_timer_enabled) | 263 | if (btcoex->hw_timer_enabled) |
244 | ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); | 264 | ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer); |
245 | 265 | ||
246 | timer_period = is_btscan ? btcoex->btscan_no_stomp : | ||
247 | btcoex->btcoex_no_stomp; | ||
248 | ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period, | 266 | ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period, |
249 | timer_period * 10); | 267 | timer_period * 10); |
250 | btcoex->hw_timer_enabled = true; | 268 | btcoex->hw_timer_enabled = true; |
251 | } | 269 | } |
252 | 270 | ||
253 | ath9k_ps_restore(sc); | 271 | ath9k_ps_restore(sc); |
272 | |||
254 | skip_hw_wakeup: | 273 | skip_hw_wakeup: |
255 | timer_period = btcoex->btcoex_period; | 274 | mod_timer(&btcoex->period_timer, |
256 | mod_timer(&btcoex->period_timer, jiffies + msecs_to_jiffies(timer_period)); | 275 | jiffies + msecs_to_jiffies(btcoex->btcoex_period)); |
257 | } | 276 | } |
258 | 277 | ||
259 | /* | 278 | /* |
@@ -273,7 +292,8 @@ static void ath_btcoex_no_stomp_timer(void *arg) | |||
273 | spin_lock_bh(&btcoex->btcoex_lock); | 292 | spin_lock_bh(&btcoex->btcoex_lock); |
274 | 293 | ||
275 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || | 294 | if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW || |
276 | test_bit(BT_OP_SCAN, &btcoex->op_flags)) | 295 | (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && |
296 | test_bit(BT_OP_SCAN, &btcoex->op_flags))) | ||
277 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); | 297 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); |
278 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) | 298 | else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) |
279 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); | 299 | ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW); |
@@ -474,4 +494,52 @@ int ath9k_init_btcoex(struct ath_softc *sc) | |||
474 | return 0; | 494 | return 0; |
475 | } | 495 | } |
476 | 496 | ||
497 | int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 len, u32 size) | ||
498 | { | ||
499 | #define ATH_DUMP_BTCOEX(_s, _val) \ | ||
500 | do { \ | ||
501 | len += snprintf(buf + len, size - len, \ | ||
502 | "%20s : %10d\n", _s, (_val)); \ | ||
503 | } while (0) | ||
504 | |||
505 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
506 | struct ath_mci_profile *mci = &btcoex->mci; | ||
507 | struct ath_hw *ah = sc->sc_ah; | ||
508 | struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; | ||
509 | int i; | ||
510 | |||
511 | ATH_DUMP_BTCOEX("Total BT profiles", NUM_PROF(mci)); | ||
512 | ATH_DUMP_BTCOEX("Number of MGMT", mci->num_mgmt); | ||
513 | ATH_DUMP_BTCOEX("Number of SCO", mci->num_sco); | ||
514 | ATH_DUMP_BTCOEX("Number of A2DP", mci->num_a2dp); | ||
515 | ATH_DUMP_BTCOEX("Number of HID", mci->num_hid); | ||
516 | ATH_DUMP_BTCOEX("Number of PAN", mci->num_pan); | ||
517 | ATH_DUMP_BTCOEX("Number of ACL", mci->num_other_acl); | ||
518 | ATH_DUMP_BTCOEX("Number of BDR", mci->num_bdr); | ||
519 | ATH_DUMP_BTCOEX("Aggr. Limit", mci->aggr_limit); | ||
520 | ATH_DUMP_BTCOEX("Stomp Type", btcoex->bt_stomp_type); | ||
521 | ATH_DUMP_BTCOEX("BTCoex Period (msec)", btcoex->btcoex_period); | ||
522 | ATH_DUMP_BTCOEX("Duty Cycle", btcoex->duty_cycle); | ||
523 | ATH_DUMP_BTCOEX("BT Wait time", btcoex->bt_wait_time); | ||
524 | ATH_DUMP_BTCOEX("Concurrent Tx", btcoex_hw->mci.concur_tx); | ||
525 | ATH_DUMP_BTCOEX("Concur RSSI count", btcoex->rssi_count); | ||
526 | len += snprintf(buf + len, size - len, "BT Weights: "); | ||
527 | for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++) | ||
528 | len += snprintf(buf + len, size - len, "%08x ", | ||
529 | btcoex_hw->bt_weight[i]); | ||
530 | len += snprintf(buf + len, size - len, "\n"); | ||
531 | len += snprintf(buf + len, size - len, "WLAN Weights: "); | ||
532 | for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++) | ||
533 | len += snprintf(buf + len, size - len, "%08x ", | ||
534 | btcoex_hw->wlan_weight[i]); | ||
535 | len += snprintf(buf + len, size - len, "\n"); | ||
536 | len += snprintf(buf + len, size - len, "Tx Priorities: "); | ||
537 | for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++) | ||
538 | len += snprintf(buf + len, size - len, "%08x ", | ||
539 | btcoex_hw->tx_prio[i]); | ||
540 | len += snprintf(buf + len, size - len, "\n"); | ||
541 | #undef ATH_DUMP_BTCOEX | ||
542 | |||
543 | return len; | ||
544 | } | ||
477 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ | 545 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ |
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 924c4616c3d9..f5dda84176c3 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c | |||
@@ -38,6 +38,7 @@ static struct usb_device_id ath9k_hif_usb_ids[] = { | |||
38 | { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ | 38 | { USB_DEVICE(0x04CA, 0x4605) }, /* Liteon */ |
39 | { USB_DEVICE(0x040D, 0x3801) }, /* VIA */ | 39 | { USB_DEVICE(0x040D, 0x3801) }, /* VIA */ |
40 | { USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */ | 40 | { USB_DEVICE(0x0cf3, 0xb003) }, /* Ubiquiti WifiStation Ext */ |
41 | { USB_DEVICE(0x0cf3, 0xb002) }, /* Ubiquiti WifiStation */ | ||
41 | { USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */ | 42 | { USB_DEVICE(0x057c, 0x8403) }, /* AVM FRITZ!WLAN 11N v2 USB */ |
42 | 43 | ||
43 | { USB_DEVICE(0x0cf3, 0x7015), | 44 | { USB_DEVICE(0x0cf3, 0x7015), |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index d98255eb1b9a..5ecf1287dddd 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -694,6 +694,20 @@ err_hw: | |||
694 | return ret; | 694 | return ret; |
695 | } | 695 | } |
696 | 696 | ||
697 | static const struct ieee80211_iface_limit if_limits[] = { | ||
698 | { .max = 2, .types = BIT(NL80211_IFTYPE_STATION) | | ||
699 | BIT(NL80211_IFTYPE_P2P_CLIENT) }, | ||
700 | { .max = 2, .types = BIT(NL80211_IFTYPE_AP) | | ||
701 | BIT(NL80211_IFTYPE_P2P_GO) }, | ||
702 | }; | ||
703 | |||
704 | static const struct ieee80211_iface_combination if_comb = { | ||
705 | .limits = if_limits, | ||
706 | .n_limits = ARRAY_SIZE(if_limits), | ||
707 | .max_interfaces = 2, | ||
708 | .num_different_channels = 1, | ||
709 | }; | ||
710 | |||
697 | static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, | 711 | static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, |
698 | struct ieee80211_hw *hw) | 712 | struct ieee80211_hw *hw) |
699 | { | 713 | { |
@@ -716,6 +730,9 @@ static void ath9k_set_hw_capab(struct ath9k_htc_priv *priv, | |||
716 | BIT(NL80211_IFTYPE_P2P_GO) | | 730 | BIT(NL80211_IFTYPE_P2P_GO) | |
717 | BIT(NL80211_IFTYPE_P2P_CLIENT); | 731 | BIT(NL80211_IFTYPE_P2P_CLIENT); |
718 | 732 | ||
733 | hw->wiphy->iface_combinations = &if_comb; | ||
734 | hw->wiphy->n_iface_combinations = 1; | ||
735 | |||
719 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 736 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
720 | 737 | ||
721 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN | | 738 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN | |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index ca78e33ca23e..66f6a74c508e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -1036,26 +1036,6 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, | |||
1036 | 1036 | ||
1037 | mutex_lock(&priv->mutex); | 1037 | mutex_lock(&priv->mutex); |
1038 | 1038 | ||
1039 | if (priv->nvifs >= ATH9K_HTC_MAX_VIF) { | ||
1040 | mutex_unlock(&priv->mutex); | ||
1041 | return -ENOBUFS; | ||
1042 | } | ||
1043 | |||
1044 | if (priv->num_ibss_vif || | ||
1045 | (priv->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) { | ||
1046 | ath_err(common, "IBSS coexistence with other modes is not allowed\n"); | ||
1047 | mutex_unlock(&priv->mutex); | ||
1048 | return -ENOBUFS; | ||
1049 | } | ||
1050 | |||
1051 | if (((vif->type == NL80211_IFTYPE_AP) || | ||
1052 | (vif->type == NL80211_IFTYPE_ADHOC)) && | ||
1053 | ((priv->num_ap_vif + priv->num_ibss_vif) >= ATH9K_HTC_MAX_BCN_VIF)) { | ||
1054 | ath_err(common, "Max. number of beaconing interfaces reached\n"); | ||
1055 | mutex_unlock(&priv->mutex); | ||
1056 | return -ENOBUFS; | ||
1057 | } | ||
1058 | |||
1059 | ath9k_htc_ps_wakeup(priv); | 1039 | ath9k_htc_ps_wakeup(priv); |
1060 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); | 1040 | memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); |
1061 | memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); | 1041 | memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 8e1559aba495..71cd9f0c96af 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -2153,9 +2153,6 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah) | |||
2153 | AR_RTC_FORCE_WAKE_EN); | 2153 | AR_RTC_FORCE_WAKE_EN); |
2154 | udelay(50); | 2154 | udelay(50); |
2155 | 2155 | ||
2156 | if (ath9k_hw_mci_is_enabled(ah)) | ||
2157 | ar9003_mci_set_power_awake(ah); | ||
2158 | |||
2159 | for (i = POWER_UP_TIME / 50; i > 0; i--) { | 2156 | for (i = POWER_UP_TIME / 50; i > 0; i--) { |
2160 | val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; | 2157 | val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; |
2161 | if (val == AR_RTC_STATUS_ON) | 2158 | if (val == AR_RTC_STATUS_ON) |
@@ -2171,6 +2168,9 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah) | |||
2171 | return false; | 2168 | return false; |
2172 | } | 2169 | } |
2173 | 2170 | ||
2171 | if (ath9k_hw_mci_is_enabled(ah)) | ||
2172 | ar9003_mci_set_power_awake(ah); | ||
2173 | |||
2174 | REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); | 2174 | REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); |
2175 | 2175 | ||
2176 | return true; | 2176 | return true; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index dbc1b7a4cbfd..3e73bfe2315e 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -401,6 +401,7 @@ enum ath9k_int { | |||
401 | struct ath9k_hw_cal_data { | 401 | struct ath9k_hw_cal_data { |
402 | u16 channel; | 402 | u16 channel; |
403 | u32 channelFlags; | 403 | u32 channelFlags; |
404 | u32 chanmode; | ||
404 | int32_t CalValid; | 405 | int32_t CalValid; |
405 | int8_t iCoff; | 406 | int8_t iCoff; |
406 | int8_t qCoff; | 407 | int8_t qCoff; |
@@ -834,6 +835,7 @@ struct ath_hw { | |||
834 | int coarse_low[5]; | 835 | int coarse_low[5]; |
835 | int firpwr[5]; | 836 | int firpwr[5]; |
836 | enum ath9k_ani_cmd ani_function; | 837 | enum ath9k_ani_cmd ani_function; |
838 | u32 ani_skip_count; | ||
837 | 839 | ||
838 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 840 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
839 | struct ath_btcoex_hw btcoex_hw; | 841 | struct ath_btcoex_hw btcoex_hw; |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index fad3ccd5cd91..546bae93647b 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -687,6 +687,7 @@ static const struct ieee80211_iface_combination if_comb = { | |||
687 | .n_limits = ARRAY_SIZE(if_limits), | 687 | .n_limits = ARRAY_SIZE(if_limits), |
688 | .max_interfaces = 2048, | 688 | .max_interfaces = 2048, |
689 | .num_different_channels = 1, | 689 | .num_different_channels = 1, |
690 | .beacon_int_infra_match = true, | ||
690 | }; | 691 | }; |
691 | 692 | ||
692 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | 693 | void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) |
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index 7b88b9c39ccd..223b9693527e 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c | |||
@@ -350,8 +350,18 @@ void ath_ani_calibrate(unsigned long data) | |||
350 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; | 350 | ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; |
351 | 351 | ||
352 | /* Only calibrate if awake */ | 352 | /* Only calibrate if awake */ |
353 | if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) | 353 | if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) { |
354 | if (++ah->ani_skip_count >= ATH_ANI_MAX_SKIP_COUNT) { | ||
355 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
356 | sc->ps_flags |= PS_WAIT_FOR_ANI; | ||
357 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
358 | } | ||
354 | goto set_timer; | 359 | goto set_timer; |
360 | } | ||
361 | ah->ani_skip_count = 0; | ||
362 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | ||
363 | sc->ps_flags &= ~PS_WAIT_FOR_ANI; | ||
364 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | ||
355 | 365 | ||
356 | ath9k_ps_wakeup(sc); | 366 | ath9k_ps_wakeup(sc); |
357 | 367 | ||
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index dd45edfa6bae..578a7234aa56 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -131,7 +131,8 @@ void ath9k_ps_restore(struct ath_softc *sc) | |||
131 | !(sc->ps_flags & (PS_WAIT_FOR_BEACON | | 131 | !(sc->ps_flags & (PS_WAIT_FOR_BEACON | |
132 | PS_WAIT_FOR_CAB | | 132 | PS_WAIT_FOR_CAB | |
133 | PS_WAIT_FOR_PSPOLL_DATA | | 133 | PS_WAIT_FOR_PSPOLL_DATA | |
134 | PS_WAIT_FOR_TX_ACK))) { | 134 | PS_WAIT_FOR_TX_ACK | |
135 | PS_WAIT_FOR_ANI))) { | ||
135 | mode = ATH9K_PM_NETWORK_SLEEP; | 136 | mode = ATH9K_PM_NETWORK_SLEEP; |
136 | if (ath9k_hw_btcoex_is_enabled(sc->sc_ah)) | 137 | if (ath9k_hw_btcoex_is_enabled(sc->sc_ah)) |
137 | ath9k_btcoex_stop_gen_timer(sc); | 138 | ath9k_btcoex_stop_gen_timer(sc); |
@@ -292,6 +293,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, | |||
292 | goto out; | 293 | goto out; |
293 | } | 294 | } |
294 | 295 | ||
296 | if (ath9k_hw_mci_is_enabled(sc->sc_ah) && | ||
297 | (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) | ||
298 | ath9k_mci_set_txpower(sc, true, false); | ||
299 | |||
295 | if (!ath_complete_reset(sc, true)) | 300 | if (!ath_complete_reset(sc, true)) |
296 | r = -EIO; | 301 | r = -EIO; |
297 | 302 | ||
@@ -1449,6 +1454,9 @@ static void ath9k_set_assoc_state(struct ath_softc *sc, | |||
1449 | sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; | 1454 | sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON; |
1450 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 1455 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
1451 | 1456 | ||
1457 | if (ath9k_hw_mci_is_enabled(sc->sc_ah)) | ||
1458 | ath9k_mci_update_wlan_channels(sc, false); | ||
1459 | |||
1452 | ath_dbg(common, CONFIG, | 1460 | ath_dbg(common, CONFIG, |
1453 | "Primary Station interface: %pM, BSSID: %pM\n", | 1461 | "Primary Station interface: %pM, BSSID: %pM\n", |
1454 | vif->addr, common->curbssid); | 1462 | vif->addr, common->curbssid); |
@@ -1505,6 +1513,8 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
1505 | memset(common->curbssid, 0, ETH_ALEN); | 1513 | memset(common->curbssid, 0, ETH_ALEN); |
1506 | common->curaid = 0; | 1514 | common->curaid = 0; |
1507 | ath9k_hw_write_associd(sc->sc_ah); | 1515 | ath9k_hw_write_associd(sc->sc_ah); |
1516 | if (ath9k_hw_mci_is_enabled(sc->sc_ah)) | ||
1517 | ath9k_mci_update_wlan_channels(sc, true); | ||
1508 | } | 1518 | } |
1509 | } | 1519 | } |
1510 | 1520 | ||
diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index ec2d7c807567..0dd2cbb52d65 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c | |||
@@ -43,6 +43,7 @@ static bool ath_mci_add_profile(struct ath_common *common, | |||
43 | struct ath_mci_profile_info *info) | 43 | struct ath_mci_profile_info *info) |
44 | { | 44 | { |
45 | struct ath_mci_profile_info *entry; | 45 | struct ath_mci_profile_info *entry; |
46 | u8 voice_priority[] = { 110, 110, 110, 112, 110, 110, 114, 116, 118 }; | ||
46 | 47 | ||
47 | if ((mci->num_sco == ATH_MCI_MAX_SCO_PROFILE) && | 48 | if ((mci->num_sco == ATH_MCI_MAX_SCO_PROFILE) && |
48 | (info->type == MCI_GPM_COEX_PROFILE_VOICE)) | 49 | (info->type == MCI_GPM_COEX_PROFILE_VOICE)) |
@@ -59,6 +60,12 @@ static bool ath_mci_add_profile(struct ath_common *common, | |||
59 | memcpy(entry, info, 10); | 60 | memcpy(entry, info, 10); |
60 | INC_PROF(mci, info); | 61 | INC_PROF(mci, info); |
61 | list_add_tail(&entry->list, &mci->info); | 62 | list_add_tail(&entry->list, &mci->info); |
63 | if (info->type == MCI_GPM_COEX_PROFILE_VOICE) { | ||
64 | if (info->voice_type < sizeof(voice_priority)) | ||
65 | mci->voice_priority = voice_priority[info->voice_type]; | ||
66 | else | ||
67 | mci->voice_priority = 110; | ||
68 | } | ||
62 | 69 | ||
63 | return true; | 70 | return true; |
64 | } | 71 | } |
@@ -150,7 +157,7 @@ static void ath_mci_update_scheme(struct ath_softc *sc) | |||
150 | * For single PAN/FTP profile, allocate 35% for BT | 157 | * For single PAN/FTP profile, allocate 35% for BT |
151 | * to improve WLAN throughput. | 158 | * to improve WLAN throughput. |
152 | */ | 159 | */ |
153 | btcoex->duty_cycle = 35; | 160 | btcoex->duty_cycle = AR_SREV_9565(sc->sc_ah) ? 40 : 35; |
154 | btcoex->btcoex_period = 53; | 161 | btcoex->btcoex_period = 53; |
155 | ath_dbg(common, MCI, | 162 | ath_dbg(common, MCI, |
156 | "Single PAN/FTP bt period %d ms dutycycle %d\n", | 163 | "Single PAN/FTP bt period %d ms dutycycle %d\n", |
@@ -250,6 +257,57 @@ static void ath9k_mci_work(struct work_struct *work) | |||
250 | ath_mci_update_scheme(sc); | 257 | ath_mci_update_scheme(sc); |
251 | } | 258 | } |
252 | 259 | ||
260 | static void ath_mci_update_stomp_txprio(u8 cur_txprio, u8 *stomp_prio) | ||
261 | { | ||
262 | if (cur_txprio < stomp_prio[ATH_BTCOEX_STOMP_NONE]) | ||
263 | stomp_prio[ATH_BTCOEX_STOMP_NONE] = cur_txprio; | ||
264 | |||
265 | if (cur_txprio > stomp_prio[ATH_BTCOEX_STOMP_ALL]) | ||
266 | stomp_prio[ATH_BTCOEX_STOMP_ALL] = cur_txprio; | ||
267 | |||
268 | if ((cur_txprio > ATH_MCI_HI_PRIO) && | ||
269 | (cur_txprio < stomp_prio[ATH_BTCOEX_STOMP_LOW])) | ||
270 | stomp_prio[ATH_BTCOEX_STOMP_LOW] = cur_txprio; | ||
271 | } | ||
272 | |||
273 | static void ath_mci_set_concur_txprio(struct ath_softc *sc) | ||
274 | { | ||
275 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
276 | struct ath_mci_profile *mci = &btcoex->mci; | ||
277 | u8 stomp_txprio[] = { 0, 0, 0, 0 }; /* all, low, none, low_ftp */ | ||
278 | |||
279 | if (mci->num_mgmt) { | ||
280 | stomp_txprio[ATH_BTCOEX_STOMP_ALL] = ATH_MCI_INQUIRY_PRIO; | ||
281 | if (!mci->num_pan && !mci->num_other_acl) | ||
282 | stomp_txprio[ATH_BTCOEX_STOMP_NONE] = | ||
283 | ATH_MCI_INQUIRY_PRIO; | ||
284 | } else { | ||
285 | u8 prof_prio[] = { 50, 90, 94, 52 };/* RFCOMM, A2DP, HID, PAN */ | ||
286 | |||
287 | stomp_txprio[ATH_BTCOEX_STOMP_LOW] = | ||
288 | stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0xff; | ||
289 | |||
290 | if (mci->num_sco) | ||
291 | ath_mci_update_stomp_txprio(mci->voice_priority, | ||
292 | stomp_txprio); | ||
293 | if (mci->num_other_acl) | ||
294 | ath_mci_update_stomp_txprio(prof_prio[0], stomp_txprio); | ||
295 | if (mci->num_a2dp) | ||
296 | ath_mci_update_stomp_txprio(prof_prio[1], stomp_txprio); | ||
297 | if (mci->num_hid) | ||
298 | ath_mci_update_stomp_txprio(prof_prio[2], stomp_txprio); | ||
299 | if (mci->num_pan) | ||
300 | ath_mci_update_stomp_txprio(prof_prio[3], stomp_txprio); | ||
301 | |||
302 | if (stomp_txprio[ATH_BTCOEX_STOMP_NONE] == 0xff) | ||
303 | stomp_txprio[ATH_BTCOEX_STOMP_NONE] = 0; | ||
304 | |||
305 | if (stomp_txprio[ATH_BTCOEX_STOMP_LOW] == 0xff) | ||
306 | stomp_txprio[ATH_BTCOEX_STOMP_LOW] = 0; | ||
307 | } | ||
308 | ath9k_hw_btcoex_set_concur_txprio(sc->sc_ah, stomp_txprio); | ||
309 | } | ||
310 | |||
253 | static u8 ath_mci_process_profile(struct ath_softc *sc, | 311 | static u8 ath_mci_process_profile(struct ath_softc *sc, |
254 | struct ath_mci_profile_info *info) | 312 | struct ath_mci_profile_info *info) |
255 | { | 313 | { |
@@ -281,6 +339,7 @@ static u8 ath_mci_process_profile(struct ath_softc *sc, | |||
281 | } else | 339 | } else |
282 | ath_mci_del_profile(common, mci, entry); | 340 | ath_mci_del_profile(common, mci, entry); |
283 | 341 | ||
342 | ath_mci_set_concur_txprio(sc); | ||
284 | return 1; | 343 | return 1; |
285 | } | 344 | } |
286 | 345 | ||
@@ -314,6 +373,7 @@ static u8 ath_mci_process_status(struct ath_softc *sc, | |||
314 | mci->num_mgmt++; | 373 | mci->num_mgmt++; |
315 | } while (++i < ATH_MCI_MAX_PROFILE); | 374 | } while (++i < ATH_MCI_MAX_PROFILE); |
316 | 375 | ||
376 | ath_mci_set_concur_txprio(sc); | ||
317 | if (old_num_mgmt != mci->num_mgmt) | 377 | if (old_num_mgmt != mci->num_mgmt) |
318 | return 1; | 378 | return 1; |
319 | 379 | ||
@@ -600,3 +660,112 @@ void ath_mci_enable(struct ath_softc *sc) | |||
600 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) | 660 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) |
601 | sc->sc_ah->imask |= ATH9K_INT_MCI; | 661 | sc->sc_ah->imask |= ATH9K_INT_MCI; |
602 | } | 662 | } |
663 | |||
664 | void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all) | ||
665 | { | ||
666 | struct ath_hw *ah = sc->sc_ah; | ||
667 | struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; | ||
668 | struct ath9k_channel *chan = ah->curchan; | ||
669 | u32 channelmap[] = {0x00000000, 0xffff0000, 0xffffffff, 0x7fffffff}; | ||
670 | int i; | ||
671 | s16 chan_start, chan_end; | ||
672 | u16 wlan_chan; | ||
673 | |||
674 | if (!chan || !IS_CHAN_2GHZ(chan)) | ||
675 | return; | ||
676 | |||
677 | if (allow_all) | ||
678 | goto send_wlan_chan; | ||
679 | |||
680 | wlan_chan = chan->channel - 2402; | ||
681 | |||
682 | chan_start = wlan_chan - 10; | ||
683 | chan_end = wlan_chan + 10; | ||
684 | |||
685 | if (chan->chanmode == CHANNEL_G_HT40PLUS) | ||
686 | chan_end += 20; | ||
687 | else if (chan->chanmode == CHANNEL_G_HT40MINUS) | ||
688 | chan_start -= 20; | ||
689 | |||
690 | /* adjust side band */ | ||
691 | chan_start -= 7; | ||
692 | chan_end += 7; | ||
693 | |||
694 | if (chan_start <= 0) | ||
695 | chan_start = 0; | ||
696 | if (chan_end >= ATH_MCI_NUM_BT_CHANNELS) | ||
697 | chan_end = ATH_MCI_NUM_BT_CHANNELS - 1; | ||
698 | |||
699 | ath_dbg(ath9k_hw_common(ah), MCI, | ||
700 | "WLAN current channel %d mask BT channel %d - %d\n", | ||
701 | wlan_chan, chan_start, chan_end); | ||
702 | |||
703 | for (i = chan_start; i < chan_end; i++) | ||
704 | MCI_GPM_CLR_CHANNEL_BIT(&channelmap, i); | ||
705 | |||
706 | send_wlan_chan: | ||
707 | /* update and send wlan channels info to BT */ | ||
708 | for (i = 0; i < 4; i++) | ||
709 | mci->wlan_channels[i] = channelmap[i]; | ||
710 | ar9003_mci_send_wlan_channels(ah); | ||
711 | ar9003_mci_state(ah, MCI_STATE_SEND_VERSION_QUERY); | ||
712 | } | ||
713 | |||
714 | void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel, | ||
715 | bool concur_tx) | ||
716 | { | ||
717 | struct ath_hw *ah = sc->sc_ah; | ||
718 | struct ath9k_hw_mci *mci_hw = &sc->sc_ah->btcoex_hw.mci; | ||
719 | bool old_concur_tx = mci_hw->concur_tx; | ||
720 | |||
721 | if (!(mci_hw->config & ATH_MCI_CONFIG_CONCUR_TX)) { | ||
722 | mci_hw->concur_tx = false; | ||
723 | return; | ||
724 | } | ||
725 | |||
726 | if (!IS_CHAN_2GHZ(ah->curchan)) | ||
727 | return; | ||
728 | |||
729 | if (setchannel) { | ||
730 | struct ath9k_hw_cal_data *caldata = &sc->caldata; | ||
731 | if ((caldata->chanmode == CHANNEL_G_HT40PLUS) && | ||
732 | (ah->curchan->channel > caldata->channel) && | ||
733 | (ah->curchan->channel <= caldata->channel + 20)) | ||
734 | return; | ||
735 | if ((caldata->chanmode == CHANNEL_G_HT40MINUS) && | ||
736 | (ah->curchan->channel < caldata->channel) && | ||
737 | (ah->curchan->channel >= caldata->channel - 20)) | ||
738 | return; | ||
739 | mci_hw->concur_tx = false; | ||
740 | } else | ||
741 | mci_hw->concur_tx = concur_tx; | ||
742 | |||
743 | if (old_concur_tx != mci_hw->concur_tx) | ||
744 | ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false); | ||
745 | } | ||
746 | |||
747 | void ath9k_mci_update_rssi(struct ath_softc *sc) | ||
748 | { | ||
749 | struct ath_hw *ah = sc->sc_ah; | ||
750 | struct ath_btcoex *btcoex = &sc->btcoex; | ||
751 | struct ath9k_hw_mci *mci_hw = &sc->sc_ah->btcoex_hw.mci; | ||
752 | |||
753 | if (!(mci_hw->config & ATH_MCI_CONFIG_CONCUR_TX)) | ||
754 | return; | ||
755 | |||
756 | if (ah->stats.avgbrssi >= 40) { | ||
757 | if (btcoex->rssi_count < 0) | ||
758 | btcoex->rssi_count = 0; | ||
759 | if (++btcoex->rssi_count >= ATH_MCI_CONCUR_TX_SWITCH) { | ||
760 | btcoex->rssi_count = 0; | ||
761 | ath9k_mci_set_txpower(sc, false, true); | ||
762 | } | ||
763 | } else { | ||
764 | if (btcoex->rssi_count > 0) | ||
765 | btcoex->rssi_count = 0; | ||
766 | if (--btcoex->rssi_count <= -ATH_MCI_CONCUR_TX_SWITCH) { | ||
767 | btcoex->rssi_count = 0; | ||
768 | ath9k_mci_set_txpower(sc, false, false); | ||
769 | } | ||
770 | } | ||
771 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/mci.h b/drivers/net/wireless/ath/ath9k/mci.h index fc14eea034eb..06958837620c 100644 --- a/drivers/net/wireless/ath/ath9k/mci.h +++ b/drivers/net/wireless/ath/ath9k/mci.h | |||
@@ -32,6 +32,27 @@ | |||
32 | #define ATH_MCI_MAX_PROFILE (ATH_MCI_MAX_ACL_PROFILE +\ | 32 | #define ATH_MCI_MAX_PROFILE (ATH_MCI_MAX_ACL_PROFILE +\ |
33 | ATH_MCI_MAX_SCO_PROFILE) | 33 | ATH_MCI_MAX_SCO_PROFILE) |
34 | 34 | ||
35 | #define ATH_MCI_INQUIRY_PRIO 62 | ||
36 | #define ATH_MCI_HI_PRIO 60 | ||
37 | #define ATH_MCI_NUM_BT_CHANNELS 79 | ||
38 | #define ATH_MCI_CONCUR_TX_SWITCH 5 | ||
39 | |||
40 | #define MCI_GPM_SET_CHANNEL_BIT(_p_gpm, _bt_chan) \ | ||
41 | do { \ | ||
42 | if (_bt_chan < ATH_MCI_NUM_BT_CHANNELS) { \ | ||
43 | *(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_CHANNEL_MAP + \ | ||
44 | (_bt_chan / 8)) |= (1 << (_bt_chan & 7)); \ | ||
45 | } \ | ||
46 | } while (0) | ||
47 | |||
48 | #define MCI_GPM_CLR_CHANNEL_BIT(_p_gpm, _bt_chan) \ | ||
49 | do { \ | ||
50 | if (_bt_chan < ATH_MCI_NUM_BT_CHANNELS) { \ | ||
51 | *(((u8 *)(_p_gpm)) + MCI_GPM_COEX_B_CHANNEL_MAP + \ | ||
52 | (_bt_chan / 8)) &= ~(1 << (_bt_chan & 7));\ | ||
53 | } \ | ||
54 | } while (0) | ||
55 | |||
35 | #define INC_PROF(_mci, _info) do { \ | 56 | #define INC_PROF(_mci, _info) do { \ |
36 | switch (_info->type) { \ | 57 | switch (_info->type) { \ |
37 | case MCI_GPM_COEX_PROFILE_RFCOMM:\ | 58 | case MCI_GPM_COEX_PROFILE_RFCOMM:\ |
@@ -49,6 +70,7 @@ | |||
49 | _mci->num_pan++; \ | 70 | _mci->num_pan++; \ |
50 | break; \ | 71 | break; \ |
51 | case MCI_GPM_COEX_PROFILE_VOICE: \ | 72 | case MCI_GPM_COEX_PROFILE_VOICE: \ |
73 | case MCI_GPM_COEX_PROFILE_A2DPVO:\ | ||
52 | _mci->num_sco++; \ | 74 | _mci->num_sco++; \ |
53 | break; \ | 75 | break; \ |
54 | default: \ | 76 | default: \ |
@@ -73,6 +95,7 @@ | |||
73 | _mci->num_pan--; \ | 95 | _mci->num_pan--; \ |
74 | break; \ | 96 | break; \ |
75 | case MCI_GPM_COEX_PROFILE_VOICE: \ | 97 | case MCI_GPM_COEX_PROFILE_VOICE: \ |
98 | case MCI_GPM_COEX_PROFILE_A2DPVO:\ | ||
76 | _mci->num_sco--; \ | 99 | _mci->num_sco--; \ |
77 | break; \ | 100 | break; \ |
78 | default: \ | 101 | default: \ |
@@ -113,6 +136,7 @@ struct ath_mci_profile { | |||
113 | u8 num_pan; | 136 | u8 num_pan; |
114 | u8 num_other_acl; | 137 | u8 num_other_acl; |
115 | u8 num_bdr; | 138 | u8 num_bdr; |
139 | u8 voice_priority; | ||
116 | }; | 140 | }; |
117 | 141 | ||
118 | struct ath_mci_buf { | 142 | struct ath_mci_buf { |
@@ -130,13 +154,25 @@ void ath_mci_flush_profile(struct ath_mci_profile *mci); | |||
130 | int ath_mci_setup(struct ath_softc *sc); | 154 | int ath_mci_setup(struct ath_softc *sc); |
131 | void ath_mci_cleanup(struct ath_softc *sc); | 155 | void ath_mci_cleanup(struct ath_softc *sc); |
132 | void ath_mci_intr(struct ath_softc *sc); | 156 | void ath_mci_intr(struct ath_softc *sc); |
157 | void ath9k_mci_update_rssi(struct ath_softc *sc); | ||
133 | 158 | ||
134 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT | 159 | #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT |
135 | void ath_mci_enable(struct ath_softc *sc); | 160 | void ath_mci_enable(struct ath_softc *sc); |
161 | void ath9k_mci_update_wlan_channels(struct ath_softc *sc, bool allow_all); | ||
162 | void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel, | ||
163 | bool concur_tx); | ||
136 | #else | 164 | #else |
137 | static inline void ath_mci_enable(struct ath_softc *sc) | 165 | static inline void ath_mci_enable(struct ath_softc *sc) |
138 | { | 166 | { |
139 | } | 167 | } |
168 | static inline void ath9k_mci_update_wlan_channels(struct ath_softc *sc, | ||
169 | bool allow_all) | ||
170 | { | ||
171 | } | ||
172 | static inline void ath9k_mci_set_txpower(struct ath_softc *sc, bool setchannel, | ||
173 | bool concur_tx) | ||
174 | { | ||
175 | } | ||
140 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ | 176 | #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */ |
141 | 177 | ||
142 | #endif /* MCI_H*/ | 178 | #endif /* MCI_H*/ |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 83d16e7ed272..a04028bce28b 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -1105,7 +1105,10 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1105 | else | 1105 | else |
1106 | rs.is_mybeacon = false; | 1106 | rs.is_mybeacon = false; |
1107 | 1107 | ||
1108 | sc->rx.num_pkts++; | 1108 | if (ieee80211_is_data_present(hdr->frame_control) && |
1109 | !ieee80211_is_qos_nullfunc(hdr->frame_control)) | ||
1110 | sc->rx.num_pkts++; | ||
1111 | |||
1109 | ath_debug_stat_rx(sc, &rs); | 1112 | ath_debug_stat_rx(sc, &rs); |
1110 | 1113 | ||
1111 | /* | 1114 | /* |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 4e6760f8596d..ad3c82c09177 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -907,10 +907,6 @@ | |||
907 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ | 907 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ |
908 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20)) | 908 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20)) |
909 | 909 | ||
910 | #define AR_SREV_9462_20_OR_LATER(_ah) \ | ||
911 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ | ||
912 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20)) | ||
913 | |||
914 | #define AR_SREV_9565(_ah) \ | 910 | #define AR_SREV_9565(_ah) \ |
915 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565)) | 911 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565)) |
916 | 912 | ||
@@ -2315,6 +2311,8 @@ enum { | |||
2315 | #define AR_BTCOEX_MAX_TXPWR(_x) (0x18c0 + ((_x) << 2)) | 2311 | #define AR_BTCOEX_MAX_TXPWR(_x) (0x18c0 + ((_x) << 2)) |
2316 | #define AR_BTCOEX_WL_LNA 0x1940 | 2312 | #define AR_BTCOEX_WL_LNA 0x1940 |
2317 | #define AR_BTCOEX_RFGAIN_CTRL 0x1944 | 2313 | #define AR_BTCOEX_RFGAIN_CTRL 0x1944 |
2314 | #define AR_BTCOEX_WL_LNA_TIMEOUT 0x003FFFFF | ||
2315 | #define AR_BTCOEX_WL_LNA_TIMEOUT_S 0 | ||
2318 | 2316 | ||
2319 | #define AR_BTCOEX_CTRL2 0x1948 | 2317 | #define AR_BTCOEX_CTRL2 0x1948 |
2320 | #define AR_BTCOEX_CTRL2_TXPWR_THRESH 0x0007F800 | 2318 | #define AR_BTCOEX_CTRL2_TXPWR_THRESH 0x0007F800 |
@@ -2360,4 +2358,11 @@ enum { | |||
2360 | #define AR_GLB_SWREG_DISCONT_MODE 0x2002c | 2358 | #define AR_GLB_SWREG_DISCONT_MODE 0x2002c |
2361 | #define AR_GLB_SWREG_DISCONT_EN_BT_WLAN 0x3 | 2359 | #define AR_GLB_SWREG_DISCONT_EN_BT_WLAN 0x3 |
2362 | 2360 | ||
2361 | #define AR_MCI_MISC 0x1a74 | ||
2362 | #define AR_MCI_MISC_HW_FIX_EN 0x00000001 | ||
2363 | #define AR_MCI_MISC_HW_FIX_EN_S 0 | ||
2364 | #define AR_MCI_DBG_CNT_CTRL 0x1a78 | ||
2365 | #define AR_MCI_DBG_CNT_CTRL_ENABLE 0x00000001 | ||
2366 | #define AR_MCI_DBG_CNT_CTRL_ENABLE_S 0 | ||
2367 | |||
2363 | #endif | 2368 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c index a483d518758c..9f8563091bea 100644 --- a/drivers/net/wireless/ath/ath9k/wow.c +++ b/drivers/net/wireless/ath/ath9k/wow.c | |||
@@ -118,7 +118,7 @@ static void ath9k_wow_create_keep_alive_pattern(struct ath_hw *ah) | |||
118 | (ap_mac_addr[1] << 8) | (ap_mac_addr[0]); | 118 | (ap_mac_addr[1] << 8) | (ap_mac_addr[0]); |
119 | data_word[5] = (ap_mac_addr[5] << 8) | (ap_mac_addr[4]); | 119 | data_word[5] = (ap_mac_addr[5] << 8) | (ap_mac_addr[4]); |
120 | 120 | ||
121 | if (AR_SREV_9462_20_OR_LATER(ah)) { | 121 | if (AR_SREV_9462_20(ah)) { |
122 | /* AR9462 2.0 has an extra descriptor word (time based | 122 | /* AR9462 2.0 has an extra descriptor word (time based |
123 | * discard) compared to other chips */ | 123 | * discard) compared to other chips */ |
124 | REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0); | 124 | REG_WRITE(ah, (AR_WOW_KA_DESC_WORD2 + (12 * 4)), 0); |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 378bd70256b2..1ffca7511fa8 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -312,6 +312,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) | |||
312 | } | 312 | } |
313 | 313 | ||
314 | bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); | 314 | bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); |
315 | bf->bf_next = NULL; | ||
315 | list_del(&bf->list); | 316 | list_del(&bf->list); |
316 | 317 | ||
317 | spin_unlock_bh(&sc->tx.txbuflock); | 318 | spin_unlock_bh(&sc->tx.txbuflock); |
@@ -1774,6 +1775,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, | |||
1774 | list_add_tail(&bf->list, &bf_head); | 1775 | list_add_tail(&bf->list, &bf_head); |
1775 | bf->bf_state.bf_type = 0; | 1776 | bf->bf_state.bf_type = 0; |
1776 | 1777 | ||
1778 | bf->bf_next = NULL; | ||
1777 | bf->bf_lastbf = bf; | 1779 | bf->bf_lastbf = bf; |
1778 | ath_tx_fill_desc(sc, bf, txq, fi->framelen); | 1780 | ath_tx_fill_desc(sc, bf, txq, fi->framelen); |
1779 | ath_tx_txqaddbuf(sc, txq, &bf_head, false); | 1781 | ath_tx_txqaddbuf(sc, txq, &bf_head, false); |
diff --git a/drivers/net/wireless/ath/carl9170/mac.c b/drivers/net/wireless/ath/carl9170/mac.c index e3b1b6e87760..24d75ab94f0d 100644 --- a/drivers/net/wireless/ath/carl9170/mac.c +++ b/drivers/net/wireless/ath/carl9170/mac.c | |||
@@ -343,7 +343,24 @@ int carl9170_set_operating_mode(struct ar9170 *ar) | |||
343 | break; | 343 | break; |
344 | } | 344 | } |
345 | } else { | 345 | } else { |
346 | mac_addr = NULL; | 346 | /* |
347 | * Enable monitor mode | ||
348 | * | ||
349 | * rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER; | ||
350 | * sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC; | ||
351 | * | ||
352 | * When the hardware is in SNIFFER_PROMISC mode, | ||
353 | * it generates spurious ACKs for every incoming | ||
354 | * frame. This confuses every peer in the | ||
355 | * vicinity and the network throughput will suffer | ||
356 | * badly. | ||
357 | * | ||
358 | * Hence, the hardware will be put into station | ||
359 | * mode and just the rx filters are disabled. | ||
360 | */ | ||
361 | cam_mode |= AR9170_MAC_CAM_STA; | ||
362 | rx_ctrl |= AR9170_MAC_RX_CTRL_PASS_TO_HOST; | ||
363 | mac_addr = common->macaddr; | ||
347 | bssid = NULL; | 364 | bssid = NULL; |
348 | } | 365 | } |
349 | rcu_read_unlock(); | 366 | rcu_read_unlock(); |
@@ -355,8 +372,6 @@ int carl9170_set_operating_mode(struct ar9170 *ar) | |||
355 | enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE; | 372 | enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE; |
356 | 373 | ||
357 | if (ar->sniffer_enabled) { | 374 | if (ar->sniffer_enabled) { |
358 | rx_ctrl |= AR9170_MAC_RX_CTRL_ACK_IN_SNIFFER; | ||
359 | sniffer |= AR9170_MAC_SNIFFER_ENABLE_PROMISC; | ||
360 | enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE; | 375 | enc_mode |= AR9170_MAC_ENCRYPTION_RX_SOFTWARE; |
361 | } | 376 | } |
362 | 377 | ||
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index a0b723078547..6d22382875bc 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c | |||
@@ -164,9 +164,6 @@ void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) | |||
164 | struct carl9170_rsp *cmd = buf; | 164 | struct carl9170_rsp *cmd = buf; |
165 | struct ieee80211_vif *vif; | 165 | struct ieee80211_vif *vif; |
166 | 166 | ||
167 | if (carl9170_check_sequence(ar, cmd->hdr.seq)) | ||
168 | return; | ||
169 | |||
170 | if ((cmd->hdr.cmd & CARL9170_RSP_FLAG) != CARL9170_RSP_FLAG) { | 167 | if ((cmd->hdr.cmd & CARL9170_RSP_FLAG) != CARL9170_RSP_FLAG) { |
171 | if (!(cmd->hdr.cmd & CARL9170_CMD_ASYNC_FLAG)) | 168 | if (!(cmd->hdr.cmd & CARL9170_CMD_ASYNC_FLAG)) |
172 | carl9170_cmd_callback(ar, len, buf); | 169 | carl9170_cmd_callback(ar, len, buf); |
@@ -663,6 +660,35 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms, | |||
663 | return false; | 660 | return false; |
664 | } | 661 | } |
665 | 662 | ||
663 | static int carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len, | ||
664 | struct ieee80211_rx_status *status) | ||
665 | { | ||
666 | struct sk_buff *skb; | ||
667 | |||
668 | /* (driver) frame trap handler | ||
669 | * | ||
670 | * Because power-saving mode handing has to be implemented by | ||
671 | * the driver/firmware. We have to check each incoming beacon | ||
672 | * from the associated AP, if there's new data for us (either | ||
673 | * broadcast/multicast or unicast) we have to react quickly. | ||
674 | * | ||
675 | * So, if you have you want to add additional frame trap | ||
676 | * handlers, this would be the perfect place! | ||
677 | */ | ||
678 | |||
679 | carl9170_ps_beacon(ar, buf, len); | ||
680 | |||
681 | carl9170_ba_check(ar, buf, len); | ||
682 | |||
683 | skb = carl9170_rx_copy_data(buf, len); | ||
684 | if (!skb) | ||
685 | return -ENOMEM; | ||
686 | |||
687 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | ||
688 | ieee80211_rx(ar->hw, skb); | ||
689 | return 0; | ||
690 | } | ||
691 | |||
666 | /* | 692 | /* |
667 | * If the frame alignment is right (or the kernel has | 693 | * If the frame alignment is right (or the kernel has |
668 | * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there | 694 | * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there |
@@ -672,14 +698,12 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms, | |||
672 | * mode, and we need to observe the proper ordering, | 698 | * mode, and we need to observe the proper ordering, |
673 | * this is non-trivial. | 699 | * this is non-trivial. |
674 | */ | 700 | */ |
675 | 701 | static void carl9170_rx_untie_data(struct ar9170 *ar, u8 *buf, int len) | |
676 | static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) | ||
677 | { | 702 | { |
678 | struct ar9170_rx_head *head; | 703 | struct ar9170_rx_head *head; |
679 | struct ar9170_rx_macstatus *mac; | 704 | struct ar9170_rx_macstatus *mac; |
680 | struct ar9170_rx_phystatus *phy = NULL; | 705 | struct ar9170_rx_phystatus *phy = NULL; |
681 | struct ieee80211_rx_status status; | 706 | struct ieee80211_rx_status status; |
682 | struct sk_buff *skb; | ||
683 | int mpdu_len; | 707 | int mpdu_len; |
684 | u8 mac_status; | 708 | u8 mac_status; |
685 | 709 | ||
@@ -791,18 +815,10 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) | |||
791 | if (phy) | 815 | if (phy) |
792 | carl9170_rx_phy_status(ar, phy, &status); | 816 | carl9170_rx_phy_status(ar, phy, &status); |
793 | 817 | ||
794 | carl9170_ps_beacon(ar, buf, mpdu_len); | 818 | if (carl9170_handle_mpdu(ar, buf, mpdu_len, &status)) |
795 | |||
796 | carl9170_ba_check(ar, buf, mpdu_len); | ||
797 | |||
798 | skb = carl9170_rx_copy_data(buf, mpdu_len); | ||
799 | if (!skb) | ||
800 | goto drop; | 819 | goto drop; |
801 | 820 | ||
802 | memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); | ||
803 | ieee80211_rx(ar->hw, skb); | ||
804 | return; | 821 | return; |
805 | |||
806 | drop: | 822 | drop: |
807 | ar->rx_dropped++; | 823 | ar->rx_dropped++; |
808 | } | 824 | } |
@@ -820,6 +836,9 @@ static void carl9170_rx_untie_cmds(struct ar9170 *ar, const u8 *respbuf, | |||
820 | if (unlikely(i > resplen)) | 836 | if (unlikely(i > resplen)) |
821 | break; | 837 | break; |
822 | 838 | ||
839 | if (carl9170_check_sequence(ar, cmd->hdr.seq)) | ||
840 | break; | ||
841 | |||
823 | carl9170_handle_command_response(ar, cmd, cmd->hdr.len + 4); | 842 | carl9170_handle_command_response(ar, cmd, cmd->hdr.len + 4); |
824 | } | 843 | } |
825 | 844 | ||
@@ -851,7 +870,7 @@ static void __carl9170_rx(struct ar9170 *ar, u8 *buf, unsigned int len) | |||
851 | if (i == 12) | 870 | if (i == 12) |
852 | carl9170_rx_untie_cmds(ar, buf, len); | 871 | carl9170_rx_untie_cmds(ar, buf, len); |
853 | else | 872 | else |
854 | carl9170_handle_mpdu(ar, buf, len); | 873 | carl9170_rx_untie_data(ar, buf, len); |
855 | } | 874 | } |
856 | 875 | ||
857 | static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len) | 876 | static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len) |
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c index 888152ce3eca..307bc0ddff99 100644 --- a/drivers/net/wireless/ath/carl9170/usb.c +++ b/drivers/net/wireless/ath/carl9170/usb.c | |||
@@ -295,6 +295,13 @@ static void carl9170_usb_rx_irq_complete(struct urb *urb) | |||
295 | goto resubmit; | 295 | goto resubmit; |
296 | } | 296 | } |
297 | 297 | ||
298 | /* | ||
299 | * While the carl9170 firmware does not use this EP, the | ||
300 | * firmware loader in the EEPROM unfortunately does. | ||
301 | * Therefore we need to be ready to handle out-of-band | ||
302 | * responses and traps in case the firmware crashed and | ||
303 | * the loader took over again. | ||
304 | */ | ||
298 | carl9170_handle_command_response(ar, urb->transfer_buffer, | 305 | carl9170_handle_command_response(ar, urb->transfer_buffer, |
299 | urb->actual_length); | 306 | urb->actual_length); |
300 | 307 | ||
diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c index 19befb331073..39e8a590d7fc 100644 --- a/drivers/net/wireless/ath/hw.c +++ b/drivers/net/wireless/ath/hw.c | |||
@@ -20,8 +20,8 @@ | |||
20 | #include "ath.h" | 20 | #include "ath.h" |
21 | #include "reg.h" | 21 | #include "reg.h" |
22 | 22 | ||
23 | #define REG_READ (common->ops->read) | 23 | #define REG_READ (common->ops->read) |
24 | #define REG_WRITE (common->ops->write) | 24 | #define REG_WRITE(_ah, _reg, _val) (common->ops->write)(_ah, _val, _reg) |
25 | 25 | ||
26 | /** | 26 | /** |
27 | * ath_hw_set_bssid_mask - filter out bssids we listen | 27 | * ath_hw_set_bssid_mask - filter out bssids we listen |
@@ -119,8 +119,8 @@ void ath_hw_setbssidmask(struct ath_common *common) | |||
119 | { | 119 | { |
120 | void *ah = common->ah; | 120 | void *ah = common->ah; |
121 | 121 | ||
122 | REG_WRITE(ah, get_unaligned_le32(common->bssidmask), AR_BSSMSKL); | 122 | REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(common->bssidmask)); |
123 | REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU); | 123 | REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(common->bssidmask + 4)); |
124 | } | 124 | } |
125 | EXPORT_SYMBOL(ath_hw_setbssidmask); | 125 | EXPORT_SYMBOL(ath_hw_setbssidmask); |
126 | 126 | ||
@@ -139,7 +139,7 @@ void ath_hw_cycle_counters_update(struct ath_common *common) | |||
139 | void *ah = common->ah; | 139 | void *ah = common->ah; |
140 | 140 | ||
141 | /* freeze */ | 141 | /* freeze */ |
142 | REG_WRITE(ah, AR_MIBC_FMC, AR_MIBC); | 142 | REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC); |
143 | 143 | ||
144 | /* read */ | 144 | /* read */ |
145 | cycles = REG_READ(ah, AR_CCCNT); | 145 | cycles = REG_READ(ah, AR_CCCNT); |
@@ -148,13 +148,13 @@ void ath_hw_cycle_counters_update(struct ath_common *common) | |||
148 | tx = REG_READ(ah, AR_TFCNT); | 148 | tx = REG_READ(ah, AR_TFCNT); |
149 | 149 | ||
150 | /* clear */ | 150 | /* clear */ |
151 | REG_WRITE(ah, 0, AR_CCCNT); | 151 | REG_WRITE(ah, AR_CCCNT, 0); |
152 | REG_WRITE(ah, 0, AR_RFCNT); | 152 | REG_WRITE(ah, AR_RFCNT, 0); |
153 | REG_WRITE(ah, 0, AR_RCCNT); | 153 | REG_WRITE(ah, AR_RCCNT, 0); |
154 | REG_WRITE(ah, 0, AR_TFCNT); | 154 | REG_WRITE(ah, AR_TFCNT, 0); |
155 | 155 | ||
156 | /* unfreeze */ | 156 | /* unfreeze */ |
157 | REG_WRITE(ah, 0, AR_MIBC); | 157 | REG_WRITE(ah, AR_MIBC, 0); |
158 | 158 | ||
159 | /* update all cycle counters here */ | 159 | /* update all cycle counters here */ |
160 | common->cc_ani.cycles += cycles; | 160 | common->cc_ani.cycles += cycles; |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 73730e94e0ac..ddd6a4f78097 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -4652,7 +4652,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev) | |||
4652 | switch (dev->dev->bus_type) { | 4652 | switch (dev->dev->bus_type) { |
4653 | #ifdef CONFIG_B43_BCMA | 4653 | #ifdef CONFIG_B43_BCMA |
4654 | case B43_BUS_BCMA: | 4654 | case B43_BUS_BCMA: |
4655 | bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci, | 4655 | bcma_core_pci_irq_ctl(&dev->dev->bdev->bus->drv_pci[0], |
4656 | dev->dev->bdev, true); | 4656 | dev->dev->bdev, true); |
4657 | break; | 4657 | break; |
4658 | #endif | 4658 | #endif |
@@ -5404,6 +5404,8 @@ static void b43_bcma_remove(struct bcma_device *core) | |||
5404 | cancel_work_sync(&wldev->restart_work); | 5404 | cancel_work_sync(&wldev->restart_work); |
5405 | 5405 | ||
5406 | B43_WARN_ON(!wl); | 5406 | B43_WARN_ON(!wl); |
5407 | if (!wldev->fw.ucode.data) | ||
5408 | return; /* NULL if firmware never loaded */ | ||
5407 | if (wl->current_dev == wldev && wl->hw_registred) { | 5409 | if (wl->current_dev == wldev && wl->hw_registred) { |
5408 | b43_leds_stop(wldev); | 5410 | b43_leds_stop(wldev); |
5409 | ieee80211_unregister_hw(wl->hw); | 5411 | ieee80211_unregister_hw(wl->hw); |
@@ -5478,6 +5480,8 @@ static void b43_ssb_remove(struct ssb_device *sdev) | |||
5478 | cancel_work_sync(&wldev->restart_work); | 5480 | cancel_work_sync(&wldev->restart_work); |
5479 | 5481 | ||
5480 | B43_WARN_ON(!wl); | 5482 | B43_WARN_ON(!wl); |
5483 | if (!wldev->fw.ucode.data) | ||
5484 | return; /* NULL if firmware never loaded */ | ||
5481 | if (wl->current_dev == wldev && wl->hw_registred) { | 5485 | if (wl->current_dev == wldev && wl->hw_registred) { |
5482 | b43_leds_stop(wldev); | 5486 | b43_leds_stop(wldev); |
5483 | ieee80211_unregister_hw(wl->hw); | 5487 | ieee80211_unregister_hw(wl->hw); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile index 9d5170b6df50..fe80b637c519 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile | |||
@@ -24,6 +24,7 @@ ccflags-y += -D__CHECK_ENDIAN__ | |||
24 | obj-$(CONFIG_BRCMFMAC) += brcmfmac.o | 24 | obj-$(CONFIG_BRCMFMAC) += brcmfmac.o |
25 | brcmfmac-objs += \ | 25 | brcmfmac-objs += \ |
26 | wl_cfg80211.o \ | 26 | wl_cfg80211.o \ |
27 | fwil.o \ | ||
27 | dhd_cdc.o \ | 28 | dhd_cdc.o \ |
28 | dhd_common.o \ | 29 | dhd_common.o \ |
29 | dhd_linux.o | 30 | dhd_linux.o |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 17e7ae73e008..8704daa2758f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h | |||
@@ -318,6 +318,12 @@ struct brcmf_event { | |||
318 | #define BRCMF_E_LINK_ASSOC_REC 3 | 318 | #define BRCMF_E_LINK_ASSOC_REC 3 |
319 | #define BRCMF_E_LINK_BSSCFG_DIS 4 | 319 | #define BRCMF_E_LINK_BSSCFG_DIS 4 |
320 | 320 | ||
321 | /* Small, medium and maximum buffer size for dcmd | ||
322 | */ | ||
323 | #define BRCMF_DCMD_SMLEN 256 | ||
324 | #define BRCMF_DCMD_MEDLEN 1536 | ||
325 | #define BRCMF_DCMD_MAXLEN 8192 | ||
326 | |||
321 | /* Pattern matching filter. Specifies an offset within received packets to | 327 | /* Pattern matching filter. Specifies an offset within received packets to |
322 | * start matching, the pattern to match, the size of the pattern, and a bitmask | 328 | * start matching, the pattern to match, the size of the pattern, and a bitmask |
323 | * that indicates which bits within the pattern should be matched. | 329 | * that indicates which bits within the pattern should be matched. |
@@ -623,7 +629,6 @@ struct brcmf_pub { | |||
623 | u8 wme_dp; /* wme discard priority */ | 629 | u8 wme_dp; /* wme discard priority */ |
624 | 630 | ||
625 | /* Dongle media info */ | 631 | /* Dongle media info */ |
626 | bool iswl; /* Dongle-resident driver is wl */ | ||
627 | unsigned long drv_version; /* Version of dongle-resident driver */ | 632 | unsigned long drv_version; /* Version of dongle-resident driver */ |
628 | u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */ | 633 | u8 mac[ETH_ALEN]; /* MAC address obtained from dongle */ |
629 | 634 | ||
@@ -651,16 +656,10 @@ struct brcmf_pub { | |||
651 | int in_suspend; /* flag set to 1 when early suspend called */ | 656 | int in_suspend; /* flag set to 1 when early suspend called */ |
652 | int dtim_skip; /* dtim skip , default 0 means wake each dtim */ | 657 | int dtim_skip; /* dtim skip , default 0 means wake each dtim */ |
653 | 658 | ||
654 | /* Pkt filter defination */ | ||
655 | char *pktfilter[100]; | ||
656 | int pktfilter_count; | ||
657 | |||
658 | u8 country_code[BRCM_CNTRY_BUF_SZ]; | ||
659 | char eventmask[BRCMF_EVENTING_MASK_LEN]; | ||
660 | |||
661 | struct brcmf_if *iflist[BRCMF_MAX_IFS]; | 659 | struct brcmf_if *iflist[BRCMF_MAX_IFS]; |
662 | 660 | ||
663 | struct mutex proto_block; | 661 | struct mutex proto_block; |
662 | unsigned char proto_buf[BRCMF_DCMD_MAXLEN]; | ||
664 | 663 | ||
665 | struct work_struct setmacaddr_work; | 664 | struct work_struct setmacaddr_work; |
666 | struct work_struct multicast_work; | 665 | struct work_struct multicast_work; |
@@ -671,6 +670,11 @@ struct brcmf_pub { | |||
671 | #endif | 670 | #endif |
672 | }; | 671 | }; |
673 | 672 | ||
673 | struct bcmevent_name { | ||
674 | uint event; | ||
675 | const char *name; | ||
676 | }; | ||
677 | |||
674 | struct brcmf_if_event { | 678 | struct brcmf_if_event { |
675 | u8 ifidx; | 679 | u8 ifidx; |
676 | u8 action; | 680 | u8 action; |
@@ -678,47 +682,60 @@ struct brcmf_if_event { | |||
678 | u8 bssidx; | 682 | u8 bssidx; |
679 | }; | 683 | }; |
680 | 684 | ||
681 | struct bcmevent_name { | 685 | /* forward declaration */ |
682 | uint event; | 686 | struct brcmf_cfg80211_vif; |
683 | const char *name; | 687 | |
688 | /** | ||
689 | * struct brcmf_if - interface control information. | ||
690 | * | ||
691 | * @drvr: points to device related information. | ||
692 | * @vif: points to cfg80211 specific interface information. | ||
693 | * @ndev: associated network device. | ||
694 | * @stats: interface specific network statistics. | ||
695 | * @idx: interface index in device firmware. | ||
696 | * @bssidx: index of bss associated with this interface. | ||
697 | * @mac_addr: assigned mac address. | ||
698 | */ | ||
699 | struct brcmf_if { | ||
700 | struct brcmf_pub *drvr; | ||
701 | struct brcmf_cfg80211_vif *vif; | ||
702 | struct net_device *ndev; | ||
703 | struct net_device_stats stats; | ||
704 | int idx; | ||
705 | s32 bssidx; | ||
706 | u8 mac_addr[ETH_ALEN]; | ||
684 | }; | 707 | }; |
685 | 708 | ||
709 | static inline s32 brcmf_ndev_bssidx(struct net_device *ndev) | ||
710 | { | ||
711 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
712 | return ifp->bssidx; | ||
713 | } | ||
714 | |||
686 | extern const struct bcmevent_name bcmevent_names[]; | 715 | extern const struct bcmevent_name bcmevent_names[]; |
687 | 716 | ||
688 | extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen, | 717 | extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen, |
689 | char *buf, uint len); | 718 | char *buf, uint len); |
690 | extern uint brcmf_c_mkiovar_bsscfg(char *name, char *data, uint datalen, | ||
691 | char *buf, uint buflen, s32 bssidx); | ||
692 | 719 | ||
693 | extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev); | 720 | extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev); |
694 | 721 | ||
695 | extern s32 brcmf_exec_dcmd(struct net_device *dev, u32 cmd, void *arg, u32 len); | ||
696 | extern int brcmf_netlink_dcmd(struct net_device *ndev, struct brcmf_dcmd *dcmd); | ||
697 | |||
698 | /* Return pointer to interface name */ | 722 | /* Return pointer to interface name */ |
699 | extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx); | 723 | extern char *brcmf_ifname(struct brcmf_pub *drvr, int idx); |
700 | 724 | ||
701 | /* Query dongle */ | 725 | /* Query dongle */ |
702 | extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, | 726 | extern int brcmf_proto_cdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, |
703 | uint cmd, void *buf, uint len); | 727 | uint cmd, void *buf, uint len); |
704 | 728 | extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd, | |
705 | #ifdef DEBUG | 729 | void *buf, uint len); |
706 | extern int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size); | ||
707 | #endif /* DEBUG */ | ||
708 | 730 | ||
709 | extern int brcmf_ifname2idx(struct brcmf_pub *drvr, char *name); | 731 | extern int brcmf_ifname2idx(struct brcmf_pub *drvr, char *name); |
710 | extern int brcmf_c_host_event(struct brcmf_pub *drvr, int *idx, | 732 | extern int brcmf_c_host_event(struct brcmf_pub *drvr, int *idx, |
711 | void *pktdata, struct brcmf_event_msg *, | 733 | void *pktdata, struct brcmf_event_msg *, |
712 | void **data_ptr); | 734 | void **data_ptr); |
713 | 735 | ||
736 | extern int brcmf_net_attach(struct brcmf_if *ifp); | ||
737 | extern struct brcmf_if *brcmf_add_if(struct device *dev, int ifidx, s32 bssidx, | ||
738 | char *name, u8 *mac_addr); | ||
714 | extern void brcmf_del_if(struct brcmf_pub *drvr, int ifidx); | 739 | extern void brcmf_del_if(struct brcmf_pub *drvr, int ifidx); |
715 | 740 | ||
716 | extern void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg); | ||
717 | extern void brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, | ||
718 | int enable, int master_mode); | ||
719 | |||
720 | #define BRCMF_DCMD_SMLEN 256 /* "small" cmd buffer required */ | ||
721 | #define BRCMF_DCMD_MEDLEN 1536 /* "med" cmd buffer required */ | ||
722 | #define BRCMF_DCMD_MAXLEN 8192 /* max length cmd buffer required */ | ||
723 | |||
724 | #endif /* _BRCMF_H_ */ | 741 | #endif /* _BRCMF_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h index 9b8ee19ea55d..265580f5b270 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h | |||
@@ -111,9 +111,6 @@ extern void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, | |||
111 | 111 | ||
112 | extern int brcmf_bus_start(struct device *dev); | 112 | extern int brcmf_bus_start(struct device *dev); |
113 | 113 | ||
114 | extern int brcmf_add_if(struct device *dev, int ifidx, | ||
115 | char *name, u8 *mac_addr); | ||
116 | |||
117 | #ifdef CONFIG_BRCMFMAC_SDIO | 114 | #ifdef CONFIG_BRCMFMAC_SDIO |
118 | extern void brcmf_sdio_exit(void); | 115 | extern void brcmf_sdio_exit(void); |
119 | extern void brcmf_sdio_init(void); | 116 | extern void brcmf_sdio_init(void); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c index a5c15cac5e7d..b9d8a5adfd43 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_cdc.c | |||
@@ -458,35 +458,6 @@ void brcmf_proto_detach(struct brcmf_pub *drvr) | |||
458 | drvr->prot = NULL; | 458 | drvr->prot = NULL; |
459 | } | 459 | } |
460 | 460 | ||
461 | int brcmf_proto_init(struct brcmf_pub *drvr) | ||
462 | { | ||
463 | int ret = 0; | ||
464 | char buf[128]; | ||
465 | |||
466 | brcmf_dbg(TRACE, "Enter\n"); | ||
467 | |||
468 | mutex_lock(&drvr->proto_block); | ||
469 | |||
470 | /* Get the device MAC address */ | ||
471 | strcpy(buf, "cur_etheraddr"); | ||
472 | ret = brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, | ||
473 | buf, sizeof(buf)); | ||
474 | if (ret < 0) { | ||
475 | mutex_unlock(&drvr->proto_block); | ||
476 | return ret; | ||
477 | } | ||
478 | memcpy(drvr->mac, buf, ETH_ALEN); | ||
479 | |||
480 | mutex_unlock(&drvr->proto_block); | ||
481 | |||
482 | ret = brcmf_c_preinit_dcmds(drvr); | ||
483 | |||
484 | /* Always assumes wl for now */ | ||
485 | drvr->iswl = true; | ||
486 | |||
487 | return ret; | ||
488 | } | ||
489 | |||
490 | void brcmf_proto_stop(struct brcmf_pub *drvr) | 461 | void brcmf_proto_stop(struct brcmf_pub *drvr) |
491 | { | 462 | { |
492 | /* Nothing to do for CDC */ | 463 | /* Nothing to do for CDC */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 15c5db5752d1..866b66995bb0 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c | |||
@@ -28,12 +28,17 @@ | |||
28 | #include "dhd_bus.h" | 28 | #include "dhd_bus.h" |
29 | #include "dhd_proto.h" | 29 | #include "dhd_proto.h" |
30 | #include "dhd_dbg.h" | 30 | #include "dhd_dbg.h" |
31 | #include "fwil.h" | ||
31 | 32 | ||
32 | #define BRCM_OUI "\x00\x10\x18" | 33 | #define BRCM_OUI "\x00\x10\x18" |
33 | #define DOT11_OUI_LEN 3 | 34 | #define DOT11_OUI_LEN 3 |
34 | #define BCMILCP_BCM_SUBTYPE_EVENT 1 | 35 | #define BCMILCP_BCM_SUBTYPE_EVENT 1 |
35 | #define PKTFILTER_BUF_SIZE 2048 | 36 | #define PKTFILTER_BUF_SIZE 128 |
36 | #define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */ | 37 | #define BRCMF_ARPOL_MODE 0xb /* agent|snoop|peer_autoreply */ |
38 | #define BRCMF_DEFAULT_BCN_TIMEOUT 3 | ||
39 | #define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40 | ||
40 | #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40 | ||
41 | #define BRCMF_DEFAULT_PACKET_FILTER "100 0 0 0 0x01 0x00" | ||
37 | 42 | ||
38 | #define MSGTRACE_VERSION 1 | 43 | #define MSGTRACE_VERSION 1 |
39 | 44 | ||
@@ -88,52 +93,6 @@ brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen) | |||
88 | return len; | 93 | return len; |
89 | } | 94 | } |
90 | 95 | ||
91 | uint | ||
92 | brcmf_c_mkiovar_bsscfg(char *name, char *data, uint datalen, | ||
93 | char *buf, uint buflen, s32 bssidx) | ||
94 | { | ||
95 | const s8 *prefix = "bsscfg:"; | ||
96 | s8 *p; | ||
97 | u32 prefixlen; | ||
98 | u32 namelen; | ||
99 | u32 iolen; | ||
100 | __le32 bssidx_le; | ||
101 | |||
102 | if (bssidx == 0) | ||
103 | return brcmf_c_mkiovar(name, data, datalen, buf, buflen); | ||
104 | |||
105 | prefixlen = (u32) strlen(prefix); /* lengh of bsscfg prefix */ | ||
106 | namelen = (u32) strlen(name) + 1; /* lengh of iovar name + null */ | ||
107 | iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen; | ||
108 | |||
109 | if (buflen < 0 || iolen > (u32)buflen) { | ||
110 | brcmf_dbg(ERROR, "buffer is too short\n"); | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | p = buf; | ||
115 | |||
116 | /* copy prefix, no null */ | ||
117 | memcpy(p, prefix, prefixlen); | ||
118 | p += prefixlen; | ||
119 | |||
120 | /* copy iovar name including null */ | ||
121 | memcpy(p, name, namelen); | ||
122 | p += namelen; | ||
123 | |||
124 | /* bss config index as first data */ | ||
125 | bssidx_le = cpu_to_le32(bssidx); | ||
126 | memcpy(p, &bssidx_le, sizeof(bssidx_le)); | ||
127 | p += sizeof(bssidx_le); | ||
128 | |||
129 | /* parameter buffer follows */ | ||
130 | if (datalen) | ||
131 | memcpy(p, data, datalen); | ||
132 | |||
133 | return iolen; | ||
134 | |||
135 | } | ||
136 | |||
137 | bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, | 96 | bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, |
138 | struct sk_buff *pkt, int prec) | 97 | struct sk_buff *pkt, int prec) |
139 | { | 98 | { |
@@ -490,6 +449,7 @@ brcmf_c_host_event(struct brcmf_pub *drvr, int *ifidx, void *pktdata, | |||
490 | /* check whether packet is a BRCM event pkt */ | 449 | /* check whether packet is a BRCM event pkt */ |
491 | struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata; | 450 | struct brcmf_event *pvt_data = (struct brcmf_event *) pktdata; |
492 | struct brcmf_if_event *ifevent; | 451 | struct brcmf_if_event *ifevent; |
452 | struct brcmf_if *ifp; | ||
493 | char *event_data; | 453 | char *event_data; |
494 | u32 type, status; | 454 | u32 type, status; |
495 | u16 flags; | 455 | u16 flags; |
@@ -525,12 +485,17 @@ brcmf_c_host_event(struct brcmf_pub *drvr, int *ifidx, void *pktdata, | |||
525 | brcmf_dbg(TRACE, "if event\n"); | 485 | brcmf_dbg(TRACE, "if event\n"); |
526 | 486 | ||
527 | if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) { | 487 | if (ifevent->ifidx > 0 && ifevent->ifidx < BRCMF_MAX_IFS) { |
528 | if (ifevent->action == BRCMF_E_IF_ADD) | 488 | if (ifevent->action == BRCMF_E_IF_ADD) { |
529 | brcmf_add_if(drvr->dev, ifevent->ifidx, | 489 | ifp = brcmf_add_if(drvr->dev, ifevent->ifidx, |
530 | event->ifname, | 490 | ifevent->bssidx, |
531 | pvt_data->eth.h_dest); | 491 | event->ifname, |
532 | else | 492 | pvt_data->eth.h_dest); |
493 | if (IS_ERR(ifp)) | ||
494 | return PTR_ERR(ifp); | ||
495 | brcmf_net_attach(ifp); | ||
496 | } else { | ||
533 | brcmf_del_if(drvr, ifevent->ifidx); | 497 | brcmf_del_if(drvr, ifevent->ifidx); |
498 | } | ||
534 | } else { | 499 | } else { |
535 | brcmf_dbg(ERROR, "Invalid ifidx %d for %s\n", | 500 | brcmf_dbg(ERROR, "Invalid ifidx %d for %s\n", |
536 | ifevent->ifidx, event->ifname); | 501 | ifevent->ifidx, event->ifname); |
@@ -603,90 +568,57 @@ static int brcmf_c_pattern_atoh(char *src, char *dst) | |||
603 | return i; | 568 | return i; |
604 | } | 569 | } |
605 | 570 | ||
606 | void | 571 | static void |
607 | brcmf_c_pktfilter_offload_enable(struct brcmf_pub *drvr, char *arg, int enable, | 572 | brcmf_c_pktfilter_offload_enable(struct brcmf_if *ifp, char *arg, int enable, |
608 | int master_mode) | 573 | int master_mode) |
609 | { | 574 | { |
610 | unsigned long res; | 575 | unsigned long res; |
611 | char *argv[8]; | 576 | char *argv; |
612 | int i = 0; | ||
613 | const char *str; | ||
614 | int buf_len; | ||
615 | int str_len; | ||
616 | char *arg_save = NULL, *arg_org = NULL; | 577 | char *arg_save = NULL, *arg_org = NULL; |
617 | int rc; | 578 | s32 err; |
618 | char buf[128]; | ||
619 | struct brcmf_pkt_filter_enable_le enable_parm; | 579 | struct brcmf_pkt_filter_enable_le enable_parm; |
620 | struct brcmf_pkt_filter_enable_le *pkt_filterp; | ||
621 | __le32 mmode_le; | ||
622 | 580 | ||
623 | arg_save = kmalloc(strlen(arg) + 1, GFP_ATOMIC); | 581 | arg_save = kstrdup(arg, GFP_ATOMIC); |
624 | if (!arg_save) | 582 | if (!arg_save) |
625 | goto fail; | 583 | goto fail; |
626 | 584 | ||
627 | arg_org = arg_save; | 585 | arg_org = arg_save; |
628 | memcpy(arg_save, arg, strlen(arg) + 1); | ||
629 | 586 | ||
630 | argv[i] = strsep(&arg_save, " "); | 587 | argv = strsep(&arg_save, " "); |
631 | 588 | ||
632 | i = 0; | 589 | if (argv == NULL) { |
633 | if (NULL == argv[i]) { | ||
634 | brcmf_dbg(ERROR, "No args provided\n"); | 590 | brcmf_dbg(ERROR, "No args provided\n"); |
635 | goto fail; | 591 | goto fail; |
636 | } | 592 | } |
637 | 593 | ||
638 | str = "pkt_filter_enable"; | ||
639 | str_len = strlen(str); | ||
640 | strncpy(buf, str, str_len); | ||
641 | buf[str_len] = '\0'; | ||
642 | buf_len = str_len + 1; | ||
643 | |||
644 | pkt_filterp = (struct brcmf_pkt_filter_enable_le *) (buf + str_len + 1); | ||
645 | |||
646 | /* Parse packet filter id. */ | 594 | /* Parse packet filter id. */ |
647 | enable_parm.id = 0; | 595 | enable_parm.id = 0; |
648 | if (!kstrtoul(argv[i], 0, &res)) | 596 | if (!kstrtoul(argv, 0, &res)) |
649 | enable_parm.id = cpu_to_le32((u32)res); | 597 | enable_parm.id = cpu_to_le32((u32)res); |
650 | 598 | ||
651 | /* Parse enable/disable value. */ | 599 | /* Enable/disable the specified filter. */ |
652 | enable_parm.enable = cpu_to_le32(enable); | 600 | enable_parm.enable = cpu_to_le32(enable); |
653 | 601 | ||
654 | buf_len += sizeof(enable_parm); | 602 | err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_enable", &enable_parm, |
655 | memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm)); | 603 | sizeof(enable_parm)); |
604 | if (err) | ||
605 | brcmf_dbg(ERROR, "Set pkt_filter_enable error (%d)\n", err); | ||
656 | 606 | ||
657 | /* Enable/disable the specified filter. */ | 607 | /* Control the master mode */ |
658 | rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len); | 608 | err = brcmf_fil_iovar_int_set(ifp, "pkt_filter_mode", master_mode); |
659 | rc = rc >= 0 ? 0 : rc; | 609 | if (err) |
660 | if (rc) | 610 | brcmf_dbg(ERROR, "Set pkt_filter_mode error (%d)\n", err); |
661 | brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n", | ||
662 | arg, rc); | ||
663 | else | ||
664 | brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg); | ||
665 | |||
666 | /* Contorl the master mode */ | ||
667 | mmode_le = cpu_to_le32(master_mode); | ||
668 | brcmf_c_mkiovar("pkt_filter_mode", (char *)&mmode_le, 4, buf, | ||
669 | sizeof(buf)); | ||
670 | rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, | ||
671 | sizeof(buf)); | ||
672 | rc = rc >= 0 ? 0 : rc; | ||
673 | if (rc) | ||
674 | brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n", | ||
675 | arg, rc); | ||
676 | 611 | ||
677 | fail: | 612 | fail: |
678 | kfree(arg_org); | 613 | kfree(arg_org); |
679 | } | 614 | } |
680 | 615 | ||
681 | void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg) | 616 | static void brcmf_c_pktfilter_offload_set(struct brcmf_if *ifp, char *arg) |
682 | { | 617 | { |
683 | const char *str; | 618 | struct brcmf_pkt_filter_le *pkt_filter; |
684 | struct brcmf_pkt_filter_le pkt_filter; | ||
685 | struct brcmf_pkt_filter_le *pkt_filterp; | ||
686 | unsigned long res; | 619 | unsigned long res; |
687 | int buf_len; | 620 | int buf_len; |
688 | int str_len; | 621 | s32 err; |
689 | int rc; | ||
690 | u32 mask_size; | 622 | u32 mask_size; |
691 | u32 pattern_size; | 623 | u32 pattern_size; |
692 | char *argv[8], *buf = NULL; | 624 | char *argv[8], *buf = NULL; |
@@ -704,104 +636,64 @@ void brcmf_c_pktfilter_offload_set(struct brcmf_pub *drvr, char *arg) | |||
704 | goto fail; | 636 | goto fail; |
705 | 637 | ||
706 | argv[i] = strsep(&arg_save, " "); | 638 | argv[i] = strsep(&arg_save, " "); |
707 | while (argv[i++]) | 639 | while (argv[i]) { |
640 | i++; | ||
641 | if (i >= 8) { | ||
642 | brcmf_dbg(ERROR, "Too many parameters\n"); | ||
643 | goto fail; | ||
644 | } | ||
708 | argv[i] = strsep(&arg_save, " "); | 645 | argv[i] = strsep(&arg_save, " "); |
646 | } | ||
709 | 647 | ||
710 | i = 0; | 648 | if (i != 6) { |
711 | if (NULL == argv[i]) { | 649 | brcmf_dbg(ERROR, "Not enough args provided %d\n", i); |
712 | brcmf_dbg(ERROR, "No args provided\n"); | ||
713 | goto fail; | 650 | goto fail; |
714 | } | 651 | } |
715 | 652 | ||
716 | str = "pkt_filter_add"; | 653 | pkt_filter = (struct brcmf_pkt_filter_le *)buf; |
717 | strcpy(buf, str); | ||
718 | str_len = strlen(str); | ||
719 | buf_len = str_len + 1; | ||
720 | |||
721 | pkt_filterp = (struct brcmf_pkt_filter_le *) (buf + str_len + 1); | ||
722 | 654 | ||
723 | /* Parse packet filter id. */ | 655 | /* Parse packet filter id. */ |
724 | pkt_filter.id = 0; | 656 | pkt_filter->id = 0; |
725 | if (!kstrtoul(argv[i], 0, &res)) | 657 | if (!kstrtoul(argv[0], 0, &res)) |
726 | pkt_filter.id = cpu_to_le32((u32)res); | 658 | pkt_filter->id = cpu_to_le32((u32)res); |
727 | |||
728 | if (NULL == argv[++i]) { | ||
729 | brcmf_dbg(ERROR, "Polarity not provided\n"); | ||
730 | goto fail; | ||
731 | } | ||
732 | 659 | ||
733 | /* Parse filter polarity. */ | 660 | /* Parse filter polarity. */ |
734 | pkt_filter.negate_match = 0; | 661 | pkt_filter->negate_match = 0; |
735 | if (!kstrtoul(argv[i], 0, &res)) | 662 | if (!kstrtoul(argv[1], 0, &res)) |
736 | pkt_filter.negate_match = cpu_to_le32((u32)res); | 663 | pkt_filter->negate_match = cpu_to_le32((u32)res); |
737 | |||
738 | if (NULL == argv[++i]) { | ||
739 | brcmf_dbg(ERROR, "Filter type not provided\n"); | ||
740 | goto fail; | ||
741 | } | ||
742 | 664 | ||
743 | /* Parse filter type. */ | 665 | /* Parse filter type. */ |
744 | pkt_filter.type = 0; | 666 | pkt_filter->type = 0; |
745 | if (!kstrtoul(argv[i], 0, &res)) | 667 | if (!kstrtoul(argv[2], 0, &res)) |
746 | pkt_filter.type = cpu_to_le32((u32)res); | 668 | pkt_filter->type = cpu_to_le32((u32)res); |
747 | |||
748 | if (NULL == argv[++i]) { | ||
749 | brcmf_dbg(ERROR, "Offset not provided\n"); | ||
750 | goto fail; | ||
751 | } | ||
752 | 669 | ||
753 | /* Parse pattern filter offset. */ | 670 | /* Parse pattern filter offset. */ |
754 | pkt_filter.u.pattern.offset = 0; | 671 | pkt_filter->u.pattern.offset = 0; |
755 | if (!kstrtoul(argv[i], 0, &res)) | 672 | if (!kstrtoul(argv[3], 0, &res)) |
756 | pkt_filter.u.pattern.offset = cpu_to_le32((u32)res); | 673 | pkt_filter->u.pattern.offset = cpu_to_le32((u32)res); |
757 | |||
758 | if (NULL == argv[++i]) { | ||
759 | brcmf_dbg(ERROR, "Bitmask not provided\n"); | ||
760 | goto fail; | ||
761 | } | ||
762 | 674 | ||
763 | /* Parse pattern filter mask. */ | 675 | /* Parse pattern filter mask. */ |
764 | mask_size = | 676 | mask_size = brcmf_c_pattern_atoh(argv[4], |
765 | brcmf_c_pattern_atoh | 677 | (char *)pkt_filter->u.pattern.mask_and_pattern); |
766 | (argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern); | ||
767 | |||
768 | if (NULL == argv[++i]) { | ||
769 | brcmf_dbg(ERROR, "Pattern not provided\n"); | ||
770 | goto fail; | ||
771 | } | ||
772 | 678 | ||
773 | /* Parse pattern filter pattern. */ | 679 | /* Parse pattern filter pattern. */ |
774 | pattern_size = | 680 | pattern_size = brcmf_c_pattern_atoh(argv[5], |
775 | brcmf_c_pattern_atoh(argv[i], | 681 | (char *)&pkt_filter->u.pattern.mask_and_pattern[mask_size]); |
776 | (char *)&pkt_filterp->u.pattern. | ||
777 | mask_and_pattern[mask_size]); | ||
778 | 682 | ||
779 | if (mask_size != pattern_size) { | 683 | if (mask_size != pattern_size) { |
780 | brcmf_dbg(ERROR, "Mask and pattern not the same size\n"); | 684 | brcmf_dbg(ERROR, "Mask and pattern not the same size\n"); |
781 | goto fail; | 685 | goto fail; |
782 | } | 686 | } |
783 | 687 | ||
784 | pkt_filter.u.pattern.size_bytes = cpu_to_le32(mask_size); | 688 | pkt_filter->u.pattern.size_bytes = cpu_to_le32(mask_size); |
785 | buf_len += BRCMF_PKT_FILTER_FIXED_LEN; | 689 | buf_len = sizeof(*pkt_filter); |
786 | buf_len += (BRCMF_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size); | 690 | buf_len -= sizeof(pkt_filter->u.pattern.mask_and_pattern); |
787 | 691 | buf_len += mask_size + pattern_size; | |
788 | /* Keep-alive attributes are set in local | ||
789 | * variable (keep_alive_pkt), and | ||
790 | ** then memcpy'ed into buffer (keep_alive_pktp) since there is no | ||
791 | ** guarantee that the buffer is properly aligned. | ||
792 | */ | ||
793 | memcpy((char *)pkt_filterp, | ||
794 | &pkt_filter, | ||
795 | BRCMF_PKT_FILTER_FIXED_LEN + BRCMF_PKT_FILTER_PATTERN_FIXED_LEN); | ||
796 | |||
797 | rc = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, buf, buf_len); | ||
798 | rc = rc >= 0 ? 0 : rc; | ||
799 | 692 | ||
800 | if (rc) | 693 | err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_add", pkt_filter, |
801 | brcmf_dbg(TRACE, "failed to add pktfilter %s, retcode = %d\n", | 694 | buf_len); |
802 | arg, rc); | 695 | if (err) |
803 | else | 696 | brcmf_dbg(ERROR, "Set pkt_filter_add error (%d)\n", err); |
804 | brcmf_dbg(TRACE, "successfully added pktfilter %s\n", arg); | ||
805 | 697 | ||
806 | fail: | 698 | fail: |
807 | kfree(arg_org); | 699 | kfree(arg_org); |
@@ -809,130 +701,125 @@ fail: | |||
809 | kfree(buf); | 701 | kfree(buf); |
810 | } | 702 | } |
811 | 703 | ||
812 | static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode) | 704 | int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) |
813 | { | 705 | { |
814 | char iovbuf[32]; | 706 | s8 eventmask[BRCMF_EVENTING_MASK_LEN]; |
815 | int retcode; | 707 | u8 buf[BRCMF_DCMD_SMLEN]; |
816 | __le32 arp_mode_le; | 708 | char *ptr; |
817 | 709 | s32 err; | |
818 | arp_mode_le = cpu_to_le32(arp_mode); | ||
819 | brcmf_c_mkiovar("arp_ol", (char *)&arp_mode_le, 4, iovbuf, | ||
820 | sizeof(iovbuf)); | ||
821 | retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, | ||
822 | iovbuf, sizeof(iovbuf)); | ||
823 | retcode = retcode >= 0 ? 0 : retcode; | ||
824 | if (retcode) | ||
825 | brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, retcode = %d\n", | ||
826 | arp_mode, retcode); | ||
827 | else | ||
828 | brcmf_dbg(TRACE, "successfully set ARP offload mode to 0x%x\n", | ||
829 | arp_mode); | ||
830 | } | ||
831 | |||
832 | static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable) | ||
833 | { | ||
834 | char iovbuf[32]; | ||
835 | int retcode; | ||
836 | __le32 arp_enable_le; | ||
837 | |||
838 | arp_enable_le = cpu_to_le32(arp_enable); | ||
839 | |||
840 | brcmf_c_mkiovar("arpoe", (char *)&arp_enable_le, 4, | ||
841 | iovbuf, sizeof(iovbuf)); | ||
842 | retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, | ||
843 | iovbuf, sizeof(iovbuf)); | ||
844 | retcode = retcode >= 0 ? 0 : retcode; | ||
845 | if (retcode) | ||
846 | brcmf_dbg(TRACE, "failed to enable ARP offload to %d, retcode = %d\n", | ||
847 | arp_enable, retcode); | ||
848 | else | ||
849 | brcmf_dbg(TRACE, "successfully enabled ARP offload to %d\n", | ||
850 | arp_enable); | ||
851 | } | ||
852 | |||
853 | int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) | ||
854 | { | ||
855 | char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; /* Room for | ||
856 | "event_msgs" + '\0' + bitvec */ | ||
857 | char buf[128], *ptr; | ||
858 | __le32 roaming_le = cpu_to_le32(1); | ||
859 | __le32 bcn_timeout_le = cpu_to_le32(3); | ||
860 | __le32 scan_assoc_time_le = cpu_to_le32(40); | ||
861 | __le32 scan_unassoc_time_le = cpu_to_le32(40); | ||
862 | int i; | ||
863 | struct brcmf_bus_dcmd *cmdlst; | 710 | struct brcmf_bus_dcmd *cmdlst; |
864 | struct list_head *cur, *q; | 711 | struct list_head *cur, *q; |
865 | 712 | ||
866 | mutex_lock(&drvr->proto_block); | 713 | /* retreive mac address */ |
867 | 714 | err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, | |
868 | /* Set Country code */ | 715 | sizeof(ifp->mac_addr)); |
869 | if (drvr->country_code[0] != 0) { | 716 | if (err < 0) { |
870 | if (brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_COUNTRY, | 717 | brcmf_dbg(ERROR, "Retreiving cur_etheraddr failed, %d\n", |
871 | drvr->country_code, | 718 | err); |
872 | sizeof(drvr->country_code)) < 0) | 719 | goto done; |
873 | brcmf_dbg(ERROR, "country code setting failed\n"); | ||
874 | } | 720 | } |
721 | memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac)); | ||
875 | 722 | ||
876 | /* query for 'ver' to get version info from firmware */ | 723 | /* query for 'ver' to get version info from firmware */ |
877 | memset(buf, 0, sizeof(buf)); | 724 | memset(buf, 0, sizeof(buf)); |
878 | ptr = buf; | 725 | strcpy(buf, "ver"); |
879 | brcmf_c_mkiovar("ver", NULL, 0, buf, sizeof(buf)); | 726 | err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf)); |
880 | brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, buf, sizeof(buf)); | 727 | if (err < 0) { |
728 | brcmf_dbg(ERROR, "Retreiving version information failed, %d\n", | ||
729 | err); | ||
730 | goto done; | ||
731 | } | ||
732 | ptr = (char *)buf; | ||
881 | strsep(&ptr, "\n"); | 733 | strsep(&ptr, "\n"); |
882 | /* Print fw version info */ | 734 | /* Print fw version info */ |
883 | brcmf_dbg(ERROR, "Firmware version = %s\n", buf); | 735 | brcmf_dbg(ERROR, "Firmware version = %s\n", buf); |
884 | 736 | ||
885 | /* Setup timeout if Beacons are lost and roam is off to report | 737 | /* |
886 | link down */ | 738 | * Setup timeout if Beacons are lost and roam is off to report |
887 | brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout_le, 4, iovbuf, | 739 | * link down |
888 | sizeof(iovbuf)); | 740 | */ |
889 | brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, | 741 | err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", |
890 | sizeof(iovbuf)); | 742 | BRCMF_DEFAULT_BCN_TIMEOUT); |
743 | if (err) { | ||
744 | brcmf_dbg(ERROR, "bcn_timeout error (%d)\n", err); | ||
745 | goto done; | ||
746 | } | ||
891 | 747 | ||
892 | /* Enable/Disable build-in roaming to allowed ext supplicant to take | 748 | /* Enable/Disable build-in roaming to allowed ext supplicant to take |
893 | of romaing */ | 749 | * of romaing |
894 | brcmf_c_mkiovar("roam_off", (char *)&roaming_le, 4, | 750 | */ |
895 | iovbuf, sizeof(iovbuf)); | 751 | err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1); |
896 | brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, | 752 | if (err) { |
897 | sizeof(iovbuf)); | 753 | brcmf_dbg(ERROR, "roam_off error (%d)\n", err); |
898 | 754 | goto done; | |
899 | /* Setup event_msgs */ | 755 | } |
900 | brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN, | 756 | |
901 | iovbuf, sizeof(iovbuf)); | 757 | /* Setup event_msgs, enable E_IF */ |
902 | brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, | 758 | err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask, |
903 | sizeof(iovbuf)); | 759 | BRCMF_EVENTING_MASK_LEN); |
904 | 760 | if (err) { | |
905 | brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME, | 761 | brcmf_dbg(ERROR, "Get event_msgs error (%d)\n", err); |
906 | (char *)&scan_assoc_time_le, sizeof(scan_assoc_time_le)); | 762 | goto done; |
907 | brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME, | 763 | } |
908 | (char *)&scan_unassoc_time_le, sizeof(scan_unassoc_time_le)); | 764 | setbit(eventmask, BRCMF_E_IF); |
909 | 765 | err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask, | |
910 | /* Set and enable ARP offload feature */ | 766 | BRCMF_EVENTING_MASK_LEN); |
911 | brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE); | 767 | if (err) { |
912 | brcmf_c_arp_offload_enable(drvr, true); | 768 | brcmf_dbg(ERROR, "Set event_msgs error (%d)\n", err); |
913 | 769 | goto done; | |
914 | /* Set up pkt filter */ | 770 | } |
915 | for (i = 0; i < drvr->pktfilter_count; i++) { | 771 | |
916 | brcmf_c_pktfilter_offload_set(drvr, drvr->pktfilter[i]); | 772 | /* Setup default scan channel time */ |
917 | brcmf_c_pktfilter_offload_enable(drvr, drvr->pktfilter[i], | 773 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, |
918 | 0, true); | 774 | BRCMF_DEFAULT_SCAN_CHANNEL_TIME); |
775 | if (err) { | ||
776 | brcmf_dbg(ERROR, "BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n", | ||
777 | err); | ||
778 | goto done; | ||
919 | } | 779 | } |
920 | 780 | ||
781 | /* Setup default scan unassoc time */ | ||
782 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME, | ||
783 | BRCMF_DEFAULT_SCAN_UNASSOC_TIME); | ||
784 | if (err) { | ||
785 | brcmf_dbg(ERROR, "BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n", | ||
786 | err); | ||
787 | goto done; | ||
788 | } | ||
789 | |||
790 | /* Try to set and enable ARP offload feature, this may fail */ | ||
791 | err = brcmf_fil_iovar_int_set(ifp, "arp_ol", BRCMF_ARPOL_MODE); | ||
792 | if (err) { | ||
793 | brcmf_dbg(TRACE, "failed to set ARP offload mode to 0x%x, err = %d\n", | ||
794 | BRCMF_ARPOL_MODE, err); | ||
795 | err = 0; | ||
796 | } else { | ||
797 | err = brcmf_fil_iovar_int_set(ifp, "arpoe", 1); | ||
798 | if (err) { | ||
799 | brcmf_dbg(TRACE, "failed to enable ARP offload err = %d\n", | ||
800 | err); | ||
801 | err = 0; | ||
802 | } else | ||
803 | brcmf_dbg(TRACE, "successfully enabled ARP offload to 0x%x\n", | ||
804 | BRCMF_ARPOL_MODE); | ||
805 | } | ||
806 | |||
807 | /* Setup packet filter */ | ||
808 | brcmf_c_pktfilter_offload_set(ifp, BRCMF_DEFAULT_PACKET_FILTER); | ||
809 | brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER, | ||
810 | 0, true); | ||
811 | |||
921 | /* set bus specific command if there is any */ | 812 | /* set bus specific command if there is any */ |
922 | list_for_each_safe(cur, q, &drvr->bus_if->dcmd_list) { | 813 | list_for_each_safe(cur, q, &ifp->drvr->bus_if->dcmd_list) { |
923 | cmdlst = list_entry(cur, struct brcmf_bus_dcmd, list); | 814 | cmdlst = list_entry(cur, struct brcmf_bus_dcmd, list); |
924 | if (cmdlst->name && cmdlst->param && cmdlst->param_len) { | 815 | if (cmdlst->name && cmdlst->param && cmdlst->param_len) { |
925 | brcmf_c_mkiovar(cmdlst->name, cmdlst->param, | 816 | brcmf_fil_iovar_data_set(ifp, cmdlst->name, |
926 | cmdlst->param_len, iovbuf, | 817 | cmdlst->param, |
927 | sizeof(iovbuf)); | 818 | cmdlst->param_len); |
928 | brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, | ||
929 | iovbuf, sizeof(iovbuf)); | ||
930 | } | 819 | } |
931 | list_del(cur); | 820 | list_del(cur); |
932 | kfree(cmdlst); | 821 | kfree(cmdlst); |
933 | } | 822 | } |
934 | 823 | done: | |
935 | mutex_unlock(&drvr->proto_block); | 824 | return err; |
936 | |||
937 | return 0; | ||
938 | } | 825 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c index 7f89540b56da..862d2acb7a16 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c | |||
@@ -16,8 +16,10 @@ | |||
16 | #include <linux/debugfs.h> | 16 | #include <linux/debugfs.h> |
17 | #include <linux/if_ether.h> | 17 | #include <linux/if_ether.h> |
18 | #include <linux/if.h> | 18 | #include <linux/if.h> |
19 | #include <linux/netdevice.h> | ||
19 | #include <linux/ieee80211.h> | 20 | #include <linux/ieee80211.h> |
20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/netdevice.h> | ||
21 | 23 | ||
22 | #include <defs.h> | 24 | #include <defs.h> |
23 | #include <brcmu_wifi.h> | 25 | #include <brcmu_wifi.h> |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h index fb508c2256dd..eefa6c2560cc 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h | |||
@@ -31,6 +31,7 @@ | |||
31 | #define BRCMF_EVENT_VAL 0x0800 | 31 | #define BRCMF_EVENT_VAL 0x0800 |
32 | #define BRCMF_BTA_VAL 0x1000 | 32 | #define BRCMF_BTA_VAL 0x1000 |
33 | #define BRCMF_ISCAN_VAL 0x2000 | 33 | #define BRCMF_ISCAN_VAL 0x2000 |
34 | #define BRCMF_FIL_VAL 0x4000 | ||
34 | 35 | ||
35 | #if defined(DEBUG) | 36 | #if defined(DEBUG) |
36 | 37 | ||
@@ -56,6 +57,7 @@ do { \ | |||
56 | #define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL) | 57 | #define BRCMF_BYTES_ON() (brcmf_msg_level & BRCMF_BYTES_VAL) |
57 | #define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL) | 58 | #define BRCMF_GLOM_ON() (brcmf_msg_level & BRCMF_GLOM_VAL) |
58 | #define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL) | 59 | #define BRCMF_EVENT_ON() (brcmf_msg_level & BRCMF_EVENT_VAL) |
60 | #define BRCMF_FIL_ON() (brcmf_msg_level & BRCMF_FIL_VAL) | ||
59 | 61 | ||
60 | #else /* (defined DEBUG) || (defined DEBUG) */ | 62 | #else /* (defined DEBUG) || (defined DEBUG) */ |
61 | 63 | ||
@@ -67,6 +69,7 @@ do { \ | |||
67 | #define BRCMF_BYTES_ON() 0 | 69 | #define BRCMF_BYTES_ON() 0 |
68 | #define BRCMF_GLOM_ON() 0 | 70 | #define BRCMF_GLOM_ON() 0 |
69 | #define BRCMF_EVENT_ON() 0 | 71 | #define BRCMF_EVENT_ON() 0 |
72 | #define BRCMF_FIL_ON() 0 | ||
70 | 73 | ||
71 | #endif /* defined(DEBUG) */ | 74 | #endif /* defined(DEBUG) */ |
72 | 75 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c index d7c76ce9d8cb..297652339fda 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c | |||
@@ -52,16 +52,6 @@ MODULE_SUPPORTED_DEVICE("Broadcom 802.11n WLAN fullmac cards"); | |||
52 | MODULE_LICENSE("Dual BSD/GPL"); | 52 | MODULE_LICENSE("Dual BSD/GPL"); |
53 | 53 | ||
54 | 54 | ||
55 | /* Interface control information */ | ||
56 | struct brcmf_if { | ||
57 | struct brcmf_pub *drvr; /* back pointer to brcmf_pub */ | ||
58 | /* OS/stack specifics */ | ||
59 | struct net_device *ndev; | ||
60 | struct net_device_stats stats; | ||
61 | int idx; /* iface idx in dongle */ | ||
62 | u8 mac_addr[ETH_ALEN]; /* assigned MAC address */ | ||
63 | }; | ||
64 | |||
65 | /* Error bits */ | 55 | /* Error bits */ |
66 | int brcmf_msg_level = BRCMF_ERROR_VAL; | 56 | int brcmf_msg_level = BRCMF_ERROR_VAL; |
67 | module_param(brcmf_msg_level, int, 0); | 57 | module_param(brcmf_msg_level, int, 0); |
@@ -629,12 +619,9 @@ static int brcmf_ethtool(struct brcmf_pub *drvr, void __user *uaddr) | |||
629 | brcmf_dbg(ERROR, "dongle is not up\n"); | 619 | brcmf_dbg(ERROR, "dongle is not up\n"); |
630 | return -ENODEV; | 620 | return -ENODEV; |
631 | } | 621 | } |
632 | |||
633 | /* finally, report dongle driver type */ | 622 | /* finally, report dongle driver type */ |
634 | else if (drvr->iswl) | ||
635 | sprintf(info.driver, "wl"); | ||
636 | else | 623 | else |
637 | sprintf(info.driver, "xx"); | 624 | sprintf(info.driver, "wl"); |
638 | 625 | ||
639 | sprintf(info.version, "%lu", drvr->drv_version); | 626 | sprintf(info.version, "%lu", drvr->drv_version); |
640 | if (copy_to_user(uaddr, &info, sizeof(info))) | 627 | if (copy_to_user(uaddr, &info, sizeof(info))) |
@@ -719,65 +706,6 @@ static int brcmf_netdev_ioctl_entry(struct net_device *ndev, struct ifreq *ifr, | |||
719 | return -EOPNOTSUPP; | 706 | return -EOPNOTSUPP; |
720 | } | 707 | } |
721 | 708 | ||
722 | /* called only from within this driver. Sends a command to the dongle. */ | ||
723 | s32 brcmf_exec_dcmd(struct net_device *ndev, u32 cmd, void *arg, u32 len) | ||
724 | { | ||
725 | struct brcmf_dcmd dcmd; | ||
726 | s32 err = 0; | ||
727 | int buflen = 0; | ||
728 | bool is_set_key_cmd; | ||
729 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
730 | struct brcmf_pub *drvr = ifp->drvr; | ||
731 | |||
732 | memset(&dcmd, 0, sizeof(dcmd)); | ||
733 | dcmd.cmd = cmd; | ||
734 | dcmd.buf = arg; | ||
735 | dcmd.len = len; | ||
736 | |||
737 | if (dcmd.buf != NULL) | ||
738 | buflen = min_t(uint, dcmd.len, BRCMF_DCMD_MAXLEN); | ||
739 | |||
740 | /* send to dongle (must be up, and wl) */ | ||
741 | if ((drvr->bus_if->state != BRCMF_BUS_DATA)) { | ||
742 | brcmf_dbg(ERROR, "DONGLE_DOWN\n"); | ||
743 | err = -EIO; | ||
744 | goto done; | ||
745 | } | ||
746 | |||
747 | if (!drvr->iswl) { | ||
748 | err = -EIO; | ||
749 | goto done; | ||
750 | } | ||
751 | |||
752 | /* | ||
753 | * Intercept BRCMF_C_SET_KEY CMD - serialize M4 send and | ||
754 | * set key CMD to prevent M4 encryption. | ||
755 | */ | ||
756 | is_set_key_cmd = ((dcmd.cmd == BRCMF_C_SET_KEY) || | ||
757 | ((dcmd.cmd == BRCMF_C_SET_VAR) && | ||
758 | !(strncmp("wsec_key", dcmd.buf, 9))) || | ||
759 | ((dcmd.cmd == BRCMF_C_SET_VAR) && | ||
760 | !(strncmp("bsscfg:wsec_key", dcmd.buf, 15)))); | ||
761 | if (is_set_key_cmd) | ||
762 | brcmf_netdev_wait_pend8021x(ndev); | ||
763 | |||
764 | err = brcmf_proto_dcmd(drvr, ifp->idx, &dcmd, buflen); | ||
765 | |||
766 | done: | ||
767 | if (err > 0) | ||
768 | err = 0; | ||
769 | |||
770 | return err; | ||
771 | } | ||
772 | |||
773 | int brcmf_netlink_dcmd(struct net_device *ndev, struct brcmf_dcmd *dcmd) | ||
774 | { | ||
775 | brcmf_dbg(TRACE, "enter: cmd %x buf %p len %d\n", | ||
776 | dcmd->cmd, dcmd->buf, dcmd->len); | ||
777 | |||
778 | return brcmf_exec_dcmd(ndev, dcmd->cmd, dcmd->buf, dcmd->len); | ||
779 | } | ||
780 | |||
781 | static int brcmf_netdev_stop(struct net_device *ndev) | 709 | static int brcmf_netdev_stop(struct net_device *ndev) |
782 | { | 710 | { |
783 | struct brcmf_if *ifp = netdev_priv(ndev); | 711 | struct brcmf_if *ifp = netdev_priv(ndev); |
@@ -851,7 +779,7 @@ static const struct net_device_ops brcmf_netdev_ops_pri = { | |||
851 | .ndo_set_rx_mode = brcmf_netdev_set_multicast_list | 779 | .ndo_set_rx_mode = brcmf_netdev_set_multicast_list |
852 | }; | 780 | }; |
853 | 781 | ||
854 | static int brcmf_net_attach(struct brcmf_if *ifp) | 782 | int brcmf_net_attach(struct brcmf_if *ifp) |
855 | { | 783 | { |
856 | struct brcmf_pub *drvr = ifp->drvr; | 784 | struct brcmf_pub *drvr = ifp->drvr; |
857 | struct net_device *ndev; | 785 | struct net_device *ndev; |
@@ -885,15 +813,6 @@ static int brcmf_net_attach(struct brcmf_if *ifp) | |||
885 | 813 | ||
886 | memcpy(ndev->dev_addr, temp_addr, ETH_ALEN); | 814 | memcpy(ndev->dev_addr, temp_addr, ETH_ALEN); |
887 | 815 | ||
888 | /* attach to cfg80211 for primary interface */ | ||
889 | if (!ifp->idx) { | ||
890 | drvr->config = brcmf_cfg80211_attach(ndev, drvr->dev, drvr); | ||
891 | if (drvr->config == NULL) { | ||
892 | brcmf_dbg(ERROR, "wl_cfg80211_attach failed\n"); | ||
893 | goto fail; | ||
894 | } | ||
895 | } | ||
896 | |||
897 | if (register_netdev(ndev) != 0) { | 816 | if (register_netdev(ndev) != 0) { |
898 | brcmf_dbg(ERROR, "couldn't register the net device\n"); | 817 | brcmf_dbg(ERROR, "couldn't register the net device\n"); |
899 | goto fail; | 818 | goto fail; |
@@ -905,11 +824,12 @@ static int brcmf_net_attach(struct brcmf_if *ifp) | |||
905 | 824 | ||
906 | fail: | 825 | fail: |
907 | ndev->netdev_ops = NULL; | 826 | ndev->netdev_ops = NULL; |
827 | free_netdev(ndev); | ||
908 | return -EBADE; | 828 | return -EBADE; |
909 | } | 829 | } |
910 | 830 | ||
911 | int | 831 | struct brcmf_if *brcmf_add_if(struct device *dev, int ifidx, s32 bssidx, |
912 | brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr) | 832 | char *name, u8 *mac_addr) |
913 | { | 833 | { |
914 | struct brcmf_if *ifp; | 834 | struct brcmf_if *ifp; |
915 | struct net_device *ndev; | 835 | struct net_device *ndev; |
@@ -936,7 +856,7 @@ brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr) | |||
936 | ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup); | 856 | ndev = alloc_netdev(sizeof(struct brcmf_if), name, ether_setup); |
937 | if (!ndev) { | 857 | if (!ndev) { |
938 | brcmf_dbg(ERROR, "OOM - alloc_netdev\n"); | 858 | brcmf_dbg(ERROR, "OOM - alloc_netdev\n"); |
939 | return -ENOMEM; | 859 | return ERR_PTR(-ENOMEM); |
940 | } | 860 | } |
941 | 861 | ||
942 | ifp = netdev_priv(ndev); | 862 | ifp = netdev_priv(ndev); |
@@ -944,20 +864,14 @@ brcmf_add_if(struct device *dev, int ifidx, char *name, u8 *mac_addr) | |||
944 | ifp->drvr = drvr; | 864 | ifp->drvr = drvr; |
945 | drvr->iflist[ifidx] = ifp; | 865 | drvr->iflist[ifidx] = ifp; |
946 | ifp->idx = ifidx; | 866 | ifp->idx = ifidx; |
867 | ifp->bssidx = bssidx; | ||
947 | if (mac_addr != NULL) | 868 | if (mac_addr != NULL) |
948 | memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN); | 869 | memcpy(&ifp->mac_addr, mac_addr, ETH_ALEN); |
949 | 870 | ||
950 | if (brcmf_net_attach(ifp)) { | ||
951 | brcmf_dbg(ERROR, "brcmf_net_attach failed"); | ||
952 | free_netdev(ifp->ndev); | ||
953 | drvr->iflist[ifidx] = NULL; | ||
954 | return -EOPNOTSUPP; | ||
955 | } | ||
956 | |||
957 | brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n", | 871 | brcmf_dbg(TRACE, " ==== pid:%x, net_device for if:%s created ===\n", |
958 | current->pid, ifp->ndev->name); | 872 | current->pid, ifp->ndev->name); |
959 | 873 | ||
960 | return 0; | 874 | return ifp; |
961 | } | 875 | } |
962 | 876 | ||
963 | void brcmf_del_if(struct brcmf_pub *drvr, int ifidx) | 877 | void brcmf_del_if(struct brcmf_pub *drvr, int ifidx) |
@@ -1036,10 +950,9 @@ fail: | |||
1036 | int brcmf_bus_start(struct device *dev) | 950 | int brcmf_bus_start(struct device *dev) |
1037 | { | 951 | { |
1038 | int ret = -1; | 952 | int ret = -1; |
1039 | /* Room for "event_msgs" + '\0' + bitvec */ | ||
1040 | char iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; | ||
1041 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 953 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
1042 | struct brcmf_pub *drvr = bus_if->drvr; | 954 | struct brcmf_pub *drvr = bus_if->drvr; |
955 | struct brcmf_if *ifp; | ||
1043 | 956 | ||
1044 | brcmf_dbg(TRACE, "\n"); | 957 | brcmf_dbg(TRACE, "\n"); |
1045 | 958 | ||
@@ -1050,49 +963,30 @@ int brcmf_bus_start(struct device *dev) | |||
1050 | return ret; | 963 | return ret; |
1051 | } | 964 | } |
1052 | 965 | ||
1053 | brcmf_c_mkiovar("event_msgs", drvr->eventmask, BRCMF_EVENTING_MASK_LEN, | 966 | /* add primary networking interface */ |
1054 | iovbuf, sizeof(iovbuf)); | 967 | ifp = brcmf_add_if(dev, 0, 0, "wlan%d", NULL); |
1055 | brcmf_proto_cdc_query_dcmd(drvr, 0, BRCMF_C_GET_VAR, iovbuf, | 968 | if (IS_ERR(ifp)) |
1056 | sizeof(iovbuf)); | 969 | return PTR_ERR(ifp); |
1057 | memcpy(drvr->eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN); | 970 | |
1058 | 971 | /* signal bus ready */ | |
1059 | setbit(drvr->eventmask, BRCMF_E_SET_SSID); | 972 | bus_if->state = BRCMF_BUS_DATA; |
1060 | setbit(drvr->eventmask, BRCMF_E_PRUNE); | 973 | |
1061 | setbit(drvr->eventmask, BRCMF_E_AUTH); | 974 | /* Bus is ready, do any initialization */ |
1062 | setbit(drvr->eventmask, BRCMF_E_REASSOC); | 975 | ret = brcmf_c_preinit_dcmds(ifp); |
1063 | setbit(drvr->eventmask, BRCMF_E_REASSOC_IND); | ||
1064 | setbit(drvr->eventmask, BRCMF_E_DEAUTH_IND); | ||
1065 | setbit(drvr->eventmask, BRCMF_E_DISASSOC_IND); | ||
1066 | setbit(drvr->eventmask, BRCMF_E_DISASSOC); | ||
1067 | setbit(drvr->eventmask, BRCMF_E_JOIN); | ||
1068 | setbit(drvr->eventmask, BRCMF_E_ASSOC_IND); | ||
1069 | setbit(drvr->eventmask, BRCMF_E_PSK_SUP); | ||
1070 | setbit(drvr->eventmask, BRCMF_E_LINK); | ||
1071 | setbit(drvr->eventmask, BRCMF_E_NDIS_LINK); | ||
1072 | setbit(drvr->eventmask, BRCMF_E_MIC_ERROR); | ||
1073 | setbit(drvr->eventmask, BRCMF_E_PMKID_CACHE); | ||
1074 | setbit(drvr->eventmask, BRCMF_E_TXFAIL); | ||
1075 | setbit(drvr->eventmask, BRCMF_E_JOIN_START); | ||
1076 | setbit(drvr->eventmask, BRCMF_E_SCAN_COMPLETE); | ||
1077 | |||
1078 | /* enable dongle roaming event */ | ||
1079 | |||
1080 | drvr->pktfilter_count = 1; | ||
1081 | /* Setup filter to allow only unicast */ | ||
1082 | drvr->pktfilter[0] = "100 0 0 0 0x01 0x00"; | ||
1083 | |||
1084 | /* Bus is ready, do any protocol initialization */ | ||
1085 | ret = brcmf_proto_init(drvr); | ||
1086 | if (ret < 0) | 976 | if (ret < 0) |
1087 | return ret; | 977 | return ret; |
1088 | 978 | ||
1089 | /* add primary networking interface */ | 979 | drvr->config = brcmf_cfg80211_attach(drvr); |
1090 | ret = brcmf_add_if(dev, 0, "wlan%d", drvr->mac); | 980 | if (drvr->config == NULL) |
1091 | if (ret < 0) | 981 | return -ENOMEM; |
982 | |||
983 | ret = brcmf_net_attach(ifp); | ||
984 | if (ret < 0) { | ||
985 | brcmf_dbg(ERROR, "brcmf_net_attach failed"); | ||
986 | drvr->iflist[0] = NULL; | ||
1092 | return ret; | 987 | return ret; |
988 | } | ||
1093 | 989 | ||
1094 | /* signal bus ready */ | ||
1095 | bus_if->state = BRCMF_BUS_DATA; | ||
1096 | return 0; | 990 | return 0; |
1097 | } | 991 | } |
1098 | 992 | ||
@@ -1163,42 +1057,6 @@ int brcmf_netdev_wait_pend8021x(struct net_device *ndev) | |||
1163 | return pend; | 1057 | return pend; |
1164 | } | 1058 | } |
1165 | 1059 | ||
1166 | #ifdef DEBUG | ||
1167 | int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size) | ||
1168 | { | ||
1169 | int ret = 0; | ||
1170 | struct file *fp; | ||
1171 | mm_segment_t old_fs; | ||
1172 | loff_t pos = 0; | ||
1173 | |||
1174 | /* change to KERNEL_DS address limit */ | ||
1175 | old_fs = get_fs(); | ||
1176 | set_fs(KERNEL_DS); | ||
1177 | |||
1178 | /* open file to write */ | ||
1179 | fp = filp_open("/tmp/mem_dump", O_WRONLY | O_CREAT, 0640); | ||
1180 | if (!fp) { | ||
1181 | brcmf_dbg(ERROR, "open file error\n"); | ||
1182 | ret = -1; | ||
1183 | goto exit; | ||
1184 | } | ||
1185 | |||
1186 | /* Write buf to file */ | ||
1187 | fp->f_op->write(fp, (char __user *)buf, size, &pos); | ||
1188 | |||
1189 | exit: | ||
1190 | /* free buf before return */ | ||
1191 | kfree(buf); | ||
1192 | /* close file before return */ | ||
1193 | if (fp) | ||
1194 | filp_close(fp, NULL); | ||
1195 | /* restore previous address limit */ | ||
1196 | set_fs(old_fs); | ||
1197 | |||
1198 | return ret; | ||
1199 | } | ||
1200 | #endif /* DEBUG */ | ||
1201 | |||
1202 | static void brcmf_driver_init(struct work_struct *work) | 1060 | static void brcmf_driver_init(struct work_struct *work) |
1203 | { | 1061 | { |
1204 | brcmf_debugfs_init(); | 1062 | brcmf_debugfs_init(); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h index 6bc4425a8b0f..7fe6779b90cf 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_proto.h | |||
@@ -27,11 +27,6 @@ extern int brcmf_proto_attach(struct brcmf_pub *drvr); | |||
27 | /* Unlink, frees allocated protocol memory (including brcmf_proto) */ | 27 | /* Unlink, frees allocated protocol memory (including brcmf_proto) */ |
28 | extern void brcmf_proto_detach(struct brcmf_pub *drvr); | 28 | extern void brcmf_proto_detach(struct brcmf_pub *drvr); |
29 | 29 | ||
30 | /* Initialize protocol: sync w/dongle state. | ||
31 | * Sets dongle media info (iswl, drv_version, mac address). | ||
32 | */ | ||
33 | extern int brcmf_proto_init(struct brcmf_pub *drvr); | ||
34 | |||
35 | /* Stop protocol: sync w/dongle state. */ | 30 | /* Stop protocol: sync w/dongle state. */ |
36 | extern void brcmf_proto_stop(struct brcmf_pub *drvr); | 31 | extern void brcmf_proto_stop(struct brcmf_pub *drvr); |
37 | 32 | ||
@@ -45,7 +40,8 @@ extern void brcmf_proto_hdrpush(struct brcmf_pub *, int ifidx, | |||
45 | extern int brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx, | 40 | extern int brcmf_proto_dcmd(struct brcmf_pub *drvr, int ifidx, |
46 | struct brcmf_dcmd *dcmd, int len); | 41 | struct brcmf_dcmd *dcmd, int len); |
47 | 42 | ||
48 | extern int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr); | 43 | /* Sets dongle media info (drv_version, mac address). */ |
44 | extern int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); | ||
49 | 45 | ||
50 | extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, | 46 | extern int brcmf_proto_cdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, |
51 | uint cmd, void *buf, uint len); | 47 | uint cmd, void *buf, uint len); |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 3564686add9a..415f2be36375 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c | |||
@@ -614,6 +614,12 @@ static const uint max_roundup = 512; | |||
614 | 614 | ||
615 | #define ALIGNMENT 4 | 615 | #define ALIGNMENT 4 |
616 | 616 | ||
617 | enum brcmf_sdio_frmtype { | ||
618 | BRCMF_SDIO_FT_NORMAL, | ||
619 | BRCMF_SDIO_FT_SUPER, | ||
620 | BRCMF_SDIO_FT_SUB, | ||
621 | }; | ||
622 | |||
617 | static void pkt_align(struct sk_buff *p, int len, int align) | 623 | static void pkt_align(struct sk_buff *p, int len, int align) |
618 | { | 624 | { |
619 | uint datalign; | 625 | uint datalign; |
@@ -1032,7 +1038,8 @@ static void brcmf_sdbrcm_free_glom(struct brcmf_sdio *bus) | |||
1032 | } | 1038 | } |
1033 | 1039 | ||
1034 | static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, | 1040 | static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, |
1035 | struct brcmf_sdio_read *rd) | 1041 | struct brcmf_sdio_read *rd, |
1042 | enum brcmf_sdio_frmtype type) | ||
1036 | { | 1043 | { |
1037 | u16 len, checksum; | 1044 | u16 len, checksum; |
1038 | u8 rx_seq, fc, tx_seq_max; | 1045 | u8 rx_seq, fc, tx_seq_max; |
@@ -1059,6 +1066,15 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, | |||
1059 | brcmf_dbg(ERROR, "HW header length error\n"); | 1066 | brcmf_dbg(ERROR, "HW header length error\n"); |
1060 | return false; | 1067 | return false; |
1061 | } | 1068 | } |
1069 | if (type == BRCMF_SDIO_FT_SUPER && | ||
1070 | (roundup(len, bus->blocksize) != rd->len)) { | ||
1071 | brcmf_dbg(ERROR, "HW superframe header length error\n"); | ||
1072 | return false; | ||
1073 | } | ||
1074 | if (type == BRCMF_SDIO_FT_SUB && len > rd->len) { | ||
1075 | brcmf_dbg(ERROR, "HW subframe header length error\n"); | ||
1076 | return false; | ||
1077 | } | ||
1062 | rd->len = len; | 1078 | rd->len = len; |
1063 | 1079 | ||
1064 | /* | 1080 | /* |
@@ -1071,9 +1087,16 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, | |||
1071 | * Byte 5: Maximum Sequence number allow for Tx | 1087 | * Byte 5: Maximum Sequence number allow for Tx |
1072 | * Byte 6~7: Reserved | 1088 | * Byte 6~7: Reserved |
1073 | */ | 1089 | */ |
1090 | if (type == BRCMF_SDIO_FT_SUPER && | ||
1091 | SDPCM_GLOMDESC(&header[SDPCM_FRAMETAG_LEN])) { | ||
1092 | brcmf_dbg(ERROR, "Glom descriptor found in superframe head\n"); | ||
1093 | rd->len = 0; | ||
1094 | return false; | ||
1095 | } | ||
1074 | rx_seq = SDPCM_PACKET_SEQUENCE(&header[SDPCM_FRAMETAG_LEN]); | 1096 | rx_seq = SDPCM_PACKET_SEQUENCE(&header[SDPCM_FRAMETAG_LEN]); |
1075 | rd->channel = SDPCM_PACKET_CHANNEL(&header[SDPCM_FRAMETAG_LEN]); | 1097 | rd->channel = SDPCM_PACKET_CHANNEL(&header[SDPCM_FRAMETAG_LEN]); |
1076 | if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL) { | 1098 | if (len > MAX_RX_DATASZ && rd->channel != SDPCM_CONTROL_CHANNEL && |
1099 | type != BRCMF_SDIO_FT_SUPER) { | ||
1077 | brcmf_dbg(ERROR, "HW header length too long\n"); | 1100 | brcmf_dbg(ERROR, "HW header length too long\n"); |
1078 | bus->sdiodev->bus_if->dstats.rx_errors++; | 1101 | bus->sdiodev->bus_if->dstats.rx_errors++; |
1079 | bus->sdcnt.rx_toolong++; | 1102 | bus->sdcnt.rx_toolong++; |
@@ -1081,6 +1104,17 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, | |||
1081 | rd->len = 0; | 1104 | rd->len = 0; |
1082 | return false; | 1105 | return false; |
1083 | } | 1106 | } |
1107 | if (type == BRCMF_SDIO_FT_SUPER && rd->channel != SDPCM_GLOM_CHANNEL) { | ||
1108 | brcmf_dbg(ERROR, "Wrong channel for superframe\n"); | ||
1109 | rd->len = 0; | ||
1110 | return false; | ||
1111 | } | ||
1112 | if (type == BRCMF_SDIO_FT_SUB && rd->channel != SDPCM_DATA_CHANNEL && | ||
1113 | rd->channel != SDPCM_EVENT_CHANNEL) { | ||
1114 | brcmf_dbg(ERROR, "Wrong channel for subframe\n"); | ||
1115 | rd->len = 0; | ||
1116 | return false; | ||
1117 | } | ||
1084 | rd->dat_offset = SDPCM_DOFFSET_VALUE(&header[SDPCM_FRAMETAG_LEN]); | 1118 | rd->dat_offset = SDPCM_DOFFSET_VALUE(&header[SDPCM_FRAMETAG_LEN]); |
1085 | if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) { | 1119 | if (rd->dat_offset < SDPCM_HDRLEN || rd->dat_offset > rd->len) { |
1086 | brcmf_dbg(ERROR, "seq %d: bad data offset\n", rx_seq); | 1120 | brcmf_dbg(ERROR, "seq %d: bad data offset\n", rx_seq); |
@@ -1095,6 +1129,9 @@ static bool brcmf_sdio_hdparser(struct brcmf_sdio *bus, u8 *header, | |||
1095 | bus->sdcnt.rx_badseq++; | 1129 | bus->sdcnt.rx_badseq++; |
1096 | rd->seq_num = rx_seq; | 1130 | rd->seq_num = rx_seq; |
1097 | } | 1131 | } |
1132 | /* no need to check the reset for subframe */ | ||
1133 | if (type == BRCMF_SDIO_FT_SUB) | ||
1134 | return true; | ||
1098 | rd->len_nxtfrm = header[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; | 1135 | rd->len_nxtfrm = header[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; |
1099 | if (rd->len_nxtfrm << 4 > MAX_RX_DATASZ) { | 1136 | if (rd->len_nxtfrm << 4 > MAX_RX_DATASZ) { |
1100 | /* only warm for NON glom packet */ | 1137 | /* only warm for NON glom packet */ |
@@ -1126,16 +1163,16 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1126 | u16 dlen, totlen; | 1163 | u16 dlen, totlen; |
1127 | u8 *dptr, num = 0; | 1164 | u8 *dptr, num = 0; |
1128 | 1165 | ||
1129 | u16 sublen, check; | 1166 | u16 sublen; |
1130 | struct sk_buff *pfirst, *pnext; | 1167 | struct sk_buff *pfirst, *pnext; |
1131 | 1168 | ||
1132 | int errcode; | 1169 | int errcode; |
1133 | u8 chan, seq, doff, sfdoff; | 1170 | u8 doff, sfdoff; |
1134 | u8 txmax; | ||
1135 | 1171 | ||
1136 | int ifidx = 0; | 1172 | int ifidx = 0; |
1137 | bool usechain = bus->use_rxchain; | 1173 | bool usechain = bus->use_rxchain; |
1138 | u16 next_len; | 1174 | |
1175 | struct brcmf_sdio_read rd_new; | ||
1139 | 1176 | ||
1140 | /* If packets, issue read(s) and send up packet chain */ | 1177 | /* If packets, issue read(s) and send up packet chain */ |
1141 | /* Return sequence numbers consumed? */ | 1178 | /* Return sequence numbers consumed? */ |
@@ -1279,68 +1316,15 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1279 | pfirst->data, min_t(int, pfirst->len, 48), | 1316 | pfirst->data, min_t(int, pfirst->len, 48), |
1280 | "SUPERFRAME:\n"); | 1317 | "SUPERFRAME:\n"); |
1281 | 1318 | ||
1282 | /* Validate the superframe header */ | 1319 | rd_new.seq_num = rxseq; |
1283 | dptr = (u8 *) (pfirst->data); | 1320 | rd_new.len = dlen; |
1284 | sublen = get_unaligned_le16(dptr); | 1321 | errcode = -!brcmf_sdio_hdparser(bus, pfirst->data, &rd_new, |
1285 | check = get_unaligned_le16(dptr + sizeof(u16)); | 1322 | BRCMF_SDIO_FT_SUPER); |
1286 | 1323 | bus->cur_read.len = rd_new.len_nxtfrm << 4; | |
1287 | chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); | ||
1288 | seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); | ||
1289 | next_len = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; | ||
1290 | if ((next_len << 4) > MAX_RX_DATASZ) { | ||
1291 | brcmf_dbg(INFO, "nextlen too large (%d) seq %d\n", | ||
1292 | next_len, seq); | ||
1293 | next_len = 0; | ||
1294 | } | ||
1295 | bus->cur_read.len = next_len << 4; | ||
1296 | doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); | ||
1297 | txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); | ||
1298 | |||
1299 | errcode = 0; | ||
1300 | if ((u16)~(sublen ^ check)) { | ||
1301 | brcmf_dbg(ERROR, "(superframe): HW hdr error: len/check 0x%04x/0x%04x\n", | ||
1302 | sublen, check); | ||
1303 | errcode = -1; | ||
1304 | } else if (roundup(sublen, bus->blocksize) != dlen) { | ||
1305 | brcmf_dbg(ERROR, "(superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n", | ||
1306 | sublen, roundup(sublen, bus->blocksize), | ||
1307 | dlen); | ||
1308 | errcode = -1; | ||
1309 | } else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) != | ||
1310 | SDPCM_GLOM_CHANNEL) { | ||
1311 | brcmf_dbg(ERROR, "(superframe): bad channel %d\n", | ||
1312 | SDPCM_PACKET_CHANNEL( | ||
1313 | &dptr[SDPCM_FRAMETAG_LEN])); | ||
1314 | errcode = -1; | ||
1315 | } else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) { | ||
1316 | brcmf_dbg(ERROR, "(superframe): got 2nd descriptor?\n"); | ||
1317 | errcode = -1; | ||
1318 | } else if ((doff < SDPCM_HDRLEN) || | ||
1319 | (doff > (pfirst->len - SDPCM_HDRLEN))) { | ||
1320 | brcmf_dbg(ERROR, "(superframe): Bad data offset %d: HW %d pkt %d min %d\n", | ||
1321 | doff, sublen, pfirst->len, SDPCM_HDRLEN); | ||
1322 | errcode = -1; | ||
1323 | } | ||
1324 | |||
1325 | /* Check sequence number of superframe SW header */ | ||
1326 | if (rxseq != seq) { | ||
1327 | brcmf_dbg(INFO, "(superframe) rx_seq %d, expected %d\n", | ||
1328 | seq, rxseq); | ||
1329 | bus->sdcnt.rx_badseq++; | ||
1330 | rxseq = seq; | ||
1331 | } | ||
1332 | |||
1333 | /* Check window for sanity */ | ||
1334 | if ((u8) (txmax - bus->tx_seq) > 0x40) { | ||
1335 | brcmf_dbg(ERROR, "unlikely tx max %d with tx_seq %d\n", | ||
1336 | txmax, bus->tx_seq); | ||
1337 | txmax = bus->tx_seq + 2; | ||
1338 | } | ||
1339 | bus->tx_max = txmax; | ||
1340 | 1324 | ||
1341 | /* Remove superframe header, remember offset */ | 1325 | /* Remove superframe header, remember offset */ |
1342 | skb_pull(pfirst, doff); | 1326 | skb_pull(pfirst, rd_new.dat_offset); |
1343 | sfdoff = doff; | 1327 | sfdoff = rd_new.dat_offset; |
1344 | num = 0; | 1328 | num = 0; |
1345 | 1329 | ||
1346 | /* Validate all the subframe headers */ | 1330 | /* Validate all the subframe headers */ |
@@ -1349,34 +1333,14 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1349 | if (errcode) | 1333 | if (errcode) |
1350 | break; | 1334 | break; |
1351 | 1335 | ||
1352 | dptr = (u8 *) (pnext->data); | 1336 | rd_new.len = pnext->len; |
1353 | dlen = (u16) (pnext->len); | 1337 | rd_new.seq_num = rxseq++; |
1354 | sublen = get_unaligned_le16(dptr); | 1338 | errcode = -!brcmf_sdio_hdparser(bus, pnext->data, |
1355 | check = get_unaligned_le16(dptr + sizeof(u16)); | 1339 | &rd_new, |
1356 | chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); | 1340 | BRCMF_SDIO_FT_SUB); |
1357 | doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); | ||
1358 | brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), | 1341 | brcmf_dbg_hex_dump(BRCMF_GLOM_ON(), |
1359 | dptr, 32, "subframe:\n"); | 1342 | pnext->data, 32, "subframe:\n"); |
1360 | 1343 | ||
1361 | if ((u16)~(sublen ^ check)) { | ||
1362 | brcmf_dbg(ERROR, "(subframe %d): HW hdr error: len/check 0x%04x/0x%04x\n", | ||
1363 | num, sublen, check); | ||
1364 | errcode = -1; | ||
1365 | } else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) { | ||
1366 | brcmf_dbg(ERROR, "(subframe %d): length mismatch: len 0x%04x, expect 0x%04x\n", | ||
1367 | num, sublen, dlen); | ||
1368 | errcode = -1; | ||
1369 | } else if ((chan != SDPCM_DATA_CHANNEL) && | ||
1370 | (chan != SDPCM_EVENT_CHANNEL)) { | ||
1371 | brcmf_dbg(ERROR, "(subframe %d): bad channel %d\n", | ||
1372 | num, chan); | ||
1373 | errcode = -1; | ||
1374 | } else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) { | ||
1375 | brcmf_dbg(ERROR, "(subframe %d): Bad data offset %d: HW %d min %d\n", | ||
1376 | num, doff, sublen, SDPCM_HDRLEN); | ||
1377 | errcode = -1; | ||
1378 | } | ||
1379 | /* increase the subframe count */ | ||
1380 | num++; | 1344 | num++; |
1381 | } | 1345 | } |
1382 | 1346 | ||
@@ -1402,27 +1366,11 @@ static u8 brcmf_sdbrcm_rxglom(struct brcmf_sdio *bus, u8 rxseq) | |||
1402 | skb_queue_walk_safe(&bus->glom, pfirst, pnext) { | 1366 | skb_queue_walk_safe(&bus->glom, pfirst, pnext) { |
1403 | dptr = (u8 *) (pfirst->data); | 1367 | dptr = (u8 *) (pfirst->data); |
1404 | sublen = get_unaligned_le16(dptr); | 1368 | sublen = get_unaligned_le16(dptr); |
1405 | chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); | ||
1406 | seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); | ||
1407 | doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); | 1369 | doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); |
1408 | 1370 | ||
1409 | brcmf_dbg(GLOM, "Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n", | ||
1410 | num, pfirst, pfirst->data, | ||
1411 | pfirst->len, sublen, chan, seq); | ||
1412 | |||
1413 | /* precondition: chan == SDPCM_DATA_CHANNEL || | ||
1414 | chan == SDPCM_EVENT_CHANNEL */ | ||
1415 | |||
1416 | if (rxseq != seq) { | ||
1417 | brcmf_dbg(GLOM, "rx_seq %d, expected %d\n", | ||
1418 | seq, rxseq); | ||
1419 | bus->sdcnt.rx_badseq++; | ||
1420 | rxseq = seq; | ||
1421 | } | ||
1422 | rxseq++; | ||
1423 | |||
1424 | brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(), | 1371 | brcmf_dbg_hex_dump(BRCMF_BYTES_ON() && BRCMF_DATA_ON(), |
1425 | dptr, dlen, "Rx Subframe Data:\n"); | 1372 | dptr, pfirst->len, |
1373 | "Rx Subframe Data:\n"); | ||
1426 | 1374 | ||
1427 | __skb_trim(pfirst, sublen); | 1375 | __skb_trim(pfirst, sublen); |
1428 | skb_pull(pfirst, doff); | 1376 | skb_pull(pfirst, doff); |
@@ -1642,7 +1590,8 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1642 | bus->rxhdr, SDPCM_HDRLEN, | 1590 | bus->rxhdr, SDPCM_HDRLEN, |
1643 | "RxHdr:\n"); | 1591 | "RxHdr:\n"); |
1644 | 1592 | ||
1645 | if (!brcmf_sdio_hdparser(bus, bus->rxhdr, rd)) { | 1593 | if (!brcmf_sdio_hdparser(bus, bus->rxhdr, rd, |
1594 | BRCMF_SDIO_FT_NORMAL)) { | ||
1646 | if (!bus->rxpending) | 1595 | if (!bus->rxpending) |
1647 | break; | 1596 | break; |
1648 | else | 1597 | else |
@@ -1701,7 +1650,8 @@ static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes) | |||
1701 | } else { | 1650 | } else { |
1702 | memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN); | 1651 | memcpy(bus->rxhdr, pkt->data, SDPCM_HDRLEN); |
1703 | rd_new.seq_num = rd->seq_num; | 1652 | rd_new.seq_num = rd->seq_num; |
1704 | if (!brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new)) { | 1653 | if (!brcmf_sdio_hdparser(bus, bus->rxhdr, &rd_new, |
1654 | BRCMF_SDIO_FT_NORMAL)) { | ||
1705 | rd->len = 0; | 1655 | rd->len = 0; |
1706 | brcmu_pkt_buf_free_skb(pkt); | 1656 | brcmu_pkt_buf_free_skb(pkt); |
1707 | } | 1657 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c new file mode 100644 index 000000000000..4b272c3d237c --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c | |||
@@ -0,0 +1,336 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | /* FWIL is the Firmware Interface Layer. In this module the support functions | ||
18 | * are located to set and get variables to and from the firmware. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/netdevice.h> | ||
23 | #include <defs.h> | ||
24 | #include <brcmu_utils.h> | ||
25 | #include <brcmu_wifi.h> | ||
26 | #include "dhd.h" | ||
27 | #include "dhd_bus.h" | ||
28 | #include "dhd_dbg.h" | ||
29 | #include "fwil.h" | ||
30 | |||
31 | |||
32 | static s32 | ||
33 | brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) | ||
34 | { | ||
35 | struct brcmf_pub *drvr = ifp->drvr; | ||
36 | s32 err; | ||
37 | |||
38 | if (drvr->bus_if->state == BRCMF_BUS_DOWN) { | ||
39 | brcmf_dbg(ERROR, "bus is down. we have nothing to do.\n"); | ||
40 | return -EIO; | ||
41 | } | ||
42 | |||
43 | if (data != NULL) | ||
44 | len = min_t(uint, len, BRCMF_DCMD_MAXLEN); | ||
45 | if (set) | ||
46 | err = brcmf_proto_cdc_set_dcmd(drvr, ifp->idx, cmd, data, len); | ||
47 | else | ||
48 | err = brcmf_proto_cdc_query_dcmd(drvr, ifp->idx, cmd, data, | ||
49 | len); | ||
50 | |||
51 | if (err >= 0) | ||
52 | err = 0; | ||
53 | else | ||
54 | brcmf_dbg(ERROR, "Failed err=%d\n", err); | ||
55 | |||
56 | return err; | ||
57 | } | ||
58 | |||
59 | s32 | ||
60 | brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len) | ||
61 | { | ||
62 | s32 err; | ||
63 | |||
64 | mutex_lock(&ifp->drvr->proto_block); | ||
65 | |||
66 | brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len); | ||
67 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data"); | ||
68 | |||
69 | err = brcmf_fil_cmd_data(ifp, cmd, data, len, true); | ||
70 | mutex_unlock(&ifp->drvr->proto_block); | ||
71 | |||
72 | return err; | ||
73 | } | ||
74 | |||
75 | s32 | ||
76 | brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len) | ||
77 | { | ||
78 | s32 err; | ||
79 | |||
80 | mutex_lock(&ifp->drvr->proto_block); | ||
81 | err = brcmf_fil_cmd_data(ifp, cmd, data, len, false); | ||
82 | |||
83 | brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len); | ||
84 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data"); | ||
85 | |||
86 | mutex_unlock(&ifp->drvr->proto_block); | ||
87 | |||
88 | return err; | ||
89 | } | ||
90 | |||
91 | |||
92 | s32 | ||
93 | brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data) | ||
94 | { | ||
95 | s32 err; | ||
96 | __le32 data_le = cpu_to_le32(data); | ||
97 | |||
98 | mutex_lock(&ifp->drvr->proto_block); | ||
99 | err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), true); | ||
100 | mutex_unlock(&ifp->drvr->proto_block); | ||
101 | |||
102 | return err; | ||
103 | } | ||
104 | |||
105 | s32 | ||
106 | brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data) | ||
107 | { | ||
108 | s32 err; | ||
109 | __le32 data_le = cpu_to_le32(*data); | ||
110 | |||
111 | mutex_lock(&ifp->drvr->proto_block); | ||
112 | err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), false); | ||
113 | mutex_unlock(&ifp->drvr->proto_block); | ||
114 | *data = le32_to_cpu(data_le); | ||
115 | |||
116 | return err; | ||
117 | } | ||
118 | |||
119 | static u32 | ||
120 | brcmf_create_iovar(char *name, char *data, u32 datalen, char *buf, u32 buflen) | ||
121 | { | ||
122 | u32 len; | ||
123 | |||
124 | len = strlen(name) + 1; | ||
125 | |||
126 | if ((len + datalen) > buflen) | ||
127 | return 0; | ||
128 | |||
129 | memcpy(buf, name, len); | ||
130 | |||
131 | /* append data onto the end of the name string */ | ||
132 | if (data && datalen) | ||
133 | memcpy(&buf[len], data, datalen); | ||
134 | |||
135 | return len + datalen; | ||
136 | } | ||
137 | |||
138 | |||
139 | s32 | ||
140 | brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data, | ||
141 | u32 len) | ||
142 | { | ||
143 | struct brcmf_pub *drvr = ifp->drvr; | ||
144 | s32 err; | ||
145 | u32 buflen; | ||
146 | |||
147 | mutex_lock(&drvr->proto_block); | ||
148 | |||
149 | brcmf_dbg(FIL, "name=%s, len=%d\n", name, len); | ||
150 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data"); | ||
151 | |||
152 | buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf, | ||
153 | sizeof(drvr->proto_buf)); | ||
154 | if (buflen) { | ||
155 | err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf, | ||
156 | buflen, true); | ||
157 | } else { | ||
158 | err = -EPERM; | ||
159 | brcmf_dbg(ERROR, "Creating iovar failed\n"); | ||
160 | } | ||
161 | |||
162 | mutex_unlock(&drvr->proto_block); | ||
163 | return err; | ||
164 | } | ||
165 | |||
166 | s32 | ||
167 | brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data, | ||
168 | u32 len) | ||
169 | { | ||
170 | struct brcmf_pub *drvr = ifp->drvr; | ||
171 | s32 err; | ||
172 | u32 buflen; | ||
173 | |||
174 | mutex_lock(&drvr->proto_block); | ||
175 | |||
176 | buflen = brcmf_create_iovar(name, data, len, drvr->proto_buf, | ||
177 | sizeof(drvr->proto_buf)); | ||
178 | if (buflen) { | ||
179 | err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf, | ||
180 | buflen, false); | ||
181 | if (err == 0) | ||
182 | memcpy(data, drvr->proto_buf, len); | ||
183 | } else { | ||
184 | err = -EPERM; | ||
185 | brcmf_dbg(ERROR, "Creating iovar failed\n"); | ||
186 | } | ||
187 | |||
188 | brcmf_dbg(FIL, "name=%s, len=%d\n", name, len); | ||
189 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data"); | ||
190 | |||
191 | mutex_unlock(&drvr->proto_block); | ||
192 | return err; | ||
193 | } | ||
194 | |||
195 | s32 | ||
196 | brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data) | ||
197 | { | ||
198 | __le32 data_le = cpu_to_le32(data); | ||
199 | |||
200 | return brcmf_fil_iovar_data_set(ifp, name, &data_le, sizeof(data_le)); | ||
201 | } | ||
202 | |||
203 | s32 | ||
204 | brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data) | ||
205 | { | ||
206 | __le32 data_le = cpu_to_le32(*data); | ||
207 | s32 err; | ||
208 | |||
209 | err = brcmf_fil_iovar_data_get(ifp, name, &data_le, sizeof(data_le)); | ||
210 | if (err == 0) | ||
211 | *data = le32_to_cpu(data_le); | ||
212 | return err; | ||
213 | } | ||
214 | |||
215 | static u32 | ||
216 | brcmf_create_bsscfg(s32 bssidx, char *name, char *data, u32 datalen, char *buf, | ||
217 | u32 buflen) | ||
218 | { | ||
219 | const s8 *prefix = "bsscfg:"; | ||
220 | s8 *p; | ||
221 | u32 prefixlen; | ||
222 | u32 namelen; | ||
223 | u32 iolen; | ||
224 | __le32 bssidx_le; | ||
225 | |||
226 | if (bssidx == 0) | ||
227 | return brcmf_create_iovar(name, data, datalen, buf, buflen); | ||
228 | |||
229 | prefixlen = strlen(prefix); | ||
230 | namelen = strlen(name) + 1; /* lengh of iovar name + null */ | ||
231 | iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen; | ||
232 | |||
233 | if (buflen < iolen) { | ||
234 | brcmf_dbg(ERROR, "buffer is too short\n"); | ||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | p = buf; | ||
239 | |||
240 | /* copy prefix, no null */ | ||
241 | memcpy(p, prefix, prefixlen); | ||
242 | p += prefixlen; | ||
243 | |||
244 | /* copy iovar name including null */ | ||
245 | memcpy(p, name, namelen); | ||
246 | p += namelen; | ||
247 | |||
248 | /* bss config index as first data */ | ||
249 | bssidx_le = cpu_to_le32(bssidx); | ||
250 | memcpy(p, &bssidx_le, sizeof(bssidx_le)); | ||
251 | p += sizeof(bssidx_le); | ||
252 | |||
253 | /* parameter buffer follows */ | ||
254 | if (datalen) | ||
255 | memcpy(p, data, datalen); | ||
256 | |||
257 | return iolen; | ||
258 | } | ||
259 | |||
260 | s32 | ||
261 | brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name, | ||
262 | void *data, u32 len) | ||
263 | { | ||
264 | struct brcmf_pub *drvr = ifp->drvr; | ||
265 | s32 err; | ||
266 | u32 buflen; | ||
267 | |||
268 | mutex_lock(&drvr->proto_block); | ||
269 | |||
270 | brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len); | ||
271 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data"); | ||
272 | |||
273 | buflen = brcmf_create_bsscfg(ifp->bssidx, name, data, len, | ||
274 | drvr->proto_buf, sizeof(drvr->proto_buf)); | ||
275 | if (buflen) { | ||
276 | err = brcmf_fil_cmd_data(ifp, BRCMF_C_SET_VAR, drvr->proto_buf, | ||
277 | buflen, true); | ||
278 | } else { | ||
279 | err = -EPERM; | ||
280 | brcmf_dbg(ERROR, "Creating bsscfg failed\n"); | ||
281 | } | ||
282 | |||
283 | mutex_unlock(&drvr->proto_block); | ||
284 | return err; | ||
285 | } | ||
286 | |||
287 | s32 | ||
288 | brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, | ||
289 | void *data, u32 len) | ||
290 | { | ||
291 | struct brcmf_pub *drvr = ifp->drvr; | ||
292 | s32 err; | ||
293 | u32 buflen; | ||
294 | |||
295 | mutex_lock(&drvr->proto_block); | ||
296 | |||
297 | buflen = brcmf_create_bsscfg(ifp->bssidx, name, NULL, len, | ||
298 | drvr->proto_buf, sizeof(drvr->proto_buf)); | ||
299 | if (buflen) { | ||
300 | err = brcmf_fil_cmd_data(ifp, BRCMF_C_GET_VAR, drvr->proto_buf, | ||
301 | buflen, false); | ||
302 | if (err == 0) | ||
303 | memcpy(data, drvr->proto_buf, len); | ||
304 | } else { | ||
305 | err = -EPERM; | ||
306 | brcmf_dbg(ERROR, "Creating bsscfg failed\n"); | ||
307 | } | ||
308 | brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len); | ||
309 | brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data, len, "data"); | ||
310 | |||
311 | mutex_unlock(&drvr->proto_block); | ||
312 | return err; | ||
313 | |||
314 | } | ||
315 | |||
316 | s32 | ||
317 | brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data) | ||
318 | { | ||
319 | __le32 data_le = cpu_to_le32(data); | ||
320 | |||
321 | return brcmf_fil_bsscfg_data_set(ifp, name, &data_le, | ||
322 | sizeof(data_le)); | ||
323 | } | ||
324 | |||
325 | s32 | ||
326 | brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data) | ||
327 | { | ||
328 | __le32 data_le = cpu_to_le32(*data); | ||
329 | s32 err; | ||
330 | |||
331 | err = brcmf_fil_bsscfg_data_get(ifp, name, &data_le, | ||
332 | sizeof(data_le)); | ||
333 | if (err == 0) | ||
334 | *data = le32_to_cpu(data_le); | ||
335 | return err; | ||
336 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h new file mode 100644 index 000000000000..16eb8202fb1e --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.h | |||
@@ -0,0 +1,39 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Broadcom Corporation | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _fwil_h_ | ||
18 | #define _fwil_h_ | ||
19 | |||
20 | s32 brcmf_fil_cmd_data_set(struct brcmf_if *ifp, u32 cmd, void *data, u32 len); | ||
21 | s32 brcmf_fil_cmd_data_get(struct brcmf_if *ifp, u32 cmd, void *data, u32 len); | ||
22 | s32 brcmf_fil_cmd_int_set(struct brcmf_if *ifp, u32 cmd, u32 data); | ||
23 | s32 brcmf_fil_cmd_int_get(struct brcmf_if *ifp, u32 cmd, u32 *data); | ||
24 | |||
25 | s32 brcmf_fil_iovar_data_set(struct brcmf_if *ifp, char *name, void *data, | ||
26 | u32 len); | ||
27 | s32 brcmf_fil_iovar_data_get(struct brcmf_if *ifp, char *name, void *data, | ||
28 | u32 len); | ||
29 | s32 brcmf_fil_iovar_int_set(struct brcmf_if *ifp, char *name, u32 data); | ||
30 | s32 brcmf_fil_iovar_int_get(struct brcmf_if *ifp, char *name, u32 *data); | ||
31 | |||
32 | s32 brcmf_fil_bsscfg_data_set(struct brcmf_if *ifp, char *name, void *data, | ||
33 | u32 len); | ||
34 | s32 brcmf_fil_bsscfg_data_get(struct brcmf_if *ifp, char *name, void *data, | ||
35 | u32 len); | ||
36 | s32 brcmf_fil_bsscfg_int_set(struct brcmf_if *ifp, char *name, u32 data); | ||
37 | s32 brcmf_fil_bsscfg_int_get(struct brcmf_if *ifp, char *name, u32 *data); | ||
38 | |||
39 | #endif /* _fwil_h_ */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index a2b4b1e71017..484a6e4f23a2 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
@@ -42,7 +42,6 @@ | |||
42 | 42 | ||
43 | #define IOCTL_RESP_TIMEOUT 2000 | 43 | #define IOCTL_RESP_TIMEOUT 2000 |
44 | 44 | ||
45 | #define BRCMF_USB_SYNC_TIMEOUT 300 /* ms */ | ||
46 | #define BRCMF_USB_DLIMAGE_SPINWAIT 100 /* in unit of ms */ | 45 | #define BRCMF_USB_DLIMAGE_SPINWAIT 100 /* in unit of ms */ |
47 | #define BRCMF_USB_DLIMAGE_LIMIT 500 /* spinwait limit (ms) */ | 46 | #define BRCMF_USB_DLIMAGE_LIMIT 500 /* spinwait limit (ms) */ |
48 | 47 | ||
@@ -116,10 +115,6 @@ struct brcmf_usbdev_info { | |||
116 | u8 *image; /* buffer for combine fw and nvram */ | 115 | u8 *image; /* buffer for combine fw and nvram */ |
117 | int image_len; | 116 | int image_len; |
118 | 117 | ||
119 | wait_queue_head_t wait; | ||
120 | bool waitdone; | ||
121 | int sync_urb_status; | ||
122 | |||
123 | struct usb_device *usbdev; | 118 | struct usb_device *usbdev; |
124 | struct device *dev; | 119 | struct device *dev; |
125 | 120 | ||
@@ -131,7 +126,6 @@ struct brcmf_usbdev_info { | |||
131 | int ctl_urb_status; | 126 | int ctl_urb_status; |
132 | int ctl_completed; | 127 | int ctl_completed; |
133 | wait_queue_head_t ioctl_resp_wait; | 128 | wait_queue_head_t ioctl_resp_wait; |
134 | wait_queue_head_t ctrl_wait; | ||
135 | ulong ctl_op; | 129 | ulong ctl_op; |
136 | 130 | ||
137 | struct urb *bulk_urb; /* used for FW download */ | 131 | struct urb *bulk_urb; /* used for FW download */ |
@@ -754,34 +748,14 @@ static void brcmf_usb_down(struct device *dev) | |||
754 | brcmf_usb_free_q(&devinfo->rx_postq, true); | 748 | brcmf_usb_free_q(&devinfo->rx_postq, true); |
755 | } | 749 | } |
756 | 750 | ||
757 | static int | ||
758 | brcmf_usb_sync_wait(struct brcmf_usbdev_info *devinfo, u16 time) | ||
759 | { | ||
760 | int ret; | ||
761 | int err = 0; | ||
762 | int ms = time; | ||
763 | |||
764 | ret = wait_event_interruptible_timeout(devinfo->wait, | ||
765 | devinfo->waitdone == true, (ms * HZ / 1000)); | ||
766 | |||
767 | if ((devinfo->waitdone == false) || (devinfo->sync_urb_status)) { | ||
768 | brcmf_dbg(ERROR, "timeout(%d) or urb err=%d\n", | ||
769 | ret, devinfo->sync_urb_status); | ||
770 | err = -EINVAL; | ||
771 | } | ||
772 | devinfo->waitdone = false; | ||
773 | return err; | ||
774 | } | ||
775 | |||
776 | static void | 751 | static void |
777 | brcmf_usb_sync_complete(struct urb *urb) | 752 | brcmf_usb_sync_complete(struct urb *urb) |
778 | { | 753 | { |
779 | struct brcmf_usbdev_info *devinfo = | 754 | struct brcmf_usbdev_info *devinfo = |
780 | (struct brcmf_usbdev_info *)urb->context; | 755 | (struct brcmf_usbdev_info *)urb->context; |
781 | 756 | ||
782 | devinfo->waitdone = true; | 757 | devinfo->ctl_completed = true; |
783 | wake_up_interruptible(&devinfo->wait); | 758 | brcmf_usb_ioctl_resp_wake(devinfo); |
784 | devinfo->sync_urb_status = urb->status; | ||
785 | } | 759 | } |
786 | 760 | ||
787 | static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd, | 761 | static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd, |
@@ -813,6 +787,7 @@ static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd, | |||
813 | (void *) tmpbuf, size, | 787 | (void *) tmpbuf, size, |
814 | (usb_complete_t)brcmf_usb_sync_complete, devinfo); | 788 | (usb_complete_t)brcmf_usb_sync_complete, devinfo); |
815 | 789 | ||
790 | devinfo->ctl_completed = false; | ||
816 | ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC); | 791 | ret = usb_submit_urb(devinfo->ctl_urb, GFP_ATOMIC); |
817 | if (ret < 0) { | 792 | if (ret < 0) { |
818 | brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret); | 793 | brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret); |
@@ -820,11 +795,11 @@ static bool brcmf_usb_dl_cmd(struct brcmf_usbdev_info *devinfo, u8 cmd, | |||
820 | return false; | 795 | return false; |
821 | } | 796 | } |
822 | 797 | ||
823 | ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT); | 798 | ret = brcmf_usb_ioctl_resp_wait(devinfo); |
824 | memcpy(buffer, tmpbuf, buflen); | 799 | memcpy(buffer, tmpbuf, buflen); |
825 | kfree(tmpbuf); | 800 | kfree(tmpbuf); |
826 | 801 | ||
827 | return (ret == 0); | 802 | return ret; |
828 | } | 803 | } |
829 | 804 | ||
830 | static bool | 805 | static bool |
@@ -918,13 +893,14 @@ brcmf_usb_dl_send_bulk(struct brcmf_usbdev_info *devinfo, void *buffer, int len) | |||
918 | 893 | ||
919 | devinfo->bulk_urb->transfer_flags |= URB_ZERO_PACKET; | 894 | devinfo->bulk_urb->transfer_flags |= URB_ZERO_PACKET; |
920 | 895 | ||
896 | devinfo->ctl_completed = false; | ||
921 | ret = usb_submit_urb(devinfo->bulk_urb, GFP_ATOMIC); | 897 | ret = usb_submit_urb(devinfo->bulk_urb, GFP_ATOMIC); |
922 | if (ret) { | 898 | if (ret) { |
923 | brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret); | 899 | brcmf_dbg(ERROR, "usb_submit_urb failed %d\n", ret); |
924 | return ret; | 900 | return ret; |
925 | } | 901 | } |
926 | ret = brcmf_usb_sync_wait(devinfo, BRCMF_USB_SYNC_TIMEOUT); | 902 | ret = brcmf_usb_ioctl_resp_wait(devinfo); |
927 | return ret; | 903 | return (ret == 0); |
928 | } | 904 | } |
929 | 905 | ||
930 | static int | 906 | static int |
@@ -1284,7 +1260,6 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo, | |||
1284 | goto error; | 1260 | goto error; |
1285 | } | 1261 | } |
1286 | 1262 | ||
1287 | init_waitqueue_head(&devinfo->wait); | ||
1288 | if (!brcmf_usb_dlneeded(devinfo)) | 1263 | if (!brcmf_usb_dlneeded(devinfo)) |
1289 | return &devinfo->bus_pub; | 1264 | return &devinfo->bus_pub; |
1290 | 1265 | ||
@@ -1339,7 +1314,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo, | |||
1339 | } | 1314 | } |
1340 | 1315 | ||
1341 | ret = brcmf_bus_start(dev); | 1316 | ret = brcmf_bus_start(dev); |
1342 | if (ret == -ENOLINK) { | 1317 | if (ret) { |
1343 | brcmf_dbg(ERROR, "dongle is not responding\n"); | 1318 | brcmf_dbg(ERROR, "dongle is not responding\n"); |
1344 | brcmf_detach(dev); | 1319 | brcmf_detach(dev); |
1345 | goto fail; | 1320 | goto fail; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 0e952092ee8f..cb30feaa565b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <brcmu_wifi.h> | 35 | #include <brcmu_wifi.h> |
36 | #include "dhd.h" | 36 | #include "dhd.h" |
37 | #include "wl_cfg80211.h" | 37 | #include "wl_cfg80211.h" |
38 | #include "fwil.h" | ||
38 | 39 | ||
39 | #define BRCMF_SCAN_IE_LEN_MAX 2048 | 40 | #define BRCMF_SCAN_IE_LEN_MAX 2048 |
40 | #define BRCMF_PNO_VERSION 2 | 41 | #define BRCMF_PNO_VERSION 2 |
@@ -48,6 +49,8 @@ | |||
48 | #define BRCMF_PNO_SCAN_COMPLETE 1 | 49 | #define BRCMF_PNO_SCAN_COMPLETE 1 |
49 | #define BRCMF_PNO_SCAN_INCOMPLETE 0 | 50 | #define BRCMF_PNO_SCAN_INCOMPLETE 0 |
50 | 51 | ||
52 | #define BRCMF_IFACE_MAX_CNT 2 | ||
53 | |||
51 | #define TLV_LEN_OFF 1 /* length offset */ | 54 | #define TLV_LEN_OFF 1 /* length offset */ |
52 | #define TLV_HDR_LEN 2 /* header length */ | 55 | #define TLV_HDR_LEN 2 /* header length */ |
53 | #define TLV_BODY_OFF 2 /* body offset */ | 56 | #define TLV_BODY_OFF 2 /* body offset */ |
@@ -91,16 +94,13 @@ | |||
91 | #define BRCMF_ASSOC_PARAMS_FIXED_SIZE \ | 94 | #define BRCMF_ASSOC_PARAMS_FIXED_SIZE \ |
92 | (sizeof(struct brcmf_assoc_params_le) - sizeof(u16)) | 95 | (sizeof(struct brcmf_assoc_params_le) - sizeof(u16)) |
93 | 96 | ||
94 | static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255}; | ||
95 | |||
96 | static u32 brcmf_dbg_level = WL_DBG_ERR; | 97 | static u32 brcmf_dbg_level = WL_DBG_ERR; |
97 | 98 | ||
98 | static bool check_sys_up(struct wiphy *wiphy) | 99 | static bool check_vif_up(struct brcmf_cfg80211_vif *vif) |
99 | { | 100 | { |
100 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 101 | if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state)) { |
101 | if (!test_bit(WL_STATUS_READY, &cfg->status)) { | 102 | WL_INFO("device is not ready : status (%lu)\n", |
102 | WL_INFO("device is not ready : status (%d)\n", | 103 | vif->sme_state); |
103 | (int)cfg->status); | ||
104 | return false; | 104 | return false; |
105 | } | 105 | } |
106 | return true; | 106 | return true; |
@@ -391,55 +391,29 @@ static u8 brcmf_mw_to_qdbm(u16 mw) | |||
391 | return qdbm; | 391 | return qdbm; |
392 | } | 392 | } |
393 | 393 | ||
394 | /* function for reading/writing a single u32 from/to the dongle */ | 394 | static u16 channel_to_chanspec(struct ieee80211_channel *ch) |
395 | static int | ||
396 | brcmf_exec_dcmd_u32(struct net_device *ndev, u32 cmd, u32 *par) | ||
397 | { | 395 | { |
398 | int err; | 396 | u16 chanspec; |
399 | __le32 par_le = cpu_to_le32(*par); | ||
400 | |||
401 | err = brcmf_exec_dcmd(ndev, cmd, &par_le, sizeof(__le32)); | ||
402 | *par = le32_to_cpu(par_le); | ||
403 | |||
404 | return err; | ||
405 | } | ||
406 | |||
407 | static s32 | ||
408 | brcmf_dev_iovar_setbuf_bsscfg(struct net_device *ndev, s8 *name, | ||
409 | void *param, s32 paramlen, | ||
410 | void *buf, s32 buflen, s32 bssidx) | ||
411 | { | ||
412 | s32 err = -ENOMEM; | ||
413 | u32 len; | ||
414 | |||
415 | len = brcmf_c_mkiovar_bsscfg(name, param, paramlen, | ||
416 | buf, buflen, bssidx); | ||
417 | BUG_ON(!len); | ||
418 | if (len > 0) | ||
419 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len); | ||
420 | if (err) | ||
421 | WL_ERR("error (%d)\n", err); | ||
422 | 397 | ||
423 | return err; | 398 | chanspec = ieee80211_frequency_to_channel(ch->center_freq); |
424 | } | 399 | chanspec &= WL_CHANSPEC_CHAN_MASK; |
425 | 400 | ||
426 | static s32 | 401 | if (ch->band == IEEE80211_BAND_2GHZ) |
427 | brcmf_dev_iovar_getbuf_bsscfg(struct net_device *ndev, s8 *name, | 402 | chanspec |= WL_CHANSPEC_BAND_2G; |
428 | void *param, s32 paramlen, | 403 | else |
429 | void *buf, s32 buflen, s32 bssidx) | 404 | chanspec |= WL_CHANSPEC_BAND_5G; |
430 | { | ||
431 | s32 err = -ENOMEM; | ||
432 | u32 len; | ||
433 | |||
434 | len = brcmf_c_mkiovar_bsscfg(name, param, paramlen, | ||
435 | buf, buflen, bssidx); | ||
436 | BUG_ON(!len); | ||
437 | if (len > 0) | ||
438 | err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, buf, len); | ||
439 | if (err) | ||
440 | WL_ERR("error (%d)\n", err); | ||
441 | 405 | ||
442 | return err; | 406 | if (ch->flags & IEEE80211_CHAN_NO_HT40) { |
407 | chanspec |= WL_CHANSPEC_BW_20; | ||
408 | chanspec |= WL_CHANSPEC_CTL_SB_NONE; | ||
409 | } else { | ||
410 | chanspec |= WL_CHANSPEC_BW_40; | ||
411 | if (ch->flags & IEEE80211_CHAN_NO_HT40PLUS) | ||
412 | chanspec |= WL_CHANSPEC_CTL_SB_LOWER; | ||
413 | else | ||
414 | chanspec |= WL_CHANSPEC_CTL_SB_UPPER; | ||
415 | } | ||
416 | return chanspec; | ||
443 | } | 417 | } |
444 | 418 | ||
445 | static void convert_key_from_CPU(struct brcmf_wsec_key *key, | 419 | static void convert_key_from_CPU(struct brcmf_wsec_key *key, |
@@ -457,18 +431,17 @@ static void convert_key_from_CPU(struct brcmf_wsec_key *key, | |||
457 | } | 431 | } |
458 | 432 | ||
459 | static int | 433 | static int |
460 | send_key_to_dongle(struct brcmf_cfg80211_info *cfg, s32 bssidx, | 434 | send_key_to_dongle(struct net_device *ndev, struct brcmf_wsec_key *key) |
461 | struct net_device *ndev, struct brcmf_wsec_key *key) | ||
462 | { | 435 | { |
463 | int err; | 436 | int err; |
464 | struct brcmf_wsec_key_le key_le; | 437 | struct brcmf_wsec_key_le key_le; |
465 | 438 | ||
466 | convert_key_from_CPU(key, &key_le); | 439 | convert_key_from_CPU(key, &key_le); |
467 | 440 | ||
468 | err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le, | 441 | brcmf_netdev_wait_pend8021x(ndev); |
469 | sizeof(key_le), | 442 | |
470 | cfg->extra_buf, | 443 | err = brcmf_fil_bsscfg_data_set(netdev_priv(ndev), "wsec_key", &key_le, |
471 | WL_EXTRA_BUF_MAX, bssidx); | 444 | sizeof(key_le)); |
472 | 445 | ||
473 | if (err) | 446 | if (err) |
474 | WL_ERR("wsec_key error (%d)\n", err); | 447 | WL_ERR("wsec_key error (%d)\n", err); |
@@ -480,6 +453,7 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, | |||
480 | enum nl80211_iftype type, u32 *flags, | 453 | enum nl80211_iftype type, u32 *flags, |
481 | struct vif_params *params) | 454 | struct vif_params *params) |
482 | { | 455 | { |
456 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
483 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 457 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
484 | s32 infra = 0; | 458 | s32 infra = 0; |
485 | s32 ap = 0; | 459 | s32 ap = 0; |
@@ -511,7 +485,7 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, | |||
511 | } | 485 | } |
512 | 486 | ||
513 | if (ap) { | 487 | if (ap) { |
514 | set_bit(WL_STATUS_AP_CREATING, &cfg->status); | 488 | set_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); |
515 | if (!cfg->ap_info) | 489 | if (!cfg->ap_info) |
516 | cfg->ap_info = kzalloc(sizeof(*cfg->ap_info), | 490 | cfg->ap_info = kzalloc(sizeof(*cfg->ap_info), |
517 | GFP_KERNEL); | 491 | GFP_KERNEL); |
@@ -521,7 +495,8 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, | |||
521 | } | 495 | } |
522 | WL_INFO("IF Type = AP\n"); | 496 | WL_INFO("IF Type = AP\n"); |
523 | } else { | 497 | } else { |
524 | err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra); | 498 | err = brcmf_fil_cmd_int_set(netdev_priv(ndev), |
499 | BRCMF_C_SET_INFRA, infra); | ||
525 | if (err) { | 500 | if (err) { |
526 | WL_ERR("WLC_SET_INFRA error (%d)\n", err); | 501 | WL_ERR("WLC_SET_INFRA error (%d)\n", err); |
527 | err = -EAGAIN; | 502 | err = -EAGAIN; |
@@ -539,99 +514,13 @@ done: | |||
539 | return err; | 514 | return err; |
540 | } | 515 | } |
541 | 516 | ||
542 | static s32 brcmf_dev_intvar_set(struct net_device *ndev, s8 *name, s32 val) | ||
543 | { | ||
544 | s8 buf[BRCMF_DCMD_SMLEN]; | ||
545 | u32 len; | ||
546 | s32 err = 0; | ||
547 | __le32 val_le; | ||
548 | |||
549 | val_le = cpu_to_le32(val); | ||
550 | len = brcmf_c_mkiovar(name, (char *)(&val_le), sizeof(val_le), buf, | ||
551 | sizeof(buf)); | ||
552 | BUG_ON(!len); | ||
553 | |||
554 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len); | ||
555 | if (err) | ||
556 | WL_ERR("error (%d)\n", err); | ||
557 | |||
558 | return err; | ||
559 | } | ||
560 | |||
561 | static s32 | ||
562 | brcmf_dev_intvar_get(struct net_device *ndev, s8 *name, s32 *retval) | ||
563 | { | ||
564 | union { | ||
565 | s8 buf[BRCMF_DCMD_SMLEN]; | ||
566 | __le32 val; | ||
567 | } var; | ||
568 | u32 len; | ||
569 | u32 data_null; | ||
570 | s32 err = 0; | ||
571 | |||
572 | len = | ||
573 | brcmf_c_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), | ||
574 | sizeof(var.buf)); | ||
575 | BUG_ON(!len); | ||
576 | err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, &var, len); | ||
577 | if (err) | ||
578 | WL_ERR("error (%d)\n", err); | ||
579 | |||
580 | *retval = le32_to_cpu(var.val); | ||
581 | |||
582 | return err; | ||
583 | } | ||
584 | |||
585 | static s32 | ||
586 | brcmf_dev_intvar_set_bsscfg(struct net_device *ndev, s8 *name, u32 val, | ||
587 | s32 bssidx) | ||
588 | { | ||
589 | s8 buf[BRCMF_DCMD_SMLEN]; | ||
590 | __le32 val_le; | ||
591 | |||
592 | val_le = cpu_to_le32(val); | ||
593 | |||
594 | return brcmf_dev_iovar_setbuf_bsscfg(ndev, name, &val_le, | ||
595 | sizeof(val_le), buf, sizeof(buf), | ||
596 | bssidx); | ||
597 | } | ||
598 | |||
599 | static s32 | ||
600 | brcmf_dev_intvar_get_bsscfg(struct net_device *ndev, s8 *name, s32 *val, | ||
601 | s32 bssidx) | ||
602 | { | ||
603 | s8 buf[BRCMF_DCMD_SMLEN]; | ||
604 | s32 err; | ||
605 | __le32 val_le; | ||
606 | |||
607 | memset(buf, 0, sizeof(buf)); | ||
608 | err = brcmf_dev_iovar_getbuf_bsscfg(ndev, name, val, sizeof(*val), buf, | ||
609 | sizeof(buf), bssidx); | ||
610 | if (err == 0) { | ||
611 | memcpy(&val_le, buf, sizeof(val_le)); | ||
612 | *val = le32_to_cpu(val_le); | ||
613 | } | ||
614 | return err; | ||
615 | } | ||
616 | |||
617 | |||
618 | /* | ||
619 | * For now brcmf_find_bssidx will return 0. Once p2p gets implemented this | ||
620 | * should return the ndev matching bssidx. | ||
621 | */ | ||
622 | static s32 | ||
623 | brcmf_find_bssidx(struct brcmf_cfg80211_info *cfg, struct net_device *ndev) | ||
624 | { | ||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | static void brcmf_set_mpc(struct net_device *ndev, int mpc) | 517 | static void brcmf_set_mpc(struct net_device *ndev, int mpc) |
629 | { | 518 | { |
519 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
630 | s32 err = 0; | 520 | s32 err = 0; |
631 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | ||
632 | 521 | ||
633 | if (test_bit(WL_STATUS_READY, &cfg->status)) { | 522 | if (check_vif_up(ifp->vif)) { |
634 | err = brcmf_dev_intvar_set(ndev, "mpc", mpc); | 523 | err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc); |
635 | if (err) { | 524 | if (err) { |
636 | WL_ERR("fail to set mpc\n"); | 525 | WL_ERR("fail to set mpc\n"); |
637 | return; | 526 | return; |
@@ -643,7 +532,7 @@ static void brcmf_set_mpc(struct net_device *ndev, int mpc) | |||
643 | static void brcmf_iscan_prep(struct brcmf_scan_params_le *params_le, | 532 | static void brcmf_iscan_prep(struct brcmf_scan_params_le *params_le, |
644 | struct brcmf_ssid *ssid) | 533 | struct brcmf_ssid *ssid) |
645 | { | 534 | { |
646 | memcpy(params_le->bssid, ether_bcast, ETH_ALEN); | 535 | memset(params_le->bssid, 0xFF, ETH_ALEN); |
647 | params_le->bss_type = DOT11_BSSTYPE_ANY; | 536 | params_le->bss_type = DOT11_BSSTYPE_ANY; |
648 | params_le->scan_type = 0; | 537 | params_le->scan_type = 0; |
649 | params_le->channel_num = 0; | 538 | params_le->channel_num = 0; |
@@ -658,30 +547,6 @@ static void brcmf_iscan_prep(struct brcmf_scan_params_le *params_le, | |||
658 | } | 547 | } |
659 | 548 | ||
660 | static s32 | 549 | static s32 |
661 | brcmf_dev_iovar_setbuf(struct net_device *ndev, s8 * iovar, void *param, | ||
662 | s32 paramlen, void *bufptr, s32 buflen) | ||
663 | { | ||
664 | s32 iolen; | ||
665 | |||
666 | iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen); | ||
667 | BUG_ON(!iolen); | ||
668 | |||
669 | return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, bufptr, iolen); | ||
670 | } | ||
671 | |||
672 | static s32 | ||
673 | brcmf_dev_iovar_getbuf(struct net_device *ndev, s8 * iovar, void *param, | ||
674 | s32 paramlen, void *bufptr, s32 buflen) | ||
675 | { | ||
676 | s32 iolen; | ||
677 | |||
678 | iolen = brcmf_c_mkiovar(iovar, param, paramlen, bufptr, buflen); | ||
679 | BUG_ON(!iolen); | ||
680 | |||
681 | return brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, bufptr, buflen); | ||
682 | } | ||
683 | |||
684 | static s32 | ||
685 | brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan, | 550 | brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan, |
686 | struct brcmf_ssid *ssid, u16 action) | 551 | struct brcmf_ssid *ssid, u16 action) |
687 | { | 552 | { |
@@ -703,8 +568,8 @@ brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan, | |||
703 | params->action = cpu_to_le16(action); | 568 | params->action = cpu_to_le16(action); |
704 | params->scan_duration = cpu_to_le16(0); | 569 | params->scan_duration = cpu_to_le16(0); |
705 | 570 | ||
706 | err = brcmf_dev_iovar_setbuf(iscan->ndev, "iscan", params, params_size, | 571 | err = brcmf_fil_iovar_data_set(netdev_priv(iscan->ndev), "iscan", |
707 | iscan->dcmd_buf, BRCMF_DCMD_SMLEN); | 572 | params, params_size); |
708 | if (err) { | 573 | if (err) { |
709 | if (err == -EBUSY) | 574 | if (err == -EBUSY) |
710 | WL_INFO("system busy : iscan canceled\n"); | 575 | WL_INFO("system busy : iscan canceled\n"); |
@@ -721,7 +586,7 @@ static s32 brcmf_do_iscan(struct brcmf_cfg80211_info *cfg) | |||
721 | struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg); | 586 | struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg); |
722 | struct net_device *ndev = cfg_to_ndev(cfg); | 587 | struct net_device *ndev = cfg_to_ndev(cfg); |
723 | struct brcmf_ssid ssid; | 588 | struct brcmf_ssid ssid; |
724 | __le32 passive_scan; | 589 | u32 passive_scan; |
725 | s32 err = 0; | 590 | s32 err = 0; |
726 | 591 | ||
727 | /* Broadcast scan by default */ | 592 | /* Broadcast scan by default */ |
@@ -729,9 +594,9 @@ static s32 brcmf_do_iscan(struct brcmf_cfg80211_info *cfg) | |||
729 | 594 | ||
730 | iscan->state = WL_ISCAN_STATE_SCANING; | 595 | iscan->state = WL_ISCAN_STATE_SCANING; |
731 | 596 | ||
732 | passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1); | 597 | passive_scan = cfg->active_scan ? 0 : 1; |
733 | err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCMF_C_SET_PASSIVE_SCAN, | 598 | err = brcmf_fil_cmd_int_set(netdev_priv(ndev), |
734 | &passive_scan, sizeof(passive_scan)); | 599 | BRCMF_C_SET_PASSIVE_SCAN, passive_scan); |
735 | if (err) { | 600 | if (err) { |
736 | WL_ERR("error (%d)\n", err); | 601 | WL_ERR("error (%d)\n", err); |
737 | return err; | 602 | return err; |
@@ -754,27 +619,27 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, | |||
754 | struct cfg80211_scan_request *request, | 619 | struct cfg80211_scan_request *request, |
755 | struct cfg80211_ssid *this_ssid) | 620 | struct cfg80211_ssid *this_ssid) |
756 | { | 621 | { |
622 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
757 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | 623 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); |
758 | struct cfg80211_ssid *ssids; | 624 | struct cfg80211_ssid *ssids; |
759 | struct brcmf_cfg80211_scan_req *sr = cfg->scan_req_int; | 625 | struct brcmf_cfg80211_scan_req *sr = cfg->scan_req_int; |
760 | __le32 passive_scan; | 626 | u32 passive_scan; |
761 | bool iscan_req; | 627 | bool iscan_req; |
762 | bool spec_scan; | 628 | bool spec_scan; |
763 | s32 err = 0; | 629 | s32 err = 0; |
764 | u32 SSID_len; | 630 | u32 SSID_len; |
765 | 631 | ||
766 | if (test_bit(WL_STATUS_SCANNING, &cfg->status)) { | 632 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { |
767 | WL_ERR("Scanning already : status (%lu)\n", cfg->status); | 633 | WL_ERR("Scanning already: status (%lu)\n", cfg->scan_status); |
768 | return -EAGAIN; | 634 | return -EAGAIN; |
769 | } | 635 | } |
770 | if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg->status)) { | 636 | if (test_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status)) { |
771 | WL_ERR("Scanning being aborted : status (%lu)\n", | 637 | WL_ERR("Scanning being aborted: status (%lu)\n", |
772 | cfg->status); | 638 | cfg->scan_status); |
773 | return -EAGAIN; | 639 | return -EAGAIN; |
774 | } | 640 | } |
775 | if (test_bit(WL_STATUS_CONNECTING, &cfg->status)) { | 641 | if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) { |
776 | WL_ERR("Connecting : status (%lu)\n", | 642 | WL_ERR("Connecting: status (%lu)\n", ifp->vif->sme_state); |
777 | cfg->status); | ||
778 | return -EAGAIN; | 643 | return -EAGAIN; |
779 | } | 644 | } |
780 | 645 | ||
@@ -792,7 +657,7 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, | |||
792 | } | 657 | } |
793 | 658 | ||
794 | cfg->scan_request = request; | 659 | cfg->scan_request = request; |
795 | set_bit(WL_STATUS_SCANNING, &cfg->status); | 660 | set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
796 | if (iscan_req) { | 661 | if (iscan_req) { |
797 | err = brcmf_do_iscan(cfg); | 662 | err = brcmf_do_iscan(cfg); |
798 | if (!err) | 663 | if (!err) |
@@ -813,16 +678,16 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, | |||
813 | WL_SCAN("Broadcast scan\n"); | 678 | WL_SCAN("Broadcast scan\n"); |
814 | } | 679 | } |
815 | 680 | ||
816 | passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1); | 681 | passive_scan = cfg->active_scan ? 0 : 1; |
817 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN, | 682 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN, |
818 | &passive_scan, sizeof(passive_scan)); | 683 | passive_scan); |
819 | if (err) { | 684 | if (err) { |
820 | WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err); | 685 | WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err); |
821 | goto scan_out; | 686 | goto scan_out; |
822 | } | 687 | } |
823 | brcmf_set_mpc(ndev, 0); | 688 | brcmf_set_mpc(ndev, 0); |
824 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le, | 689 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, |
825 | sizeof(sr->ssid_le)); | 690 | &sr->ssid_le, sizeof(sr->ssid_le)); |
826 | if (err) { | 691 | if (err) { |
827 | if (err == -EBUSY) | 692 | if (err == -EBUSY) |
828 | WL_INFO("system busy : scan for \"%s\" " | 693 | WL_INFO("system busy : scan for \"%s\" " |
@@ -838,7 +703,7 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, | |||
838 | return 0; | 703 | return 0; |
839 | 704 | ||
840 | scan_out: | 705 | scan_out: |
841 | clear_bit(WL_STATUS_SCANNING, &cfg->status); | 706 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
842 | cfg->scan_request = NULL; | 707 | cfg->scan_request = NULL; |
843 | return err; | 708 | return err; |
844 | } | 709 | } |
@@ -851,12 +716,10 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, | |||
851 | s32 i; | 716 | s32 i; |
852 | s32 offset; | 717 | s32 offset; |
853 | u16 chanspec; | 718 | u16 chanspec; |
854 | u16 channel; | ||
855 | struct ieee80211_channel *req_channel; | ||
856 | char *ptr; | 719 | char *ptr; |
857 | struct brcmf_ssid_le ssid_le; | 720 | struct brcmf_ssid_le ssid_le; |
858 | 721 | ||
859 | memcpy(params_le->bssid, ether_bcast, ETH_ALEN); | 722 | memset(params_le->bssid, 0xFF, ETH_ALEN); |
860 | params_le->bss_type = DOT11_BSSTYPE_ANY; | 723 | params_le->bss_type = DOT11_BSSTYPE_ANY; |
861 | params_le->scan_type = 0; | 724 | params_le->scan_type = 0; |
862 | params_le->channel_num = 0; | 725 | params_le->channel_num = 0; |
@@ -876,30 +739,9 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, | |||
876 | WL_SCAN("### List of channelspecs to scan ### %d\n", n_channels); | 739 | WL_SCAN("### List of channelspecs to scan ### %d\n", n_channels); |
877 | if (n_channels > 0) { | 740 | if (n_channels > 0) { |
878 | for (i = 0; i < n_channels; i++) { | 741 | for (i = 0; i < n_channels; i++) { |
879 | chanspec = 0; | 742 | chanspec = channel_to_chanspec(request->channels[i]); |
880 | req_channel = request->channels[i]; | ||
881 | channel = ieee80211_frequency_to_channel( | ||
882 | req_channel->center_freq); | ||
883 | if (req_channel->band == IEEE80211_BAND_2GHZ) | ||
884 | chanspec |= WL_CHANSPEC_BAND_2G; | ||
885 | else | ||
886 | chanspec |= WL_CHANSPEC_BAND_5G; | ||
887 | |||
888 | if (req_channel->flags & IEEE80211_CHAN_NO_HT40) { | ||
889 | chanspec |= WL_CHANSPEC_BW_20; | ||
890 | chanspec |= WL_CHANSPEC_CTL_SB_NONE; | ||
891 | } else { | ||
892 | chanspec |= WL_CHANSPEC_BW_40; | ||
893 | if (req_channel->flags & | ||
894 | IEEE80211_CHAN_NO_HT40PLUS) | ||
895 | chanspec |= WL_CHANSPEC_CTL_SB_LOWER; | ||
896 | else | ||
897 | chanspec |= WL_CHANSPEC_CTL_SB_UPPER; | ||
898 | } | ||
899 | |||
900 | chanspec |= (channel & WL_CHANSPEC_CHAN_MASK); | ||
901 | WL_SCAN("Chan : %d, Channel spec: %x\n", | 743 | WL_SCAN("Chan : %d, Channel spec: %x\n", |
902 | channel, chanspec); | 744 | request->channels[i]->hw_value, chanspec); |
903 | params_le->channel_list[i] = cpu_to_le16(chanspec); | 745 | params_le->channel_list[i] = cpu_to_le16(chanspec); |
904 | } | 746 | } |
905 | } else { | 747 | } else { |
@@ -966,7 +808,7 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, | |||
966 | /* Do a scan abort to stop the driver's scan engine */ | 808 | /* Do a scan abort to stop the driver's scan engine */ |
967 | WL_SCAN("ABORT scan in firmware\n"); | 809 | WL_SCAN("ABORT scan in firmware\n"); |
968 | memset(¶ms_le, 0, sizeof(params_le)); | 810 | memset(¶ms_le, 0, sizeof(params_le)); |
969 | memcpy(params_le.bssid, ether_bcast, ETH_ALEN); | 811 | memset(params_le.bssid, 0xFF, ETH_ALEN); |
970 | params_le.bss_type = DOT11_BSSTYPE_ANY; | 812 | params_le.bss_type = DOT11_BSSTYPE_ANY; |
971 | params_le.scan_type = 0; | 813 | params_le.scan_type = 0; |
972 | params_le.channel_num = cpu_to_le32(1); | 814 | params_le.channel_num = cpu_to_le32(1); |
@@ -977,8 +819,8 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, | |||
977 | /* Scan is aborted by setting channel_list[0] to -1 */ | 819 | /* Scan is aborted by setting channel_list[0] to -1 */ |
978 | params_le.channel_list[0] = cpu_to_le16(-1); | 820 | params_le.channel_list[0] = cpu_to_le16(-1); |
979 | /* E-Scan (or anyother type) can be aborted by SCAN */ | 821 | /* E-Scan (or anyother type) can be aborted by SCAN */ |
980 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, ¶ms_le, | 822 | err = brcmf_fil_cmd_data_set(netdev_priv(ndev), BRCMF_C_SCAN, |
981 | sizeof(params_le)); | 823 | ¶ms_le, sizeof(params_le)); |
982 | if (err) | 824 | if (err) |
983 | WL_ERR("Scan abort failed\n"); | 825 | WL_ERR("Scan abort failed\n"); |
984 | } | 826 | } |
@@ -998,7 +840,7 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, | |||
998 | cfg80211_scan_done(scan_request, aborted); | 840 | cfg80211_scan_done(scan_request, aborted); |
999 | brcmf_set_mpc(ndev, 1); | 841 | brcmf_set_mpc(ndev, 1); |
1000 | } | 842 | } |
1001 | if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) { | 843 | if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { |
1002 | WL_ERR("Scan complete while device not scanning\n"); | 844 | WL_ERR("Scan complete while device not scanning\n"); |
1003 | return -EPERM; | 845 | return -EPERM; |
1004 | } | 846 | } |
@@ -1036,8 +878,8 @@ brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, | |||
1036 | params->action = cpu_to_le16(action); | 878 | params->action = cpu_to_le16(action); |
1037 | params->sync_id = cpu_to_le16(0x1234); | 879 | params->sync_id = cpu_to_le16(0x1234); |
1038 | 880 | ||
1039 | err = brcmf_dev_iovar_setbuf(ndev, "escan", params, params_size, | 881 | err = brcmf_fil_iovar_data_set(netdev_priv(ndev), "escan", |
1040 | cfg->escan_ioctl_buf, BRCMF_DCMD_MEDLEN); | 882 | params, params_size); |
1041 | if (err) { | 883 | if (err) { |
1042 | if (err == -EBUSY) | 884 | if (err == -EBUSY) |
1043 | WL_INFO("system busy : escan canceled\n"); | 885 | WL_INFO("system busy : escan canceled\n"); |
@@ -1055,16 +897,16 @@ brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, | |||
1055 | struct net_device *ndev, struct cfg80211_scan_request *request) | 897 | struct net_device *ndev, struct cfg80211_scan_request *request) |
1056 | { | 898 | { |
1057 | s32 err; | 899 | s32 err; |
1058 | __le32 passive_scan; | 900 | u32 passive_scan; |
1059 | struct brcmf_scan_results *results; | 901 | struct brcmf_scan_results *results; |
1060 | 902 | ||
1061 | WL_SCAN("Enter\n"); | 903 | WL_SCAN("Enter\n"); |
1062 | cfg->escan_info.ndev = ndev; | 904 | cfg->escan_info.ndev = ndev; |
1063 | cfg->escan_info.wiphy = wiphy; | 905 | cfg->escan_info.wiphy = wiphy; |
1064 | cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANNING; | 906 | cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANNING; |
1065 | passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1); | 907 | passive_scan = cfg->active_scan ? 0 : 1; |
1066 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN, | 908 | err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PASSIVE_SCAN, |
1067 | &passive_scan, sizeof(passive_scan)); | 909 | passive_scan); |
1068 | if (err) { | 910 | if (err) { |
1069 | WL_ERR("error (%d)\n", err); | 911 | WL_ERR("error (%d)\n", err); |
1070 | return err; | 912 | return err; |
@@ -1086,10 +928,11 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, | |||
1086 | struct cfg80211_scan_request *request, | 928 | struct cfg80211_scan_request *request, |
1087 | struct cfg80211_ssid *this_ssid) | 929 | struct cfg80211_ssid *this_ssid) |
1088 | { | 930 | { |
931 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
1089 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | 932 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); |
1090 | struct cfg80211_ssid *ssids; | 933 | struct cfg80211_ssid *ssids; |
1091 | struct brcmf_cfg80211_scan_req *sr = cfg->scan_req_int; | 934 | struct brcmf_cfg80211_scan_req *sr = cfg->scan_req_int; |
1092 | __le32 passive_scan; | 935 | u32 passive_scan; |
1093 | bool escan_req; | 936 | bool escan_req; |
1094 | bool spec_scan; | 937 | bool spec_scan; |
1095 | s32 err; | 938 | s32 err; |
@@ -1097,18 +940,17 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, | |||
1097 | 940 | ||
1098 | WL_SCAN("START ESCAN\n"); | 941 | WL_SCAN("START ESCAN\n"); |
1099 | 942 | ||
1100 | if (test_bit(WL_STATUS_SCANNING, &cfg->status)) { | 943 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { |
1101 | WL_ERR("Scanning already : status (%lu)\n", cfg->status); | 944 | WL_ERR("Scanning already: status (%lu)\n", cfg->scan_status); |
1102 | return -EAGAIN; | 945 | return -EAGAIN; |
1103 | } | 946 | } |
1104 | if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg->status)) { | 947 | if (test_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status)) { |
1105 | WL_ERR("Scanning being aborted : status (%lu)\n", | 948 | WL_ERR("Scanning being aborted: status (%lu)\n", |
1106 | cfg->status); | 949 | cfg->scan_status); |
1107 | return -EAGAIN; | 950 | return -EAGAIN; |
1108 | } | 951 | } |
1109 | if (test_bit(WL_STATUS_CONNECTING, &cfg->status)) { | 952 | if (test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) { |
1110 | WL_ERR("Connecting : status (%lu)\n", | 953 | WL_ERR("Connecting: status (%lu)\n", ifp->vif->sme_state); |
1111 | cfg->status); | ||
1112 | return -EAGAIN; | 954 | return -EAGAIN; |
1113 | } | 955 | } |
1114 | 956 | ||
@@ -1128,7 +970,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, | |||
1128 | } | 970 | } |
1129 | 971 | ||
1130 | cfg->scan_request = request; | 972 | cfg->scan_request = request; |
1131 | set_bit(WL_STATUS_SCANNING, &cfg->status); | 973 | set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
1132 | if (escan_req) { | 974 | if (escan_req) { |
1133 | err = brcmf_do_escan(cfg, wiphy, ndev, request); | 975 | err = brcmf_do_escan(cfg, wiphy, ndev, request); |
1134 | if (!err) | 976 | if (!err) |
@@ -1149,16 +991,16 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, | |||
1149 | } else | 991 | } else |
1150 | WL_SCAN("Broadcast scan\n"); | 992 | WL_SCAN("Broadcast scan\n"); |
1151 | 993 | ||
1152 | passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1); | 994 | passive_scan = cfg->active_scan ? 0 : 1; |
1153 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN, | 995 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PASSIVE_SCAN, |
1154 | &passive_scan, sizeof(passive_scan)); | 996 | passive_scan); |
1155 | if (err) { | 997 | if (err) { |
1156 | WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err); | 998 | WL_ERR("WLC_SET_PASSIVE_SCAN error (%d)\n", err); |
1157 | goto scan_out; | 999 | goto scan_out; |
1158 | } | 1000 | } |
1159 | brcmf_set_mpc(ndev, 0); | 1001 | brcmf_set_mpc(ndev, 0); |
1160 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN, &sr->ssid_le, | 1002 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCAN, |
1161 | sizeof(sr->ssid_le)); | 1003 | &sr->ssid_le, sizeof(sr->ssid_le)); |
1162 | if (err) { | 1004 | if (err) { |
1163 | if (err == -EBUSY) | 1005 | if (err == -EBUSY) |
1164 | WL_INFO("BUSY: scan for \"%s\" canceled\n", | 1006 | WL_INFO("BUSY: scan for \"%s\" canceled\n", |
@@ -1174,7 +1016,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, | |||
1174 | return 0; | 1016 | return 0; |
1175 | 1017 | ||
1176 | scan_out: | 1018 | scan_out: |
1177 | clear_bit(WL_STATUS_SCANNING, &cfg->status); | 1019 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
1178 | if (timer_pending(&cfg->escan_timeout)) | 1020 | if (timer_pending(&cfg->escan_timeout)) |
1179 | del_timer_sync(&cfg->escan_timeout); | 1021 | del_timer_sync(&cfg->escan_timeout); |
1180 | cfg->scan_request = NULL; | 1022 | cfg->scan_request = NULL; |
@@ -1182,8 +1024,7 @@ scan_out: | |||
1182 | } | 1024 | } |
1183 | 1025 | ||
1184 | static s32 | 1026 | static s32 |
1185 | brcmf_cfg80211_scan(struct wiphy *wiphy, | 1027 | brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) |
1186 | struct cfg80211_scan_request *request) | ||
1187 | { | 1028 | { |
1188 | struct net_device *ndev = request->wdev->netdev; | 1029 | struct net_device *ndev = request->wdev->netdev; |
1189 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | 1030 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); |
@@ -1191,7 +1032,8 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, | |||
1191 | 1032 | ||
1192 | WL_TRACE("Enter\n"); | 1033 | WL_TRACE("Enter\n"); |
1193 | 1034 | ||
1194 | if (!check_sys_up(wiphy)) | 1035 | if (!check_vif_up(container_of(request->wdev, |
1036 | struct brcmf_cfg80211_vif, wdev))) | ||
1195 | return -EIO; | 1037 | return -EIO; |
1196 | 1038 | ||
1197 | if (cfg->iscan_on) | 1039 | if (cfg->iscan_on) |
@@ -1210,7 +1052,8 @@ static s32 brcmf_set_rts(struct net_device *ndev, u32 rts_threshold) | |||
1210 | { | 1052 | { |
1211 | s32 err = 0; | 1053 | s32 err = 0; |
1212 | 1054 | ||
1213 | err = brcmf_dev_intvar_set(ndev, "rtsthresh", rts_threshold); | 1055 | err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "rtsthresh", |
1056 | rts_threshold); | ||
1214 | if (err) | 1057 | if (err) |
1215 | WL_ERR("Error (%d)\n", err); | 1058 | WL_ERR("Error (%d)\n", err); |
1216 | 1059 | ||
@@ -1221,7 +1064,8 @@ static s32 brcmf_set_frag(struct net_device *ndev, u32 frag_threshold) | |||
1221 | { | 1064 | { |
1222 | s32 err = 0; | 1065 | s32 err = 0; |
1223 | 1066 | ||
1224 | err = brcmf_dev_intvar_set(ndev, "fragthresh", frag_threshold); | 1067 | err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "fragthresh", |
1068 | frag_threshold); | ||
1225 | if (err) | 1069 | if (err) |
1226 | WL_ERR("Error (%d)\n", err); | 1070 | WL_ERR("Error (%d)\n", err); |
1227 | 1071 | ||
@@ -1233,7 +1077,7 @@ static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l) | |||
1233 | s32 err = 0; | 1077 | s32 err = 0; |
1234 | u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL); | 1078 | u32 cmd = (l ? BRCM_SET_LRL : BRCM_SET_SRL); |
1235 | 1079 | ||
1236 | err = brcmf_exec_dcmd_u32(ndev, cmd, &retry); | 1080 | err = brcmf_fil_cmd_int_set(netdev_priv(ndev), cmd, retry); |
1237 | if (err) { | 1081 | if (err) { |
1238 | WL_ERR("cmd (%d) , error (%d)\n", cmd, err); | 1082 | WL_ERR("cmd (%d) , error (%d)\n", cmd, err); |
1239 | return err; | 1083 | return err; |
@@ -1245,10 +1089,11 @@ static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
1245 | { | 1089 | { |
1246 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 1090 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
1247 | struct net_device *ndev = cfg_to_ndev(cfg); | 1091 | struct net_device *ndev = cfg_to_ndev(cfg); |
1092 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
1248 | s32 err = 0; | 1093 | s32 err = 0; |
1249 | 1094 | ||
1250 | WL_TRACE("Enter\n"); | 1095 | WL_TRACE("Enter\n"); |
1251 | if (!check_sys_up(wiphy)) | 1096 | if (!check_vif_up(ifp->vif)) |
1252 | return -EIO; | 1097 | return -EIO; |
1253 | 1098 | ||
1254 | if (changed & WIPHY_PARAM_RTS_THRESHOLD && | 1099 | if (changed & WIPHY_PARAM_RTS_THRESHOLD && |
@@ -1327,7 +1172,8 @@ static void brcmf_link_down(struct brcmf_cfg80211_info *cfg) | |||
1327 | if (cfg->link_up) { | 1172 | if (cfg->link_up) { |
1328 | ndev = cfg_to_ndev(cfg); | 1173 | ndev = cfg_to_ndev(cfg); |
1329 | WL_INFO("Call WLC_DISASSOC to stop excess roaming\n "); | 1174 | WL_INFO("Call WLC_DISASSOC to stop excess roaming\n "); |
1330 | err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, NULL, 0); | 1175 | err = brcmf_fil_cmd_data_set(netdev_priv(ndev), |
1176 | BRCMF_C_DISASSOC, NULL, 0); | ||
1331 | if (err) | 1177 | if (err) |
1332 | WL_ERR("WLC_DISASSOC failed (%d)\n", err); | 1178 | WL_ERR("WLC_DISASSOC failed (%d)\n", err); |
1333 | cfg->link_up = false; | 1179 | cfg->link_up = false; |
@@ -1340,7 +1186,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, | |||
1340 | struct cfg80211_ibss_params *params) | 1186 | struct cfg80211_ibss_params *params) |
1341 | { | 1187 | { |
1342 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 1188 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
1343 | struct brcmf_cfg80211_profile *profile = cfg->profile; | 1189 | struct brcmf_if *ifp = netdev_priv(ndev); |
1190 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | ||
1344 | struct brcmf_join_params join_params; | 1191 | struct brcmf_join_params join_params; |
1345 | size_t join_params_size = 0; | 1192 | size_t join_params_size = 0; |
1346 | s32 err = 0; | 1193 | s32 err = 0; |
@@ -1348,7 +1195,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, | |||
1348 | s32 bcnprd; | 1195 | s32 bcnprd; |
1349 | 1196 | ||
1350 | WL_TRACE("Enter\n"); | 1197 | WL_TRACE("Enter\n"); |
1351 | if (!check_sys_up(wiphy)) | 1198 | if (!check_vif_up(ifp->vif)) |
1352 | return -EIO; | 1199 | return -EIO; |
1353 | 1200 | ||
1354 | if (params->ssid) | 1201 | if (params->ssid) |
@@ -1358,7 +1205,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, | |||
1358 | return -EOPNOTSUPP; | 1205 | return -EOPNOTSUPP; |
1359 | } | 1206 | } |
1360 | 1207 | ||
1361 | set_bit(WL_STATUS_CONNECTING, &cfg->status); | 1208 | set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state); |
1362 | 1209 | ||
1363 | if (params->bssid) | 1210 | if (params->bssid) |
1364 | WL_CONN("BSSID: %pM\n", params->bssid); | 1211 | WL_CONN("BSSID: %pM\n", params->bssid); |
@@ -1399,7 +1246,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, | |||
1399 | if (params->privacy) | 1246 | if (params->privacy) |
1400 | wsec |= WEP_ENABLED; | 1247 | wsec |= WEP_ENABLED; |
1401 | 1248 | ||
1402 | err = brcmf_dev_intvar_set(ndev, "wsec", wsec); | 1249 | err = brcmf_fil_iovar_int_set(ifp, "wsec", wsec); |
1403 | if (err) { | 1250 | if (err) { |
1404 | WL_ERR("wsec failed (%d)\n", err); | 1251 | WL_ERR("wsec failed (%d)\n", err); |
1405 | goto done; | 1252 | goto done; |
@@ -1411,7 +1258,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, | |||
1411 | else | 1258 | else |
1412 | bcnprd = 100; | 1259 | bcnprd = 100; |
1413 | 1260 | ||
1414 | err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_BCNPRD, &bcnprd); | 1261 | err = brcmf_fil_cmd_int_set(ifp, BRCM_SET_BCNPRD, bcnprd); |
1415 | if (err) { | 1262 | if (err) { |
1416 | WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err); | 1263 | WL_ERR("WLC_SET_BCNPRD failed (%d)\n", err); |
1417 | goto done; | 1264 | goto done; |
@@ -1434,7 +1281,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, | |||
1434 | BRCMF_ASSOC_PARAMS_FIXED_SIZE; | 1281 | BRCMF_ASSOC_PARAMS_FIXED_SIZE; |
1435 | memcpy(profile->bssid, params->bssid, ETH_ALEN); | 1282 | memcpy(profile->bssid, params->bssid, ETH_ALEN); |
1436 | } else { | 1283 | } else { |
1437 | memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN); | 1284 | memset(join_params.params_le.bssid, 0xFF, ETH_ALEN); |
1438 | memset(profile->bssid, 0, ETH_ALEN); | 1285 | memset(profile->bssid, 0, ETH_ALEN); |
1439 | } | 1286 | } |
1440 | 1287 | ||
@@ -1453,8 +1300,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, | |||
1453 | 1300 | ||
1454 | /* set channel for starter */ | 1301 | /* set channel for starter */ |
1455 | target_channel = cfg->channel; | 1302 | target_channel = cfg->channel; |
1456 | err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_CHANNEL, | 1303 | err = brcmf_fil_cmd_int_set(ifp, BRCM_SET_CHANNEL, |
1457 | &target_channel); | 1304 | target_channel); |
1458 | if (err) { | 1305 | if (err) { |
1459 | WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err); | 1306 | WL_ERR("WLC_SET_CHANNEL failed (%d)\n", err); |
1460 | goto done; | 1307 | goto done; |
@@ -1465,8 +1312,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, | |||
1465 | cfg->ibss_starter = false; | 1312 | cfg->ibss_starter = false; |
1466 | 1313 | ||
1467 | 1314 | ||
1468 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, | 1315 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, |
1469 | &join_params, join_params_size); | 1316 | &join_params, join_params_size); |
1470 | if (err) { | 1317 | if (err) { |
1471 | WL_ERR("WLC_SET_SSID failed (%d)\n", err); | 1318 | WL_ERR("WLC_SET_SSID failed (%d)\n", err); |
1472 | goto done; | 1319 | goto done; |
@@ -1474,7 +1321,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, | |||
1474 | 1321 | ||
1475 | done: | 1322 | done: |
1476 | if (err) | 1323 | if (err) |
1477 | clear_bit(WL_STATUS_CONNECTING, &cfg->status); | 1324 | clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state); |
1478 | WL_TRACE("Exit\n"); | 1325 | WL_TRACE("Exit\n"); |
1479 | return err; | 1326 | return err; |
1480 | } | 1327 | } |
@@ -1483,10 +1330,11 @@ static s32 | |||
1483 | brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) | 1330 | brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) |
1484 | { | 1331 | { |
1485 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 1332 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
1333 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
1486 | s32 err = 0; | 1334 | s32 err = 0; |
1487 | 1335 | ||
1488 | WL_TRACE("Enter\n"); | 1336 | WL_TRACE("Enter\n"); |
1489 | if (!check_sys_up(wiphy)) | 1337 | if (!check_vif_up(ifp->vif)) |
1490 | return -EIO; | 1338 | return -EIO; |
1491 | 1339 | ||
1492 | brcmf_link_down(cfg); | 1340 | brcmf_link_down(cfg); |
@@ -1499,8 +1347,7 @@ brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) | |||
1499 | static s32 brcmf_set_wpa_version(struct net_device *ndev, | 1347 | static s32 brcmf_set_wpa_version(struct net_device *ndev, |
1500 | struct cfg80211_connect_params *sme) | 1348 | struct cfg80211_connect_params *sme) |
1501 | { | 1349 | { |
1502 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | 1350 | struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); |
1503 | struct brcmf_cfg80211_profile *profile = cfg->profile; | ||
1504 | struct brcmf_cfg80211_security *sec; | 1351 | struct brcmf_cfg80211_security *sec; |
1505 | s32 val = 0; | 1352 | s32 val = 0; |
1506 | s32 err = 0; | 1353 | s32 err = 0; |
@@ -1512,7 +1359,7 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev, | |||
1512 | else | 1359 | else |
1513 | val = WPA_AUTH_DISABLED; | 1360 | val = WPA_AUTH_DISABLED; |
1514 | WL_CONN("setting wpa_auth to 0x%0x\n", val); | 1361 | WL_CONN("setting wpa_auth to 0x%0x\n", val); |
1515 | err = brcmf_dev_intvar_set(ndev, "wpa_auth", val); | 1362 | err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "wpa_auth", val); |
1516 | if (err) { | 1363 | if (err) { |
1517 | WL_ERR("set wpa_auth failed (%d)\n", err); | 1364 | WL_ERR("set wpa_auth failed (%d)\n", err); |
1518 | return err; | 1365 | return err; |
@@ -1525,8 +1372,7 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev, | |||
1525 | static s32 brcmf_set_auth_type(struct net_device *ndev, | 1372 | static s32 brcmf_set_auth_type(struct net_device *ndev, |
1526 | struct cfg80211_connect_params *sme) | 1373 | struct cfg80211_connect_params *sme) |
1527 | { | 1374 | { |
1528 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | 1375 | struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); |
1529 | struct brcmf_cfg80211_profile *profile = cfg->profile; | ||
1530 | struct brcmf_cfg80211_security *sec; | 1376 | struct brcmf_cfg80211_security *sec; |
1531 | s32 val = 0; | 1377 | s32 val = 0; |
1532 | s32 err = 0; | 1378 | s32 err = 0; |
@@ -1552,7 +1398,7 @@ static s32 brcmf_set_auth_type(struct net_device *ndev, | |||
1552 | break; | 1398 | break; |
1553 | } | 1399 | } |
1554 | 1400 | ||
1555 | err = brcmf_dev_intvar_set(ndev, "auth", val); | 1401 | err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "auth", val); |
1556 | if (err) { | 1402 | if (err) { |
1557 | WL_ERR("set auth failed (%d)\n", err); | 1403 | WL_ERR("set auth failed (%d)\n", err); |
1558 | return err; | 1404 | return err; |
@@ -1566,8 +1412,7 @@ static s32 | |||
1566 | brcmf_set_set_cipher(struct net_device *ndev, | 1412 | brcmf_set_set_cipher(struct net_device *ndev, |
1567 | struct cfg80211_connect_params *sme) | 1413 | struct cfg80211_connect_params *sme) |
1568 | { | 1414 | { |
1569 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | 1415 | struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); |
1570 | struct brcmf_cfg80211_profile *profile = cfg->profile; | ||
1571 | struct brcmf_cfg80211_security *sec; | 1416 | struct brcmf_cfg80211_security *sec; |
1572 | s32 pval = 0; | 1417 | s32 pval = 0; |
1573 | s32 gval = 0; | 1418 | s32 gval = 0; |
@@ -1617,7 +1462,7 @@ brcmf_set_set_cipher(struct net_device *ndev, | |||
1617 | } | 1462 | } |
1618 | 1463 | ||
1619 | WL_CONN("pval (%d) gval (%d)\n", pval, gval); | 1464 | WL_CONN("pval (%d) gval (%d)\n", pval, gval); |
1620 | err = brcmf_dev_intvar_set(ndev, "wsec", pval | gval); | 1465 | err = brcmf_fil_iovar_int_set(netdev_priv(ndev), "wsec", pval | gval); |
1621 | if (err) { | 1466 | if (err) { |
1622 | WL_ERR("error (%d)\n", err); | 1467 | WL_ERR("error (%d)\n", err); |
1623 | return err; | 1468 | return err; |
@@ -1633,14 +1478,14 @@ brcmf_set_set_cipher(struct net_device *ndev, | |||
1633 | static s32 | 1478 | static s32 |
1634 | brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) | 1479 | brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) |
1635 | { | 1480 | { |
1636 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | 1481 | struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); |
1637 | struct brcmf_cfg80211_profile *profile = cfg->profile; | ||
1638 | struct brcmf_cfg80211_security *sec; | 1482 | struct brcmf_cfg80211_security *sec; |
1639 | s32 val = 0; | 1483 | s32 val = 0; |
1640 | s32 err = 0; | 1484 | s32 err = 0; |
1641 | 1485 | ||
1642 | if (sme->crypto.n_akm_suites) { | 1486 | if (sme->crypto.n_akm_suites) { |
1643 | err = brcmf_dev_intvar_get(ndev, "wpa_auth", &val); | 1487 | err = brcmf_fil_iovar_int_get(netdev_priv(ndev), |
1488 | "wpa_auth", &val); | ||
1644 | if (err) { | 1489 | if (err) { |
1645 | WL_ERR("could not get wpa_auth (%d)\n", err); | 1490 | WL_ERR("could not get wpa_auth (%d)\n", err); |
1646 | return err; | 1491 | return err; |
@@ -1674,7 +1519,8 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) | |||
1674 | } | 1519 | } |
1675 | 1520 | ||
1676 | WL_CONN("setting wpa_auth to %d\n", val); | 1521 | WL_CONN("setting wpa_auth to %d\n", val); |
1677 | err = brcmf_dev_intvar_set(ndev, "wpa_auth", val); | 1522 | err = brcmf_fil_iovar_int_set(netdev_priv(ndev), |
1523 | "wpa_auth", val); | ||
1678 | if (err) { | 1524 | if (err) { |
1679 | WL_ERR("could not set wpa_auth (%d)\n", err); | 1525 | WL_ERR("could not set wpa_auth (%d)\n", err); |
1680 | return err; | 1526 | return err; |
@@ -1690,13 +1536,11 @@ static s32 | |||
1690 | brcmf_set_sharedkey(struct net_device *ndev, | 1536 | brcmf_set_sharedkey(struct net_device *ndev, |
1691 | struct cfg80211_connect_params *sme) | 1537 | struct cfg80211_connect_params *sme) |
1692 | { | 1538 | { |
1693 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | 1539 | struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); |
1694 | struct brcmf_cfg80211_profile *profile = cfg->profile; | ||
1695 | struct brcmf_cfg80211_security *sec; | 1540 | struct brcmf_cfg80211_security *sec; |
1696 | struct brcmf_wsec_key key; | 1541 | struct brcmf_wsec_key key; |
1697 | s32 val; | 1542 | s32 val; |
1698 | s32 err = 0; | 1543 | s32 err = 0; |
1699 | s32 bssidx; | ||
1700 | 1544 | ||
1701 | WL_CONN("key len (%d)\n", sme->key_len); | 1545 | WL_CONN("key len (%d)\n", sme->key_len); |
1702 | 1546 | ||
@@ -1739,15 +1583,14 @@ brcmf_set_sharedkey(struct net_device *ndev, | |||
1739 | WL_CONN("key length (%d) key index (%d) algo (%d)\n", | 1583 | WL_CONN("key length (%d) key index (%d) algo (%d)\n", |
1740 | key.len, key.index, key.algo); | 1584 | key.len, key.index, key.algo); |
1741 | WL_CONN("key \"%s\"\n", key.data); | 1585 | WL_CONN("key \"%s\"\n", key.data); |
1742 | bssidx = brcmf_find_bssidx(cfg, ndev); | 1586 | err = send_key_to_dongle(ndev, &key); |
1743 | err = send_key_to_dongle(cfg, bssidx, ndev, &key); | ||
1744 | if (err) | 1587 | if (err) |
1745 | return err; | 1588 | return err; |
1746 | 1589 | ||
1747 | if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) { | 1590 | if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) { |
1748 | WL_CONN("set auth_type to shared key\n"); | 1591 | WL_CONN("set auth_type to shared key\n"); |
1749 | val = WL_AUTH_SHARED_KEY; /* shared key */ | 1592 | val = WL_AUTH_SHARED_KEY; /* shared key */ |
1750 | err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", val, bssidx); | 1593 | err = brcmf_fil_bsscfg_int_set(netdev_priv(ndev), "auth", val); |
1751 | if (err) | 1594 | if (err) |
1752 | WL_ERR("set auth failed (%d)\n", err); | 1595 | WL_ERR("set auth failed (%d)\n", err); |
1753 | } | 1596 | } |
@@ -1759,7 +1602,8 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, | |||
1759 | struct cfg80211_connect_params *sme) | 1602 | struct cfg80211_connect_params *sme) |
1760 | { | 1603 | { |
1761 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 1604 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
1762 | struct brcmf_cfg80211_profile *profile = cfg->profile; | 1605 | struct brcmf_if *ifp = netdev_priv(ndev); |
1606 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | ||
1763 | struct ieee80211_channel *chan = sme->channel; | 1607 | struct ieee80211_channel *chan = sme->channel; |
1764 | struct brcmf_join_params join_params; | 1608 | struct brcmf_join_params join_params; |
1765 | size_t join_params_size; | 1609 | size_t join_params_size; |
@@ -1768,7 +1612,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, | |||
1768 | s32 err = 0; | 1612 | s32 err = 0; |
1769 | 1613 | ||
1770 | WL_TRACE("Enter\n"); | 1614 | WL_TRACE("Enter\n"); |
1771 | if (!check_sys_up(wiphy)) | 1615 | if (!check_vif_up(ifp->vif)) |
1772 | return -EIO; | 1616 | return -EIO; |
1773 | 1617 | ||
1774 | if (!sme->ssid) { | 1618 | if (!sme->ssid) { |
@@ -1776,7 +1620,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, | |||
1776 | return -EOPNOTSUPP; | 1620 | return -EOPNOTSUPP; |
1777 | } | 1621 | } |
1778 | 1622 | ||
1779 | set_bit(WL_STATUS_CONNECTING, &cfg->status); | 1623 | set_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state); |
1780 | 1624 | ||
1781 | if (chan) { | 1625 | if (chan) { |
1782 | cfg->channel = | 1626 | cfg->channel = |
@@ -1827,7 +1671,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, | |||
1827 | memcpy(&profile->ssid.SSID, sme->ssid, profile->ssid.SSID_len); | 1671 | memcpy(&profile->ssid.SSID, sme->ssid, profile->ssid.SSID_len); |
1828 | join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len); | 1672 | join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len); |
1829 | 1673 | ||
1830 | memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN); | 1674 | memset(join_params.params_le.bssid, 0xFF, ETH_ALEN); |
1831 | 1675 | ||
1832 | if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN) | 1676 | if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN) |
1833 | WL_CONN("ssid \"%s\", len (%d)\n", | 1677 | WL_CONN("ssid \"%s\", len (%d)\n", |
@@ -1835,14 +1679,14 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, | |||
1835 | 1679 | ||
1836 | brcmf_ch_to_chanspec(cfg->channel, | 1680 | brcmf_ch_to_chanspec(cfg->channel, |
1837 | &join_params, &join_params_size); | 1681 | &join_params, &join_params_size); |
1838 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, | 1682 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, |
1839 | &join_params, join_params_size); | 1683 | &join_params, join_params_size); |
1840 | if (err) | 1684 | if (err) |
1841 | WL_ERR("WLC_SET_SSID failed (%d)\n", err); | 1685 | WL_ERR("WLC_SET_SSID failed (%d)\n", err); |
1842 | 1686 | ||
1843 | done: | 1687 | done: |
1844 | if (err) | 1688 | if (err) |
1845 | clear_bit(WL_STATUS_CONNECTING, &cfg->status); | 1689 | clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state); |
1846 | WL_TRACE("Exit\n"); | 1690 | WL_TRACE("Exit\n"); |
1847 | return err; | 1691 | return err; |
1848 | } | 1692 | } |
@@ -1852,20 +1696,21 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, | |||
1852 | u16 reason_code) | 1696 | u16 reason_code) |
1853 | { | 1697 | { |
1854 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 1698 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
1855 | struct brcmf_cfg80211_profile *profile = cfg->profile; | 1699 | struct brcmf_if *ifp = netdev_priv(ndev); |
1700 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | ||
1856 | struct brcmf_scb_val_le scbval; | 1701 | struct brcmf_scb_val_le scbval; |
1857 | s32 err = 0; | 1702 | s32 err = 0; |
1858 | 1703 | ||
1859 | WL_TRACE("Enter. Reason code = %d\n", reason_code); | 1704 | WL_TRACE("Enter. Reason code = %d\n", reason_code); |
1860 | if (!check_sys_up(wiphy)) | 1705 | if (!check_vif_up(ifp->vif)) |
1861 | return -EIO; | 1706 | return -EIO; |
1862 | 1707 | ||
1863 | clear_bit(WL_STATUS_CONNECTED, &cfg->status); | 1708 | clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state); |
1864 | 1709 | ||
1865 | memcpy(&scbval.ea, &profile->bssid, ETH_ALEN); | 1710 | memcpy(&scbval.ea, &profile->bssid, ETH_ALEN); |
1866 | scbval.val = cpu_to_le32(reason_code); | 1711 | scbval.val = cpu_to_le32(reason_code); |
1867 | err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, &scbval, | 1712 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_DISASSOC, |
1868 | sizeof(struct brcmf_scb_val_le)); | 1713 | &scbval, sizeof(scbval)); |
1869 | if (err) | 1714 | if (err) |
1870 | WL_ERR("error (%d)\n", err); | 1715 | WL_ERR("error (%d)\n", err); |
1871 | 1716 | ||
@@ -1882,13 +1727,14 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, | |||
1882 | 1727 | ||
1883 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 1728 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
1884 | struct net_device *ndev = cfg_to_ndev(cfg); | 1729 | struct net_device *ndev = cfg_to_ndev(cfg); |
1730 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
1885 | u16 txpwrmw; | 1731 | u16 txpwrmw; |
1886 | s32 err = 0; | 1732 | s32 err = 0; |
1887 | s32 disable = 0; | 1733 | s32 disable = 0; |
1888 | s32 dbm = MBM_TO_DBM(mbm); | 1734 | s32 dbm = MBM_TO_DBM(mbm); |
1889 | 1735 | ||
1890 | WL_TRACE("Enter\n"); | 1736 | WL_TRACE("Enter\n"); |
1891 | if (!check_sys_up(wiphy)) | 1737 | if (!check_vif_up(ifp->vif)) |
1892 | return -EIO; | 1738 | return -EIO; |
1893 | 1739 | ||
1894 | switch (type) { | 1740 | switch (type) { |
@@ -1905,7 +1751,7 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, | |||
1905 | } | 1751 | } |
1906 | /* Make sure radio is off or on as far as software is concerned */ | 1752 | /* Make sure radio is off or on as far as software is concerned */ |
1907 | disable = WL_RADIO_SW_DISABLE << 16; | 1753 | disable = WL_RADIO_SW_DISABLE << 16; |
1908 | err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_RADIO, &disable); | 1754 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_RADIO, disable); |
1909 | if (err) | 1755 | if (err) |
1910 | WL_ERR("WLC_SET_RADIO error (%d)\n", err); | 1756 | WL_ERR("WLC_SET_RADIO error (%d)\n", err); |
1911 | 1757 | ||
@@ -1913,8 +1759,8 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, | |||
1913 | txpwrmw = 0xffff; | 1759 | txpwrmw = 0xffff; |
1914 | else | 1760 | else |
1915 | txpwrmw = (u16) dbm; | 1761 | txpwrmw = (u16) dbm; |
1916 | err = brcmf_dev_intvar_set(ndev, "qtxpower", | 1762 | err = brcmf_fil_iovar_int_set(ifp, "qtxpower", |
1917 | (s32) (brcmf_mw_to_qdbm(txpwrmw))); | 1763 | (s32)brcmf_mw_to_qdbm(txpwrmw)); |
1918 | if (err) | 1764 | if (err) |
1919 | WL_ERR("qtxpower error (%d)\n", err); | 1765 | WL_ERR("qtxpower error (%d)\n", err); |
1920 | cfg->conf->tx_power = dbm; | 1766 | cfg->conf->tx_power = dbm; |
@@ -1927,16 +1773,16 @@ done: | |||
1927 | static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm) | 1773 | static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm) |
1928 | { | 1774 | { |
1929 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 1775 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
1930 | struct net_device *ndev = cfg_to_ndev(cfg); | 1776 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); |
1931 | s32 txpwrdbm; | 1777 | s32 txpwrdbm; |
1932 | u8 result; | 1778 | u8 result; |
1933 | s32 err = 0; | 1779 | s32 err = 0; |
1934 | 1780 | ||
1935 | WL_TRACE("Enter\n"); | 1781 | WL_TRACE("Enter\n"); |
1936 | if (!check_sys_up(wiphy)) | 1782 | if (!check_vif_up(ifp->vif)) |
1937 | return -EIO; | 1783 | return -EIO; |
1938 | 1784 | ||
1939 | err = brcmf_dev_intvar_get(ndev, "qtxpower", &txpwrdbm); | 1785 | err = brcmf_fil_iovar_int_get(ifp, "qtxpower", &txpwrdbm); |
1940 | if (err) { | 1786 | if (err) { |
1941 | WL_ERR("error (%d)\n", err); | 1787 | WL_ERR("error (%d)\n", err); |
1942 | goto done; | 1788 | goto done; |
@@ -1954,19 +1800,17 @@ static s32 | |||
1954 | brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, | 1800 | brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, |
1955 | u8 key_idx, bool unicast, bool multicast) | 1801 | u8 key_idx, bool unicast, bool multicast) |
1956 | { | 1802 | { |
1957 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 1803 | struct brcmf_if *ifp = netdev_priv(ndev); |
1958 | u32 index; | 1804 | u32 index; |
1959 | u32 wsec; | 1805 | u32 wsec; |
1960 | s32 err = 0; | 1806 | s32 err = 0; |
1961 | s32 bssidx; | ||
1962 | 1807 | ||
1963 | WL_TRACE("Enter\n"); | 1808 | WL_TRACE("Enter\n"); |
1964 | WL_CONN("key index (%d)\n", key_idx); | 1809 | WL_CONN("key index (%d)\n", key_idx); |
1965 | if (!check_sys_up(wiphy)) | 1810 | if (!check_vif_up(ifp->vif)) |
1966 | return -EIO; | 1811 | return -EIO; |
1967 | 1812 | ||
1968 | bssidx = brcmf_find_bssidx(cfg, ndev); | 1813 | err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec); |
1969 | err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx); | ||
1970 | if (err) { | 1814 | if (err) { |
1971 | WL_ERR("WLC_GET_WSEC error (%d)\n", err); | 1815 | WL_ERR("WLC_GET_WSEC error (%d)\n", err); |
1972 | goto done; | 1816 | goto done; |
@@ -1975,8 +1819,8 @@ brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, | |||
1975 | if (wsec & WEP_ENABLED) { | 1819 | if (wsec & WEP_ENABLED) { |
1976 | /* Just select a new current key */ | 1820 | /* Just select a new current key */ |
1977 | index = key_idx; | 1821 | index = key_idx; |
1978 | err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_KEY_PRIMARY, | 1822 | err = brcmf_fil_cmd_int_set(ifp, |
1979 | &index); | 1823 | BRCMF_C_SET_KEY_PRIMARY, index); |
1980 | if (err) | 1824 | if (err) |
1981 | WL_ERR("error (%d)\n", err); | 1825 | WL_ERR("error (%d)\n", err); |
1982 | } | 1826 | } |
@@ -1989,11 +1833,8 @@ static s32 | |||
1989 | brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, | 1833 | brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, |
1990 | u8 key_idx, const u8 *mac_addr, struct key_params *params) | 1834 | u8 key_idx, const u8 *mac_addr, struct key_params *params) |
1991 | { | 1835 | { |
1992 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | ||
1993 | struct brcmf_wsec_key key; | 1836 | struct brcmf_wsec_key key; |
1994 | struct brcmf_wsec_key_le key_le; | ||
1995 | s32 err = 0; | 1837 | s32 err = 0; |
1996 | s32 bssidx; | ||
1997 | 1838 | ||
1998 | memset(&key, 0, sizeof(key)); | 1839 | memset(&key, 0, sizeof(key)); |
1999 | key.index = (u32) key_idx; | 1840 | key.index = (u32) key_idx; |
@@ -2002,11 +1843,10 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, | |||
2002 | if (!is_multicast_ether_addr(mac_addr)) | 1843 | if (!is_multicast_ether_addr(mac_addr)) |
2003 | memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN); | 1844 | memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN); |
2004 | key.len = (u32) params->key_len; | 1845 | key.len = (u32) params->key_len; |
2005 | bssidx = brcmf_find_bssidx(cfg, ndev); | ||
2006 | /* check for key index change */ | 1846 | /* check for key index change */ |
2007 | if (key.len == 0) { | 1847 | if (key.len == 0) { |
2008 | /* key delete */ | 1848 | /* key delete */ |
2009 | err = send_key_to_dongle(cfg, bssidx, ndev, &key); | 1849 | err = send_key_to_dongle(ndev, &key); |
2010 | if (err) | 1850 | if (err) |
2011 | WL_ERR("key delete error (%d)\n", err); | 1851 | WL_ERR("key delete error (%d)\n", err); |
2012 | } else { | 1852 | } else { |
@@ -2061,13 +1901,7 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, | |||
2061 | WL_ERR("Invalid cipher (0x%x)\n", params->cipher); | 1901 | WL_ERR("Invalid cipher (0x%x)\n", params->cipher); |
2062 | return -EINVAL; | 1902 | return -EINVAL; |
2063 | } | 1903 | } |
2064 | convert_key_from_CPU(&key, &key_le); | 1904 | err = send_key_to_dongle(ndev, &key); |
2065 | |||
2066 | brcmf_netdev_wait_pend8021x(ndev); | ||
2067 | err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le, | ||
2068 | sizeof(key_le), | ||
2069 | cfg->extra_buf, | ||
2070 | WL_EXTRA_BUF_MAX, bssidx); | ||
2071 | if (err) | 1905 | if (err) |
2072 | WL_ERR("wsec_key error (%d)\n", err); | 1906 | WL_ERR("wsec_key error (%d)\n", err); |
2073 | } | 1907 | } |
@@ -2080,16 +1914,16 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
2080 | struct key_params *params) | 1914 | struct key_params *params) |
2081 | { | 1915 | { |
2082 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 1916 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
1917 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
2083 | struct brcmf_wsec_key key; | 1918 | struct brcmf_wsec_key key; |
2084 | s32 val; | 1919 | s32 val; |
2085 | s32 wsec; | 1920 | s32 wsec; |
2086 | s32 err = 0; | 1921 | s32 err = 0; |
2087 | u8 keybuf[8]; | 1922 | u8 keybuf[8]; |
2088 | s32 bssidx; | ||
2089 | 1923 | ||
2090 | WL_TRACE("Enter\n"); | 1924 | WL_TRACE("Enter\n"); |
2091 | WL_CONN("key index (%d)\n", key_idx); | 1925 | WL_CONN("key index (%d)\n", key_idx); |
2092 | if (!check_sys_up(wiphy)) | 1926 | if (!check_vif_up(ifp->vif)) |
2093 | return -EIO; | 1927 | return -EIO; |
2094 | 1928 | ||
2095 | if (mac_addr) { | 1929 | if (mac_addr) { |
@@ -2147,18 +1981,17 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, | |||
2147 | goto done; | 1981 | goto done; |
2148 | } | 1982 | } |
2149 | 1983 | ||
2150 | bssidx = brcmf_find_bssidx(cfg, ndev); | 1984 | err = send_key_to_dongle(ndev, &key); |
2151 | err = send_key_to_dongle(cfg, bssidx, ndev, &key); | ||
2152 | if (err) | 1985 | if (err) |
2153 | goto done; | 1986 | goto done; |
2154 | 1987 | ||
2155 | err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx); | 1988 | err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec); |
2156 | if (err) { | 1989 | if (err) { |
2157 | WL_ERR("get wsec error (%d)\n", err); | 1990 | WL_ERR("get wsec error (%d)\n", err); |
2158 | goto done; | 1991 | goto done; |
2159 | } | 1992 | } |
2160 | wsec |= val; | 1993 | wsec |= val; |
2161 | err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", wsec, bssidx); | 1994 | err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec); |
2162 | if (err) { | 1995 | if (err) { |
2163 | WL_ERR("set wsec error (%d)\n", err); | 1996 | WL_ERR("set wsec error (%d)\n", err); |
2164 | goto done; | 1997 | goto done; |
@@ -2173,13 +2006,12 @@ static s32 | |||
2173 | brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, | 2006 | brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, |
2174 | u8 key_idx, bool pairwise, const u8 *mac_addr) | 2007 | u8 key_idx, bool pairwise, const u8 *mac_addr) |
2175 | { | 2008 | { |
2176 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 2009 | struct brcmf_if *ifp = netdev_priv(ndev); |
2177 | struct brcmf_wsec_key key; | 2010 | struct brcmf_wsec_key key; |
2178 | s32 err = 0; | 2011 | s32 err = 0; |
2179 | s32 bssidx; | ||
2180 | 2012 | ||
2181 | WL_TRACE("Enter\n"); | 2013 | WL_TRACE("Enter\n"); |
2182 | if (!check_sys_up(wiphy)) | 2014 | if (!check_vif_up(ifp->vif)) |
2183 | return -EIO; | 2015 | return -EIO; |
2184 | 2016 | ||
2185 | memset(&key, 0, sizeof(key)); | 2017 | memset(&key, 0, sizeof(key)); |
@@ -2191,8 +2023,7 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, | |||
2191 | WL_CONN("key index (%d)\n", key_idx); | 2023 | WL_CONN("key index (%d)\n", key_idx); |
2192 | 2024 | ||
2193 | /* Set the new key/index */ | 2025 | /* Set the new key/index */ |
2194 | bssidx = brcmf_find_bssidx(cfg, ndev); | 2026 | err = send_key_to_dongle(ndev, &key); |
2195 | err = send_key_to_dongle(cfg, bssidx, ndev, &key); | ||
2196 | if (err) { | 2027 | if (err) { |
2197 | if (err == -EINVAL) { | 2028 | if (err == -EINVAL) { |
2198 | if (key.index >= DOT11_MAX_DEFAULT_KEYS) | 2029 | if (key.index >= DOT11_MAX_DEFAULT_KEYS) |
@@ -2213,22 +2044,20 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, | |||
2213 | void (*callback) (void *cookie, struct key_params * params)) | 2044 | void (*callback) (void *cookie, struct key_params * params)) |
2214 | { | 2045 | { |
2215 | struct key_params params; | 2046 | struct key_params params; |
2216 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 2047 | struct brcmf_if *ifp = netdev_priv(ndev); |
2217 | struct brcmf_cfg80211_profile *profile = cfg->profile; | 2048 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; |
2218 | struct brcmf_cfg80211_security *sec; | 2049 | struct brcmf_cfg80211_security *sec; |
2219 | s32 wsec; | 2050 | s32 wsec; |
2220 | s32 err = 0; | 2051 | s32 err = 0; |
2221 | s32 bssidx; | ||
2222 | 2052 | ||
2223 | WL_TRACE("Enter\n"); | 2053 | WL_TRACE("Enter\n"); |
2224 | WL_CONN("key index (%d)\n", key_idx); | 2054 | WL_CONN("key index (%d)\n", key_idx); |
2225 | if (!check_sys_up(wiphy)) | 2055 | if (!check_vif_up(ifp->vif)) |
2226 | return -EIO; | 2056 | return -EIO; |
2227 | 2057 | ||
2228 | memset(¶ms, 0, sizeof(params)); | 2058 | memset(¶ms, 0, sizeof(params)); |
2229 | 2059 | ||
2230 | bssidx = brcmf_find_bssidx(cfg, ndev); | 2060 | err = brcmf_fil_bsscfg_int_get(ifp, "wsec", &wsec); |
2231 | err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx); | ||
2232 | if (err) { | 2061 | if (err) { |
2233 | WL_ERR("WLC_GET_WSEC error (%d)\n", err); | 2062 | WL_ERR("WLC_GET_WSEC error (%d)\n", err); |
2234 | /* Ignore this error, may happen during DISASSOC */ | 2063 | /* Ignore this error, may happen during DISASSOC */ |
@@ -2280,33 +2109,33 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | |||
2280 | u8 *mac, struct station_info *sinfo) | 2109 | u8 *mac, struct station_info *sinfo) |
2281 | { | 2110 | { |
2282 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 2111 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
2283 | struct brcmf_cfg80211_profile *profile = cfg->profile; | 2112 | struct brcmf_if *ifp = netdev_priv(ndev); |
2113 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | ||
2284 | struct brcmf_scb_val_le scb_val; | 2114 | struct brcmf_scb_val_le scb_val; |
2285 | int rssi; | 2115 | int rssi; |
2286 | s32 rate; | 2116 | s32 rate; |
2287 | s32 err = 0; | 2117 | s32 err = 0; |
2288 | u8 *bssid = profile->bssid; | 2118 | u8 *bssid = profile->bssid; |
2289 | struct brcmf_sta_info_le *sta_info_le; | 2119 | struct brcmf_sta_info_le sta_info_le; |
2290 | 2120 | ||
2291 | WL_TRACE("Enter, MAC %pM\n", mac); | 2121 | WL_TRACE("Enter, MAC %pM\n", mac); |
2292 | if (!check_sys_up(wiphy)) | 2122 | if (!check_vif_up(ifp->vif)) |
2293 | return -EIO; | 2123 | return -EIO; |
2294 | 2124 | ||
2295 | if (cfg->conf->mode == WL_MODE_AP) { | 2125 | if (cfg->conf->mode == WL_MODE_AP) { |
2296 | err = brcmf_dev_iovar_getbuf(ndev, "sta_info", mac, ETH_ALEN, | 2126 | memcpy(&sta_info_le, mac, ETH_ALEN); |
2297 | cfg->dcmd_buf, | 2127 | err = brcmf_fil_iovar_data_get(ifp, "sta_info", |
2298 | WL_DCMD_LEN_MAX); | 2128 | &sta_info_le, |
2129 | sizeof(sta_info_le)); | ||
2299 | if (err < 0) { | 2130 | if (err < 0) { |
2300 | WL_ERR("GET STA INFO failed, %d\n", err); | 2131 | WL_ERR("GET STA INFO failed, %d\n", err); |
2301 | goto done; | 2132 | goto done; |
2302 | } | 2133 | } |
2303 | sta_info_le = (struct brcmf_sta_info_le *)cfg->dcmd_buf; | ||
2304 | |||
2305 | sinfo->filled = STATION_INFO_INACTIVE_TIME; | 2134 | sinfo->filled = STATION_INFO_INACTIVE_TIME; |
2306 | sinfo->inactive_time = le32_to_cpu(sta_info_le->idle) * 1000; | 2135 | sinfo->inactive_time = le32_to_cpu(sta_info_le.idle) * 1000; |
2307 | if (le32_to_cpu(sta_info_le->flags) & BRCMF_STA_ASSOC) { | 2136 | if (le32_to_cpu(sta_info_le.flags) & BRCMF_STA_ASSOC) { |
2308 | sinfo->filled |= STATION_INFO_CONNECTED_TIME; | 2137 | sinfo->filled |= STATION_INFO_CONNECTED_TIME; |
2309 | sinfo->connected_time = le32_to_cpu(sta_info_le->in); | 2138 | sinfo->connected_time = le32_to_cpu(sta_info_le.in); |
2310 | } | 2139 | } |
2311 | WL_TRACE("STA idle time : %d ms, connected time :%d sec\n", | 2140 | WL_TRACE("STA idle time : %d ms, connected time :%d sec\n", |
2312 | sinfo->inactive_time, sinfo->connected_time); | 2141 | sinfo->inactive_time, sinfo->connected_time); |
@@ -2318,7 +2147,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | |||
2318 | goto done; | 2147 | goto done; |
2319 | } | 2148 | } |
2320 | /* Report the current tx rate */ | 2149 | /* Report the current tx rate */ |
2321 | err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_RATE, &rate); | 2150 | err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_RATE, &rate); |
2322 | if (err) { | 2151 | if (err) { |
2323 | WL_ERR("Could not get rate (%d)\n", err); | 2152 | WL_ERR("Could not get rate (%d)\n", err); |
2324 | goto done; | 2153 | goto done; |
@@ -2328,10 +2157,11 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, | |||
2328 | WL_CONN("Rate %d Mbps\n", rate / 2); | 2157 | WL_CONN("Rate %d Mbps\n", rate / 2); |
2329 | } | 2158 | } |
2330 | 2159 | ||
2331 | if (test_bit(WL_STATUS_CONNECTED, &cfg->status)) { | 2160 | if (test_bit(BRCMF_VIF_STATUS_CONNECTED, |
2161 | &ifp->vif->sme_state)) { | ||
2332 | memset(&scb_val, 0, sizeof(scb_val)); | 2162 | memset(&scb_val, 0, sizeof(scb_val)); |
2333 | err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val, | 2163 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_RSSI, |
2334 | sizeof(scb_val)); | 2164 | &scb_val, sizeof(scb_val)); |
2335 | if (err) { | 2165 | if (err) { |
2336 | WL_ERR("Could not get rssi (%d)\n", err); | 2166 | WL_ERR("Could not get rssi (%d)\n", err); |
2337 | goto done; | 2167 | goto done; |
@@ -2356,6 +2186,7 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, | |||
2356 | s32 pm; | 2186 | s32 pm; |
2357 | s32 err = 0; | 2187 | s32 err = 0; |
2358 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 2188 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
2189 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
2359 | 2190 | ||
2360 | WL_TRACE("Enter\n"); | 2191 | WL_TRACE("Enter\n"); |
2361 | 2192 | ||
@@ -2367,7 +2198,7 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, | |||
2367 | * FW later while initializing the dongle | 2198 | * FW later while initializing the dongle |
2368 | */ | 2199 | */ |
2369 | cfg->pwr_save = enabled; | 2200 | cfg->pwr_save = enabled; |
2370 | if (!test_bit(WL_STATUS_READY, &cfg->status)) { | 2201 | if (!check_vif_up(ifp->vif)) { |
2371 | 2202 | ||
2372 | WL_INFO("Device is not ready, storing the value in cfg_info struct\n"); | 2203 | WL_INFO("Device is not ready, storing the value in cfg_info struct\n"); |
2373 | goto done; | 2204 | goto done; |
@@ -2376,7 +2207,7 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, | |||
2376 | pm = enabled ? PM_FAST : PM_OFF; | 2207 | pm = enabled ? PM_FAST : PM_OFF; |
2377 | WL_INFO("power save %s\n", (pm ? "enabled" : "disabled")); | 2208 | WL_INFO("power save %s\n", (pm ? "enabled" : "disabled")); |
2378 | 2209 | ||
2379 | err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &pm); | 2210 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, pm); |
2380 | if (err) { | 2211 | if (err) { |
2381 | if (err == -ENODEV) | 2212 | if (err == -ENODEV) |
2382 | WL_ERR("net_device is not ready yet\n"); | 2213 | WL_ERR("net_device is not ready yet\n"); |
@@ -2393,6 +2224,7 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev, | |||
2393 | const u8 *addr, | 2224 | const u8 *addr, |
2394 | const struct cfg80211_bitrate_mask *mask) | 2225 | const struct cfg80211_bitrate_mask *mask) |
2395 | { | 2226 | { |
2227 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
2396 | struct brcm_rateset_le rateset_le; | 2228 | struct brcm_rateset_le rateset_le; |
2397 | s32 rate; | 2229 | s32 rate; |
2398 | s32 val; | 2230 | s32 val; |
@@ -2402,13 +2234,13 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev, | |||
2402 | s32 err = 0; | 2234 | s32 err = 0; |
2403 | 2235 | ||
2404 | WL_TRACE("Enter\n"); | 2236 | WL_TRACE("Enter\n"); |
2405 | if (!check_sys_up(wiphy)) | 2237 | if (!check_vif_up(ifp->vif)) |
2406 | return -EIO; | 2238 | return -EIO; |
2407 | 2239 | ||
2408 | /* addr param is always NULL. ignore it */ | 2240 | /* addr param is always NULL. ignore it */ |
2409 | /* Get current rateset */ | 2241 | /* Get current rateset */ |
2410 | err = brcmf_exec_dcmd(ndev, BRCM_GET_CURR_RATESET, &rateset_le, | 2242 | err = brcmf_fil_cmd_data_get(ifp, BRCM_GET_CURR_RATESET, |
2411 | sizeof(rateset_le)); | 2243 | &rateset_le, sizeof(rateset_le)); |
2412 | if (err) { | 2244 | if (err) { |
2413 | WL_ERR("could not get current rateset (%d)\n", err); | 2245 | WL_ERR("could not get current rateset (%d)\n", err); |
2414 | goto done; | 2246 | goto done; |
@@ -2435,8 +2267,8 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev, | |||
2435 | * Set rate override, | 2267 | * Set rate override, |
2436 | * Since the is a/b/g-blind, both a/bg_rate are enforced. | 2268 | * Since the is a/b/g-blind, both a/bg_rate are enforced. |
2437 | */ | 2269 | */ |
2438 | err_bg = brcmf_dev_intvar_set(ndev, "bg_rate", rate); | 2270 | err_bg = brcmf_fil_iovar_int_set(ifp, "bg_rate", rate); |
2439 | err_a = brcmf_dev_intvar_set(ndev, "a_rate", rate); | 2271 | err_a = brcmf_fil_iovar_int_set(ifp, "a_rate", rate); |
2440 | if (err_bg && err_a) { | 2272 | if (err_bg && err_a) { |
2441 | WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a); | 2273 | WL_ERR("could not set fixed rate (%d) (%d)\n", err_bg, err_a); |
2442 | err = err_bg | err_a; | 2274 | err = err_bg | err_a; |
@@ -2565,7 +2397,8 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg, | |||
2565 | 2397 | ||
2566 | *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX); | 2398 | *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX); |
2567 | 2399 | ||
2568 | err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_BSS_INFO, buf, WL_BSS_INFO_MAX); | 2400 | err = brcmf_fil_cmd_data_get(netdev_priv(ndev), BRCMF_C_GET_BSS_INFO, |
2401 | buf, WL_BSS_INFO_MAX); | ||
2569 | if (err) { | 2402 | if (err) { |
2570 | WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err); | 2403 | WL_ERR("WLC_GET_BSS_INFO failed: %d\n", err); |
2571 | goto CleanUp; | 2404 | goto CleanUp; |
@@ -2674,7 +2507,7 @@ brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, | |||
2674 | return false; | 2507 | return false; |
2675 | } | 2508 | } |
2676 | 2509 | ||
2677 | struct brcmf_vs_tlv * | 2510 | static struct brcmf_vs_tlv * |
2678 | brcmf_find_wpaie(u8 *parse, u32 len) | 2511 | brcmf_find_wpaie(u8 *parse, u32 len) |
2679 | { | 2512 | { |
2680 | struct brcmf_tlv *ie; | 2513 | struct brcmf_tlv *ie; |
@@ -2689,7 +2522,9 @@ brcmf_find_wpaie(u8 *parse, u32 len) | |||
2689 | 2522 | ||
2690 | static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) | 2523 | static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) |
2691 | { | 2524 | { |
2692 | struct brcmf_cfg80211_profile *profile = cfg->profile; | 2525 | struct net_device *ndev = cfg_to_ndev(cfg); |
2526 | struct brcmf_cfg80211_profile *profile = ndev_to_prof(ndev); | ||
2527 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
2693 | struct brcmf_bss_info_le *bi; | 2528 | struct brcmf_bss_info_le *bi; |
2694 | struct brcmf_ssid *ssid; | 2529 | struct brcmf_ssid *ssid; |
2695 | struct brcmf_tlv *tim; | 2530 | struct brcmf_tlv *tim; |
@@ -2706,8 +2541,8 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) | |||
2706 | ssid = &profile->ssid; | 2541 | ssid = &profile->ssid; |
2707 | 2542 | ||
2708 | *(__le32 *)cfg->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX); | 2543 | *(__le32 *)cfg->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX); |
2709 | err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCMF_C_GET_BSS_INFO, | 2544 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, |
2710 | cfg->extra_buf, WL_EXTRA_BUF_MAX); | 2545 | cfg->extra_buf, WL_EXTRA_BUF_MAX); |
2711 | if (err) { | 2546 | if (err) { |
2712 | WL_ERR("Could not get bss info %d\n", err); | 2547 | WL_ERR("Could not get bss info %d\n", err); |
2713 | goto update_bss_info_out; | 2548 | goto update_bss_info_out; |
@@ -2732,8 +2567,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) | |||
2732 | * so we speficially query dtim information to dongle. | 2567 | * so we speficially query dtim information to dongle. |
2733 | */ | 2568 | */ |
2734 | u32 var; | 2569 | u32 var; |
2735 | err = brcmf_dev_intvar_get(cfg_to_ndev(cfg), | 2570 | err = brcmf_fil_iovar_int_get(ifp, "dtim_assoc", &var); |
2736 | "dtim_assoc", &var); | ||
2737 | if (err) { | 2571 | if (err) { |
2738 | WL_ERR("wl dtim_assoc failed (%d)\n", err); | 2572 | WL_ERR("wl dtim_assoc failed (%d)\n", err); |
2739 | goto update_bss_info_out; | 2573 | goto update_bss_info_out; |
@@ -2741,9 +2575,6 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) | |||
2741 | dtim_period = (u8)var; | 2575 | dtim_period = (u8)var; |
2742 | } | 2576 | } |
2743 | 2577 | ||
2744 | profile->beacon_interval = beacon_interval; | ||
2745 | profile->dtim_period = dtim_period; | ||
2746 | |||
2747 | update_bss_info_out: | 2578 | update_bss_info_out: |
2748 | WL_TRACE("Exit"); | 2579 | WL_TRACE("Exit"); |
2749 | return err; | 2580 | return err; |
@@ -2755,7 +2586,7 @@ static void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg) | |||
2755 | struct escan_info *escan = &cfg->escan_info; | 2586 | struct escan_info *escan = &cfg->escan_info; |
2756 | struct brcmf_ssid ssid; | 2587 | struct brcmf_ssid ssid; |
2757 | 2588 | ||
2758 | set_bit(WL_STATUS_SCAN_ABORTING, &cfg->status); | 2589 | set_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status); |
2759 | if (cfg->iscan_on) { | 2590 | if (cfg->iscan_on) { |
2760 | iscan->state = WL_ISCAN_STATE_IDLE; | 2591 | iscan->state = WL_ISCAN_STATE_IDLE; |
2761 | 2592 | ||
@@ -2781,8 +2612,8 @@ static void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg) | |||
2781 | escan->escan_state = WL_ESCAN_STATE_IDLE; | 2612 | escan->escan_state = WL_ESCAN_STATE_IDLE; |
2782 | brcmf_notify_escan_complete(cfg, escan->ndev, true, true); | 2613 | brcmf_notify_escan_complete(cfg, escan->ndev, true, true); |
2783 | } | 2614 | } |
2784 | clear_bit(WL_STATUS_SCANNING, &cfg->status); | 2615 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
2785 | clear_bit(WL_STATUS_SCAN_ABORTING, &cfg->status); | 2616 | clear_bit(BRCMF_SCAN_STATUS_ABORT, &cfg->scan_status); |
2786 | } | 2617 | } |
2787 | 2618 | ||
2788 | static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan, | 2619 | static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan, |
@@ -2791,7 +2622,7 @@ static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan, | |||
2791 | struct brcmf_cfg80211_info *cfg = iscan_to_cfg(iscan); | 2622 | struct brcmf_cfg80211_info *cfg = iscan_to_cfg(iscan); |
2792 | struct net_device *ndev = cfg_to_ndev(cfg); | 2623 | struct net_device *ndev = cfg_to_ndev(cfg); |
2793 | 2624 | ||
2794 | if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) { | 2625 | if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { |
2795 | WL_ERR("Scan complete while device not scanning\n"); | 2626 | WL_ERR("Scan complete while device not scanning\n"); |
2796 | return; | 2627 | return; |
2797 | } | 2628 | } |
@@ -2820,7 +2651,6 @@ static s32 | |||
2820 | brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status, | 2651 | brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status, |
2821 | struct brcmf_scan_results **bss_list) | 2652 | struct brcmf_scan_results **bss_list) |
2822 | { | 2653 | { |
2823 | struct brcmf_iscan_results list; | ||
2824 | struct brcmf_scan_results *results; | 2654 | struct brcmf_scan_results *results; |
2825 | struct brcmf_scan_results_le *results_le; | 2655 | struct brcmf_scan_results_le *results_le; |
2826 | struct brcmf_iscan_results *list_buf; | 2656 | struct brcmf_iscan_results *list_buf; |
@@ -2830,15 +2660,13 @@ brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status, | |||
2830 | list_buf = (struct brcmf_iscan_results *)iscan->scan_buf; | 2660 | list_buf = (struct brcmf_iscan_results *)iscan->scan_buf; |
2831 | results = &list_buf->results; | 2661 | results = &list_buf->results; |
2832 | results_le = &list_buf->results_le; | 2662 | results_le = &list_buf->results_le; |
2833 | results->buflen = BRCMF_ISCAN_RESULTS_FIXED_SIZE; | 2663 | results_le->buflen = cpu_to_le32(sizeof(iscan->scan_buf)); |
2834 | results->version = 0; | 2664 | results_le->version = 0; |
2835 | results->count = 0; | 2665 | results_le->count = 0; |
2836 | 2666 | ||
2837 | memset(&list, 0, sizeof(list)); | 2667 | err = brcmf_fil_iovar_data_get(netdev_priv(iscan->ndev), "iscanresults", |
2838 | list.results_le.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX); | 2668 | iscan->scan_buf, |
2839 | err = brcmf_dev_iovar_getbuf(iscan->ndev, "iscanresults", &list, | 2669 | sizeof(iscan->scan_buf)); |
2840 | BRCMF_ISCAN_RESULTS_FIXED_SIZE, | ||
2841 | iscan->scan_buf, WL_ISCAN_BUF_MAX); | ||
2842 | if (err) { | 2670 | if (err) { |
2843 | WL_ERR("error (%d)\n", err); | 2671 | WL_ERR("error (%d)\n", err); |
2844 | return err; | 2672 | return err; |
@@ -3052,10 +2880,10 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg, | |||
3052 | status = be32_to_cpu(e->status); | 2880 | status = be32_to_cpu(e->status); |
3053 | 2881 | ||
3054 | if (!ndev || !cfg->escan_on || | 2882 | if (!ndev || !cfg->escan_on || |
3055 | !test_bit(WL_STATUS_SCANNING, &cfg->status)) { | 2883 | !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { |
3056 | WL_ERR("scan not ready ndev %p wl->escan_on %d drv_status %x\n", | 2884 | WL_ERR("scan not ready ndev %p wl->escan_on %d drv_status %x\n", |
3057 | ndev, cfg->escan_on, | 2885 | ndev, cfg->escan_on, |
3058 | !test_bit(WL_STATUS_SCANNING, &cfg->status)); | 2886 | !test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)); |
3059 | return -EPERM; | 2887 | return -EPERM; |
3060 | } | 2888 | } |
3061 | 2889 | ||
@@ -3159,16 +2987,17 @@ static __always_inline void brcmf_delay(u32 ms) | |||
3159 | static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) | 2987 | static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) |
3160 | { | 2988 | { |
3161 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 2989 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
2990 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | ||
3162 | 2991 | ||
3163 | /* | 2992 | /* |
3164 | * Check for WL_STATUS_READY before any function call which | 2993 | * Check for BRCMF_VIF_STATUS_READY before any function call which |
3165 | * could result is bus access. Don't block the resume for | 2994 | * could result is bus access. Don't block the resume for |
3166 | * any driver error conditions | 2995 | * any driver error conditions |
3167 | */ | 2996 | */ |
3168 | WL_TRACE("Enter\n"); | 2997 | WL_TRACE("Enter\n"); |
3169 | 2998 | ||
3170 | if (test_bit(WL_STATUS_READY, &cfg->status)) | 2999 | if (check_vif_up(ifp->vif)) |
3171 | brcmf_invoke_iscan(wiphy_to_cfg(wiphy)); | 3000 | brcmf_invoke_iscan(cfg); |
3172 | 3001 | ||
3173 | WL_TRACE("Exit\n"); | 3002 | WL_TRACE("Exit\n"); |
3174 | return 0; | 3003 | return 0; |
@@ -3179,85 +3008,53 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, | |||
3179 | { | 3008 | { |
3180 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 3009 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
3181 | struct net_device *ndev = cfg_to_ndev(cfg); | 3010 | struct net_device *ndev = cfg_to_ndev(cfg); |
3011 | struct brcmf_cfg80211_vif *vif; | ||
3182 | 3012 | ||
3183 | WL_TRACE("Enter\n"); | 3013 | WL_TRACE("Enter\n"); |
3184 | 3014 | ||
3185 | /* | 3015 | /* |
3186 | * Check for WL_STATUS_READY before any function call which | 3016 | * if the primary net_device is not READY there is nothing |
3187 | * could result is bus access. Don't block the suspend for | 3017 | * we can do but pray resume goes smoothly. |
3188 | * any driver error conditions | ||
3189 | */ | ||
3190 | |||
3191 | /* | ||
3192 | * While going to suspend if associated with AP disassociate | ||
3193 | * from AP to save power while system is in suspended state | ||
3194 | */ | 3018 | */ |
3195 | if ((test_bit(WL_STATUS_CONNECTED, &cfg->status) || | 3019 | vif = ((struct brcmf_if *)netdev_priv(ndev))->vif; |
3196 | test_bit(WL_STATUS_CONNECTING, &cfg->status)) && | 3020 | if (!check_vif_up(vif)) |
3197 | test_bit(WL_STATUS_READY, &cfg->status)) { | 3021 | goto exit; |
3198 | WL_INFO("Disassociating from AP" | ||
3199 | " while entering suspend state\n"); | ||
3200 | brcmf_link_down(cfg); | ||
3201 | 3022 | ||
3023 | list_for_each_entry(vif, &cfg->vif_list, list) { | ||
3024 | if (!test_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state)) | ||
3025 | continue; | ||
3202 | /* | 3026 | /* |
3203 | * Make sure WPA_Supplicant receives all the event | 3027 | * While going to suspend if associated with AP disassociate |
3204 | * generated due to DISASSOC call to the fw to keep | 3028 | * from AP to save power while system is in suspended state |
3205 | * the state fw and WPA_Supplicant state consistent | ||
3206 | */ | 3029 | */ |
3207 | brcmf_delay(500); | 3030 | if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state) || |
3031 | test_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state)) { | ||
3032 | WL_INFO("Disassociating from AP before suspend\n"); | ||
3033 | brcmf_link_down(cfg); | ||
3034 | |||
3035 | /* Make sure WPA_Supplicant receives all the event | ||
3036 | * generated due to DISASSOC call to the fw to keep | ||
3037 | * the state fw and WPA_Supplicant state consistent | ||
3038 | */ | ||
3039 | brcmf_delay(500); | ||
3040 | } | ||
3208 | } | 3041 | } |
3209 | 3042 | ||
3210 | if (test_bit(WL_STATUS_READY, &cfg->status)) | 3043 | /* end any scanning */ |
3044 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) | ||
3211 | brcmf_abort_scanning(cfg); | 3045 | brcmf_abort_scanning(cfg); |
3212 | else | ||
3213 | clear_bit(WL_STATUS_SCANNING, &cfg->status); | ||
3214 | 3046 | ||
3215 | /* Turn off watchdog timer */ | 3047 | /* Turn off watchdog timer */ |
3216 | if (test_bit(WL_STATUS_READY, &cfg->status)) | 3048 | brcmf_set_mpc(ndev, 1); |
3217 | brcmf_set_mpc(ndev, 1); | ||
3218 | 3049 | ||
3050 | exit: | ||
3219 | WL_TRACE("Exit\n"); | 3051 | WL_TRACE("Exit\n"); |
3220 | 3052 | /* clear any scanning activity */ | |
3053 | cfg->scan_status = 0; | ||
3221 | return 0; | 3054 | return 0; |
3222 | } | 3055 | } |
3223 | 3056 | ||
3224 | static __used s32 | 3057 | static __used s32 |
3225 | brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len) | ||
3226 | { | ||
3227 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | ||
3228 | u32 buflen; | ||
3229 | |||
3230 | buflen = brcmf_c_mkiovar(name, buf, len, cfg->dcmd_buf, | ||
3231 | WL_DCMD_LEN_MAX); | ||
3232 | BUG_ON(!buflen); | ||
3233 | |||
3234 | return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg->dcmd_buf, | ||
3235 | buflen); | ||
3236 | } | ||
3237 | |||
3238 | static s32 | ||
3239 | brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf, | ||
3240 | s32 buf_len) | ||
3241 | { | ||
3242 | struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); | ||
3243 | u32 len; | ||
3244 | s32 err = 0; | ||
3245 | |||
3246 | len = brcmf_c_mkiovar(name, NULL, 0, cfg->dcmd_buf, | ||
3247 | WL_DCMD_LEN_MAX); | ||
3248 | BUG_ON(!len); | ||
3249 | err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg->dcmd_buf, | ||
3250 | WL_DCMD_LEN_MAX); | ||
3251 | if (err) { | ||
3252 | WL_ERR("error (%d)\n", err); | ||
3253 | return err; | ||
3254 | } | ||
3255 | memcpy(buf, cfg->dcmd_buf, buf_len); | ||
3256 | |||
3257 | return err; | ||
3258 | } | ||
3259 | |||
3260 | static __used s32 | ||
3261 | brcmf_update_pmklist(struct net_device *ndev, | 3058 | brcmf_update_pmklist(struct net_device *ndev, |
3262 | struct brcmf_cfg80211_pmk_list *pmk_list, s32 err) | 3059 | struct brcmf_cfg80211_pmk_list *pmk_list, s32 err) |
3263 | { | 3060 | { |
@@ -3275,8 +3072,8 @@ brcmf_update_pmklist(struct net_device *ndev, | |||
3275 | } | 3072 | } |
3276 | 3073 | ||
3277 | if (!err) | 3074 | if (!err) |
3278 | brcmf_dev_bufvar_set(ndev, "pmkid_info", (char *)pmk_list, | 3075 | brcmf_fil_iovar_data_set(netdev_priv(ndev), "pmkid_info", |
3279 | sizeof(*pmk_list)); | 3076 | (char *)pmk_list, sizeof(*pmk_list)); |
3280 | 3077 | ||
3281 | return err; | 3078 | return err; |
3282 | } | 3079 | } |
@@ -3286,13 +3083,14 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, | |||
3286 | struct cfg80211_pmksa *pmksa) | 3083 | struct cfg80211_pmksa *pmksa) |
3287 | { | 3084 | { |
3288 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 3085 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
3086 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
3289 | struct pmkid_list *pmkids = &cfg->pmk_list->pmkids; | 3087 | struct pmkid_list *pmkids = &cfg->pmk_list->pmkids; |
3290 | s32 err = 0; | 3088 | s32 err = 0; |
3291 | int i; | 3089 | int i; |
3292 | int pmkid_len; | 3090 | int pmkid_len; |
3293 | 3091 | ||
3294 | WL_TRACE("Enter\n"); | 3092 | WL_TRACE("Enter\n"); |
3295 | if (!check_sys_up(wiphy)) | 3093 | if (!check_vif_up(ifp->vif)) |
3296 | return -EIO; | 3094 | return -EIO; |
3297 | 3095 | ||
3298 | pmkid_len = le32_to_cpu(pmkids->npmkid); | 3096 | pmkid_len = le32_to_cpu(pmkids->npmkid); |
@@ -3325,12 +3123,13 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, | |||
3325 | struct cfg80211_pmksa *pmksa) | 3123 | struct cfg80211_pmksa *pmksa) |
3326 | { | 3124 | { |
3327 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 3125 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
3126 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
3328 | struct pmkid_list pmkid; | 3127 | struct pmkid_list pmkid; |
3329 | s32 err = 0; | 3128 | s32 err = 0; |
3330 | int i, pmkid_len; | 3129 | int i, pmkid_len; |
3331 | 3130 | ||
3332 | WL_TRACE("Enter\n"); | 3131 | WL_TRACE("Enter\n"); |
3333 | if (!check_sys_up(wiphy)) | 3132 | if (!check_vif_up(ifp->vif)) |
3334 | return -EIO; | 3133 | return -EIO; |
3335 | 3134 | ||
3336 | memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN); | 3135 | memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN); |
@@ -3375,10 +3174,11 @@ static s32 | |||
3375 | brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) | 3174 | brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) |
3376 | { | 3175 | { |
3377 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 3176 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
3177 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
3378 | s32 err = 0; | 3178 | s32 err = 0; |
3379 | 3179 | ||
3380 | WL_TRACE("Enter\n"); | 3180 | WL_TRACE("Enter\n"); |
3381 | if (!check_sys_up(wiphy)) | 3181 | if (!check_vif_up(ifp->vif)) |
3382 | return -EIO; | 3182 | return -EIO; |
3383 | 3183 | ||
3384 | memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list)); | 3184 | memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list)); |
@@ -3478,15 +3278,15 @@ brcmf_notify_sched_scan_results(struct brcmf_cfg80211_info *cfg, | |||
3478 | if (request->n_ssids) | 3278 | if (request->n_ssids) |
3479 | request->ssids = &ssid[0]; | 3279 | request->ssids = &ssid[0]; |
3480 | 3280 | ||
3481 | if (test_bit(WL_STATUS_SCANNING, &cfg->status)) { | 3281 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { |
3482 | /* Abort any on-going scan */ | 3282 | /* Abort any on-going scan */ |
3483 | brcmf_abort_scanning(cfg); | 3283 | brcmf_abort_scanning(cfg); |
3484 | } | 3284 | } |
3485 | 3285 | ||
3486 | set_bit(WL_STATUS_SCANNING, &cfg->status); | 3286 | set_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
3487 | err = brcmf_do_escan(cfg, wiphy, ndev, request); | 3287 | err = brcmf_do_escan(cfg, wiphy, ndev, request); |
3488 | if (err) { | 3288 | if (err) { |
3489 | clear_bit(WL_STATUS_SCANNING, &cfg->status); | 3289 | clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status); |
3490 | goto out_err; | 3290 | goto out_err; |
3491 | } | 3291 | } |
3492 | cfg->sched_escan = true; | 3292 | cfg->sched_escan = true; |
@@ -3512,15 +3312,14 @@ out_err: | |||
3512 | #ifndef CONFIG_BRCMISCAN | 3312 | #ifndef CONFIG_BRCMISCAN |
3513 | static int brcmf_dev_pno_clean(struct net_device *ndev) | 3313 | static int brcmf_dev_pno_clean(struct net_device *ndev) |
3514 | { | 3314 | { |
3515 | char iovbuf[128]; | ||
3516 | int ret; | 3315 | int ret; |
3517 | 3316 | ||
3518 | /* Disable pfn */ | 3317 | /* Disable pfn */ |
3519 | ret = brcmf_dev_intvar_set(ndev, "pfn", 0); | 3318 | ret = brcmf_fil_iovar_int_set(netdev_priv(ndev), "pfn", 0); |
3520 | if (ret == 0) { | 3319 | if (ret == 0) { |
3521 | /* clear pfn */ | 3320 | /* clear pfn */ |
3522 | ret = brcmf_dev_iovar_setbuf(ndev, "pfnclear", NULL, 0, | 3321 | ret = brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfnclear", |
3523 | iovbuf, sizeof(iovbuf)); | 3322 | NULL, 0); |
3524 | } | 3323 | } |
3525 | if (ret < 0) | 3324 | if (ret < 0) |
3526 | WL_ERR("failed code %d\n", ret); | 3325 | WL_ERR("failed code %d\n", ret); |
@@ -3531,7 +3330,6 @@ static int brcmf_dev_pno_clean(struct net_device *ndev) | |||
3531 | static int brcmf_dev_pno_config(struct net_device *ndev) | 3330 | static int brcmf_dev_pno_config(struct net_device *ndev) |
3532 | { | 3331 | { |
3533 | struct brcmf_pno_param_le pfn_param; | 3332 | struct brcmf_pno_param_le pfn_param; |
3534 | char iovbuf[128]; | ||
3535 | 3333 | ||
3536 | memset(&pfn_param, 0, sizeof(pfn_param)); | 3334 | memset(&pfn_param, 0, sizeof(pfn_param)); |
3537 | pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION); | 3335 | pfn_param.version = cpu_to_le32(BRCMF_PNO_VERSION); |
@@ -3544,9 +3342,8 @@ static int brcmf_dev_pno_config(struct net_device *ndev) | |||
3544 | /* set up pno scan fr */ | 3342 | /* set up pno scan fr */ |
3545 | pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME); | 3343 | pfn_param.scan_freq = cpu_to_le32(BRCMF_PNO_TIME); |
3546 | 3344 | ||
3547 | return brcmf_dev_iovar_setbuf(ndev, "pfn_set", | 3345 | return brcmf_fil_iovar_data_set(netdev_priv(ndev), "pfn_set", |
3548 | &pfn_param, sizeof(pfn_param), | 3346 | &pfn_param, sizeof(pfn_param)); |
3549 | iovbuf, sizeof(iovbuf)); | ||
3550 | } | 3347 | } |
3551 | 3348 | ||
3552 | static int | 3349 | static int |
@@ -3554,7 +3351,7 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, | |||
3554 | struct net_device *ndev, | 3351 | struct net_device *ndev, |
3555 | struct cfg80211_sched_scan_request *request) | 3352 | struct cfg80211_sched_scan_request *request) |
3556 | { | 3353 | { |
3557 | char iovbuf[128]; | 3354 | struct brcmf_if *ifp = netdev_priv(ndev); |
3558 | struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); | 3355 | struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); |
3559 | struct brcmf_pno_net_param_le pfn; | 3356 | struct brcmf_pno_net_param_le pfn; |
3560 | int i; | 3357 | int i; |
@@ -3562,14 +3359,14 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, | |||
3562 | 3359 | ||
3563 | WL_SCAN("Enter n_match_sets:%d n_ssids:%d\n", | 3360 | WL_SCAN("Enter n_match_sets:%d n_ssids:%d\n", |
3564 | request->n_match_sets, request->n_ssids); | 3361 | request->n_match_sets, request->n_ssids); |
3565 | if (test_bit(WL_STATUS_SCANNING, &cfg->status)) { | 3362 | if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { |
3566 | WL_ERR("Scanning already : status (%lu)\n", cfg->status); | 3363 | WL_ERR("Scanning already: status (%lu)\n", cfg->scan_status); |
3567 | return -EAGAIN; | 3364 | return -EAGAIN; |
3568 | } | 3365 | } |
3569 | 3366 | ||
3570 | if (!request || !request->n_ssids || !request->n_match_sets) { | 3367 | if (!request || !request->n_ssids || !request->n_match_sets) { |
3571 | WL_ERR("Invalid sched scan req!! n_ssids:%d\n", | 3368 | WL_ERR("Invalid sched scan req!! n_ssids:%d\n", |
3572 | request->n_ssids); | 3369 | request ? request->n_ssids : 0); |
3573 | return -EINVAL; | 3370 | return -EINVAL; |
3574 | } | 3371 | } |
3575 | 3372 | ||
@@ -3620,15 +3417,14 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, | |||
3620 | pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT); | 3417 | pfn.flags = cpu_to_le32(1 << BRCMF_PNO_HIDDEN_BIT); |
3621 | pfn.ssid.SSID_len = cpu_to_le32(ssid_len); | 3418 | pfn.ssid.SSID_len = cpu_to_le32(ssid_len); |
3622 | memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len); | 3419 | memcpy(pfn.ssid.SSID, ssid->ssid, ssid_len); |
3623 | ret = brcmf_dev_iovar_setbuf(ndev, "pfn_add", | 3420 | ret = brcmf_fil_iovar_data_set(ifp, "pfn_add", &pfn, |
3624 | &pfn, sizeof(pfn), | 3421 | sizeof(pfn)); |
3625 | iovbuf, sizeof(iovbuf)); | ||
3626 | WL_SCAN(">>> PNO filter %s for ssid (%s)\n", | 3422 | WL_SCAN(">>> PNO filter %s for ssid (%s)\n", |
3627 | ret == 0 ? "set" : "failed", | 3423 | ret == 0 ? "set" : "failed", |
3628 | ssid->ssid); | 3424 | ssid->ssid); |
3629 | } | 3425 | } |
3630 | /* Enable the PNO */ | 3426 | /* Enable the PNO */ |
3631 | if (brcmf_dev_intvar_set(ndev, "pfn", 1) < 0) { | 3427 | if (brcmf_fil_iovar_int_set(ifp, "pfn", 1) < 0) { |
3632 | WL_ERR("PNO enable failed!! ret=%d\n", ret); | 3428 | WL_ERR("PNO enable failed!! ret=%d\n", ret); |
3633 | return -EINVAL; | 3429 | return -EINVAL; |
3634 | } | 3430 | } |
@@ -3656,12 +3452,20 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy, | |||
3656 | static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len) | 3452 | static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len) |
3657 | { | 3453 | { |
3658 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 3454 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
3659 | struct net_device *ndev = cfg->wdev->netdev; | 3455 | struct net_device *ndev = cfg_to_ndev(cfg); |
3660 | struct brcmf_dcmd *dcmd = data; | 3456 | struct brcmf_dcmd *dcmd = data; |
3661 | struct sk_buff *reply; | 3457 | struct sk_buff *reply; |
3662 | int ret; | 3458 | int ret; |
3663 | 3459 | ||
3664 | ret = brcmf_netlink_dcmd(ndev, dcmd); | 3460 | WL_TRACE("cmd %x set %d buf %p len %d\n", dcmd->cmd, dcmd->set, |
3461 | dcmd->buf, dcmd->len); | ||
3462 | |||
3463 | if (dcmd->set) | ||
3464 | ret = brcmf_fil_cmd_data_set(netdev_priv(ndev), dcmd->cmd, | ||
3465 | dcmd->buf, dcmd->len); | ||
3466 | else | ||
3467 | ret = brcmf_fil_cmd_data_get(netdev_priv(ndev), dcmd->cmd, | ||
3468 | dcmd->buf, dcmd->len); | ||
3665 | if (ret == 0) { | 3469 | if (ret == 0) { |
3666 | reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*dcmd)); | 3470 | reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*dcmd)); |
3667 | nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*dcmd), dcmd); | 3471 | nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*dcmd), dcmd); |
@@ -3673,23 +3477,23 @@ static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len) | |||
3673 | 3477 | ||
3674 | static s32 brcmf_configure_opensecurity(struct net_device *ndev, s32 bssidx) | 3478 | static s32 brcmf_configure_opensecurity(struct net_device *ndev, s32 bssidx) |
3675 | { | 3479 | { |
3480 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
3676 | s32 err; | 3481 | s32 err; |
3677 | 3482 | ||
3678 | /* set auth */ | 3483 | /* set auth */ |
3679 | err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", 0, bssidx); | 3484 | err = brcmf_fil_bsscfg_int_set(ifp, "auth", 0); |
3680 | if (err < 0) { | 3485 | if (err < 0) { |
3681 | WL_ERR("auth error %d\n", err); | 3486 | WL_ERR("auth error %d\n", err); |
3682 | return err; | 3487 | return err; |
3683 | } | 3488 | } |
3684 | /* set wsec */ | 3489 | /* set wsec */ |
3685 | err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", 0, bssidx); | 3490 | err = brcmf_fil_bsscfg_int_set(ifp, "wsec", 0); |
3686 | if (err < 0) { | 3491 | if (err < 0) { |
3687 | WL_ERR("wsec error %d\n", err); | 3492 | WL_ERR("wsec error %d\n", err); |
3688 | return err; | 3493 | return err; |
3689 | } | 3494 | } |
3690 | /* set upper-layer auth */ | 3495 | /* set upper-layer auth */ |
3691 | err = brcmf_dev_intvar_set_bsscfg(ndev, "wpa_auth", | 3496 | err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", WPA_AUTH_NONE); |
3692 | WPA_AUTH_NONE, bssidx); | ||
3693 | if (err < 0) { | 3497 | if (err < 0) { |
3694 | WL_ERR("wpa_auth error %d\n", err); | 3498 | WL_ERR("wpa_auth error %d\n", err); |
3695 | return err; | 3499 | return err; |
@@ -3710,6 +3514,7 @@ static s32 | |||
3710 | brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie, | 3514 | brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie, |
3711 | bool is_rsn_ie, s32 bssidx) | 3515 | bool is_rsn_ie, s32 bssidx) |
3712 | { | 3516 | { |
3517 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
3713 | u32 auth = 0; /* d11 open authentication */ | 3518 | u32 auth = 0; /* d11 open authentication */ |
3714 | u16 count; | 3519 | u16 count; |
3715 | s32 err = 0; | 3520 | s32 err = 0; |
@@ -3850,8 +3655,8 @@ brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie, | |||
3850 | wme_bss_disable = 0; | 3655 | wme_bss_disable = 0; |
3851 | } | 3656 | } |
3852 | /* set wme_bss_disable to sync RSN Capabilities */ | 3657 | /* set wme_bss_disable to sync RSN Capabilities */ |
3853 | err = brcmf_dev_intvar_set_bsscfg(ndev, "wme_bss_disable", | 3658 | err = brcmf_fil_bsscfg_int_set(ifp, "wme_bss_disable", |
3854 | wme_bss_disable, bssidx); | 3659 | wme_bss_disable); |
3855 | if (err < 0) { | 3660 | if (err < 0) { |
3856 | WL_ERR("wme_bss_disable error %d\n", err); | 3661 | WL_ERR("wme_bss_disable error %d\n", err); |
3857 | goto exit; | 3662 | goto exit; |
@@ -3861,19 +3666,19 @@ brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie, | |||
3861 | wsec = (pval | gval | SES_OW_ENABLED); | 3666 | wsec = (pval | gval | SES_OW_ENABLED); |
3862 | 3667 | ||
3863 | /* set auth */ | 3668 | /* set auth */ |
3864 | err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", auth, bssidx); | 3669 | err = brcmf_fil_bsscfg_int_set(ifp, "auth", auth); |
3865 | if (err < 0) { | 3670 | if (err < 0) { |
3866 | WL_ERR("auth error %d\n", err); | 3671 | WL_ERR("auth error %d\n", err); |
3867 | goto exit; | 3672 | goto exit; |
3868 | } | 3673 | } |
3869 | /* set wsec */ | 3674 | /* set wsec */ |
3870 | err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", wsec, bssidx); | 3675 | err = brcmf_fil_bsscfg_int_set(ifp, "wsec", wsec); |
3871 | if (err < 0) { | 3676 | if (err < 0) { |
3872 | WL_ERR("wsec error %d\n", err); | 3677 | WL_ERR("wsec error %d\n", err); |
3873 | goto exit; | 3678 | goto exit; |
3874 | } | 3679 | } |
3875 | /* set upper-layer auth */ | 3680 | /* set upper-layer auth */ |
3876 | err = brcmf_dev_intvar_set_bsscfg(ndev, "wpa_auth", wpa_auth, bssidx); | 3681 | err = brcmf_fil_bsscfg_int_set(ifp, "wpa_auth", wpa_auth); |
3877 | if (err < 0) { | 3682 | if (err < 0) { |
3878 | WL_ERR("wpa_auth error %d\n", err); | 3683 | WL_ERR("wpa_auth error %d\n", err); |
3879 | goto exit; | 3684 | goto exit; |
@@ -3963,17 +3768,19 @@ brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd) | |||
3963 | return ie_len + VNDR_IE_HDR_SIZE; | 3768 | return ie_len + VNDR_IE_HDR_SIZE; |
3964 | } | 3769 | } |
3965 | 3770 | ||
3966 | s32 | 3771 | static s32 |
3967 | brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg, | 3772 | brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg, |
3968 | struct net_device *ndev, s32 bssidx, s32 pktflag, | 3773 | struct net_device *ndev, s32 pktflag, |
3969 | u8 *vndr_ie_buf, u32 vndr_ie_len) | 3774 | u8 *vndr_ie_buf, u32 vndr_ie_len) |
3970 | { | 3775 | { |
3776 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
3777 | struct vif_saved_ie *saved_ie = &ifp->vif->saved_ie; | ||
3971 | s32 err = 0; | 3778 | s32 err = 0; |
3972 | u8 *iovar_ie_buf; | 3779 | u8 *iovar_ie_buf; |
3973 | u8 *curr_ie_buf; | 3780 | u8 *curr_ie_buf; |
3974 | u8 *mgmt_ie_buf = NULL; | 3781 | u8 *mgmt_ie_buf = NULL; |
3975 | u32 mgmt_ie_buf_len = 0; | 3782 | int mgmt_ie_buf_len; |
3976 | u32 *mgmt_ie_len = 0; | 3783 | u32 *mgmt_ie_len; |
3977 | u32 del_add_ie_buf_len = 0; | 3784 | u32 del_add_ie_buf_len = 0; |
3978 | u32 total_ie_buf_len = 0; | 3785 | u32 total_ie_buf_len = 0; |
3979 | u32 parsed_ie_buf_len = 0; | 3786 | u32 parsed_ie_buf_len = 0; |
@@ -3982,33 +3789,31 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg, | |||
3982 | struct parsed_vndr_ie_info *vndrie_info; | 3789 | struct parsed_vndr_ie_info *vndrie_info; |
3983 | s32 i; | 3790 | s32 i; |
3984 | u8 *ptr; | 3791 | u8 *ptr; |
3985 | u32 remained_buf_len; | 3792 | int remained_buf_len; |
3986 | 3793 | ||
3987 | WL_TRACE("bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag); | 3794 | WL_TRACE("bssidx %d, pktflag : 0x%02X\n", |
3795 | brcmf_ndev_bssidx(ndev), pktflag); | ||
3988 | iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); | 3796 | iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); |
3989 | if (!iovar_ie_buf) | 3797 | if (!iovar_ie_buf) |
3990 | return -ENOMEM; | 3798 | return -ENOMEM; |
3991 | curr_ie_buf = iovar_ie_buf; | 3799 | curr_ie_buf = iovar_ie_buf; |
3992 | if (test_bit(WL_STATUS_AP_CREATING, &cfg->status) || | 3800 | if (ifp->vif->mode == WL_MODE_AP) { |
3993 | test_bit(WL_STATUS_AP_CREATED, &cfg->status)) { | ||
3994 | switch (pktflag) { | 3801 | switch (pktflag) { |
3995 | case VNDR_IE_PRBRSP_FLAG: | 3802 | case VNDR_IE_PRBRSP_FLAG: |
3996 | mgmt_ie_buf = cfg->ap_info->probe_res_ie; | 3803 | mgmt_ie_buf = saved_ie->probe_res_ie; |
3997 | mgmt_ie_len = &cfg->ap_info->probe_res_ie_len; | 3804 | mgmt_ie_len = &saved_ie->probe_res_ie_len; |
3998 | mgmt_ie_buf_len = | 3805 | mgmt_ie_buf_len = sizeof(saved_ie->probe_res_ie); |
3999 | sizeof(cfg->ap_info->probe_res_ie); | ||
4000 | break; | 3806 | break; |
4001 | case VNDR_IE_BEACON_FLAG: | 3807 | case VNDR_IE_BEACON_FLAG: |
4002 | mgmt_ie_buf = cfg->ap_info->beacon_ie; | 3808 | mgmt_ie_buf = saved_ie->beacon_ie; |
4003 | mgmt_ie_len = &cfg->ap_info->beacon_ie_len; | 3809 | mgmt_ie_len = &saved_ie->beacon_ie_len; |
4004 | mgmt_ie_buf_len = sizeof(cfg->ap_info->beacon_ie); | 3810 | mgmt_ie_buf_len = sizeof(saved_ie->beacon_ie); |
4005 | break; | 3811 | break; |
4006 | default: | 3812 | default: |
4007 | err = -EPERM; | 3813 | err = -EPERM; |
4008 | WL_ERR("not suitable type\n"); | 3814 | WL_ERR("not suitable type\n"); |
4009 | goto exit; | 3815 | goto exit; |
4010 | } | 3816 | } |
4011 | bssidx = 0; | ||
4012 | } else { | 3817 | } else { |
4013 | err = -EPERM; | 3818 | err = -EPERM; |
4014 | WL_ERR("not suitable type\n"); | 3819 | WL_ERR("not suitable type\n"); |
@@ -4104,11 +3909,8 @@ brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg, | |||
4104 | } | 3909 | } |
4105 | } | 3910 | } |
4106 | if (total_ie_buf_len) { | 3911 | if (total_ie_buf_len) { |
4107 | err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "vndr_ie", | 3912 | err = brcmf_fil_bsscfg_data_set(ifp, "vndr_ie", iovar_ie_buf, |
4108 | iovar_ie_buf, | 3913 | total_ie_buf_len); |
4109 | total_ie_buf_len, | ||
4110 | cfg->extra_buf, | ||
4111 | WL_EXTRA_BUF_MAX, bssidx); | ||
4112 | if (err) | 3914 | if (err) |
4113 | WL_ERR("vndr ie set error : %d\n", err); | 3915 | WL_ERR("vndr ie set error : %d\n", err); |
4114 | } | 3916 | } |
@@ -4123,9 +3925,9 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
4123 | struct cfg80211_ap_settings *settings) | 3925 | struct cfg80211_ap_settings *settings) |
4124 | { | 3926 | { |
4125 | s32 ie_offset; | 3927 | s32 ie_offset; |
3928 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
4126 | struct brcmf_tlv *ssid_ie; | 3929 | struct brcmf_tlv *ssid_ie; |
4127 | struct brcmf_ssid_le ssid_le; | 3930 | struct brcmf_ssid_le ssid_le; |
4128 | s32 ioctl_value; | ||
4129 | s32 err = -EPERM; | 3931 | s32 err = -EPERM; |
4130 | struct brcmf_tlv *rsn_ie; | 3932 | struct brcmf_tlv *rsn_ie; |
4131 | struct brcmf_vs_tlv *wpa_ie; | 3933 | struct brcmf_vs_tlv *wpa_ie; |
@@ -4140,7 +3942,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
4140 | settings->ssid, settings->ssid_len, settings->auth_type, | 3942 | settings->ssid, settings->ssid_len, settings->auth_type, |
4141 | settings->inactivity_timeout); | 3943 | settings->inactivity_timeout); |
4142 | 3944 | ||
4143 | if (!test_bit(WL_STATUS_AP_CREATING, &cfg->status)) { | 3945 | if (!test_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state)) { |
4144 | WL_ERR("Not in AP creation mode\n"); | 3946 | WL_ERR("Not in AP creation mode\n"); |
4145 | return -EPERM; | 3947 | return -EPERM; |
4146 | } | 3948 | } |
@@ -4164,20 +3966,17 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
4164 | } | 3966 | } |
4165 | 3967 | ||
4166 | brcmf_set_mpc(ndev, 0); | 3968 | brcmf_set_mpc(ndev, 0); |
4167 | ioctl_value = 1; | 3969 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1); |
4168 | err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_DOWN, &ioctl_value); | ||
4169 | if (err < 0) { | 3970 | if (err < 0) { |
4170 | WL_ERR("BRCMF_C_DOWN error %d\n", err); | 3971 | WL_ERR("BRCMF_C_DOWN error %d\n", err); |
4171 | goto exit; | 3972 | goto exit; |
4172 | } | 3973 | } |
4173 | ioctl_value = 1; | 3974 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1); |
4174 | err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &ioctl_value); | ||
4175 | if (err < 0) { | 3975 | if (err < 0) { |
4176 | WL_ERR("SET INFRA error %d\n", err); | 3976 | WL_ERR("SET INFRA error %d\n", err); |
4177 | goto exit; | 3977 | goto exit; |
4178 | } | 3978 | } |
4179 | ioctl_value = 1; | 3979 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1); |
4180 | err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AP, &ioctl_value); | ||
4181 | if (err < 0) { | 3980 | if (err < 0) { |
4182 | WL_ERR("setting AP mode failed %d\n", err); | 3981 | WL_ERR("setting AP mode failed %d\n", err); |
4183 | goto exit; | 3982 | goto exit; |
@@ -4226,7 +4025,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
4226 | cfg->ap_info->security_mode = false; | 4025 | cfg->ap_info->security_mode = false; |
4227 | } | 4026 | } |
4228 | /* Set Beacon IEs to FW */ | 4027 | /* Set Beacon IEs to FW */ |
4229 | err = brcmf_set_management_ie(cfg, ndev, bssidx, | 4028 | err = brcmf_set_management_ie(cfg, ndev, |
4230 | VNDR_IE_BEACON_FLAG, | 4029 | VNDR_IE_BEACON_FLAG, |
4231 | (u8 *)settings->beacon.tail, | 4030 | (u8 *)settings->beacon.tail, |
4232 | settings->beacon.tail_len); | 4031 | settings->beacon.tail_len); |
@@ -4236,7 +4035,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
4236 | WL_TRACE("Applied Vndr IEs for Beacon\n"); | 4035 | WL_TRACE("Applied Vndr IEs for Beacon\n"); |
4237 | 4036 | ||
4238 | /* Set Probe Response IEs to FW */ | 4037 | /* Set Probe Response IEs to FW */ |
4239 | err = brcmf_set_management_ie(cfg, ndev, bssidx, | 4038 | err = brcmf_set_management_ie(cfg, ndev, |
4240 | VNDR_IE_PRBRSP_FLAG, | 4039 | VNDR_IE_PRBRSP_FLAG, |
4241 | (u8 *)settings->beacon.proberesp_ies, | 4040 | (u8 *)settings->beacon.proberesp_ies, |
4242 | settings->beacon.proberesp_ies_len); | 4041 | settings->beacon.proberesp_ies_len); |
@@ -4246,25 +4045,22 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
4246 | WL_TRACE("Applied Vndr IEs for Probe Resp\n"); | 4045 | WL_TRACE("Applied Vndr IEs for Probe Resp\n"); |
4247 | 4046 | ||
4248 | if (settings->beacon_interval) { | 4047 | if (settings->beacon_interval) { |
4249 | ioctl_value = settings->beacon_interval; | 4048 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD, |
4250 | err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_BCNPRD, | 4049 | settings->beacon_interval); |
4251 | &ioctl_value); | ||
4252 | if (err < 0) { | 4050 | if (err < 0) { |
4253 | WL_ERR("Beacon Interval Set Error, %d\n", err); | 4051 | WL_ERR("Beacon Interval Set Error, %d\n", err); |
4254 | goto exit; | 4052 | goto exit; |
4255 | } | 4053 | } |
4256 | } | 4054 | } |
4257 | if (settings->dtim_period) { | 4055 | if (settings->dtim_period) { |
4258 | ioctl_value = settings->dtim_period; | 4056 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_DTIMPRD, |
4259 | err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_DTIMPRD, | 4057 | settings->dtim_period); |
4260 | &ioctl_value); | ||
4261 | if (err < 0) { | 4058 | if (err < 0) { |
4262 | WL_ERR("DTIM Interval Set Error, %d\n", err); | 4059 | WL_ERR("DTIM Interval Set Error, %d\n", err); |
4263 | goto exit; | 4060 | goto exit; |
4264 | } | 4061 | } |
4265 | } | 4062 | } |
4266 | ioctl_value = 1; | 4063 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1); |
4267 | err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_UP, &ioctl_value); | ||
4268 | if (err < 0) { | 4064 | if (err < 0) { |
4269 | WL_ERR("BRCMF_C_UP error (%d)\n", err); | 4065 | WL_ERR("BRCMF_C_UP error (%d)\n", err); |
4270 | goto exit; | 4066 | goto exit; |
@@ -4274,14 +4070,14 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, | |||
4274 | /* join parameters starts with ssid */ | 4070 | /* join parameters starts with ssid */ |
4275 | memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le)); | 4071 | memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le)); |
4276 | /* create softap */ | 4072 | /* create softap */ |
4277 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, &join_params, | 4073 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID, |
4278 | sizeof(join_params)); | 4074 | &join_params, sizeof(join_params)); |
4279 | if (err < 0) { | 4075 | if (err < 0) { |
4280 | WL_ERR("SET SSID error (%d)\n", err); | 4076 | WL_ERR("SET SSID error (%d)\n", err); |
4281 | goto exit; | 4077 | goto exit; |
4282 | } | 4078 | } |
4283 | clear_bit(WL_STATUS_AP_CREATING, &cfg->status); | 4079 | clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); |
4284 | set_bit(WL_STATUS_AP_CREATED, &cfg->status); | 4080 | set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); |
4285 | 4081 | ||
4286 | exit: | 4082 | exit: |
4287 | if (err) | 4083 | if (err) |
@@ -4291,8 +4087,8 @@ exit: | |||
4291 | 4087 | ||
4292 | static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) | 4088 | static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) |
4293 | { | 4089 | { |
4090 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
4294 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 4091 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
4295 | s32 ioctl_value; | ||
4296 | s32 err = -EPERM; | 4092 | s32 err = -EPERM; |
4297 | 4093 | ||
4298 | WL_TRACE("Enter\n"); | 4094 | WL_TRACE("Enter\n"); |
@@ -4301,21 +4097,20 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) | |||
4301 | /* Due to most likely deauths outstanding we sleep */ | 4097 | /* Due to most likely deauths outstanding we sleep */ |
4302 | /* first to make sure they get processed by fw. */ | 4098 | /* first to make sure they get processed by fw. */ |
4303 | msleep(400); | 4099 | msleep(400); |
4304 | ioctl_value = 0; | 4100 | err = brcmf_fil_cmd_int_set(netdev_priv(ndev), |
4305 | err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AP, &ioctl_value); | 4101 | BRCMF_C_SET_AP, 0); |
4306 | if (err < 0) { | 4102 | if (err < 0) { |
4307 | WL_ERR("setting AP mode failed %d\n", err); | 4103 | WL_ERR("setting AP mode failed %d\n", err); |
4308 | goto exit; | 4104 | goto exit; |
4309 | } | 4105 | } |
4310 | ioctl_value = 0; | 4106 | err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_UP, 0); |
4311 | err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_UP, &ioctl_value); | ||
4312 | if (err < 0) { | 4107 | if (err < 0) { |
4313 | WL_ERR("BRCMF_C_UP error %d\n", err); | 4108 | WL_ERR("BRCMF_C_UP error %d\n", err); |
4314 | goto exit; | 4109 | goto exit; |
4315 | } | 4110 | } |
4316 | brcmf_set_mpc(ndev, 1); | 4111 | brcmf_set_mpc(ndev, 1); |
4317 | clear_bit(WL_STATUS_AP_CREATING, &cfg->status); | 4112 | clear_bit(BRCMF_VIF_STATUS_AP_CREATING, &ifp->vif->sme_state); |
4318 | clear_bit(WL_STATUS_AP_CREATED, &cfg->status); | 4113 | clear_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state); |
4319 | } | 4114 | } |
4320 | exit: | 4115 | exit: |
4321 | return err; | 4116 | return err; |
@@ -4326,6 +4121,7 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, | |||
4326 | u8 *mac) | 4121 | u8 *mac) |
4327 | { | 4122 | { |
4328 | struct brcmf_scb_val_le scbval; | 4123 | struct brcmf_scb_val_le scbval; |
4124 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
4329 | s32 err; | 4125 | s32 err; |
4330 | 4126 | ||
4331 | if (!mac) | 4127 | if (!mac) |
@@ -4333,13 +4129,13 @@ brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, | |||
4333 | 4129 | ||
4334 | WL_TRACE("Enter %pM\n", mac); | 4130 | WL_TRACE("Enter %pM\n", mac); |
4335 | 4131 | ||
4336 | if (!check_sys_up(wiphy)) | 4132 | if (!check_vif_up(ifp->vif)) |
4337 | return -EIO; | 4133 | return -EIO; |
4338 | 4134 | ||
4339 | memcpy(&scbval.ea, mac, ETH_ALEN); | 4135 | memcpy(&scbval.ea, mac, ETH_ALEN); |
4340 | scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING); | 4136 | scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING); |
4341 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON, | 4137 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON, |
4342 | &scbval, sizeof(scbval)); | 4138 | &scbval, sizeof(scbval)); |
4343 | if (err) | 4139 | if (err) |
4344 | WL_ERR("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err); | 4140 | WL_ERR("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err); |
4345 | 4141 | ||
@@ -4410,72 +4206,97 @@ static void brcmf_wiphy_pno_params(struct wiphy *wiphy) | |||
4410 | #endif | 4206 | #endif |
4411 | } | 4207 | } |
4412 | 4208 | ||
4413 | static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev) | 4209 | static struct wiphy *brcmf_setup_wiphy(struct device *phydev) |
4414 | { | 4210 | { |
4415 | struct wireless_dev *wdev; | 4211 | struct wiphy *wiphy; |
4416 | s32 err = 0; | 4212 | s32 err = 0; |
4417 | 4213 | ||
4418 | wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); | 4214 | wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct brcmf_cfg80211_info)); |
4419 | if (!wdev) | 4215 | if (!wiphy) { |
4420 | return ERR_PTR(-ENOMEM); | ||
4421 | |||
4422 | wdev->wiphy = wiphy_new(&wl_cfg80211_ops, | ||
4423 | sizeof(struct brcmf_cfg80211_info)); | ||
4424 | if (!wdev->wiphy) { | ||
4425 | WL_ERR("Could not allocate wiphy device\n"); | 4216 | WL_ERR("Could not allocate wiphy device\n"); |
4426 | err = -ENOMEM; | 4217 | return ERR_PTR(-ENOMEM); |
4427 | goto wiphy_new_out; | 4218 | } |
4428 | } | 4219 | set_wiphy_dev(wiphy, phydev); |
4429 | set_wiphy_dev(wdev->wiphy, ndev); | 4220 | wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; |
4430 | wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; | 4221 | wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; |
4431 | wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; | 4222 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | |
4432 | wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | 4223 | BIT(NL80211_IFTYPE_ADHOC) | |
4433 | BIT(NL80211_IFTYPE_ADHOC) | | 4224 | BIT(NL80211_IFTYPE_AP); |
4434 | BIT(NL80211_IFTYPE_AP); | 4225 | wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; |
4435 | wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; | 4226 | wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set |
4436 | wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set | ||
4437 | * it as 11a by default. | 4227 | * it as 11a by default. |
4438 | * This will be updated with | 4228 | * This will be updated with |
4439 | * 11n phy tables in | 4229 | * 11n phy tables in |
4440 | * "ifconfig up" | 4230 | * "ifconfig up" |
4441 | * if phy has 11n capability | 4231 | * if phy has 11n capability |
4442 | */ | 4232 | */ |
4443 | wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 4233 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
4444 | wdev->wiphy->cipher_suites = __wl_cipher_suites; | 4234 | wiphy->cipher_suites = __wl_cipher_suites; |
4445 | wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); | 4235 | wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); |
4446 | wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power | 4236 | wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power |
4447 | * save mode | 4237 | * save mode |
4448 | * by default | 4238 | * by default |
4449 | */ | 4239 | */ |
4450 | brcmf_wiphy_pno_params(wdev->wiphy); | 4240 | brcmf_wiphy_pno_params(wiphy); |
4451 | err = wiphy_register(wdev->wiphy); | 4241 | err = wiphy_register(wiphy); |
4452 | if (err < 0) { | 4242 | if (err < 0) { |
4453 | WL_ERR("Could not register wiphy device (%d)\n", err); | 4243 | WL_ERR("Could not register wiphy device (%d)\n", err); |
4454 | goto wiphy_register_out; | 4244 | wiphy_free(wiphy); |
4245 | return ERR_PTR(err); | ||
4455 | } | 4246 | } |
4456 | return wdev; | 4247 | return wiphy; |
4248 | } | ||
4249 | |||
4250 | static | ||
4251 | struct brcmf_cfg80211_vif *brcmf_alloc_vif(struct brcmf_cfg80211_info *cfg, | ||
4252 | struct net_device *netdev, | ||
4253 | s32 mode, bool pm_block) | ||
4254 | { | ||
4255 | struct brcmf_cfg80211_vif *vif; | ||
4256 | |||
4257 | if (cfg->vif_cnt == BRCMF_IFACE_MAX_CNT) | ||
4258 | return ERR_PTR(-ENOSPC); | ||
4457 | 4259 | ||
4458 | wiphy_register_out: | 4260 | vif = kzalloc(sizeof(*vif), GFP_KERNEL); |
4459 | wiphy_free(wdev->wiphy); | 4261 | if (!vif) |
4262 | return ERR_PTR(-ENOMEM); | ||
4263 | |||
4264 | vif->wdev.wiphy = cfg->wiphy; | ||
4265 | vif->wdev.netdev = netdev; | ||
4266 | vif->wdev.iftype = brcmf_mode_to_nl80211_iftype(mode); | ||
4267 | |||
4268 | if (netdev) { | ||
4269 | vif->ifp = netdev_priv(netdev); | ||
4270 | netdev->ieee80211_ptr = &vif->wdev; | ||
4271 | SET_NETDEV_DEV(netdev, wiphy_dev(cfg->wiphy)); | ||
4272 | } | ||
4460 | 4273 | ||
4461 | wiphy_new_out: | 4274 | vif->mode = mode; |
4462 | kfree(wdev); | 4275 | vif->pm_block = pm_block; |
4276 | vif->roam_off = -1; | ||
4463 | 4277 | ||
4464 | return ERR_PTR(err); | 4278 | brcmf_init_prof(&vif->profile); |
4279 | |||
4280 | list_add_tail(&vif->list, &cfg->vif_list); | ||
4281 | cfg->vif_cnt++; | ||
4282 | return vif; | ||
4465 | } | 4283 | } |
4466 | 4284 | ||
4467 | static void brcmf_free_wdev(struct brcmf_cfg80211_info *cfg) | 4285 | static void brcmf_free_vif(struct brcmf_cfg80211_vif *vif) |
4468 | { | 4286 | { |
4469 | struct wireless_dev *wdev = cfg->wdev; | 4287 | struct brcmf_cfg80211_info *cfg; |
4288 | struct wiphy *wiphy; | ||
4470 | 4289 | ||
4471 | if (!wdev) { | 4290 | wiphy = vif->wdev.wiphy; |
4472 | WL_ERR("wdev is invalid\n"); | 4291 | cfg = wiphy_priv(wiphy); |
4473 | return; | 4292 | list_del(&vif->list); |
4293 | cfg->vif_cnt--; | ||
4294 | |||
4295 | kfree(vif); | ||
4296 | if (!cfg->vif_cnt) { | ||
4297 | wiphy_unregister(wiphy); | ||
4298 | wiphy_free(wiphy); | ||
4474 | } | 4299 | } |
4475 | wiphy_unregister(wdev->wiphy); | ||
4476 | wiphy_free(wdev->wiphy); | ||
4477 | kfree(wdev); | ||
4478 | cfg->wdev = NULL; | ||
4479 | } | 4300 | } |
4480 | 4301 | ||
4481 | static bool brcmf_is_linkup(struct brcmf_cfg80211_info *cfg, | 4302 | static bool brcmf_is_linkup(struct brcmf_cfg80211_info *cfg, |
@@ -4541,7 +4362,7 @@ static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg) | |||
4541 | 4362 | ||
4542 | static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg) | 4363 | static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg) |
4543 | { | 4364 | { |
4544 | struct net_device *ndev = cfg_to_ndev(cfg); | 4365 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); |
4545 | struct brcmf_cfg80211_assoc_ielen_le *assoc_info; | 4366 | struct brcmf_cfg80211_assoc_ielen_le *assoc_info; |
4546 | struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); | 4367 | struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); |
4547 | u32 req_len; | 4368 | u32 req_len; |
@@ -4550,8 +4371,8 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg) | |||
4550 | 4371 | ||
4551 | brcmf_clear_assoc_ies(cfg); | 4372 | brcmf_clear_assoc_ies(cfg); |
4552 | 4373 | ||
4553 | err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg->extra_buf, | 4374 | err = brcmf_fil_iovar_data_get(ifp, "assoc_info", |
4554 | WL_ASSOC_INFO_MAX); | 4375 | cfg->extra_buf, WL_ASSOC_INFO_MAX); |
4555 | if (err) { | 4376 | if (err) { |
4556 | WL_ERR("could not get assoc info (%d)\n", err); | 4377 | WL_ERR("could not get assoc info (%d)\n", err); |
4557 | return err; | 4378 | return err; |
@@ -4561,9 +4382,9 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg) | |||
4561 | req_len = le32_to_cpu(assoc_info->req_len); | 4382 | req_len = le32_to_cpu(assoc_info->req_len); |
4562 | resp_len = le32_to_cpu(assoc_info->resp_len); | 4383 | resp_len = le32_to_cpu(assoc_info->resp_len); |
4563 | if (req_len) { | 4384 | if (req_len) { |
4564 | err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies", | 4385 | err = brcmf_fil_iovar_data_get(ifp, "assoc_req_ies", |
4565 | cfg->extra_buf, | 4386 | cfg->extra_buf, |
4566 | WL_ASSOC_INFO_MAX); | 4387 | WL_ASSOC_INFO_MAX); |
4567 | if (err) { | 4388 | if (err) { |
4568 | WL_ERR("could not get assoc req (%d)\n", err); | 4389 | WL_ERR("could not get assoc req (%d)\n", err); |
4569 | return err; | 4390 | return err; |
@@ -4577,9 +4398,9 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg) | |||
4577 | conn_info->req_ie = NULL; | 4398 | conn_info->req_ie = NULL; |
4578 | } | 4399 | } |
4579 | if (resp_len) { | 4400 | if (resp_len) { |
4580 | err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies", | 4401 | err = brcmf_fil_iovar_data_get(ifp, "assoc_resp_ies", |
4581 | cfg->extra_buf, | 4402 | cfg->extra_buf, |
4582 | WL_ASSOC_INFO_MAX); | 4403 | WL_ASSOC_INFO_MAX); |
4583 | if (err) { | 4404 | if (err) { |
4584 | WL_ERR("could not get assoc resp (%d)\n", err); | 4405 | WL_ERR("could not get assoc resp (%d)\n", err); |
4585 | return err; | 4406 | return err; |
@@ -4603,15 +4424,17 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, | |||
4603 | struct net_device *ndev, | 4424 | struct net_device *ndev, |
4604 | const struct brcmf_event_msg *e) | 4425 | const struct brcmf_event_msg *e) |
4605 | { | 4426 | { |
4606 | struct brcmf_cfg80211_profile *profile = cfg->profile; | 4427 | struct brcmf_if *ifp = netdev_priv(ndev); |
4428 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | ||
4607 | struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); | 4429 | struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); |
4608 | struct wiphy *wiphy = cfg_to_wiphy(cfg); | 4430 | struct wiphy *wiphy = cfg_to_wiphy(cfg); |
4609 | struct brcmf_channel_info_le channel_le; | 4431 | struct ieee80211_channel *notify_channel = NULL; |
4610 | struct ieee80211_channel *notify_channel; | ||
4611 | struct ieee80211_supported_band *band; | 4432 | struct ieee80211_supported_band *band; |
4433 | struct brcmf_bss_info_le *bi; | ||
4612 | u32 freq; | 4434 | u32 freq; |
4613 | s32 err = 0; | 4435 | s32 err = 0; |
4614 | u32 target_channel; | 4436 | u32 target_channel; |
4437 | u8 *buf; | ||
4615 | 4438 | ||
4616 | WL_TRACE("Enter\n"); | 4439 | WL_TRACE("Enter\n"); |
4617 | 4440 | ||
@@ -4619,11 +4442,23 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, | |||
4619 | memcpy(profile->bssid, e->addr, ETH_ALEN); | 4442 | memcpy(profile->bssid, e->addr, ETH_ALEN); |
4620 | brcmf_update_bss_info(cfg); | 4443 | brcmf_update_bss_info(cfg); |
4621 | 4444 | ||
4622 | brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le, | 4445 | buf = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); |
4623 | sizeof(channel_le)); | 4446 | if (buf == NULL) { |
4447 | err = -ENOMEM; | ||
4448 | goto done; | ||
4449 | } | ||
4450 | |||
4451 | /* data sent to dongle has to be little endian */ | ||
4452 | *(__le32 *)buf = cpu_to_le32(WL_BSS_INFO_MAX); | ||
4453 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_BSS_INFO, | ||
4454 | buf, WL_BSS_INFO_MAX); | ||
4624 | 4455 | ||
4625 | target_channel = le32_to_cpu(channel_le.target_channel); | 4456 | if (err) |
4626 | WL_CONN("Roamed to channel %d\n", target_channel); | 4457 | goto done; |
4458 | |||
4459 | bi = (struct brcmf_bss_info_le *)(buf + 4); | ||
4460 | target_channel = bi->ctl_ch ? bi->ctl_ch : | ||
4461 | CHSPEC_CHANNEL(le16_to_cpu(bi->chanspec)); | ||
4627 | 4462 | ||
4628 | if (target_channel <= CH_MAX_2G_CHANNEL) | 4463 | if (target_channel <= CH_MAX_2G_CHANNEL) |
4629 | band = wiphy->bands[IEEE80211_BAND_2GHZ]; | 4464 | band = wiphy->bands[IEEE80211_BAND_2GHZ]; |
@@ -4633,12 +4468,14 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, | |||
4633 | freq = ieee80211_channel_to_frequency(target_channel, band->band); | 4468 | freq = ieee80211_channel_to_frequency(target_channel, band->band); |
4634 | notify_channel = ieee80211_get_channel(wiphy, freq); | 4469 | notify_channel = ieee80211_get_channel(wiphy, freq); |
4635 | 4470 | ||
4471 | done: | ||
4472 | kfree(buf); | ||
4636 | cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid, | 4473 | cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid, |
4637 | conn_info->req_ie, conn_info->req_ie_len, | 4474 | conn_info->req_ie, conn_info->req_ie_len, |
4638 | conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); | 4475 | conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); |
4639 | WL_CONN("Report roaming result\n"); | 4476 | WL_CONN("Report roaming result\n"); |
4640 | 4477 | ||
4641 | set_bit(WL_STATUS_CONNECTED, &cfg->status); | 4478 | set_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state); |
4642 | WL_TRACE("Exit\n"); | 4479 | WL_TRACE("Exit\n"); |
4643 | return err; | 4480 | return err; |
4644 | } | 4481 | } |
@@ -4648,13 +4485,15 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg, | |||
4648 | struct net_device *ndev, const struct brcmf_event_msg *e, | 4485 | struct net_device *ndev, const struct brcmf_event_msg *e, |
4649 | bool completed) | 4486 | bool completed) |
4650 | { | 4487 | { |
4651 | struct brcmf_cfg80211_profile *profile = cfg->profile; | 4488 | struct brcmf_if *ifp = netdev_priv(ndev); |
4489 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | ||
4652 | struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); | 4490 | struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); |
4653 | s32 err = 0; | 4491 | s32 err = 0; |
4654 | 4492 | ||
4655 | WL_TRACE("Enter\n"); | 4493 | WL_TRACE("Enter\n"); |
4656 | 4494 | ||
4657 | if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg->status)) { | 4495 | if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTING, |
4496 | &ifp->vif->sme_state)) { | ||
4658 | if (completed) { | 4497 | if (completed) { |
4659 | brcmf_get_assoc_ies(cfg); | 4498 | brcmf_get_assoc_ies(cfg); |
4660 | memcpy(profile->bssid, e->addr, ETH_ALEN); | 4499 | memcpy(profile->bssid, e->addr, ETH_ALEN); |
@@ -4670,7 +4509,8 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg, | |||
4670 | WLAN_STATUS_AUTH_TIMEOUT, | 4509 | WLAN_STATUS_AUTH_TIMEOUT, |
4671 | GFP_KERNEL); | 4510 | GFP_KERNEL); |
4672 | if (completed) | 4511 | if (completed) |
4673 | set_bit(WL_STATUS_CONNECTED, &cfg->status); | 4512 | set_bit(BRCMF_VIF_STATUS_CONNECTED, |
4513 | &ifp->vif->sme_state); | ||
4674 | WL_CONN("Report connect result - connection %s\n", | 4514 | WL_CONN("Report connect result - connection %s\n", |
4675 | completed ? "succeeded" : "failed"); | 4515 | completed ? "succeeded" : "failed"); |
4676 | } | 4516 | } |
@@ -4722,7 +4562,8 @@ brcmf_notify_connect_status(struct brcmf_cfg80211_info *cfg, | |||
4722 | struct net_device *ndev, | 4562 | struct net_device *ndev, |
4723 | const struct brcmf_event_msg *e, void *data) | 4563 | const struct brcmf_event_msg *e, void *data) |
4724 | { | 4564 | { |
4725 | struct brcmf_cfg80211_profile *profile = cfg->profile; | 4565 | struct brcmf_if *ifp = netdev_priv(ndev); |
4566 | struct brcmf_cfg80211_profile *profile = &ifp->vif->profile; | ||
4726 | s32 err = 0; | 4567 | s32 err = 0; |
4727 | 4568 | ||
4728 | if (cfg->conf->mode == WL_MODE_AP) { | 4569 | if (cfg->conf->mode == WL_MODE_AP) { |
@@ -4733,30 +4574,34 @@ brcmf_notify_connect_status(struct brcmf_cfg80211_info *cfg, | |||
4733 | memcpy(profile->bssid, e->addr, ETH_ALEN); | 4574 | memcpy(profile->bssid, e->addr, ETH_ALEN); |
4734 | wl_inform_ibss(cfg, ndev, e->addr); | 4575 | wl_inform_ibss(cfg, ndev, e->addr); |
4735 | cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL); | 4576 | cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL); |
4736 | clear_bit(WL_STATUS_CONNECTING, &cfg->status); | 4577 | clear_bit(BRCMF_VIF_STATUS_CONNECTING, |
4737 | set_bit(WL_STATUS_CONNECTED, &cfg->status); | 4578 | &ifp->vif->sme_state); |
4579 | set_bit(BRCMF_VIF_STATUS_CONNECTED, | ||
4580 | &ifp->vif->sme_state); | ||
4738 | } else | 4581 | } else |
4739 | brcmf_bss_connect_done(cfg, ndev, e, true); | 4582 | brcmf_bss_connect_done(cfg, ndev, e, true); |
4740 | } else if (brcmf_is_linkdown(cfg, e)) { | 4583 | } else if (brcmf_is_linkdown(cfg, e)) { |
4741 | WL_CONN("Linkdown\n"); | 4584 | WL_CONN("Linkdown\n"); |
4742 | if (brcmf_is_ibssmode(cfg)) { | 4585 | if (brcmf_is_ibssmode(cfg)) { |
4743 | clear_bit(WL_STATUS_CONNECTING, &cfg->status); | 4586 | clear_bit(BRCMF_VIF_STATUS_CONNECTING, |
4744 | if (test_and_clear_bit(WL_STATUS_CONNECTED, | 4587 | &ifp->vif->sme_state); |
4745 | &cfg->status)) | 4588 | if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED, |
4589 | &ifp->vif->sme_state)) | ||
4746 | brcmf_link_down(cfg); | 4590 | brcmf_link_down(cfg); |
4747 | } else { | 4591 | } else { |
4748 | brcmf_bss_connect_done(cfg, ndev, e, false); | 4592 | brcmf_bss_connect_done(cfg, ndev, e, false); |
4749 | if (test_and_clear_bit(WL_STATUS_CONNECTED, | 4593 | if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED, |
4750 | &cfg->status)) { | 4594 | &ifp->vif->sme_state)) { |
4751 | cfg80211_disconnected(ndev, 0, NULL, 0, | 4595 | cfg80211_disconnected(ndev, 0, NULL, 0, |
4752 | GFP_KERNEL); | 4596 | GFP_KERNEL); |
4753 | brcmf_link_down(cfg); | 4597 | brcmf_link_down(cfg); |
4754 | } | 4598 | } |
4755 | } | 4599 | } |
4756 | brcmf_init_prof(cfg->profile); | 4600 | brcmf_init_prof(ndev_to_prof(ndev)); |
4757 | } else if (brcmf_is_nonetwork(cfg, e)) { | 4601 | } else if (brcmf_is_nonetwork(cfg, e)) { |
4758 | if (brcmf_is_ibssmode(cfg)) | 4602 | if (brcmf_is_ibssmode(cfg)) |
4759 | clear_bit(WL_STATUS_CONNECTING, &cfg->status); | 4603 | clear_bit(BRCMF_VIF_STATUS_CONNECTING, |
4604 | &ifp->vif->sme_state); | ||
4760 | else | 4605 | else |
4761 | brcmf_bss_connect_done(cfg, ndev, e, false); | 4606 | brcmf_bss_connect_done(cfg, ndev, e, false); |
4762 | } | 4607 | } |
@@ -4769,12 +4614,13 @@ brcmf_notify_roaming_status(struct brcmf_cfg80211_info *cfg, | |||
4769 | struct net_device *ndev, | 4614 | struct net_device *ndev, |
4770 | const struct brcmf_event_msg *e, void *data) | 4615 | const struct brcmf_event_msg *e, void *data) |
4771 | { | 4616 | { |
4617 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
4772 | s32 err = 0; | 4618 | s32 err = 0; |
4773 | u32 event = be32_to_cpu(e->event_type); | 4619 | u32 event = be32_to_cpu(e->event_type); |
4774 | u32 status = be32_to_cpu(e->status); | 4620 | u32 status = be32_to_cpu(e->status); |
4775 | 4621 | ||
4776 | if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) { | 4622 | if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) { |
4777 | if (test_bit(WL_STATUS_CONNECTED, &cfg->status)) | 4623 | if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state)) |
4778 | brcmf_bss_roaming_done(cfg, ndev, e); | 4624 | brcmf_bss_roaming_done(cfg, ndev, e); |
4779 | else | 4625 | else |
4780 | brcmf_bss_connect_done(cfg, ndev, e, true); | 4626 | brcmf_bss_connect_done(cfg, ndev, e, true); |
@@ -4807,6 +4653,7 @@ brcmf_notify_scan_status(struct brcmf_cfg80211_info *cfg, | |||
4807 | struct net_device *ndev, | 4653 | struct net_device *ndev, |
4808 | const struct brcmf_event_msg *e, void *data) | 4654 | const struct brcmf_event_msg *e, void *data) |
4809 | { | 4655 | { |
4656 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
4810 | struct brcmf_channel_info_le channel_inform_le; | 4657 | struct brcmf_channel_info_le channel_inform_le; |
4811 | struct brcmf_scan_results_le *bss_list_le; | 4658 | struct brcmf_scan_results_le *bss_list_le; |
4812 | u32 len = WL_SCAN_BUF_MAX; | 4659 | u32 len = WL_SCAN_BUF_MAX; |
@@ -4821,15 +4668,16 @@ brcmf_notify_scan_status(struct brcmf_cfg80211_info *cfg, | |||
4821 | return brcmf_wakeup_iscan(cfg_to_iscan(cfg)); | 4668 | return brcmf_wakeup_iscan(cfg_to_iscan(cfg)); |
4822 | } | 4669 | } |
4823 | 4670 | ||
4824 | if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) { | 4671 | if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) { |
4825 | WL_ERR("Scan complete while device not scanning\n"); | 4672 | WL_ERR("Scan complete while device not scanning\n"); |
4826 | scan_abort = true; | 4673 | scan_abort = true; |
4827 | err = -EINVAL; | 4674 | err = -EINVAL; |
4828 | goto scan_done_out; | 4675 | goto scan_done_out; |
4829 | } | 4676 | } |
4830 | 4677 | ||
4831 | err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_inform_le, | 4678 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_GET_CHANNEL, |
4832 | sizeof(channel_inform_le)); | 4679 | &channel_inform_le, |
4680 | sizeof(channel_inform_le)); | ||
4833 | if (err) { | 4681 | if (err) { |
4834 | WL_ERR("scan busy (%d)\n", err); | 4682 | WL_ERR("scan busy (%d)\n", err); |
4835 | scan_abort = true; | 4683 | scan_abort = true; |
@@ -4843,8 +4691,8 @@ brcmf_notify_scan_status(struct brcmf_cfg80211_info *cfg, | |||
4843 | 4691 | ||
4844 | memset(cfg->scan_results, 0, len); | 4692 | memset(cfg->scan_results, 0, len); |
4845 | bss_list_le->buflen = cpu_to_le32(len); | 4693 | bss_list_le->buflen = cpu_to_le32(len); |
4846 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS, | 4694 | err = brcmf_fil_cmd_data_get(ifp, BRCMF_C_SCAN_RESULTS, |
4847 | cfg->scan_results, len); | 4695 | cfg->scan_results, len); |
4848 | if (err) { | 4696 | if (err) { |
4849 | WL_ERR("%s Scan_results error (%d)\n", ndev->name, err); | 4697 | WL_ERR("%s Scan_results error (%d)\n", ndev->name, err); |
4850 | err = -EINVAL; | 4698 | err = -EINVAL; |
@@ -4906,8 +4754,6 @@ static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg) | |||
4906 | cfg->bss_info = NULL; | 4754 | cfg->bss_info = NULL; |
4907 | kfree(cfg->conf); | 4755 | kfree(cfg->conf); |
4908 | cfg->conf = NULL; | 4756 | cfg->conf = NULL; |
4909 | kfree(cfg->profile); | ||
4910 | cfg->profile = NULL; | ||
4911 | kfree(cfg->scan_req_int); | 4757 | kfree(cfg->scan_req_int); |
4912 | cfg->scan_req_int = NULL; | 4758 | cfg->scan_req_int = NULL; |
4913 | kfree(cfg->escan_ioctl_buf); | 4759 | kfree(cfg->escan_ioctl_buf); |
@@ -4936,9 +4782,6 @@ static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg) | |||
4936 | cfg->conf = kzalloc(sizeof(*cfg->conf), GFP_KERNEL); | 4782 | cfg->conf = kzalloc(sizeof(*cfg->conf), GFP_KERNEL); |
4937 | if (!cfg->conf) | 4783 | if (!cfg->conf) |
4938 | goto init_priv_mem_out; | 4784 | goto init_priv_mem_out; |
4939 | cfg->profile = kzalloc(sizeof(*cfg->profile), GFP_KERNEL); | ||
4940 | if (!cfg->profile) | ||
4941 | goto init_priv_mem_out; | ||
4942 | cfg->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); | 4785 | cfg->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); |
4943 | if (!cfg->bss_info) | 4786 | if (!cfg->bss_info) |
4944 | goto init_priv_mem_out; | 4787 | goto init_priv_mem_out; |
@@ -5115,7 +4958,6 @@ static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg) | |||
5115 | return err; | 4958 | return err; |
5116 | brcmf_init_escan(cfg); | 4959 | brcmf_init_escan(cfg); |
5117 | brcmf_init_conf(cfg->conf); | 4960 | brcmf_init_conf(cfg->conf); |
5118 | brcmf_init_prof(cfg->profile); | ||
5119 | brcmf_link_down(cfg); | 4961 | brcmf_link_down(cfg); |
5120 | 4962 | ||
5121 | return err; | 4963 | return err; |
@@ -5131,12 +4973,14 @@ static void wl_deinit_priv(struct brcmf_cfg80211_info *cfg) | |||
5131 | brcmf_deinit_priv_mem(cfg); | 4973 | brcmf_deinit_priv_mem(cfg); |
5132 | } | 4974 | } |
5133 | 4975 | ||
5134 | struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct net_device *ndev, | 4976 | struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr) |
5135 | struct device *busdev, | ||
5136 | struct brcmf_pub *drvr) | ||
5137 | { | 4977 | { |
5138 | struct wireless_dev *wdev; | 4978 | struct net_device *ndev = drvr->iflist[0]->ndev; |
4979 | struct device *busdev = drvr->dev; | ||
5139 | struct brcmf_cfg80211_info *cfg; | 4980 | struct brcmf_cfg80211_info *cfg; |
4981 | struct wiphy *wiphy; | ||
4982 | struct brcmf_cfg80211_vif *vif; | ||
4983 | struct brcmf_if *ifp; | ||
5140 | s32 err = 0; | 4984 | s32 err = 0; |
5141 | 4985 | ||
5142 | if (!ndev) { | 4986 | if (!ndev) { |
@@ -5144,35 +4988,45 @@ struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct net_device *ndev, | |||
5144 | return NULL; | 4988 | return NULL; |
5145 | } | 4989 | } |
5146 | 4990 | ||
5147 | wdev = brcmf_alloc_wdev(busdev); | 4991 | ifp = netdev_priv(ndev); |
5148 | if (IS_ERR(wdev)) { | 4992 | wiphy = brcmf_setup_wiphy(busdev); |
4993 | if (IS_ERR(wiphy)) | ||
5149 | return NULL; | 4994 | return NULL; |
5150 | } | ||
5151 | 4995 | ||
5152 | wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS); | 4996 | cfg = wiphy_priv(wiphy); |
5153 | cfg = wdev_to_cfg(wdev); | 4997 | cfg->wiphy = wiphy; |
5154 | cfg->wdev = wdev; | ||
5155 | cfg->pub = drvr; | 4998 | cfg->pub = drvr; |
5156 | ndev->ieee80211_ptr = wdev; | 4999 | INIT_LIST_HEAD(&cfg->vif_list); |
5157 | SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); | 5000 | |
5158 | wdev->netdev = ndev; | 5001 | vif = brcmf_alloc_vif(cfg, ndev, WL_MODE_BSS, false); |
5002 | if (IS_ERR(vif)) { | ||
5003 | wiphy_free(wiphy); | ||
5004 | return NULL; | ||
5005 | } | ||
5006 | |||
5159 | err = wl_init_priv(cfg); | 5007 | err = wl_init_priv(cfg); |
5160 | if (err) { | 5008 | if (err) { |
5161 | WL_ERR("Failed to init iwm_priv (%d)\n", err); | 5009 | WL_ERR("Failed to init iwm_priv (%d)\n", err); |
5162 | goto cfg80211_attach_out; | 5010 | goto cfg80211_attach_out; |
5163 | } | 5011 | } |
5164 | 5012 | ||
5013 | ifp->vif = vif; | ||
5165 | return cfg; | 5014 | return cfg; |
5166 | 5015 | ||
5167 | cfg80211_attach_out: | 5016 | cfg80211_attach_out: |
5168 | brcmf_free_wdev(cfg); | 5017 | brcmf_free_vif(vif); |
5169 | return NULL; | 5018 | return NULL; |
5170 | } | 5019 | } |
5171 | 5020 | ||
5172 | void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) | 5021 | void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) |
5173 | { | 5022 | { |
5023 | struct brcmf_cfg80211_vif *vif; | ||
5024 | struct brcmf_cfg80211_vif *tmp; | ||
5025 | |||
5174 | wl_deinit_priv(cfg); | 5026 | wl_deinit_priv(cfg); |
5175 | brcmf_free_wdev(cfg); | 5027 | list_for_each_entry_safe(vif, tmp, &cfg->vif_list, list) { |
5028 | brcmf_free_vif(vif); | ||
5029 | } | ||
5176 | } | 5030 | } |
5177 | 5031 | ||
5178 | void | 5032 | void |
@@ -5186,59 +5040,20 @@ brcmf_cfg80211_event(struct net_device *ndev, | |||
5186 | schedule_work(&cfg->event_work); | 5040 | schedule_work(&cfg->event_work); |
5187 | } | 5041 | } |
5188 | 5042 | ||
5189 | static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype) | ||
5190 | { | ||
5191 | s32 infra = 0; | ||
5192 | s32 err = 0; | ||
5193 | |||
5194 | switch (iftype) { | ||
5195 | case NL80211_IFTYPE_MONITOR: | ||
5196 | case NL80211_IFTYPE_WDS: | ||
5197 | WL_ERR("type (%d) : currently we do not support this mode\n", | ||
5198 | iftype); | ||
5199 | err = -EINVAL; | ||
5200 | return err; | ||
5201 | case NL80211_IFTYPE_ADHOC: | ||
5202 | infra = 0; | ||
5203 | break; | ||
5204 | case NL80211_IFTYPE_STATION: | ||
5205 | infra = 1; | ||
5206 | break; | ||
5207 | case NL80211_IFTYPE_AP: | ||
5208 | infra = 1; | ||
5209 | break; | ||
5210 | default: | ||
5211 | err = -EINVAL; | ||
5212 | WL_ERR("invalid type (%d)\n", iftype); | ||
5213 | return err; | ||
5214 | } | ||
5215 | err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra); | ||
5216 | if (err) { | ||
5217 | WL_ERR("WLC_SET_INFRA error (%d)\n", err); | ||
5218 | return err; | ||
5219 | } | ||
5220 | |||
5221 | return 0; | ||
5222 | } | ||
5223 | |||
5224 | static s32 brcmf_dongle_eventmsg(struct net_device *ndev) | 5043 | static s32 brcmf_dongle_eventmsg(struct net_device *ndev) |
5225 | { | 5044 | { |
5226 | /* Room for "event_msgs" + '\0' + bitvec */ | ||
5227 | s8 iovbuf[BRCMF_EVENTING_MASK_LEN + 12]; | ||
5228 | s8 eventmask[BRCMF_EVENTING_MASK_LEN]; | 5045 | s8 eventmask[BRCMF_EVENTING_MASK_LEN]; |
5229 | s32 err = 0; | 5046 | s32 err = 0; |
5230 | 5047 | ||
5231 | WL_TRACE("Enter\n"); | 5048 | WL_TRACE("Enter\n"); |
5232 | 5049 | ||
5233 | /* Setup event_msgs */ | 5050 | /* Setup event_msgs */ |
5234 | brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, | 5051 | err = brcmf_fil_iovar_data_get(netdev_priv(ndev), "event_msgs", |
5235 | iovbuf, sizeof(iovbuf)); | 5052 | eventmask, BRCMF_EVENTING_MASK_LEN); |
5236 | err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, iovbuf, sizeof(iovbuf)); | ||
5237 | if (err) { | 5053 | if (err) { |
5238 | WL_ERR("Get event_msgs error (%d)\n", err); | 5054 | WL_ERR("Get event_msgs error (%d)\n", err); |
5239 | goto dongle_eventmsg_out; | 5055 | goto dongle_eventmsg_out; |
5240 | } | 5056 | } |
5241 | memcpy(eventmask, iovbuf, BRCMF_EVENTING_MASK_LEN); | ||
5242 | 5057 | ||
5243 | setbit(eventmask, BRCMF_E_SET_SSID); | 5058 | setbit(eventmask, BRCMF_E_SET_SSID); |
5244 | setbit(eventmask, BRCMF_E_ROAM); | 5059 | setbit(eventmask, BRCMF_E_ROAM); |
@@ -5262,9 +5077,8 @@ static s32 brcmf_dongle_eventmsg(struct net_device *ndev) | |||
5262 | setbit(eventmask, BRCMF_E_ESCAN_RESULT); | 5077 | setbit(eventmask, BRCMF_E_ESCAN_RESULT); |
5263 | setbit(eventmask, BRCMF_E_PFN_NET_FOUND); | 5078 | setbit(eventmask, BRCMF_E_PFN_NET_FOUND); |
5264 | 5079 | ||
5265 | brcmf_c_mkiovar("event_msgs", eventmask, BRCMF_EVENTING_MASK_LEN, | 5080 | err = brcmf_fil_iovar_data_set(netdev_priv(ndev), "event_msgs", |
5266 | iovbuf, sizeof(iovbuf)); | 5081 | eventmask, BRCMF_EVENTING_MASK_LEN); |
5267 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); | ||
5268 | if (err) { | 5082 | if (err) { |
5269 | WL_ERR("Set event_msgs error (%d)\n", err); | 5083 | WL_ERR("Set event_msgs error (%d)\n", err); |
5270 | goto dongle_eventmsg_out; | 5084 | goto dongle_eventmsg_out; |
@@ -5278,23 +5092,17 @@ dongle_eventmsg_out: | |||
5278 | static s32 | 5092 | static s32 |
5279 | brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) | 5093 | brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) |
5280 | { | 5094 | { |
5281 | s8 iovbuf[32]; | 5095 | struct brcmf_if *ifp = netdev_priv(ndev); |
5282 | s32 err = 0; | 5096 | s32 err = 0; |
5283 | __le32 roamtrigger[2]; | 5097 | __le32 roamtrigger[2]; |
5284 | __le32 roam_delta[2]; | 5098 | __le32 roam_delta[2]; |
5285 | __le32 bcn_to_le; | ||
5286 | __le32 roamvar_le; | ||
5287 | 5099 | ||
5288 | /* | 5100 | /* |
5289 | * Setup timeout if Beacons are lost and roam is | 5101 | * Setup timeout if Beacons are lost and roam is |
5290 | * off to report link down | 5102 | * off to report link down |
5291 | */ | 5103 | */ |
5292 | if (roamvar) { | 5104 | if (roamvar) { |
5293 | bcn_to_le = cpu_to_le32(bcn_timeout); | 5105 | err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", bcn_timeout); |
5294 | brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_to_le, | ||
5295 | sizeof(bcn_to_le), iovbuf, sizeof(iovbuf)); | ||
5296 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, | ||
5297 | iovbuf, sizeof(iovbuf)); | ||
5298 | if (err) { | 5106 | if (err) { |
5299 | WL_ERR("bcn_timeout error (%d)\n", err); | 5107 | WL_ERR("bcn_timeout error (%d)\n", err); |
5300 | goto dongle_rom_out; | 5108 | goto dongle_rom_out; |
@@ -5306,10 +5114,7 @@ brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) | |||
5306 | * to take care of roaming | 5114 | * to take care of roaming |
5307 | */ | 5115 | */ |
5308 | WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On"); | 5116 | WL_INFO("Internal Roaming = %s\n", roamvar ? "Off" : "On"); |
5309 | roamvar_le = cpu_to_le32(roamvar); | 5117 | err = brcmf_fil_iovar_int_set(ifp, "roam_off", roamvar); |
5310 | brcmf_c_mkiovar("roam_off", (char *)&roamvar_le, | ||
5311 | sizeof(roamvar_le), iovbuf, sizeof(iovbuf)); | ||
5312 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); | ||
5313 | if (err) { | 5118 | if (err) { |
5314 | WL_ERR("roam_off error (%d)\n", err); | 5119 | WL_ERR("roam_off error (%d)\n", err); |
5315 | goto dongle_rom_out; | 5120 | goto dongle_rom_out; |
@@ -5317,8 +5122,8 @@ brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) | |||
5317 | 5122 | ||
5318 | roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL); | 5123 | roamtrigger[0] = cpu_to_le32(WL_ROAM_TRIGGER_LEVEL); |
5319 | roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL); | 5124 | roamtrigger[1] = cpu_to_le32(BRCM_BAND_ALL); |
5320 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_TRIGGER, | 5125 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_TRIGGER, |
5321 | (void *)roamtrigger, sizeof(roamtrigger)); | 5126 | (void *)roamtrigger, sizeof(roamtrigger)); |
5322 | if (err) { | 5127 | if (err) { |
5323 | WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err); | 5128 | WL_ERR("WLC_SET_ROAM_TRIGGER error (%d)\n", err); |
5324 | goto dongle_rom_out; | 5129 | goto dongle_rom_out; |
@@ -5326,8 +5131,8 @@ brcmf_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout) | |||
5326 | 5131 | ||
5327 | roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA); | 5132 | roam_delta[0] = cpu_to_le32(WL_ROAM_DELTA); |
5328 | roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL); | 5133 | roam_delta[1] = cpu_to_le32(BRCM_BAND_ALL); |
5329 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_ROAM_DELTA, | 5134 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_ROAM_DELTA, |
5330 | (void *)roam_delta, sizeof(roam_delta)); | 5135 | (void *)roam_delta, sizeof(roam_delta)); |
5331 | if (err) { | 5136 | if (err) { |
5332 | WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err); | 5137 | WL_ERR("WLC_SET_ROAM_DELTA error (%d)\n", err); |
5333 | goto dongle_rom_out; | 5138 | goto dongle_rom_out; |
@@ -5341,13 +5146,11 @@ static s32 | |||
5341 | brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, | 5146 | brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, |
5342 | s32 scan_unassoc_time, s32 scan_passive_time) | 5147 | s32 scan_unassoc_time, s32 scan_passive_time) |
5343 | { | 5148 | { |
5149 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
5344 | s32 err = 0; | 5150 | s32 err = 0; |
5345 | __le32 scan_assoc_tm_le = cpu_to_le32(scan_assoc_time); | ||
5346 | __le32 scan_unassoc_tm_le = cpu_to_le32(scan_unassoc_time); | ||
5347 | __le32 scan_passive_tm_le = cpu_to_le32(scan_passive_time); | ||
5348 | 5151 | ||
5349 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_CHANNEL_TIME, | 5152 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, |
5350 | &scan_assoc_tm_le, sizeof(scan_assoc_tm_le)); | 5153 | scan_assoc_time); |
5351 | if (err) { | 5154 | if (err) { |
5352 | if (err == -EOPNOTSUPP) | 5155 | if (err == -EOPNOTSUPP) |
5353 | WL_INFO("Scan assoc time is not supported\n"); | 5156 | WL_INFO("Scan assoc time is not supported\n"); |
@@ -5355,8 +5158,8 @@ brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, | |||
5355 | WL_ERR("Scan assoc time error (%d)\n", err); | 5158 | WL_ERR("Scan assoc time error (%d)\n", err); |
5356 | goto dongle_scantime_out; | 5159 | goto dongle_scantime_out; |
5357 | } | 5160 | } |
5358 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_UNASSOC_TIME, | 5161 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME, |
5359 | &scan_unassoc_tm_le, sizeof(scan_unassoc_tm_le)); | 5162 | scan_unassoc_time); |
5360 | if (err) { | 5163 | if (err) { |
5361 | if (err == -EOPNOTSUPP) | 5164 | if (err == -EOPNOTSUPP) |
5362 | WL_INFO("Scan unassoc time is not supported\n"); | 5165 | WL_INFO("Scan unassoc time is not supported\n"); |
@@ -5365,8 +5168,8 @@ brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, | |||
5365 | goto dongle_scantime_out; | 5168 | goto dongle_scantime_out; |
5366 | } | 5169 | } |
5367 | 5170 | ||
5368 | err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SCAN_PASSIVE_TIME, | 5171 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_PASSIVE_TIME, |
5369 | &scan_passive_tm_le, sizeof(scan_passive_tm_le)); | 5172 | scan_passive_time); |
5370 | if (err) { | 5173 | if (err) { |
5371 | if (err == -EOPNOTSUPP) | 5174 | if (err == -EOPNOTSUPP) |
5372 | WL_INFO("Scan passive time is not supported\n"); | 5175 | WL_INFO("Scan passive time is not supported\n"); |
@@ -5381,13 +5184,14 @@ dongle_scantime_out: | |||
5381 | 5184 | ||
5382 | static s32 wl_update_wiphybands(struct brcmf_cfg80211_info *cfg) | 5185 | static s32 wl_update_wiphybands(struct brcmf_cfg80211_info *cfg) |
5383 | { | 5186 | { |
5187 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | ||
5384 | struct wiphy *wiphy; | 5188 | struct wiphy *wiphy; |
5385 | s32 phy_list; | 5189 | s32 phy_list; |
5386 | s8 phy; | 5190 | s8 phy; |
5387 | s32 err = 0; | 5191 | s32 err = 0; |
5388 | 5192 | ||
5389 | err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCM_GET_PHYLIST, | 5193 | err = brcmf_fil_cmd_data_get(ifp, BRCM_GET_PHYLIST, |
5390 | &phy_list, sizeof(phy_list)); | 5194 | &phy_list, sizeof(phy_list)); |
5391 | if (err) { | 5195 | if (err) { |
5392 | WL_ERR("error (%d)\n", err); | 5196 | WL_ERR("error (%d)\n", err); |
5393 | return err; | 5197 | return err; |
@@ -5429,7 +5233,8 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) | |||
5429 | goto default_conf_out; | 5233 | goto default_conf_out; |
5430 | 5234 | ||
5431 | power_mode = cfg->pwr_save ? PM_FAST : PM_OFF; | 5235 | power_mode = cfg->pwr_save ? PM_FAST : PM_OFF; |
5432 | err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode); | 5236 | err = brcmf_fil_cmd_int_set(netdev_priv(ndev), BRCMF_C_SET_PM, |
5237 | power_mode); | ||
5433 | if (err) | 5238 | if (err) |
5434 | goto default_conf_out; | 5239 | goto default_conf_out; |
5435 | WL_INFO("power save set to %s\n", | 5240 | WL_INFO("power save set to %s\n", |
@@ -5439,7 +5244,8 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) | |||
5439 | WL_BEACON_TIMEOUT); | 5244 | WL_BEACON_TIMEOUT); |
5440 | if (err) | 5245 | if (err) |
5441 | goto default_conf_out; | 5246 | goto default_conf_out; |
5442 | err = brcmf_dongle_mode(ndev, wdev->iftype); | 5247 | err = brcmf_cfg80211_change_iface(wdev->wiphy, ndev, wdev->iftype, |
5248 | NULL, NULL); | ||
5443 | if (err && err != -EINPROGRESS) | 5249 | if (err && err != -EINPROGRESS) |
5444 | goto default_conf_out; | 5250 | goto default_conf_out; |
5445 | err = brcmf_dongle_probecap(cfg); | 5251 | err = brcmf_dongle_probecap(cfg); |
@@ -5456,47 +5262,12 @@ default_conf_out: | |||
5456 | 5262 | ||
5457 | } | 5263 | } |
5458 | 5264 | ||
5459 | static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_info *cfg) | ||
5460 | { | ||
5461 | char buf[10+IFNAMSIZ]; | ||
5462 | struct dentry *fd; | ||
5463 | s32 err = 0; | ||
5464 | |||
5465 | sprintf(buf, "netdev:%s", cfg_to_ndev(cfg)->name); | ||
5466 | cfg->debugfsdir = debugfs_create_dir(buf, | ||
5467 | cfg_to_wiphy(cfg)->debugfsdir); | ||
5468 | |||
5469 | fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg->debugfsdir, | ||
5470 | (u16 *)&cfg->profile->beacon_interval); | ||
5471 | if (!fd) { | ||
5472 | err = -ENOMEM; | ||
5473 | goto err_out; | ||
5474 | } | ||
5475 | |||
5476 | fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg->debugfsdir, | ||
5477 | (u8 *)&cfg->profile->dtim_period); | ||
5478 | if (!fd) { | ||
5479 | err = -ENOMEM; | ||
5480 | goto err_out; | ||
5481 | } | ||
5482 | |||
5483 | err_out: | ||
5484 | return err; | ||
5485 | } | ||
5486 | |||
5487 | static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_info *cfg) | ||
5488 | { | ||
5489 | debugfs_remove_recursive(cfg->debugfsdir); | ||
5490 | cfg->debugfsdir = NULL; | ||
5491 | } | ||
5492 | |||
5493 | static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg) | 5265 | static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg) |
5494 | { | 5266 | { |
5267 | struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg)); | ||
5495 | s32 err = 0; | 5268 | s32 err = 0; |
5496 | 5269 | ||
5497 | set_bit(WL_STATUS_READY, &cfg->status); | 5270 | set_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state); |
5498 | |||
5499 | brcmf_debugfs_add_netdev_params(cfg); | ||
5500 | 5271 | ||
5501 | err = brcmf_config_dongle(cfg); | 5272 | err = brcmf_config_dongle(cfg); |
5502 | if (err) | 5273 | if (err) |
@@ -5509,13 +5280,16 @@ static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg) | |||
5509 | 5280 | ||
5510 | static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg) | 5281 | static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg) |
5511 | { | 5282 | { |
5283 | struct net_device *ndev = cfg_to_ndev(cfg); | ||
5284 | struct brcmf_if *ifp = netdev_priv(ndev); | ||
5285 | |||
5512 | /* | 5286 | /* |
5513 | * While going down, if associated with AP disassociate | 5287 | * While going down, if associated with AP disassociate |
5514 | * from AP to save power | 5288 | * from AP to save power |
5515 | */ | 5289 | */ |
5516 | if ((test_bit(WL_STATUS_CONNECTED, &cfg->status) || | 5290 | if ((test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state) || |
5517 | test_bit(WL_STATUS_CONNECTING, &cfg->status)) && | 5291 | test_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state)) && |
5518 | test_bit(WL_STATUS_READY, &cfg->status)) { | 5292 | check_vif_up(ifp->vif)) { |
5519 | WL_INFO("Disassociating from AP"); | 5293 | WL_INFO("Disassociating from AP"); |
5520 | brcmf_link_down(cfg); | 5294 | brcmf_link_down(cfg); |
5521 | 5295 | ||
@@ -5527,9 +5301,7 @@ static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg) | |||
5527 | } | 5301 | } |
5528 | 5302 | ||
5529 | brcmf_abort_scanning(cfg); | 5303 | brcmf_abort_scanning(cfg); |
5530 | clear_bit(WL_STATUS_READY, &cfg->status); | 5304 | clear_bit(BRCMF_VIF_STATUS_READY, &ifp->vif->sme_state); |
5531 | |||
5532 | brcmf_debugfs_remove_netdev(cfg); | ||
5533 | 5305 | ||
5534 | return 0; | 5306 | return 0; |
5535 | } | 5307 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 71ced174748a..1dd96f148ef7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h | |||
@@ -127,15 +127,15 @@ do { \ | |||
127 | #define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ | 127 | #define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ |
128 | #define IE_MAX_LEN 512 | 128 | #define IE_MAX_LEN 512 |
129 | 129 | ||
130 | /* dongle status */ | 130 | /** |
131 | enum wl_status { | 131 | * enum brcmf_scan_status - dongle scan status |
132 | WL_STATUS_READY, | 132 | * |
133 | WL_STATUS_SCANNING, | 133 | * @BRCMF_SCAN_STATUS_BUSY: scanning in progress on dongle. |
134 | WL_STATUS_SCAN_ABORTING, | 134 | * @BRCMF_SCAN_STATUS_ABORT: scan being aborted on dongle. |
135 | WL_STATUS_CONNECTING, | 135 | */ |
136 | WL_STATUS_CONNECTED, | 136 | enum brcmf_scan_status { |
137 | WL_STATUS_AP_CREATING, | 137 | BRCMF_SCAN_STATUS_BUSY, |
138 | WL_STATUS_AP_CREATED | 138 | BRCMF_SCAN_STATUS_ABORT, |
139 | }; | 139 | }; |
140 | 140 | ||
141 | /* wi-fi mode */ | 141 | /* wi-fi mode */ |
@@ -145,19 +145,6 @@ enum wl_mode { | |||
145 | WL_MODE_AP | 145 | WL_MODE_AP |
146 | }; | 146 | }; |
147 | 147 | ||
148 | /* dongle profile list */ | ||
149 | enum wl_prof_list { | ||
150 | WL_PROF_MODE, | ||
151 | WL_PROF_SSID, | ||
152 | WL_PROF_SEC, | ||
153 | WL_PROF_IBSS, | ||
154 | WL_PROF_BAND, | ||
155 | WL_PROF_BSSID, | ||
156 | WL_PROF_ACT, | ||
157 | WL_PROF_BEACONINT, | ||
158 | WL_PROF_DTIMPERIOD | ||
159 | }; | ||
160 | |||
161 | /* dongle iscan state */ | 148 | /* dongle iscan state */ |
162 | enum wl_iscan_state { | 149 | enum wl_iscan_state { |
163 | WL_ISCAN_STATE_IDLE, | 150 | WL_ISCAN_STATE_IDLE, |
@@ -214,25 +201,73 @@ struct brcmf_cfg80211_security { | |||
214 | u32 wpa_auth; | 201 | u32 wpa_auth; |
215 | }; | 202 | }; |
216 | 203 | ||
217 | /* ibss information for currently joined ibss network */ | 204 | /** |
218 | struct brcmf_cfg80211_ibss { | 205 | * struct brcmf_cfg80211_profile - profile information. |
219 | u8 beacon_interval; /* in millisecond */ | 206 | * |
220 | u8 atim; /* in millisecond */ | 207 | * @ssid: ssid of associated/associating ap. |
221 | s8 join_only; | 208 | * @bssid: bssid of joined/joining ibss. |
222 | u8 band; | 209 | * @sec: security information. |
223 | u8 channel; | 210 | */ |
224 | }; | ||
225 | |||
226 | /* dongle profile */ | ||
227 | struct brcmf_cfg80211_profile { | 211 | struct brcmf_cfg80211_profile { |
228 | u32 mode; | ||
229 | struct brcmf_ssid ssid; | 212 | struct brcmf_ssid ssid; |
230 | u8 bssid[ETH_ALEN]; | 213 | u8 bssid[ETH_ALEN]; |
231 | u16 beacon_interval; | ||
232 | u8 dtim_period; | ||
233 | struct brcmf_cfg80211_security sec; | 214 | struct brcmf_cfg80211_security sec; |
234 | struct brcmf_cfg80211_ibss ibss; | 215 | }; |
235 | s32 band; | 216 | |
217 | /** | ||
218 | * enum brcmf_vif_status - bit indices for vif status. | ||
219 | * | ||
220 | * @BRCMF_VIF_STATUS_READY: ready for operation. | ||
221 | * @BRCMF_VIF_STATUS_CONNECTING: connect/join in progress. | ||
222 | * @BRCMF_VIF_STATUS_CONNECTED: connected/joined succesfully. | ||
223 | * @BRCMF_VIF_STATUS_AP_CREATING: interface configured for AP operation. | ||
224 | * @BRCMF_VIF_STATUS_AP_CREATED: AP operation started. | ||
225 | */ | ||
226 | enum brcmf_vif_status { | ||
227 | BRCMF_VIF_STATUS_READY, | ||
228 | BRCMF_VIF_STATUS_CONNECTING, | ||
229 | BRCMF_VIF_STATUS_CONNECTED, | ||
230 | BRCMF_VIF_STATUS_AP_CREATING, | ||
231 | BRCMF_VIF_STATUS_AP_CREATED | ||
232 | }; | ||
233 | |||
234 | /** | ||
235 | * struct vif_saved_ie - holds saved IEs for a virtual interface. | ||
236 | * | ||
237 | * @probe_res_ie: IE info for probe response. | ||
238 | * @beacon_ie: IE info for beacon frame. | ||
239 | * @probe_res_ie_len: IE info length for probe response. | ||
240 | * @beacon_ie_len: IE info length for beacon frame. | ||
241 | */ | ||
242 | struct vif_saved_ie { | ||
243 | u8 probe_res_ie[IE_MAX_LEN]; | ||
244 | u8 beacon_ie[IE_MAX_LEN]; | ||
245 | u32 probe_res_ie_len; | ||
246 | u32 beacon_ie_len; | ||
247 | }; | ||
248 | |||
249 | /** | ||
250 | * struct brcmf_cfg80211_vif - virtual interface specific information. | ||
251 | * | ||
252 | * @ifp: lower layer interface pointer | ||
253 | * @wdev: wireless device. | ||
254 | * @profile: profile information. | ||
255 | * @mode: operating mode. | ||
256 | * @roam_off: roaming state. | ||
257 | * @sme_state: SME state using enum brcmf_vif_status bits. | ||
258 | * @pm_block: power-management blocked. | ||
259 | * @list: linked list. | ||
260 | */ | ||
261 | struct brcmf_cfg80211_vif { | ||
262 | struct brcmf_if *ifp; | ||
263 | struct wireless_dev wdev; | ||
264 | struct brcmf_cfg80211_profile profile; | ||
265 | s32 mode; | ||
266 | s32 roam_off; | ||
267 | unsigned long sme_state; | ||
268 | bool pm_block; | ||
269 | struct vif_saved_ie saved_ie; | ||
270 | struct list_head list; | ||
236 | }; | 271 | }; |
237 | 272 | ||
238 | /* dongle iscan event loop */ | 273 | /* dongle iscan event loop */ |
@@ -383,7 +418,7 @@ struct brcmf_pno_scanresults_le { | |||
383 | /** | 418 | /** |
384 | * struct brcmf_cfg80211_info - dongle private data of cfg80211 interface | 419 | * struct brcmf_cfg80211_info - dongle private data of cfg80211 interface |
385 | * | 420 | * |
386 | * @wdev: representing wl cfg80211 device. | 421 | * @wiphy: wiphy object for cfg80211 interface. |
387 | * @conf: dongle configuration. | 422 | * @conf: dongle configuration. |
388 | * @scan_request: cfg80211 scan request object. | 423 | * @scan_request: cfg80211 scan request object. |
389 | * @el: main event loop. | 424 | * @el: main event loop. |
@@ -395,12 +430,11 @@ struct brcmf_pno_scanresults_le { | |||
395 | * @scan_req_int: internal scan request object. | 430 | * @scan_req_int: internal scan request object. |
396 | * @bss_info: bss information for cfg80211 layer. | 431 | * @bss_info: bss information for cfg80211 layer. |
397 | * @ie: information element object for internal purpose. | 432 | * @ie: information element object for internal purpose. |
398 | * @profile: holding dongle profile. | ||
399 | * @iscan: iscan controller information. | 433 | * @iscan: iscan controller information. |
400 | * @conn_info: association info. | 434 | * @conn_info: association info. |
401 | * @pmk_list: wpa2 pmk list. | 435 | * @pmk_list: wpa2 pmk list. |
402 | * @event_work: event handler work struct. | 436 | * @event_work: event handler work struct. |
403 | * @status: current dongle status. | 437 | * @scan_status: scan activity on the dongle. |
404 | * @pub: common driver information. | 438 | * @pub: common driver information. |
405 | * @channel: current channel. | 439 | * @channel: current channel. |
406 | * @iscan_on: iscan on/off switch. | 440 | * @iscan_on: iscan on/off switch. |
@@ -422,10 +456,11 @@ struct brcmf_pno_scanresults_le { | |||
422 | * @escan_timeout_work: scan timeout worker. | 456 | * @escan_timeout_work: scan timeout worker. |
423 | * @escan_ioctl_buf: dongle command buffer for escan commands. | 457 | * @escan_ioctl_buf: dongle command buffer for escan commands. |
424 | * @ap_info: host ap information. | 458 | * @ap_info: host ap information. |
425 | * @ci: used to link this structure to netdev private data. | 459 | * @vif_list: linked list of vif instances. |
460 | * @vif_cnt: number of vif instances. | ||
426 | */ | 461 | */ |
427 | struct brcmf_cfg80211_info { | 462 | struct brcmf_cfg80211_info { |
428 | struct wireless_dev *wdev; | 463 | struct wiphy *wiphy; |
429 | struct brcmf_cfg80211_conf *conf; | 464 | struct brcmf_cfg80211_conf *conf; |
430 | struct cfg80211_scan_request *scan_request; | 465 | struct cfg80211_scan_request *scan_request; |
431 | struct brcmf_cfg80211_event_loop el; | 466 | struct brcmf_cfg80211_event_loop el; |
@@ -437,12 +472,11 @@ struct brcmf_cfg80211_info { | |||
437 | struct brcmf_cfg80211_scan_req *scan_req_int; | 472 | struct brcmf_cfg80211_scan_req *scan_req_int; |
438 | struct wl_cfg80211_bss_info *bss_info; | 473 | struct wl_cfg80211_bss_info *bss_info; |
439 | struct brcmf_cfg80211_ie ie; | 474 | struct brcmf_cfg80211_ie ie; |
440 | struct brcmf_cfg80211_profile *profile; | ||
441 | struct brcmf_cfg80211_iscan_ctrl *iscan; | 475 | struct brcmf_cfg80211_iscan_ctrl *iscan; |
442 | struct brcmf_cfg80211_connect_info conn_info; | 476 | struct brcmf_cfg80211_connect_info conn_info; |
443 | struct brcmf_cfg80211_pmk_list *pmk_list; | 477 | struct brcmf_cfg80211_pmk_list *pmk_list; |
444 | struct work_struct event_work; | 478 | struct work_struct event_work; |
445 | unsigned long status; | 479 | unsigned long scan_status; |
446 | struct brcmf_pub *pub; | 480 | struct brcmf_pub *pub; |
447 | u32 channel; | 481 | u32 channel; |
448 | bool iscan_on; | 482 | bool iscan_on; |
@@ -464,11 +498,13 @@ struct brcmf_cfg80211_info { | |||
464 | struct work_struct escan_timeout_work; | 498 | struct work_struct escan_timeout_work; |
465 | u8 *escan_ioctl_buf; | 499 | u8 *escan_ioctl_buf; |
466 | struct ap_info *ap_info; | 500 | struct ap_info *ap_info; |
501 | struct list_head vif_list; | ||
502 | u8 vif_cnt; | ||
467 | }; | 503 | }; |
468 | 504 | ||
469 | static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *w) | 505 | static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *cfg) |
470 | { | 506 | { |
471 | return w->wdev->wiphy; | 507 | return cfg->wiphy; |
472 | } | 508 | } |
473 | 509 | ||
474 | static inline struct brcmf_cfg80211_info *wiphy_to_cfg(struct wiphy *w) | 510 | static inline struct brcmf_cfg80211_info *wiphy_to_cfg(struct wiphy *w) |
@@ -481,9 +517,12 @@ static inline struct brcmf_cfg80211_info *wdev_to_cfg(struct wireless_dev *wd) | |||
481 | return (struct brcmf_cfg80211_info *)(wdev_priv(wd)); | 517 | return (struct brcmf_cfg80211_info *)(wdev_priv(wd)); |
482 | } | 518 | } |
483 | 519 | ||
484 | static inline struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg) | 520 | static inline |
521 | struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg) | ||
485 | { | 522 | { |
486 | return cfg->wdev->netdev; | 523 | struct brcmf_cfg80211_vif *vif; |
524 | vif = list_first_entry(&cfg->vif_list, struct brcmf_cfg80211_vif, list); | ||
525 | return vif->wdev.netdev; | ||
487 | } | 526 | } |
488 | 527 | ||
489 | static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev) | 528 | static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev) |
@@ -491,6 +530,12 @@ static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev) | |||
491 | return wdev_to_cfg(ndev->ieee80211_ptr); | 530 | return wdev_to_cfg(ndev->ieee80211_ptr); |
492 | } | 531 | } |
493 | 532 | ||
533 | static inline struct brcmf_cfg80211_profile *ndev_to_prof(struct net_device *nd) | ||
534 | { | ||
535 | struct brcmf_if *ifp = netdev_priv(nd); | ||
536 | return &ifp->vif->profile; | ||
537 | } | ||
538 | |||
494 | #define iscan_to_cfg(i) ((struct brcmf_cfg80211_info *)(i->data)) | 539 | #define iscan_to_cfg(i) ((struct brcmf_cfg80211_info *)(i->data)) |
495 | #define cfg_to_iscan(w) (w->iscan) | 540 | #define cfg_to_iscan(w) (w->iscan) |
496 | 541 | ||
@@ -500,9 +545,7 @@ brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg) | |||
500 | return &cfg->conn_info; | 545 | return &cfg->conn_info; |
501 | } | 546 | } |
502 | 547 | ||
503 | struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct net_device *ndev, | 548 | struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct brcmf_pub *drvr); |
504 | struct device *busdev, | ||
505 | struct brcmf_pub *drvr); | ||
506 | void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg); | 549 | void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg); |
507 | 550 | ||
508 | /* event handler from dongle */ | 551 | /* event handler from dongle */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c index b89f1272b93f..de96290f5ccd 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/aiutils.c | |||
@@ -692,7 +692,7 @@ void ai_pci_up(struct si_pub *sih) | |||
692 | sii = container_of(sih, struct si_info, pub); | 692 | sii = container_of(sih, struct si_info, pub); |
693 | 693 | ||
694 | if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) | 694 | if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) |
695 | bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, true); | 695 | bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci[0], true); |
696 | } | 696 | } |
697 | 697 | ||
698 | /* Unconfigure and/or apply various WARs when going down */ | 698 | /* Unconfigure and/or apply various WARs when going down */ |
@@ -703,7 +703,7 @@ void ai_pci_down(struct si_pub *sih) | |||
703 | sii = container_of(sih, struct si_info, pub); | 703 | sii = container_of(sih, struct si_info, pub); |
704 | 704 | ||
705 | if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) | 705 | if (sii->icbus->hosttype == BCMA_HOSTTYPE_PCI) |
706 | bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci, false); | 706 | bcma_core_pci_extend_L1timer(&sii->icbus->drv_pci[0], false); |
707 | } | 707 | } |
708 | 708 | ||
709 | /* Enable BT-COEX & Ex-PA for 4313 */ | 709 | /* Enable BT-COEX & Ex-PA for 4313 */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 75086b37c817..565c15abbed5 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -5077,7 +5077,7 @@ static int brcms_b_up_prep(struct brcms_hardware *wlc_hw) | |||
5077 | * Configure pci/pcmcia here instead of in brcms_c_attach() | 5077 | * Configure pci/pcmcia here instead of in brcms_c_attach() |
5078 | * to allow mfg hotswap: down, hotswap (chip power cycle), up. | 5078 | * to allow mfg hotswap: down, hotswap (chip power cycle), up. |
5079 | */ | 5079 | */ |
5080 | bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci, wlc_hw->d11core, | 5080 | bcma_core_pci_irq_ctl(&wlc_hw->d11core->bus->drv_pci[0], wlc_hw->d11core, |
5081 | true); | 5081 | true); |
5082 | 5082 | ||
5083 | /* | 5083 | /* |
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 935120fc8c93..768bf612533e 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -10472,7 +10472,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv, | |||
10472 | } else | 10472 | } else |
10473 | len = src->len; | 10473 | len = src->len; |
10474 | 10474 | ||
10475 | dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC); | 10475 | dst = alloc_skb(len + sizeof(*rt_hdr) + sizeof(u16)*2, GFP_ATOMIC); |
10476 | if (!dst) | 10476 | if (!dst) |
10477 | continue; | 10477 | continue; |
10478 | 10478 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c index 349c205d5f62..da5862064195 100644 --- a/drivers/net/wireless/iwlwifi/dvm/devices.c +++ b/drivers/net/wireless/iwlwifi/dvm/devices.c | |||
@@ -518,7 +518,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | |||
518 | * See iwlagn_mac_channel_switch. | 518 | * See iwlagn_mac_channel_switch. |
519 | */ | 519 | */ |
520 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 520 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
521 | struct iwl6000_channel_switch_cmd cmd; | 521 | struct iwl6000_channel_switch_cmd *cmd; |
522 | u32 switch_time_in_usec, ucode_switch_time; | 522 | u32 switch_time_in_usec, ucode_switch_time; |
523 | u16 ch; | 523 | u16 ch; |
524 | u32 tsf_low; | 524 | u32 tsf_low; |
@@ -527,18 +527,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | |||
527 | struct ieee80211_vif *vif = ctx->vif; | 527 | struct ieee80211_vif *vif = ctx->vif; |
528 | struct iwl_host_cmd hcmd = { | 528 | struct iwl_host_cmd hcmd = { |
529 | .id = REPLY_CHANNEL_SWITCH, | 529 | .id = REPLY_CHANNEL_SWITCH, |
530 | .len = { sizeof(cmd), }, | 530 | .len = { sizeof(*cmd), }, |
531 | .flags = CMD_SYNC, | 531 | .flags = CMD_SYNC, |
532 | .data = { &cmd, }, | 532 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, |
533 | }; | 533 | }; |
534 | int err; | ||
534 | 535 | ||
535 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | 536 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
537 | if (!cmd) | ||
538 | return -ENOMEM; | ||
539 | |||
540 | hcmd.data[0] = cmd; | ||
541 | |||
542 | cmd->band = priv->band == IEEE80211_BAND_2GHZ; | ||
536 | ch = ch_switch->channel->hw_value; | 543 | ch = ch_switch->channel->hw_value; |
537 | IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", | 544 | IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", |
538 | ctx->active.channel, ch); | 545 | ctx->active.channel, ch); |
539 | cmd.channel = cpu_to_le16(ch); | 546 | cmd->channel = cpu_to_le16(ch); |
540 | cmd.rxon_flags = ctx->staging.flags; | 547 | cmd->rxon_flags = ctx->staging.flags; |
541 | cmd.rxon_filter_flags = ctx->staging.filter_flags; | 548 | cmd->rxon_filter_flags = ctx->staging.filter_flags; |
542 | switch_count = ch_switch->count; | 549 | switch_count = ch_switch->count; |
543 | tsf_low = ch_switch->timestamp & 0x0ffffffff; | 550 | tsf_low = ch_switch->timestamp & 0x0ffffffff; |
544 | /* | 551 | /* |
@@ -554,23 +561,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | |||
554 | switch_count = 0; | 561 | switch_count = 0; |
555 | } | 562 | } |
556 | if (switch_count <= 1) | 563 | if (switch_count <= 1) |
557 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | 564 | cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time); |
558 | else { | 565 | else { |
559 | switch_time_in_usec = | 566 | switch_time_in_usec = |
560 | vif->bss_conf.beacon_int * switch_count * TIME_UNIT; | 567 | vif->bss_conf.beacon_int * switch_count * TIME_UNIT; |
561 | ucode_switch_time = iwl_usecs_to_beacons(priv, | 568 | ucode_switch_time = iwl_usecs_to_beacons(priv, |
562 | switch_time_in_usec, | 569 | switch_time_in_usec, |
563 | beacon_interval); | 570 | beacon_interval); |
564 | cmd.switch_time = iwl_add_beacon_time(priv, | 571 | cmd->switch_time = iwl_add_beacon_time(priv, |
565 | priv->ucode_beacon_time, | 572 | priv->ucode_beacon_time, |
566 | ucode_switch_time, | 573 | ucode_switch_time, |
567 | beacon_interval); | 574 | beacon_interval); |
568 | } | 575 | } |
569 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | 576 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", |
570 | cmd.switch_time); | 577 | cmd->switch_time); |
571 | cmd.expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; | 578 | cmd->expect_beacon = ch_switch->channel->flags & IEEE80211_CHAN_RADAR; |
572 | 579 | ||
573 | return iwl_dvm_send_cmd(priv, &hcmd); | 580 | err = iwl_dvm_send_cmd(priv, &hcmd); |
581 | kfree(cmd); | ||
582 | return err; | ||
574 | } | 583 | } |
575 | 584 | ||
576 | struct iwl_lib_ops iwl6000_lib = { | 585 | struct iwl_lib_ops iwl6000_lib = { |
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c index 7ff3f1430678..475df45c8320 100644 --- a/drivers/net/wireless/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/iwlwifi/dvm/main.c | |||
@@ -1191,8 +1191,6 @@ static void iwl_option_config(struct iwl_priv *priv) | |||
1191 | 1191 | ||
1192 | static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) | 1192 | static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) |
1193 | { | 1193 | { |
1194 | u16 radio_cfg; | ||
1195 | |||
1196 | priv->eeprom_data->sku = priv->eeprom_data->sku; | 1194 | priv->eeprom_data->sku = priv->eeprom_data->sku; |
1197 | 1195 | ||
1198 | if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE && | 1196 | if (priv->eeprom_data->sku & EEPROM_SKU_CAP_11N_ENABLE && |
@@ -1208,8 +1206,6 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv) | |||
1208 | 1206 | ||
1209 | IWL_INFO(priv, "Device SKU: 0x%X\n", priv->eeprom_data->sku); | 1207 | IWL_INFO(priv, "Device SKU: 0x%X\n", priv->eeprom_data->sku); |
1210 | 1208 | ||
1211 | radio_cfg = priv->eeprom_data->radio_cfg; | ||
1212 | |||
1213 | priv->hw_params.tx_chains_num = | 1209 | priv->hw_params.tx_chains_num = |
1214 | num_of_ant(priv->eeprom_data->valid_tx_ant); | 1210 | num_of_ant(priv->eeprom_data->valid_tx_ant); |
1215 | if (priv->cfg->rx_with_siso_diversity) | 1211 | if (priv->cfg->rx_with_siso_diversity) |
@@ -1334,6 +1330,9 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, | |||
1334 | /* Configure transport layer */ | 1330 | /* Configure transport layer */ |
1335 | iwl_trans_configure(priv->trans, &trans_cfg); | 1331 | iwl_trans_configure(priv->trans, &trans_cfg); |
1336 | 1332 | ||
1333 | trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD; | ||
1334 | trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start); | ||
1335 | |||
1337 | /* At this point both hw and priv are allocated. */ | 1336 | /* At this point both hw and priv are allocated. */ |
1338 | 1337 | ||
1339 | SET_IEEE80211_DEV(priv->hw, priv->trans->dev); | 1338 | SET_IEEE80211_DEV(priv->hw, priv->trans->dev); |
@@ -2152,8 +2151,6 @@ static int __init iwl_init(void) | |||
2152 | { | 2151 | { |
2153 | 2152 | ||
2154 | int ret; | 2153 | int ret; |
2155 | pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n"); | ||
2156 | pr_info(DRV_COPYRIGHT "\n"); | ||
2157 | 2154 | ||
2158 | ret = iwlagn_rate_control_register(); | 2155 | ret = iwlagn_rate_control_register(); |
2159 | if (ret) { | 2156 | if (ret) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 59a5f78402fc..678717bf62eb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h | |||
@@ -25,6 +25,39 @@ | |||
25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
26 | 26 | ||
27 | #if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ) | 27 | #if !defined(__IWLWIFI_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ) |
28 | #include <linux/skbuff.h> | ||
29 | #include <linux/ieee80211.h> | ||
30 | #include <net/cfg80211.h> | ||
31 | #include "iwl-trans.h" | ||
32 | #if !defined(__IWLWIFI_DEVICE_TRACE) | ||
33 | static inline bool iwl_trace_data(struct sk_buff *skb) | ||
34 | { | ||
35 | struct ieee80211_hdr *hdr = (void *)skb->data; | ||
36 | |||
37 | if (ieee80211_is_data(hdr->frame_control)) | ||
38 | return skb->protocol != cpu_to_be16(ETH_P_PAE); | ||
39 | return false; | ||
40 | } | ||
41 | |||
42 | static inline size_t iwl_rx_trace_len(const struct iwl_trans *trans, | ||
43 | void *rxbuf, size_t len) | ||
44 | { | ||
45 | struct iwl_cmd_header *cmd = (void *)((u8 *)rxbuf + sizeof(__le32)); | ||
46 | struct ieee80211_hdr *hdr; | ||
47 | |||
48 | if (cmd->cmd != trans->rx_mpdu_cmd) | ||
49 | return len; | ||
50 | |||
51 | hdr = (void *)((u8 *)cmd + sizeof(struct iwl_cmd_header) + | ||
52 | trans->rx_mpdu_cmd_hdr_size); | ||
53 | if (!ieee80211_is_data(hdr->frame_control)) | ||
54 | return len; | ||
55 | /* maybe try to identify EAPOL frames? */ | ||
56 | return sizeof(__le32) + sizeof(*cmd) + trans->rx_mpdu_cmd_hdr_size + | ||
57 | ieee80211_hdrlen(hdr->frame_control); | ||
58 | } | ||
59 | #endif | ||
60 | |||
28 | #define __IWLWIFI_DEVICE_TRACE | 61 | #define __IWLWIFI_DEVICE_TRACE |
29 | 62 | ||
30 | #include <linux/tracepoint.h> | 63 | #include <linux/tracepoint.h> |
@@ -235,6 +268,48 @@ TRACE_EVENT(iwlwifi_dbg, | |||
235 | ); | 268 | ); |
236 | 269 | ||
237 | #undef TRACE_SYSTEM | 270 | #undef TRACE_SYSTEM |
271 | #define TRACE_SYSTEM iwlwifi_data | ||
272 | |||
273 | TRACE_EVENT(iwlwifi_dev_tx_data, | ||
274 | TP_PROTO(const struct device *dev, | ||
275 | struct sk_buff *skb, | ||
276 | void *data, size_t data_len), | ||
277 | TP_ARGS(dev, skb, data, data_len), | ||
278 | TP_STRUCT__entry( | ||
279 | DEV_ENTRY | ||
280 | |||
281 | __dynamic_array(u8, data, iwl_trace_data(skb) ? data_len : 0) | ||
282 | ), | ||
283 | TP_fast_assign( | ||
284 | DEV_ASSIGN; | ||
285 | if (iwl_trace_data(skb)) | ||
286 | memcpy(__get_dynamic_array(data), data, data_len); | ||
287 | ), | ||
288 | TP_printk("[%s] TX frame data", __get_str(dev)) | ||
289 | ); | ||
290 | |||
291 | TRACE_EVENT(iwlwifi_dev_rx_data, | ||
292 | TP_PROTO(const struct device *dev, | ||
293 | const struct iwl_trans *trans, | ||
294 | void *rxbuf, size_t len), | ||
295 | TP_ARGS(dev, trans, rxbuf, len), | ||
296 | TP_STRUCT__entry( | ||
297 | DEV_ENTRY | ||
298 | |||
299 | __dynamic_array(u8, data, | ||
300 | len - iwl_rx_trace_len(trans, rxbuf, len)) | ||
301 | ), | ||
302 | TP_fast_assign( | ||
303 | size_t offs = iwl_rx_trace_len(trans, rxbuf, len); | ||
304 | DEV_ASSIGN; | ||
305 | if (offs < len) | ||
306 | memcpy(__get_dynamic_array(data), | ||
307 | ((u8 *)rxbuf) + offs, len - offs); | ||
308 | ), | ||
309 | TP_printk("[%s] TX frame data", __get_str(dev)) | ||
310 | ); | ||
311 | |||
312 | #undef TRACE_SYSTEM | ||
238 | #define TRACE_SYSTEM iwlwifi | 313 | #define TRACE_SYSTEM iwlwifi |
239 | 314 | ||
240 | TRACE_EVENT(iwlwifi_dev_hcmd, | 315 | TRACE_EVENT(iwlwifi_dev_hcmd, |
@@ -270,25 +345,28 @@ TRACE_EVENT(iwlwifi_dev_hcmd, | |||
270 | ); | 345 | ); |
271 | 346 | ||
272 | TRACE_EVENT(iwlwifi_dev_rx, | 347 | TRACE_EVENT(iwlwifi_dev_rx, |
273 | TP_PROTO(const struct device *dev, void *rxbuf, size_t len), | 348 | TP_PROTO(const struct device *dev, const struct iwl_trans *trans, |
274 | TP_ARGS(dev, rxbuf, len), | 349 | void *rxbuf, size_t len), |
350 | TP_ARGS(dev, trans, rxbuf, len), | ||
275 | TP_STRUCT__entry( | 351 | TP_STRUCT__entry( |
276 | DEV_ENTRY | 352 | DEV_ENTRY |
277 | __dynamic_array(u8, rxbuf, len) | 353 | __dynamic_array(u8, rxbuf, iwl_rx_trace_len(trans, rxbuf, len)) |
278 | ), | 354 | ), |
279 | TP_fast_assign( | 355 | TP_fast_assign( |
280 | DEV_ASSIGN; | 356 | DEV_ASSIGN; |
281 | memcpy(__get_dynamic_array(rxbuf), rxbuf, len); | 357 | memcpy(__get_dynamic_array(rxbuf), rxbuf, |
358 | iwl_rx_trace_len(trans, rxbuf, len)); | ||
282 | ), | 359 | ), |
283 | TP_printk("[%s] RX cmd %#.2x", | 360 | TP_printk("[%s] RX cmd %#.2x", |
284 | __get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4]) | 361 | __get_str(dev), ((u8 *)__get_dynamic_array(rxbuf))[4]) |
285 | ); | 362 | ); |
286 | 363 | ||
287 | TRACE_EVENT(iwlwifi_dev_tx, | 364 | TRACE_EVENT(iwlwifi_dev_tx, |
288 | TP_PROTO(const struct device *dev, void *tfd, size_t tfdlen, | 365 | TP_PROTO(const struct device *dev, struct sk_buff *skb, |
366 | void *tfd, size_t tfdlen, | ||
289 | void *buf0, size_t buf0_len, | 367 | void *buf0, size_t buf0_len, |
290 | void *buf1, size_t buf1_len), | 368 | void *buf1, size_t buf1_len), |
291 | TP_ARGS(dev, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len), | 369 | TP_ARGS(dev, skb, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len), |
292 | TP_STRUCT__entry( | 370 | TP_STRUCT__entry( |
293 | DEV_ENTRY | 371 | DEV_ENTRY |
294 | 372 | ||
@@ -301,14 +379,15 @@ TRACE_EVENT(iwlwifi_dev_tx, | |||
301 | * for the possible padding). | 379 | * for the possible padding). |
302 | */ | 380 | */ |
303 | __dynamic_array(u8, buf0, buf0_len) | 381 | __dynamic_array(u8, buf0, buf0_len) |
304 | __dynamic_array(u8, buf1, buf1_len) | 382 | __dynamic_array(u8, buf1, iwl_trace_data(skb) ? 0 : buf1_len) |
305 | ), | 383 | ), |
306 | TP_fast_assign( | 384 | TP_fast_assign( |
307 | DEV_ASSIGN; | 385 | DEV_ASSIGN; |
308 | __entry->framelen = buf0_len + buf1_len; | 386 | __entry->framelen = buf0_len + buf1_len; |
309 | memcpy(__get_dynamic_array(tfd), tfd, tfdlen); | 387 | memcpy(__get_dynamic_array(tfd), tfd, tfdlen); |
310 | memcpy(__get_dynamic_array(buf0), buf0, buf0_len); | 388 | memcpy(__get_dynamic_array(buf0), buf0, buf0_len); |
311 | memcpy(__get_dynamic_array(buf1), buf1, buf1_len); | 389 | if (!iwl_trace_data(skb)) |
390 | memcpy(__get_dynamic_array(buf1), buf1, buf1_len); | ||
312 | ), | 391 | ), |
313 | TP_printk("[%s] TX %.2x (%zu bytes)", | 392 | TP_printk("[%s] TX %.2x (%zu bytes)", |
314 | __get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0], | 393 | __get_str(dev), ((u8 *)__get_dynamic_array(buf0))[0], |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c index 3dfebfb8434f..54c41b44bffe 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.c +++ b/drivers/net/wireless/iwlwifi/iwl-io.c | |||
@@ -327,11 +327,11 @@ u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr) | |||
327 | EXPORT_SYMBOL_GPL(iwl_read_targ_mem); | 327 | EXPORT_SYMBOL_GPL(iwl_read_targ_mem); |
328 | 328 | ||
329 | int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr, | 329 | int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr, |
330 | void *buf, int dwords) | 330 | const void *buf, int dwords) |
331 | { | 331 | { |
332 | unsigned long flags; | 332 | unsigned long flags; |
333 | int offs, result = 0; | 333 | int offs, result = 0; |
334 | u32 *vals = buf; | 334 | const u32 *vals = buf; |
335 | 335 | ||
336 | spin_lock_irqsave(&trans->reg_lock, flags); | 336 | spin_lock_irqsave(&trans->reg_lock, flags); |
337 | if (likely(iwl_grab_nic_access(trans))) { | 337 | if (likely(iwl_grab_nic_access(trans))) { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 50d3819739d1..e1aa69f66de6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -87,7 +87,7 @@ void _iwl_read_targ_mem_dwords(struct iwl_trans *trans, u32 addr, | |||
87 | } while (0) | 87 | } while (0) |
88 | 88 | ||
89 | int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr, | 89 | int _iwl_write_targ_mem_dwords(struct iwl_trans *trans, u32 addr, |
90 | void *buf, int dwords); | 90 | const void *buf, int dwords); |
91 | 91 | ||
92 | u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr); | 92 | u32 iwl_read_targ_mem(struct iwl_trans *trans, u32 addr); |
93 | int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val); | 93 | int iwl_write_targ_mem(struct iwl_trans *trans, u32 addr, u32 val); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 9253ef1dba72..c3a4bb41e533 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h | |||
@@ -213,6 +213,9 @@ | |||
213 | #define SCD_CONTEXT_QUEUE_OFFSET(x)\ | 213 | #define SCD_CONTEXT_QUEUE_OFFSET(x)\ |
214 | (SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8)) | 214 | (SCD_CONTEXT_MEM_LOWER_BOUND + ((x) * 8)) |
215 | 215 | ||
216 | #define SCD_TX_STTS_QUEUE_OFFSET(x)\ | ||
217 | (SCD_TX_STTS_MEM_LOWER_BOUND + ((x) * 16)) | ||
218 | |||
216 | #define SCD_TRANS_TBL_OFFSET_QUEUE(x) \ | 219 | #define SCD_TRANS_TBL_OFFSET_QUEUE(x) \ |
217 | ((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc) | 220 | ((SCD_TRANS_TBL_MEM_LOWER_BOUND + ((x) * 2)) & 0xfffc) |
218 | 221 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index ff1154232885..f75ea6d73ffc 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -444,6 +444,10 @@ enum iwl_trans_state { | |||
444 | * @dev_cmd_headroom: room needed for the transport's private use before the | 444 | * @dev_cmd_headroom: room needed for the transport's private use before the |
445 | * device_cmd for Tx - for internal use only | 445 | * device_cmd for Tx - for internal use only |
446 | * The user should use iwl_trans_{alloc,free}_tx_cmd. | 446 | * The user should use iwl_trans_{alloc,free}_tx_cmd. |
447 | * @rx_mpdu_cmd: MPDU RX command ID, must be assigned by opmode before | ||
448 | * starting the firmware, used for tracing | ||
449 | * @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the | ||
450 | * start of the 802.11 header in the @rx_mpdu_cmd | ||
447 | */ | 451 | */ |
448 | struct iwl_trans { | 452 | struct iwl_trans { |
449 | const struct iwl_trans_ops *ops; | 453 | const struct iwl_trans_ops *ops; |
@@ -457,6 +461,8 @@ struct iwl_trans { | |||
457 | u32 hw_id; | 461 | u32 hw_id; |
458 | char hw_id_str[52]; | 462 | char hw_id_str[52]; |
459 | 463 | ||
464 | u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size; | ||
465 | |||
460 | bool pm_support; | 466 | bool pm_support; |
461 | 467 | ||
462 | wait_queue_head_t wait_command_queue; | 468 | wait_queue_head_t wait_command_queue; |
@@ -516,6 +522,8 @@ static inline int iwl_trans_start_fw(struct iwl_trans *trans, | |||
516 | { | 522 | { |
517 | might_sleep(); | 523 | might_sleep(); |
518 | 524 | ||
525 | WARN_ON_ONCE(!trans->rx_mpdu_cmd); | ||
526 | |||
519 | return trans->ops->start_fw(trans, fw); | 527 | return trans->ops->start_fw(trans, fw); |
520 | } | 528 | } |
521 | 529 | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index 17c8e5d82681..137af4c46a6c 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -411,7 +411,8 @@ static void iwl_rx_handle_rxbuf(struct iwl_trans *trans, | |||
411 | 411 | ||
412 | len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | 412 | len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; |
413 | len += sizeof(u32); /* account for status word */ | 413 | len += sizeof(u32); /* account for status word */ |
414 | trace_iwlwifi_dev_rx(trans->dev, pkt, len); | 414 | trace_iwlwifi_dev_rx(trans->dev, trans, pkt, len); |
415 | trace_iwlwifi_dev_rx_data(trans->dev, trans, pkt, len); | ||
415 | 416 | ||
416 | /* Reclaim a command buffer only if this packet is a response | 417 | /* Reclaim a command buffer only if this packet is a response |
417 | * to a (driver-originated) command. | 418 | * to a (driver-originated) command. |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index fe0fffd04304..f95d88df7772 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -300,7 +300,7 @@ static void iwl_trans_pcie_queue_stuck_timer(unsigned long data) | |||
300 | struct iwl_trans_pcie *trans_pcie = txq->trans_pcie; | 300 | struct iwl_trans_pcie *trans_pcie = txq->trans_pcie; |
301 | struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie); | 301 | struct iwl_trans *trans = iwl_trans_pcie_get_trans(trans_pcie); |
302 | u32 scd_sram_addr = trans_pcie->scd_base_addr + | 302 | u32 scd_sram_addr = trans_pcie->scd_base_addr + |
303 | SCD_TX_STTS_MEM_LOWER_BOUND + (16 * txq->q.id); | 303 | SCD_TX_STTS_QUEUE_OFFSET(txq->q.id); |
304 | u8 buf[16]; | 304 | u8 buf[16]; |
305 | int i; | 305 | int i; |
306 | 306 | ||
@@ -1385,11 +1385,13 @@ static int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1385 | dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen, | 1385 | dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen, |
1386 | DMA_BIDIRECTIONAL); | 1386 | DMA_BIDIRECTIONAL); |
1387 | 1387 | ||
1388 | trace_iwlwifi_dev_tx(trans->dev, | 1388 | trace_iwlwifi_dev_tx(trans->dev, skb, |
1389 | &txq->tfds[txq->q.write_ptr], | 1389 | &txq->tfds[txq->q.write_ptr], |
1390 | sizeof(struct iwl_tfd), | 1390 | sizeof(struct iwl_tfd), |
1391 | &dev_cmd->hdr, firstlen, | 1391 | &dev_cmd->hdr, firstlen, |
1392 | skb->data + hdr_len, secondlen); | 1392 | skb->data + hdr_len, secondlen); |
1393 | trace_iwlwifi_dev_tx_data(trans->dev, skb, | ||
1394 | skb->data + hdr_len, secondlen); | ||
1393 | 1395 | ||
1394 | /* start timer if queue currently empty */ | 1396 | /* start timer if queue currently empty */ |
1395 | if (txq->need_update && q->read_ptr == q->write_ptr && | 1397 | if (txq->need_update && q->read_ptr == q->write_ptr && |
@@ -1514,14 +1516,13 @@ static void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, | |||
1514 | struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; | 1516 | struct iwl_tx_queue *txq = &trans_pcie->txq[txq_id]; |
1515 | /* n_bd is usually 256 => n_bd - 1 = 0xff */ | 1517 | /* n_bd is usually 256 => n_bd - 1 = 0xff */ |
1516 | int tfd_num = ssn & (txq->q.n_bd - 1); | 1518 | int tfd_num = ssn & (txq->q.n_bd - 1); |
1517 | int freed = 0; | ||
1518 | 1519 | ||
1519 | spin_lock(&txq->lock); | 1520 | spin_lock(&txq->lock); |
1520 | 1521 | ||
1521 | if (txq->q.read_ptr != tfd_num) { | 1522 | if (txq->q.read_ptr != tfd_num) { |
1522 | IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n", | 1523 | IWL_DEBUG_TX_REPLY(trans, "[Q %d] %d -> %d (%d)\n", |
1523 | txq_id, txq->q.read_ptr, tfd_num, ssn); | 1524 | txq_id, txq->q.read_ptr, tfd_num, ssn); |
1524 | freed = iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); | 1525 | iwl_tx_queue_reclaim(trans, txq_id, tfd_num, skbs); |
1525 | if (iwl_queue_space(&txq->q) > txq->q.low_mark) | 1526 | if (iwl_queue_space(&txq->q) > txq->q.low_mark) |
1526 | iwl_wake_queue(trans, txq); | 1527 | iwl_wake_queue(trans, txq); |
1527 | } | 1528 | } |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 105e3af3c621..db3efbb84d92 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -480,21 +480,20 @@ void iwl_trans_pcie_txq_enable(struct iwl_trans *trans, int txq_id, int fifo, | |||
480 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) | 480 | void iwl_trans_pcie_txq_disable(struct iwl_trans *trans, int txq_id) |
481 | { | 481 | { |
482 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 482 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
483 | u16 rd_ptr, wr_ptr; | 483 | u32 stts_addr = trans_pcie->scd_base_addr + |
484 | int n_bd = trans_pcie->txq[txq_id].q.n_bd; | 484 | SCD_TX_STTS_QUEUE_OFFSET(txq_id); |
485 | static const u32 zero_val[4] = {}; | ||
485 | 486 | ||
486 | if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) { | 487 | if (!test_and_clear_bit(txq_id, trans_pcie->queue_used)) { |
487 | WARN_ONCE(1, "queue %d not used", txq_id); | 488 | WARN_ONCE(1, "queue %d not used", txq_id); |
488 | return; | 489 | return; |
489 | } | 490 | } |
490 | 491 | ||
491 | rd_ptr = iwl_read_prph(trans, SCD_QUEUE_RDPTR(txq_id)) & (n_bd - 1); | 492 | iwl_txq_set_inactive(trans, txq_id); |
492 | wr_ptr = iwl_read_prph(trans, SCD_QUEUE_WRPTR(txq_id)); | ||
493 | 493 | ||
494 | WARN_ONCE(rd_ptr != wr_ptr, "queue %d isn't empty: [%d,%d]", | 494 | _iwl_write_targ_mem_dwords(trans, stts_addr, |
495 | txq_id, rd_ptr, wr_ptr); | 495 | zero_val, ARRAY_SIZE(zero_val)); |
496 | 496 | ||
497 | iwl_txq_set_inactive(trans, txq_id); | ||
498 | IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); | 497 | IWL_DEBUG_TX_QUEUES(trans, "Deactivate queue %d\n", txq_id); |
499 | } | 498 | } |
500 | 499 | ||
@@ -549,7 +548,10 @@ static int iwl_enqueue_hcmd(struct iwl_trans *trans, struct iwl_host_cmd *cmd) | |||
549 | * allocated into separate TFDs, then we will need to | 548 | * allocated into separate TFDs, then we will need to |
550 | * increase the size of the buffers. | 549 | * increase the size of the buffers. |
551 | */ | 550 | */ |
552 | if (WARN_ON(copy_size > TFD_MAX_PAYLOAD_SIZE)) | 551 | if (WARN(copy_size > TFD_MAX_PAYLOAD_SIZE, |
552 | "Command %s (%#x) is too large (%d bytes)\n", | ||
553 | trans_pcie_get_cmd_string(trans_pcie, cmd->id), | ||
554 | cmd->id, copy_size)) | ||
553 | return -EINVAL; | 555 | return -EINVAL; |
554 | 556 | ||
555 | spin_lock_bh(&txq->lock); | 557 | spin_lock_bh(&txq->lock); |
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index 9402b93b9a36..4a97acd170f7 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c | |||
@@ -58,8 +58,7 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, | |||
58 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) | 58 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) |
59 | mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr); | 59 | mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr); |
60 | else | 60 | else |
61 | mwifiex_process_rx_packet(priv->adapter, | 61 | mwifiex_process_rx_packet(priv, rx_tmp_ptr); |
62 | rx_tmp_ptr); | ||
63 | } | 62 | } |
64 | } | 63 | } |
65 | 64 | ||
@@ -106,7 +105,7 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv, | |||
106 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) | 105 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) |
107 | mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr); | 106 | mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr); |
108 | else | 107 | else |
109 | mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr); | 108 | mwifiex_process_rx_packet(priv, rx_tmp_ptr); |
110 | } | 109 | } |
111 | 110 | ||
112 | spin_lock_irqsave(&priv->rx_pkt_lock, flags); | 111 | spin_lock_irqsave(&priv->rx_pkt_lock, flags); |
@@ -442,8 +441,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, | |||
442 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) | 441 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) |
443 | mwifiex_handle_uap_rx_forward(priv, payload); | 442 | mwifiex_handle_uap_rx_forward(priv, payload); |
444 | else | 443 | else |
445 | mwifiex_process_rx_packet(priv->adapter, | 444 | mwifiex_process_rx_packet(priv, payload); |
446 | payload); | ||
447 | } | 445 | } |
448 | return 0; | 446 | return 0; |
449 | } | 447 | } |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 38a58713de6a..fdb1eb861021 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -471,13 +471,13 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) | |||
471 | flag = 1; | 471 | flag = 1; |
472 | first_chan = (u32) ch->hw_value; | 472 | first_chan = (u32) ch->hw_value; |
473 | next_chan = first_chan; | 473 | next_chan = first_chan; |
474 | max_pwr = ch->max_reg_power; | 474 | max_pwr = ch->max_power; |
475 | no_of_parsed_chan = 1; | 475 | no_of_parsed_chan = 1; |
476 | continue; | 476 | continue; |
477 | } | 477 | } |
478 | 478 | ||
479 | if (ch->hw_value == next_chan + 1 && | 479 | if (ch->hw_value == next_chan + 1 && |
480 | ch->max_reg_power == max_pwr) { | 480 | ch->max_power == max_pwr) { |
481 | next_chan++; | 481 | next_chan++; |
482 | no_of_parsed_chan++; | 482 | no_of_parsed_chan++; |
483 | } else { | 483 | } else { |
@@ -488,7 +488,7 @@ static int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) | |||
488 | no_of_triplet++; | 488 | no_of_triplet++; |
489 | first_chan = (u32) ch->hw_value; | 489 | first_chan = (u32) ch->hw_value; |
490 | next_chan = first_chan; | 490 | next_chan = first_chan; |
491 | max_pwr = ch->max_reg_power; | 491 | max_pwr = ch->max_power; |
492 | no_of_parsed_chan = 1; | 492 | no_of_parsed_chan = 1; |
493 | } | 493 | } |
494 | } | 494 | } |
@@ -1819,13 +1819,17 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, | |||
1819 | 1819 | ||
1820 | wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name); | 1820 | wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name); |
1821 | 1821 | ||
1822 | if (atomic_read(&priv->wmm.tx_pkts_queued) >= | 1822 | if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) && |
1823 | atomic_read(&priv->wmm.tx_pkts_queued) >= | ||
1823 | MWIFIEX_MIN_TX_PENDING_TO_CANCEL_SCAN) { | 1824 | MWIFIEX_MIN_TX_PENDING_TO_CANCEL_SCAN) { |
1824 | dev_dbg(priv->adapter->dev, "scan rejected due to traffic\n"); | 1825 | dev_dbg(priv->adapter->dev, "scan rejected due to traffic\n"); |
1825 | return -EBUSY; | 1826 | return -EBUSY; |
1826 | } | 1827 | } |
1827 | 1828 | ||
1828 | priv->scan_request = request; | 1829 | if (priv->user_scan_cfg) { |
1830 | dev_err(priv->adapter->dev, "cmd: Scan already in process..\n"); | ||
1831 | return -EBUSY; | ||
1832 | } | ||
1829 | 1833 | ||
1830 | priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), | 1834 | priv->user_scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), |
1831 | GFP_KERNEL); | 1835 | GFP_KERNEL); |
@@ -1834,6 +1838,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, | |||
1834 | return -ENOMEM; | 1838 | return -ENOMEM; |
1835 | } | 1839 | } |
1836 | 1840 | ||
1841 | priv->scan_request = request; | ||
1842 | |||
1837 | priv->user_scan_cfg->num_ssids = request->n_ssids; | 1843 | priv->user_scan_cfg->num_ssids = request->n_ssids; |
1838 | priv->user_scan_cfg->ssid_list = request->ssids; | 1844 | priv->user_scan_cfg->ssid_list = request->ssids; |
1839 | 1845 | ||
@@ -1870,6 +1876,9 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, | |||
1870 | ret = mwifiex_scan_networks(priv, priv->user_scan_cfg); | 1876 | ret = mwifiex_scan_networks(priv, priv->user_scan_cfg); |
1871 | if (ret) { | 1877 | if (ret) { |
1872 | dev_err(priv->adapter->dev, "scan failed: %d\n", ret); | 1878 | dev_err(priv->adapter->dev, "scan failed: %d\n", ret); |
1879 | priv->scan_request = NULL; | ||
1880 | kfree(priv->user_scan_cfg); | ||
1881 | priv->user_scan_cfg = NULL; | ||
1873 | return ret; | 1882 | return ret; |
1874 | } | 1883 | } |
1875 | 1884 | ||
@@ -2113,7 +2122,6 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, | |||
2113 | } | 2122 | } |
2114 | 2123 | ||
2115 | sema_init(&priv->async_sem, 1); | 2124 | sema_init(&priv->async_sem, 1); |
2116 | priv->scan_pending_on_block = false; | ||
2117 | 2125 | ||
2118 | dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); | 2126 | dev_dbg(adapter->dev, "info: %s: Marvell 802.11 Adapter\n", dev->name); |
2119 | 2127 | ||
@@ -2251,7 +2259,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) | |||
2251 | wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1; | 2259 | wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1; |
2252 | 2260 | ||
2253 | wiphy->features |= NL80211_FEATURE_HT_IBSS | | 2261 | wiphy->features |= NL80211_FEATURE_HT_IBSS | |
2254 | NL80211_FEATURE_INACTIVITY_TIMER; | 2262 | NL80211_FEATURE_INACTIVITY_TIMER | |
2263 | NL80211_FEATURE_LOW_PRIORITY_SCAN; | ||
2255 | 2264 | ||
2256 | /* Reserve space for mwifiex specific private data for BSS */ | 2265 | /* Reserve space for mwifiex specific private data for BSS */ |
2257 | wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); | 2266 | wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 8d465107f52b..da6c49177fcc 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -917,21 +917,24 @@ mwifiex_cmd_timeout_func(unsigned long function_context) | |||
917 | 917 | ||
918 | dev_err(adapter->dev, "last_cmd_index = %d\n", | 918 | dev_err(adapter->dev, "last_cmd_index = %d\n", |
919 | adapter->dbg.last_cmd_index); | 919 | adapter->dbg.last_cmd_index); |
920 | print_hex_dump_bytes("last_cmd_id: ", DUMP_PREFIX_OFFSET, | 920 | dev_err(adapter->dev, "last_cmd_id: %*ph\n", |
921 | adapter->dbg.last_cmd_id, DBG_CMD_NUM); | 921 | (int)sizeof(adapter->dbg.last_cmd_id), |
922 | print_hex_dump_bytes("last_cmd_act: ", DUMP_PREFIX_OFFSET, | 922 | adapter->dbg.last_cmd_id); |
923 | adapter->dbg.last_cmd_act, DBG_CMD_NUM); | 923 | dev_err(adapter->dev, "last_cmd_act: %*ph\n", |
924 | (int)sizeof(adapter->dbg.last_cmd_act), | ||
925 | adapter->dbg.last_cmd_act); | ||
924 | 926 | ||
925 | dev_err(adapter->dev, "last_cmd_resp_index = %d\n", | 927 | dev_err(adapter->dev, "last_cmd_resp_index = %d\n", |
926 | adapter->dbg.last_cmd_resp_index); | 928 | adapter->dbg.last_cmd_resp_index); |
927 | print_hex_dump_bytes("last_cmd_resp_id: ", DUMP_PREFIX_OFFSET, | 929 | dev_err(adapter->dev, "last_cmd_resp_id: %*ph\n", |
928 | adapter->dbg.last_cmd_resp_id, | 930 | (int)sizeof(adapter->dbg.last_cmd_resp_id), |
929 | DBG_CMD_NUM); | 931 | adapter->dbg.last_cmd_resp_id); |
930 | 932 | ||
931 | dev_err(adapter->dev, "last_event_index = %d\n", | 933 | dev_err(adapter->dev, "last_event_index = %d\n", |
932 | adapter->dbg.last_event_index); | 934 | adapter->dbg.last_event_index); |
933 | print_hex_dump_bytes("last_event: ", DUMP_PREFIX_OFFSET, | 935 | dev_err(adapter->dev, "last_event: %*ph\n", |
934 | adapter->dbg.last_event, DBG_CMD_NUM); | 936 | (int)sizeof(adapter->dbg.last_event), |
937 | adapter->dbg.last_event); | ||
935 | 938 | ||
936 | dev_err(adapter->dev, "data_sent=%d cmd_sent=%d\n", | 939 | dev_err(adapter->dev, "data_sent=%d cmd_sent=%d\n", |
937 | adapter->data_sent, adapter->cmd_sent); | 940 | adapter->data_sent, adapter->cmd_sent); |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index b5d37a8caa09..482faace7900 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -84,18 +84,19 @@ static void scan_delay_timer_fn(unsigned long data) | |||
84 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | 84 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); |
85 | 85 | ||
86 | if (priv->user_scan_cfg) { | 86 | if (priv->user_scan_cfg) { |
87 | dev_dbg(priv->adapter->dev, | 87 | if (priv->scan_request) { |
88 | "info: %s: scan aborted\n", __func__); | 88 | dev_dbg(priv->adapter->dev, |
89 | cfg80211_scan_done(priv->scan_request, 1); | 89 | "info: aborting scan\n"); |
90 | priv->scan_request = NULL; | 90 | cfg80211_scan_done(priv->scan_request, 1); |
91 | priv->scan_request = NULL; | ||
92 | } else { | ||
93 | dev_dbg(priv->adapter->dev, | ||
94 | "info: scan already aborted\n"); | ||
95 | } | ||
96 | |||
91 | kfree(priv->user_scan_cfg); | 97 | kfree(priv->user_scan_cfg); |
92 | priv->user_scan_cfg = NULL; | 98 | priv->user_scan_cfg = NULL; |
93 | } | 99 | } |
94 | |||
95 | if (priv->scan_pending_on_block) { | ||
96 | priv->scan_pending_on_block = false; | ||
97 | up(&priv->async_sem); | ||
98 | } | ||
99 | goto done; | 100 | goto done; |
100 | } | 101 | } |
101 | 102 | ||
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index eb22dd248d54..1df767bc8b6e 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -472,6 +472,14 @@ mwifiex_open(struct net_device *dev) | |||
472 | static int | 472 | static int |
473 | mwifiex_close(struct net_device *dev) | 473 | mwifiex_close(struct net_device *dev) |
474 | { | 474 | { |
475 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
476 | |||
477 | if (priv->scan_request) { | ||
478 | dev_dbg(priv->adapter->dev, "aborting scan on ndo_stop\n"); | ||
479 | cfg80211_scan_done(priv->scan_request, 1); | ||
480 | priv->scan_request = NULL; | ||
481 | } | ||
482 | |||
475 | return 0; | 483 | return 0; |
476 | } | 484 | } |
477 | 485 | ||
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index c2d0ab146af5..81f8772dcb07 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -115,8 +115,6 @@ enum { | |||
115 | #define MWIFIEX_TYPE_DATA 0 | 115 | #define MWIFIEX_TYPE_DATA 0 |
116 | #define MWIFIEX_TYPE_EVENT 3 | 116 | #define MWIFIEX_TYPE_EVENT 3 |
117 | 117 | ||
118 | #define DBG_CMD_NUM 5 | ||
119 | |||
120 | #define MAX_BITMAP_RATES_SIZE 10 | 118 | #define MAX_BITMAP_RATES_SIZE 10 |
121 | 119 | ||
122 | #define MAX_CHANNEL_BAND_BG 14 | 120 | #define MAX_CHANNEL_BAND_BG 14 |
@@ -484,7 +482,6 @@ struct mwifiex_private { | |||
484 | u8 nick_name[16]; | 482 | u8 nick_name[16]; |
485 | u16 current_key_index; | 483 | u16 current_key_index; |
486 | struct semaphore async_sem; | 484 | struct semaphore async_sem; |
487 | u8 scan_pending_on_block; | ||
488 | u8 report_scan_result; | 485 | u8 report_scan_result; |
489 | struct cfg80211_scan_request *scan_request; | 486 | struct cfg80211_scan_request *scan_request; |
490 | struct mwifiex_user_scan_cfg *user_scan_cfg; | 487 | struct mwifiex_user_scan_cfg *user_scan_cfg; |
@@ -750,9 +747,9 @@ int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter); | |||
750 | 747 | ||
751 | int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *); | 748 | int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *); |
752 | 749 | ||
753 | int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb); | 750 | int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb); |
754 | 751 | ||
755 | int mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter, | 752 | int mwifiex_process_mgmt_packet(struct mwifiex_private *priv, |
756 | struct sk_buff *skb); | 753 | struct sk_buff *skb); |
757 | 754 | ||
758 | int mwifiex_process_event(struct mwifiex_adapter *adapter); | 755 | int mwifiex_process_event(struct mwifiex_adapter *adapter); |
@@ -809,7 +806,7 @@ void mwifiex_hs_activated_event(struct mwifiex_private *priv, | |||
809 | u8 activated); | 806 | u8 activated); |
810 | int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, | 807 | int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, |
811 | struct host_cmd_ds_command *resp); | 808 | struct host_cmd_ds_command *resp); |
812 | int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, | 809 | int mwifiex_process_rx_packet(struct mwifiex_private *priv, |
813 | struct sk_buff *skb); | 810 | struct sk_buff *skb); |
814 | int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no, | 811 | int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no, |
815 | u16 cmd_action, u32 cmd_oid, | 812 | u16 cmd_action, u32 cmd_oid, |
@@ -819,9 +816,9 @@ int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
819 | void *data_buf, void *cmd_buf); | 816 | void *data_buf, void *cmd_buf); |
820 | int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no, | 817 | int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no, |
821 | struct host_cmd_ds_command *resp); | 818 | struct host_cmd_ds_command *resp); |
822 | int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *, | 819 | int mwifiex_process_sta_rx_packet(struct mwifiex_private *, |
823 | struct sk_buff *skb); | 820 | struct sk_buff *skb); |
824 | int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter, | 821 | int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv, |
825 | struct sk_buff *skb); | 822 | struct sk_buff *skb); |
826 | int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv, | 823 | int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv, |
827 | struct sk_buff *skb); | 824 | struct sk_buff *skb); |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 5896b1fb4a2d..9189a32b7844 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -941,6 +941,11 @@ mwifiex_config_scan(struct mwifiex_private *priv, | |||
941 | chan_idx)->chan_scan_mode_bitmap | 941 | chan_idx)->chan_scan_mode_bitmap |
942 | &= ~MWIFIEX_PASSIVE_SCAN; | 942 | &= ~MWIFIEX_PASSIVE_SCAN; |
943 | 943 | ||
944 | if (*filtered_scan) | ||
945 | (scan_chan_list + | ||
946 | chan_idx)->chan_scan_mode_bitmap | ||
947 | |= MWIFIEX_DISABLE_CHAN_FILT; | ||
948 | |||
944 | if (user_scan_in->chan_list[chan_idx].scan_time) { | 949 | if (user_scan_in->chan_list[chan_idx].scan_time) { |
945 | scan_dur = (u16) user_scan_in-> | 950 | scan_dur = (u16) user_scan_in-> |
946 | chan_list[chan_idx].scan_time; | 951 | chan_list[chan_idx].scan_time; |
@@ -1762,26 +1767,39 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1762 | } | 1767 | } |
1763 | if (priv->report_scan_result) | 1768 | if (priv->report_scan_result) |
1764 | priv->report_scan_result = false; | 1769 | priv->report_scan_result = false; |
1765 | if (priv->scan_pending_on_block) { | ||
1766 | priv->scan_pending_on_block = false; | ||
1767 | up(&priv->async_sem); | ||
1768 | } | ||
1769 | 1770 | ||
1770 | if (priv->user_scan_cfg) { | 1771 | if (priv->user_scan_cfg) { |
1771 | dev_dbg(priv->adapter->dev, | 1772 | if (priv->scan_request) { |
1772 | "info: %s: sending scan results\n", __func__); | 1773 | dev_dbg(priv->adapter->dev, |
1773 | cfg80211_scan_done(priv->scan_request, 0); | 1774 | "info: notifying scan done\n"); |
1774 | priv->scan_request = NULL; | 1775 | cfg80211_scan_done(priv->scan_request, 0); |
1776 | priv->scan_request = NULL; | ||
1777 | } else { | ||
1778 | dev_dbg(priv->adapter->dev, | ||
1779 | "info: scan already aborted\n"); | ||
1780 | } | ||
1781 | |||
1775 | kfree(priv->user_scan_cfg); | 1782 | kfree(priv->user_scan_cfg); |
1776 | priv->user_scan_cfg = NULL; | 1783 | priv->user_scan_cfg = NULL; |
1777 | } | 1784 | } |
1778 | } else { | 1785 | } else { |
1779 | if (!mwifiex_wmm_lists_empty(adapter)) { | 1786 | if (priv->user_scan_cfg && !priv->scan_request) { |
1787 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | ||
1788 | flags); | ||
1789 | adapter->scan_delay_cnt = MWIFIEX_MAX_SCAN_DELAY_CNT; | ||
1790 | mod_timer(&priv->scan_delay_timer, jiffies); | ||
1791 | dev_dbg(priv->adapter->dev, | ||
1792 | "info: %s: triggerring scan abort\n", __func__); | ||
1793 | } else if (!mwifiex_wmm_lists_empty(adapter) && | ||
1794 | (priv->scan_request && (priv->scan_request->flags & | ||
1795 | NL80211_SCAN_FLAG_LOW_PRIORITY))) { | ||
1780 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | 1796 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, |
1781 | flags); | 1797 | flags); |
1782 | adapter->scan_delay_cnt = 1; | 1798 | adapter->scan_delay_cnt = 1; |
1783 | mod_timer(&priv->scan_delay_timer, jiffies + | 1799 | mod_timer(&priv->scan_delay_timer, jiffies + |
1784 | msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC)); | 1800 | msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC)); |
1801 | dev_dbg(priv->adapter->dev, | ||
1802 | "info: %s: deferring scan\n", __func__); | ||
1785 | } else { | 1803 | } else { |
1786 | /* Get scan command from scan_pending_q and put to | 1804 | /* Get scan command from scan_pending_q and put to |
1787 | cmd_pending_q */ | 1805 | cmd_pending_q */ |
@@ -1846,21 +1864,18 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, | |||
1846 | struct cfg80211_ssid *req_ssid) | 1864 | struct cfg80211_ssid *req_ssid) |
1847 | { | 1865 | { |
1848 | struct mwifiex_adapter *adapter = priv->adapter; | 1866 | struct mwifiex_adapter *adapter = priv->adapter; |
1849 | int ret = 0; | 1867 | int ret; |
1850 | struct mwifiex_user_scan_cfg *scan_cfg; | 1868 | struct mwifiex_user_scan_cfg *scan_cfg; |
1851 | 1869 | ||
1852 | if (!req_ssid) | ||
1853 | return -1; | ||
1854 | |||
1855 | if (adapter->scan_processing) { | 1870 | if (adapter->scan_processing) { |
1856 | dev_dbg(adapter->dev, "cmd: Scan already in process...\n"); | 1871 | dev_err(adapter->dev, "cmd: Scan already in process...\n"); |
1857 | return ret; | 1872 | return -EBUSY; |
1858 | } | 1873 | } |
1859 | 1874 | ||
1860 | if (priv->scan_block) { | 1875 | if (priv->scan_block) { |
1861 | dev_dbg(adapter->dev, | 1876 | dev_err(adapter->dev, |
1862 | "cmd: Scan is blocked during association...\n"); | 1877 | "cmd: Scan is blocked during association...\n"); |
1863 | return ret; | 1878 | return -EBUSY; |
1864 | } | 1879 | } |
1865 | 1880 | ||
1866 | scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); | 1881 | scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); |
@@ -1897,7 +1912,6 @@ int mwifiex_request_scan(struct mwifiex_private *priv, | |||
1897 | __func__); | 1912 | __func__); |
1898 | return -1; | 1913 | return -1; |
1899 | } | 1914 | } |
1900 | priv->scan_pending_on_block = true; | ||
1901 | 1915 | ||
1902 | priv->adapter->scan_wait_q_woken = false; | 1916 | priv->adapter->scan_wait_q_woken = false; |
1903 | 1917 | ||
@@ -1911,10 +1925,7 @@ int mwifiex_request_scan(struct mwifiex_private *priv, | |||
1911 | if (!ret) | 1925 | if (!ret) |
1912 | ret = mwifiex_wait_queue_complete(priv->adapter); | 1926 | ret = mwifiex_wait_queue_complete(priv->adapter); |
1913 | 1927 | ||
1914 | if (ret == -1) { | 1928 | up(&priv->async_sem); |
1915 | priv->scan_pending_on_block = false; | ||
1916 | up(&priv->async_sem); | ||
1917 | } | ||
1918 | 1929 | ||
1919 | return ret; | 1930 | return ret; |
1920 | } | 1931 | } |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 09e6a267f566..65c12eb3e5e7 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -85,10 +85,6 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv, | |||
85 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | 85 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); |
86 | if (priv->report_scan_result) | 86 | if (priv->report_scan_result) |
87 | priv->report_scan_result = false; | 87 | priv->report_scan_result = false; |
88 | if (priv->scan_pending_on_block) { | ||
89 | priv->scan_pending_on_block = false; | ||
90 | up(&priv->async_sem); | ||
91 | } | ||
92 | break; | 88 | break; |
93 | 89 | ||
94 | case HostCmd_CMD_MAC_CONTROL: | 90 | case HostCmd_CMD_MAC_CONTROL: |
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c index 07d32b73783e..b5c109504393 100644 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ b/drivers/net/wireless/mwifiex/sta_rx.c | |||
@@ -38,14 +38,10 @@ | |||
38 | * | 38 | * |
39 | * The completion callback is called after processing in complete. | 39 | * The completion callback is called after processing in complete. |
40 | */ | 40 | */ |
41 | int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, | 41 | int mwifiex_process_rx_packet(struct mwifiex_private *priv, |
42 | struct sk_buff *skb) | 42 | struct sk_buff *skb) |
43 | { | 43 | { |
44 | int ret; | 44 | int ret; |
45 | struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); | ||
46 | struct mwifiex_private *priv = | ||
47 | mwifiex_get_priv_by_id(adapter, rx_info->bss_num, | ||
48 | rx_info->bss_type); | ||
49 | struct rx_packet_hdr *rx_pkt_hdr; | 45 | struct rx_packet_hdr *rx_pkt_hdr; |
50 | struct rxpd *local_rx_pd; | 46 | struct rxpd *local_rx_pd; |
51 | int hdr_chop; | 47 | int hdr_chop; |
@@ -98,9 +94,9 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, | |||
98 | 94 | ||
99 | priv->rxpd_htinfo = local_rx_pd->ht_info; | 95 | priv->rxpd_htinfo = local_rx_pd->ht_info; |
100 | 96 | ||
101 | ret = mwifiex_recv_packet(adapter, skb); | 97 | ret = mwifiex_recv_packet(priv, skb); |
102 | if (ret == -1) | 98 | if (ret == -1) |
103 | dev_err(adapter->dev, "recv packet failed\n"); | 99 | dev_err(priv->adapter->dev, "recv packet failed\n"); |
104 | 100 | ||
105 | return ret; | 101 | return ret; |
106 | } | 102 | } |
@@ -117,21 +113,15 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, | |||
117 | * | 113 | * |
118 | * The completion callback is called after processing in complete. | 114 | * The completion callback is called after processing in complete. |
119 | */ | 115 | */ |
120 | int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, | 116 | int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv, |
121 | struct sk_buff *skb) | 117 | struct sk_buff *skb) |
122 | { | 118 | { |
119 | struct mwifiex_adapter *adapter = priv->adapter; | ||
123 | int ret = 0; | 120 | int ret = 0; |
124 | struct rxpd *local_rx_pd; | 121 | struct rxpd *local_rx_pd; |
125 | struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); | ||
126 | struct rx_packet_hdr *rx_pkt_hdr; | 122 | struct rx_packet_hdr *rx_pkt_hdr; |
127 | u8 ta[ETH_ALEN]; | 123 | u8 ta[ETH_ALEN]; |
128 | u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num; | 124 | u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num; |
129 | struct mwifiex_private *priv = | ||
130 | mwifiex_get_priv_by_id(adapter, rx_info->bss_num, | ||
131 | rx_info->bss_type); | ||
132 | |||
133 | if (!priv) | ||
134 | return -1; | ||
135 | 125 | ||
136 | local_rx_pd = (struct rxpd *) (skb->data); | 126 | local_rx_pd = (struct rxpd *) (skb->data); |
137 | rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type); | 127 | rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type); |
@@ -169,13 +159,13 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, | |||
169 | 159 | ||
170 | while (!skb_queue_empty(&list)) { | 160 | while (!skb_queue_empty(&list)) { |
171 | rx_skb = __skb_dequeue(&list); | 161 | rx_skb = __skb_dequeue(&list); |
172 | ret = mwifiex_recv_packet(adapter, rx_skb); | 162 | ret = mwifiex_recv_packet(priv, rx_skb); |
173 | if (ret == -1) | 163 | if (ret == -1) |
174 | dev_err(adapter->dev, "Rx of A-MSDU failed"); | 164 | dev_err(adapter->dev, "Rx of A-MSDU failed"); |
175 | } | 165 | } |
176 | return 0; | 166 | return 0; |
177 | } else if (rx_pkt_type == PKT_TYPE_MGMT) { | 167 | } else if (rx_pkt_type == PKT_TYPE_MGMT) { |
178 | ret = mwifiex_process_mgmt_packet(adapter, skb); | 168 | ret = mwifiex_process_mgmt_packet(priv, skb); |
179 | if (ret) | 169 | if (ret) |
180 | dev_err(adapter->dev, "Rx of mgmt packet failed"); | 170 | dev_err(adapter->dev, "Rx of mgmt packet failed"); |
181 | dev_kfree_skb_any(skb); | 171 | dev_kfree_skb_any(skb); |
@@ -188,7 +178,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, | |||
188 | */ | 178 | */ |
189 | if (!IS_11N_ENABLED(priv) || | 179 | if (!IS_11N_ENABLED(priv) || |
190 | memcmp(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN)) { | 180 | memcmp(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN)) { |
191 | mwifiex_process_rx_packet(adapter, skb); | 181 | mwifiex_process_rx_packet(priv, skb); |
192 | return ret; | 182 | return ret; |
193 | } | 183 | } |
194 | 184 | ||
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 2af263992e83..5cb3f7af8749 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c | |||
@@ -48,13 +48,19 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, | |||
48 | if (!priv) | 48 | if (!priv) |
49 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | 49 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); |
50 | 50 | ||
51 | if (!priv) { | ||
52 | dev_err(adapter->dev, "data: priv not found. Drop RX packet\n"); | ||
53 | dev_kfree_skb_any(skb); | ||
54 | return -1; | ||
55 | } | ||
56 | |||
51 | rx_info->bss_num = priv->bss_num; | 57 | rx_info->bss_num = priv->bss_num; |
52 | rx_info->bss_type = priv->bss_type; | 58 | rx_info->bss_type = priv->bss_type; |
53 | 59 | ||
54 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) | 60 | if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) |
55 | return mwifiex_process_uap_rx_packet(adapter, skb); | 61 | return mwifiex_process_uap_rx_packet(priv, skb); |
56 | 62 | ||
57 | return mwifiex_process_sta_rx_packet(adapter, skb); | 63 | return mwifiex_process_sta_rx_packet(priv, skb); |
58 | } | 64 | } |
59 | EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet); | 65 | EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet); |
60 | 66 | ||
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index d95a2d558fcf..8dd72240f162 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c | |||
@@ -188,10 +188,19 @@ mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg, | |||
188 | int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable); | 188 | int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable); |
189 | const u8 *var_pos = params->beacon.head + var_offset; | 189 | const u8 *var_pos = params->beacon.head + var_offset; |
190 | int len = params->beacon.head_len - var_offset; | 190 | int len = params->beacon.head_len - var_offset; |
191 | u8 rate_len = 0; | ||
191 | 192 | ||
192 | rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len); | 193 | rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len); |
193 | if (rate_ie) | 194 | if (rate_ie) { |
194 | memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len); | 195 | memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len); |
196 | rate_len = rate_ie->len; | ||
197 | } | ||
198 | |||
199 | rate_ie = (void *)cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, | ||
200 | params->beacon.tail, | ||
201 | params->beacon.tail_len); | ||
202 | if (rate_ie) | ||
203 | memcpy(bss_cfg->rates + rate_len, rate_ie + 1, rate_ie->len); | ||
195 | 204 | ||
196 | return; | 205 | return; |
197 | } | 206 | } |
diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c index 0966ac24b3b4..a018e42d117e 100644 --- a/drivers/net/wireless/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/mwifiex/uap_txrx.c | |||
@@ -146,7 +146,7 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv, | |||
146 | } | 146 | } |
147 | 147 | ||
148 | /* Forward unicat/Inter-BSS packets to kernel. */ | 148 | /* Forward unicat/Inter-BSS packets to kernel. */ |
149 | return mwifiex_process_rx_packet(adapter, skb); | 149 | return mwifiex_process_rx_packet(priv, skb); |
150 | } | 150 | } |
151 | 151 | ||
152 | /* | 152 | /* |
@@ -159,24 +159,17 @@ int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv, | |||
159 | * | 159 | * |
160 | * The completion callback is called after processing is complete. | 160 | * The completion callback is called after processing is complete. |
161 | */ | 161 | */ |
162 | int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter, | 162 | int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv, |
163 | struct sk_buff *skb) | 163 | struct sk_buff *skb) |
164 | { | 164 | { |
165 | struct mwifiex_adapter *adapter = priv->adapter; | ||
165 | int ret; | 166 | int ret; |
166 | struct uap_rxpd *uap_rx_pd; | 167 | struct uap_rxpd *uap_rx_pd; |
167 | struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); | ||
168 | struct rx_packet_hdr *rx_pkt_hdr; | 168 | struct rx_packet_hdr *rx_pkt_hdr; |
169 | u16 rx_pkt_type; | 169 | u16 rx_pkt_type; |
170 | u8 ta[ETH_ALEN], pkt_type; | 170 | u8 ta[ETH_ALEN], pkt_type; |
171 | struct mwifiex_sta_node *node; | 171 | struct mwifiex_sta_node *node; |
172 | 172 | ||
173 | struct mwifiex_private *priv = | ||
174 | mwifiex_get_priv_by_id(adapter, rx_info->bss_num, | ||
175 | rx_info->bss_type); | ||
176 | |||
177 | if (!priv) | ||
178 | return -1; | ||
179 | |||
180 | uap_rx_pd = (struct uap_rxpd *)(skb->data); | 173 | uap_rx_pd = (struct uap_rxpd *)(skb->data); |
181 | rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type); | 174 | rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type); |
182 | rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); | 175 | rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); |
@@ -210,7 +203,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter, | |||
210 | 203 | ||
211 | while (!skb_queue_empty(&list)) { | 204 | while (!skb_queue_empty(&list)) { |
212 | rx_skb = __skb_dequeue(&list); | 205 | rx_skb = __skb_dequeue(&list); |
213 | ret = mwifiex_recv_packet(adapter, rx_skb); | 206 | ret = mwifiex_recv_packet(priv, rx_skb); |
214 | if (ret) | 207 | if (ret) |
215 | dev_err(adapter->dev, | 208 | dev_err(adapter->dev, |
216 | "AP:Rx A-MSDU failed"); | 209 | "AP:Rx A-MSDU failed"); |
@@ -218,7 +211,7 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter, | |||
218 | 211 | ||
219 | return 0; | 212 | return 0; |
220 | } else if (rx_pkt_type == PKT_TYPE_MGMT) { | 213 | } else if (rx_pkt_type == PKT_TYPE_MGMT) { |
221 | ret = mwifiex_process_mgmt_packet(adapter, skb); | 214 | ret = mwifiex_process_mgmt_packet(priv, skb); |
222 | if (ret) | 215 | if (ret) |
223 | dev_err(adapter->dev, "Rx of mgmt packet failed"); | 216 | dev_err(adapter->dev, "Rx of mgmt packet failed"); |
224 | dev_kfree_skb_any(skb); | 217 | dev_kfree_skb_any(skb); |
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index ae88f80cf86b..0982375ba3b1 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c | |||
@@ -146,20 +146,16 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv, | |||
146 | * to the kernel. | 146 | * to the kernel. |
147 | */ | 147 | */ |
148 | int | 148 | int |
149 | mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter, | 149 | mwifiex_process_mgmt_packet(struct mwifiex_private *priv, |
150 | struct sk_buff *skb) | 150 | struct sk_buff *skb) |
151 | { | 151 | { |
152 | struct rxpd *rx_pd; | 152 | struct rxpd *rx_pd; |
153 | struct mwifiex_private *priv; | ||
154 | u16 pkt_len; | 153 | u16 pkt_len; |
155 | 154 | ||
156 | if (!skb) | 155 | if (!skb) |
157 | return -1; | 156 | return -1; |
158 | 157 | ||
159 | rx_pd = (struct rxpd *)skb->data; | 158 | rx_pd = (struct rxpd *)skb->data; |
160 | priv = mwifiex_get_priv_by_id(adapter, rx_pd->bss_num, rx_pd->bss_type); | ||
161 | if (!priv) | ||
162 | return -1; | ||
163 | 159 | ||
164 | skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset)); | 160 | skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset)); |
165 | skb_pull(skb, sizeof(pkt_len)); | 161 | skb_pull(skb, sizeof(pkt_len)); |
@@ -190,20 +186,11 @@ mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter, | |||
190 | * the function creates a blank SKB, fills it with the data from the | 186 | * the function creates a blank SKB, fills it with the data from the |
191 | * received buffer and then sends this new SKB to the kernel. | 187 | * received buffer and then sends this new SKB to the kernel. |
192 | */ | 188 | */ |
193 | int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb) | 189 | int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb) |
194 | { | 190 | { |
195 | struct mwifiex_rxinfo *rx_info; | ||
196 | struct mwifiex_private *priv; | ||
197 | |||
198 | if (!skb) | 191 | if (!skb) |
199 | return -1; | 192 | return -1; |
200 | 193 | ||
201 | rx_info = MWIFIEX_SKB_RXCB(skb); | ||
202 | priv = mwifiex_get_priv_by_id(adapter, rx_info->bss_num, | ||
203 | rx_info->bss_type); | ||
204 | if (!priv) | ||
205 | return -1; | ||
206 | |||
207 | skb->dev = priv->netdev; | 194 | skb->dev = priv->netdev; |
208 | skb->protocol = eth_type_trans(skb, priv->netdev); | 195 | skb->protocol = eth_type_trans(skb, priv->netdev); |
209 | skb->ip_summed = CHECKSUM_NONE; | 196 | skb->ip_summed = CHECKSUM_NONE; |
@@ -225,7 +212,7 @@ int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
225 | * fragments. Currently we fail the Filesndl-ht.scr script | 212 | * fragments. Currently we fail the Filesndl-ht.scr script |
226 | * for UDP, hence this fix | 213 | * for UDP, hence this fix |
227 | */ | 214 | */ |
228 | if ((adapter->iface_type == MWIFIEX_USB) && | 215 | if ((priv->adapter->iface_type == MWIFIEX_USB) && |
229 | (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE)) | 216 | (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE)) |
230 | skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE); | 217 | skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE); |
231 | 218 | ||
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c index 7f53cea2f205..01624dcaf73e 100644 --- a/drivers/net/wireless/orinoco/orinoco_usb.c +++ b/drivers/net/wireless/orinoco/orinoco_usb.c | |||
@@ -865,7 +865,7 @@ static int ezusb_firmware_download(struct ezusb_priv *upriv, | |||
865 | static int ezusb_access_ltv(struct ezusb_priv *upriv, | 865 | static int ezusb_access_ltv(struct ezusb_priv *upriv, |
866 | struct request_context *ctx, | 866 | struct request_context *ctx, |
867 | u16 length, const void *data, u16 frame_type, | 867 | u16 length, const void *data, u16 frame_type, |
868 | void *ans_buff, int ans_size, u16 *ans_length) | 868 | void *ans_buff, unsigned ans_size, u16 *ans_length) |
869 | { | 869 | { |
870 | int req_size; | 870 | int req_size; |
871 | int retval = 0; | 871 | int retval = 0; |
@@ -933,7 +933,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv, | |||
933 | } | 933 | } |
934 | if (ctx->in_rid) { | 934 | if (ctx->in_rid) { |
935 | struct ezusb_packet *ans = ctx->buf; | 935 | struct ezusb_packet *ans = ctx->buf; |
936 | int exp_len; | 936 | unsigned exp_len; |
937 | 937 | ||
938 | if (ans->hermes_len != 0) | 938 | if (ans->hermes_len != 0) |
939 | exp_len = le16_to_cpu(ans->hermes_len) * 2 + 12; | 939 | exp_len = le16_to_cpu(ans->hermes_len) * 2 + 12; |
@@ -949,8 +949,7 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv, | |||
949 | } | 949 | } |
950 | 950 | ||
951 | if (ans_buff) | 951 | if (ans_buff) |
952 | memcpy(ans_buff, ans->data, | 952 | memcpy(ans_buff, ans->data, min(exp_len, ans_size)); |
953 | min_t(int, exp_len, ans_size)); | ||
954 | if (ans_length) | 953 | if (ans_length) |
955 | *ans_length = le16_to_cpu(ans->hermes_len); | 954 | *ans_length = le16_to_cpu(ans->hermes_len); |
956 | } | 955 | } |
@@ -995,7 +994,7 @@ static int ezusb_read_ltv(struct hermes *hw, int bap, u16 rid, | |||
995 | struct ezusb_priv *upriv = hw->priv; | 994 | struct ezusb_priv *upriv = hw->priv; |
996 | struct request_context *ctx; | 995 | struct request_context *ctx; |
997 | 996 | ||
998 | if ((bufsize < 0) || (bufsize % 2)) | 997 | if (bufsize % 2) |
999 | return -EINVAL; | 998 | return -EINVAL; |
1000 | 999 | ||
1001 | ctx = ezusb_alloc_ctx(upriv, rid, rid); | 1000 | ctx = ezusb_alloc_ctx(upriv, rid, rid); |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index a12e84f892be..6b2e1e431dd2 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -1988,6 +1988,7 @@ static struct usb_driver rt2500usb_driver = { | |||
1988 | .disconnect = rt2x00usb_disconnect, | 1988 | .disconnect = rt2x00usb_disconnect, |
1989 | .suspend = rt2x00usb_suspend, | 1989 | .suspend = rt2x00usb_suspend, |
1990 | .resume = rt2x00usb_resume, | 1990 | .resume = rt2x00usb_resume, |
1991 | .reset_resume = rt2x00usb_resume, | ||
1991 | .disable_hub_initiated_lpm = 1, | 1992 | .disable_hub_initiated_lpm = 1, |
1992 | }; | 1993 | }; |
1993 | 1994 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 01dc8891070c..3bc206d06cd1 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -2520,20 +2520,37 @@ static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev, | |||
2520 | return comp_value; | 2520 | return comp_value; |
2521 | } | 2521 | } |
2522 | 2522 | ||
2523 | static int rt2800_get_txpower_reg_delta(struct rt2x00_dev *rt2x00dev, | ||
2524 | int power_level, int max_power) | ||
2525 | { | ||
2526 | int delta; | ||
2527 | |||
2528 | if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) | ||
2529 | return 0; | ||
2530 | |||
2531 | /* | ||
2532 | * XXX: We don't know the maximum transmit power of our hardware since | ||
2533 | * the EEPROM doesn't expose it. We only know that we are calibrated | ||
2534 | * to 100% tx power. | ||
2535 | * | ||
2536 | * Hence, we assume the regulatory limit that cfg80211 calulated for | ||
2537 | * the current channel is our maximum and if we are requested to lower | ||
2538 | * the value we just reduce our tx power accordingly. | ||
2539 | */ | ||
2540 | delta = power_level - max_power; | ||
2541 | return min(delta, 0); | ||
2542 | } | ||
2543 | |||
2523 | static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, | 2544 | static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, |
2524 | enum ieee80211_band band, int power_level, | 2545 | enum ieee80211_band band, int power_level, |
2525 | u8 txpower, int delta) | 2546 | u8 txpower, int delta) |
2526 | { | 2547 | { |
2527 | u32 reg; | ||
2528 | u16 eeprom; | 2548 | u16 eeprom; |
2529 | u8 criterion; | 2549 | u8 criterion; |
2530 | u8 eirp_txpower; | 2550 | u8 eirp_txpower; |
2531 | u8 eirp_txpower_criterion; | 2551 | u8 eirp_txpower_criterion; |
2532 | u8 reg_limit; | 2552 | u8 reg_limit; |
2533 | 2553 | ||
2534 | if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b)) | ||
2535 | return txpower; | ||
2536 | |||
2537 | if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) { | 2554 | if (test_bit(CAPABILITY_POWER_LIMIT, &rt2x00dev->cap_flags)) { |
2538 | /* | 2555 | /* |
2539 | * Check if eirp txpower exceed txpower_limit. | 2556 | * Check if eirp txpower exceed txpower_limit. |
@@ -2542,11 +2559,13 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, | |||
2542 | * .11b data rate need add additional 4dbm | 2559 | * .11b data rate need add additional 4dbm |
2543 | * when calculating eirp txpower. | 2560 | * when calculating eirp txpower. |
2544 | */ | 2561 | */ |
2545 | rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, ®); | 2562 | rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + 1, |
2546 | criterion = rt2x00_get_field32(reg, TX_PWR_CFG_0_6MBS); | 2563 | &eeprom); |
2564 | criterion = rt2x00_get_field16(eeprom, | ||
2565 | EEPROM_TXPOWER_BYRATE_RATE0); | ||
2547 | 2566 | ||
2548 | rt2x00_eeprom_read(rt2x00dev, | 2567 | rt2x00_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, |
2549 | EEPROM_EIRP_MAX_TX_POWER, &eeprom); | 2568 | &eeprom); |
2550 | 2569 | ||
2551 | if (band == IEEE80211_BAND_2GHZ) | 2570 | if (band == IEEE80211_BAND_2GHZ) |
2552 | eirp_txpower_criterion = rt2x00_get_field16(eeprom, | 2571 | eirp_txpower_criterion = rt2x00_get_field16(eeprom, |
@@ -2563,36 +2582,71 @@ static u8 rt2800_compensate_txpower(struct rt2x00_dev *rt2x00dev, int is_rate_b, | |||
2563 | } else | 2582 | } else |
2564 | reg_limit = 0; | 2583 | reg_limit = 0; |
2565 | 2584 | ||
2566 | return txpower + delta - reg_limit; | 2585 | txpower = max(0, txpower + delta - reg_limit); |
2586 | return min_t(u8, txpower, 0xc); | ||
2567 | } | 2587 | } |
2568 | 2588 | ||
2589 | /* | ||
2590 | * We configure transmit power using MAC TX_PWR_CFG_{0,...,N} registers and | ||
2591 | * BBP R1 register. TX_PWR_CFG_X allow to configure per rate TX power values, | ||
2592 | * 4 bits for each rate (tune from 0 to 15 dBm). BBP_R1 controls transmit power | ||
2593 | * for all rates, but allow to set only 4 discrete values: -12, -6, 0 and 6 dBm. | ||
2594 | * Reference per rate transmit power values are located in the EEPROM at | ||
2595 | * EEPROM_TXPOWER_BYRATE offset. We adjust them and BBP R1 settings according to | ||
2596 | * current conditions (i.e. band, bandwidth, temperature, user settings). | ||
2597 | */ | ||
2569 | static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, | 2598 | static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, |
2570 | enum ieee80211_band band, | 2599 | struct ieee80211_channel *chan, |
2571 | int power_level) | 2600 | int power_level) |
2572 | { | 2601 | { |
2573 | u8 txpower; | 2602 | u8 txpower, r1; |
2574 | u16 eeprom; | 2603 | u16 eeprom; |
2575 | int i, is_rate_b; | 2604 | u32 reg, offset; |
2576 | u32 reg; | 2605 | int i, is_rate_b, delta, power_ctrl; |
2577 | u8 r1; | 2606 | enum ieee80211_band band = chan->band; |
2578 | u32 offset; | ||
2579 | int delta; | ||
2580 | 2607 | ||
2581 | /* | 2608 | /* |
2582 | * Calculate HT40 compensation delta | 2609 | * Calculate HT40 compensation. For 40MHz we need to add or subtract |
2610 | * value read from EEPROM (different for 2GHz and for 5GHz). | ||
2583 | */ | 2611 | */ |
2584 | delta = rt2800_get_txpower_bw_comp(rt2x00dev, band); | 2612 | delta = rt2800_get_txpower_bw_comp(rt2x00dev, band); |
2585 | 2613 | ||
2586 | /* | 2614 | /* |
2587 | * calculate temperature compensation delta | 2615 | * Calculate temperature compensation. Depends on measurement of current |
2616 | * TSSI (Transmitter Signal Strength Indication) we know TX power (due | ||
2617 | * to temperature or maybe other factors) is smaller or bigger than | ||
2618 | * expected. We adjust it, based on TSSI reference and boundaries values | ||
2619 | * provided in EEPROM. | ||
2588 | */ | 2620 | */ |
2589 | delta += rt2800_get_gain_calibration_delta(rt2x00dev); | 2621 | delta += rt2800_get_gain_calibration_delta(rt2x00dev); |
2590 | 2622 | ||
2591 | /* | 2623 | /* |
2592 | * set to normal bbp tx power control mode: +/- 0dBm | 2624 | * Decrease power according to user settings, on devices with unknown |
2625 | * maximum tx power. For other devices we take user power_level into | ||
2626 | * consideration on rt2800_compensate_txpower(). | ||
2627 | */ | ||
2628 | delta += rt2800_get_txpower_reg_delta(rt2x00dev, power_level, | ||
2629 | chan->max_power); | ||
2630 | |||
2631 | /* | ||
2632 | * BBP_R1 controls TX power for all rates, it allow to set the following | ||
2633 | * gains -12, -6, 0, +6 dBm by setting values 2, 1, 0, 3 respectively. | ||
2634 | * | ||
2635 | * TODO: we do not use +6 dBm option to do not increase power beyond | ||
2636 | * regulatory limit, however this could be utilized for devices with | ||
2637 | * CAPABILITY_POWER_LIMIT. | ||
2593 | */ | 2638 | */ |
2594 | rt2800_bbp_read(rt2x00dev, 1, &r1); | 2639 | rt2800_bbp_read(rt2x00dev, 1, &r1); |
2595 | rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, 0); | 2640 | if (delta <= -12) { |
2641 | power_ctrl = 2; | ||
2642 | delta += 12; | ||
2643 | } else if (delta <= -6) { | ||
2644 | power_ctrl = 1; | ||
2645 | delta += 6; | ||
2646 | } else { | ||
2647 | power_ctrl = 0; | ||
2648 | } | ||
2649 | rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl); | ||
2596 | rt2800_bbp_write(rt2x00dev, 1, r1); | 2650 | rt2800_bbp_write(rt2x00dev, 1, r1); |
2597 | offset = TX_PWR_CFG_0; | 2651 | offset = TX_PWR_CFG_0; |
2598 | 2652 | ||
@@ -2710,7 +2764,7 @@ static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev, | |||
2710 | 2764 | ||
2711 | void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev) | 2765 | void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev) |
2712 | { | 2766 | { |
2713 | rt2800_config_txpower(rt2x00dev, rt2x00dev->curr_band, | 2767 | rt2800_config_txpower(rt2x00dev, rt2x00dev->hw->conf.channel, |
2714 | rt2x00dev->tx_power); | 2768 | rt2x00dev->tx_power); |
2715 | } | 2769 | } |
2716 | EXPORT_SYMBOL_GPL(rt2800_gain_calibration); | 2770 | EXPORT_SYMBOL_GPL(rt2800_gain_calibration); |
@@ -2845,11 +2899,11 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev, | |||
2845 | if (flags & IEEE80211_CONF_CHANGE_CHANNEL) { | 2899 | if (flags & IEEE80211_CONF_CHANGE_CHANNEL) { |
2846 | rt2800_config_channel(rt2x00dev, libconf->conf, | 2900 | rt2800_config_channel(rt2x00dev, libconf->conf, |
2847 | &libconf->rf, &libconf->channel); | 2901 | &libconf->rf, &libconf->channel); |
2848 | rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band, | 2902 | rt2800_config_txpower(rt2x00dev, libconf->conf->channel, |
2849 | libconf->conf->power_level); | 2903 | libconf->conf->power_level); |
2850 | } | 2904 | } |
2851 | if (flags & IEEE80211_CONF_CHANGE_POWER) | 2905 | if (flags & IEEE80211_CONF_CHANGE_POWER) |
2852 | rt2800_config_txpower(rt2x00dev, libconf->conf->channel->band, | 2906 | rt2800_config_txpower(rt2x00dev, libconf->conf->channel, |
2853 | libconf->conf->power_level); | 2907 | libconf->conf->power_level); |
2854 | if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) | 2908 | if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) |
2855 | rt2800_config_retry_limit(rt2x00dev, libconf); | 2909 | rt2800_config_retry_limit(rt2x00dev, libconf); |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index c9e9370eb789..3b8fb5a603f2 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -1282,6 +1282,7 @@ static struct usb_driver rt2800usb_driver = { | |||
1282 | .disconnect = rt2x00usb_disconnect, | 1282 | .disconnect = rt2x00usb_disconnect, |
1283 | .suspend = rt2x00usb_suspend, | 1283 | .suspend = rt2x00usb_suspend, |
1284 | .resume = rt2x00usb_resume, | 1284 | .resume = rt2x00usb_resume, |
1285 | .reset_resume = rt2x00usb_resume, | ||
1285 | .disable_hub_initiated_lpm = 1, | 1286 | .disable_hub_initiated_lpm = 1, |
1286 | }; | 1287 | }; |
1287 | 1288 | ||
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index e5eb43b3eee7..24eec66e9fd2 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c | |||
@@ -2535,6 +2535,7 @@ static struct usb_driver rt73usb_driver = { | |||
2535 | .disconnect = rt2x00usb_disconnect, | 2535 | .disconnect = rt2x00usb_disconnect, |
2536 | .suspend = rt2x00usb_suspend, | 2536 | .suspend = rt2x00usb_suspend, |
2537 | .resume = rt2x00usb_resume, | 2537 | .resume = rt2x00usb_resume, |
2538 | .reset_resume = rt2x00usb_resume, | ||
2538 | .disable_hub_initiated_lpm = 1, | 2539 | .disable_hub_initiated_lpm = 1, |
2539 | }; | 2540 | }; |
2540 | 2541 | ||
diff --git a/drivers/net/wireless/rtlwifi/cam.c b/drivers/net/wireless/rtlwifi/cam.c index 5b4b4d4eaf9e..ca69e35e50f1 100644 --- a/drivers/net/wireless/rtlwifi/cam.c +++ b/drivers/net/wireless/rtlwifi/cam.c | |||
@@ -52,11 +52,8 @@ static void rtl_cam_program_entry(struct ieee80211_hw *hw, u32 entry_no, | |||
52 | u32 target_content = 0; | 52 | u32 target_content = 0; |
53 | u8 entry_i; | 53 | u8 entry_i; |
54 | 54 | ||
55 | RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, | 55 | RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, "key_cont_128: %6phC\n", |
56 | "key_cont_128:\n %x:%x:%x:%x:%x:%x\n", | 56 | key_cont_128); |
57 | key_cont_128[0], key_cont_128[1], | ||
58 | key_cont_128[2], key_cont_128[3], | ||
59 | key_cont_128[4], key_cont_128[5]); | ||
60 | 57 | ||
61 | for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) { | 58 | for (entry_i = 0; entry_i < CAM_CONTENT_COUNT; entry_i++) { |
62 | target_command = entry_i + CAM_CONTENT_COUNT * entry_no; | 59 | target_command = entry_i + CAM_CONTENT_COUNT * entry_no; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index 86d73b32d995..038c02c9afed 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c | |||
@@ -1918,10 +1918,8 @@ static void rtl92ce_update_hal_rate_mask(struct ieee80211_hw *hw, | |||
1918 | (ratr_index << 28); | 1918 | (ratr_index << 28); |
1919 | rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; | 1919 | rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; |
1920 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, | 1920 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, |
1921 | "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n", | 1921 | "Rate_index:%x, ratr_val:%x, %5phC\n", |
1922 | ratr_index, ratr_bitmap, | 1922 | ratr_index, ratr_bitmap, rate_mask); |
1923 | rate_mask[0], rate_mask[1], rate_mask[2], rate_mask[3], | ||
1924 | rate_mask[4]); | ||
1925 | rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask); | 1923 | rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask); |
1926 | 1924 | ||
1927 | if (macid != 0) | 1925 | if (macid != 0) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 4bbb711a36c5..7d36a94263b0 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | |||
@@ -2169,10 +2169,8 @@ void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) | |||
2169 | ratr_index << 28); | 2169 | ratr_index << 28); |
2170 | rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; | 2170 | rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80; |
2171 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, | 2171 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, |
2172 | "Rate_index:%x, ratr_val:%x, %x:%x:%x:%x:%x\n", | 2172 | "Rate_index:%x, ratr_val:%x, %5phC\n", |
2173 | ratr_index, ratr_bitmap, | 2173 | ratr_index, ratr_bitmap, rate_mask); |
2174 | rate_mask[0], rate_mask[1], rate_mask[2], rate_mask[3], | ||
2175 | rate_mask[4]); | ||
2176 | rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask); | 2174 | rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask); |
2177 | } | 2175 | } |
2178 | 2176 | ||
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 030beb45d8b0..e3ea4b346889 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
@@ -673,7 +673,7 @@ static int rtl_usb_start(struct ieee80211_hw *hw) | |||
673 | set_hal_start(rtlhal); | 673 | set_hal_start(rtlhal); |
674 | 674 | ||
675 | /* Start bulk IN */ | 675 | /* Start bulk IN */ |
676 | _rtl_usb_receive(hw); | 676 | err = _rtl_usb_receive(hw); |
677 | } | 677 | } |
678 | 678 | ||
679 | return err; | 679 | return err; |
diff --git a/drivers/nfc/Makefile b/drivers/nfc/Makefile index bf05831fdf09..36c359043f54 100644 --- a/drivers/nfc/Makefile +++ b/drivers/nfc/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for nfc devices | 2 | # Makefile for nfc devices |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_PN544_HCI_NFC) += pn544_hci.o | 5 | obj-$(CONFIG_PN544_HCI_NFC) += pn544/ |
6 | obj-$(CONFIG_NFC_PN533) += pn533.o | 6 | obj-$(CONFIG_NFC_PN533) += pn533.o |
7 | obj-$(CONFIG_NFC_WILINK) += nfcwilink.o | 7 | obj-$(CONFIG_NFC_WILINK) += nfcwilink.o |
8 | 8 | ||
diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index 97c440a8cd61..18e279d3e836 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c | |||
@@ -84,6 +84,10 @@ MODULE_DEVICE_TABLE(usb, pn533_table); | |||
84 | #define PN533_LISTEN_TIME 2 | 84 | #define PN533_LISTEN_TIME 2 |
85 | 85 | ||
86 | /* frame definitions */ | 86 | /* frame definitions */ |
87 | #define PN533_NORMAL_FRAME_MAX_LEN 262 /* 6 (PREAMBLE, SOF, LEN, LCS, TFI) | ||
88 | 254 (DATA) | ||
89 | 2 (DCS, postamble) */ | ||
90 | |||
87 | #define PN533_FRAME_TAIL_SIZE 2 | 91 | #define PN533_FRAME_TAIL_SIZE 2 |
88 | #define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \ | 92 | #define PN533_FRAME_SIZE(f) (sizeof(struct pn533_frame) + f->datalen + \ |
89 | PN533_FRAME_TAIL_SIZE) | 93 | PN533_FRAME_TAIL_SIZE) |
@@ -1165,8 +1169,7 @@ static void pn533_poll_create_mod_list(struct pn533 *dev, | |||
1165 | pn533_poll_add_mod(dev, PN533_LISTEN_MOD); | 1169 | pn533_poll_add_mod(dev, PN533_LISTEN_MOD); |
1166 | } | 1170 | } |
1167 | 1171 | ||
1168 | static int pn533_start_poll_complete(struct pn533 *dev, void *arg, | 1172 | static int pn533_start_poll_complete(struct pn533 *dev, u8 *params, int params_len) |
1169 | u8 *params, int params_len) | ||
1170 | { | 1173 | { |
1171 | struct pn533_poll_response *resp; | 1174 | struct pn533_poll_response *resp; |
1172 | int rc; | 1175 | int rc; |
@@ -1304,8 +1307,7 @@ static void pn533_wq_tg_get_data(struct work_struct *work) | |||
1304 | } | 1307 | } |
1305 | 1308 | ||
1306 | #define ATR_REQ_GB_OFFSET 17 | 1309 | #define ATR_REQ_GB_OFFSET 17 |
1307 | static int pn533_init_target_complete(struct pn533 *dev, void *arg, | 1310 | static int pn533_init_target_complete(struct pn533 *dev, u8 *params, int params_len) |
1308 | u8 *params, int params_len) | ||
1309 | { | 1311 | { |
1310 | struct pn533_cmd_init_target_response *resp; | 1312 | struct pn533_cmd_init_target_response *resp; |
1311 | u8 frame, comm_mode = NFC_COMM_PASSIVE, *gb; | 1313 | u8 frame, comm_mode = NFC_COMM_PASSIVE, *gb; |
@@ -1402,9 +1404,9 @@ static int pn533_poll_complete(struct pn533 *dev, void *arg, | |||
1402 | if (cur_mod->len == 0) { | 1404 | if (cur_mod->len == 0) { |
1403 | del_timer(&dev->listen_timer); | 1405 | del_timer(&dev->listen_timer); |
1404 | 1406 | ||
1405 | return pn533_init_target_complete(dev, arg, params, params_len); | 1407 | return pn533_init_target_complete(dev, params, params_len); |
1406 | } else { | 1408 | } else { |
1407 | rc = pn533_start_poll_complete(dev, arg, params, params_len); | 1409 | rc = pn533_start_poll_complete(dev, params, params_len); |
1408 | if (!rc) | 1410 | if (!rc) |
1409 | return rc; | 1411 | return rc; |
1410 | } | 1412 | } |
@@ -2373,9 +2375,9 @@ static int pn533_probe(struct usb_interface *interface, | |||
2373 | goto error; | 2375 | goto error; |
2374 | } | 2376 | } |
2375 | 2377 | ||
2376 | dev->in_frame = kmalloc(dev->in_maxlen, GFP_KERNEL); | 2378 | dev->in_frame = kmalloc(PN533_NORMAL_FRAME_MAX_LEN, GFP_KERNEL); |
2377 | dev->in_urb = usb_alloc_urb(0, GFP_KERNEL); | 2379 | dev->in_urb = usb_alloc_urb(0, GFP_KERNEL); |
2378 | dev->out_frame = kmalloc(dev->out_maxlen, GFP_KERNEL); | 2380 | dev->out_frame = kmalloc(PN533_NORMAL_FRAME_MAX_LEN, GFP_KERNEL); |
2379 | dev->out_urb = usb_alloc_urb(0, GFP_KERNEL); | 2381 | dev->out_urb = usb_alloc_urb(0, GFP_KERNEL); |
2380 | 2382 | ||
2381 | if (!dev->in_frame || !dev->out_frame || | 2383 | if (!dev->in_frame || !dev->out_frame || |
diff --git a/drivers/nfc/pn544/Makefile b/drivers/nfc/pn544/Makefile new file mode 100644 index 000000000000..725733881eb3 --- /dev/null +++ b/drivers/nfc/pn544/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | # | ||
2 | # Makefile for PN544 HCI based NFC driver | ||
3 | # | ||
4 | |||
5 | obj-$(CONFIG_PN544_HCI_NFC) += pn544_i2c.o | ||
6 | |||
7 | pn544_i2c-y := pn544.o i2c.o | ||
diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c new file mode 100644 index 000000000000..fb430d882352 --- /dev/null +++ b/drivers/nfc/pn544/i2c.c | |||
@@ -0,0 +1,500 @@ | |||
1 | /* | ||
2 | * I2C Link Layer for PN544 HCI based Driver | ||
3 | * | ||
4 | * Copyright (C) 2012 Intel Corporation. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the | ||
17 | * Free Software Foundation, Inc., | ||
18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/crc-ccitt.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/i2c.h> | ||
24 | #include <linux/gpio.h> | ||
25 | #include <linux/miscdevice.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/delay.h> | ||
28 | |||
29 | #include <linux/nfc/pn544.h> | ||
30 | |||
31 | #include <net/nfc/hci.h> | ||
32 | #include <net/nfc/llc.h> | ||
33 | |||
34 | #include "pn544.h" | ||
35 | |||
36 | #define PN544_I2C_FRAME_HEADROOM 1 | ||
37 | #define PN544_I2C_FRAME_TAILROOM 2 | ||
38 | |||
39 | /* framing in HCI mode */ | ||
40 | #define PN544_HCI_I2C_LLC_LEN 1 | ||
41 | #define PN544_HCI_I2C_LLC_CRC 2 | ||
42 | #define PN544_HCI_I2C_LLC_LEN_CRC (PN544_HCI_I2C_LLC_LEN + \ | ||
43 | PN544_HCI_I2C_LLC_CRC) | ||
44 | #define PN544_HCI_I2C_LLC_MIN_SIZE (1 + PN544_HCI_I2C_LLC_LEN_CRC) | ||
45 | #define PN544_HCI_I2C_LLC_MAX_PAYLOAD 29 | ||
46 | #define PN544_HCI_I2C_LLC_MAX_SIZE (PN544_HCI_I2C_LLC_LEN_CRC + 1 + \ | ||
47 | PN544_HCI_I2C_LLC_MAX_PAYLOAD) | ||
48 | |||
49 | static struct i2c_device_id pn544_hci_i2c_id_table[] = { | ||
50 | {"pn544", 0}, | ||
51 | {} | ||
52 | }; | ||
53 | |||
54 | MODULE_DEVICE_TABLE(i2c, pn544_hci_i2c_id_table); | ||
55 | |||
56 | #define PN544_HCI_I2C_DRIVER_NAME "pn544_hci_i2c" | ||
57 | |||
58 | struct pn544_i2c_phy { | ||
59 | struct i2c_client *i2c_dev; | ||
60 | struct nfc_hci_dev *hdev; | ||
61 | |||
62 | unsigned int gpio_en; | ||
63 | unsigned int gpio_irq; | ||
64 | unsigned int gpio_fw; | ||
65 | unsigned int en_polarity; | ||
66 | |||
67 | int powered; | ||
68 | |||
69 | int hard_fault; /* | ||
70 | * < 0 if hardware error occured (e.g. i2c err) | ||
71 | * and prevents normal operation. | ||
72 | */ | ||
73 | }; | ||
74 | |||
75 | #define I2C_DUMP_SKB(info, skb) \ | ||
76 | do { \ | ||
77 | pr_debug("%s:\n", info); \ | ||
78 | print_hex_dump(KERN_DEBUG, "i2c: ", DUMP_PREFIX_OFFSET, \ | ||
79 | 16, 1, (skb)->data, (skb)->len, 0); \ | ||
80 | } while (0) | ||
81 | |||
82 | static void pn544_hci_i2c_platform_init(struct pn544_i2c_phy *phy) | ||
83 | { | ||
84 | int polarity, retry, ret; | ||
85 | char rset_cmd[] = { 0x05, 0xF9, 0x04, 0x00, 0xC3, 0xE5 }; | ||
86 | int count = sizeof(rset_cmd); | ||
87 | |||
88 | pr_info(DRIVER_DESC ": %s\n", __func__); | ||
89 | dev_info(&phy->i2c_dev->dev, "Detecting nfc_en polarity\n"); | ||
90 | |||
91 | /* Disable fw download */ | ||
92 | gpio_set_value(phy->gpio_fw, 0); | ||
93 | |||
94 | for (polarity = 0; polarity < 2; polarity++) { | ||
95 | phy->en_polarity = polarity; | ||
96 | retry = 3; | ||
97 | while (retry--) { | ||
98 | /* power off */ | ||
99 | gpio_set_value(phy->gpio_en, !phy->en_polarity); | ||
100 | usleep_range(10000, 15000); | ||
101 | |||
102 | /* power on */ | ||
103 | gpio_set_value(phy->gpio_en, phy->en_polarity); | ||
104 | usleep_range(10000, 15000); | ||
105 | |||
106 | /* send reset */ | ||
107 | dev_dbg(&phy->i2c_dev->dev, "Sending reset cmd\n"); | ||
108 | ret = i2c_master_send(phy->i2c_dev, rset_cmd, count); | ||
109 | if (ret == count) { | ||
110 | dev_info(&phy->i2c_dev->dev, | ||
111 | "nfc_en polarity : active %s\n", | ||
112 | (polarity == 0 ? "low" : "high")); | ||
113 | goto out; | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | |||
118 | dev_err(&phy->i2c_dev->dev, | ||
119 | "Could not detect nfc_en polarity, fallback to active high\n"); | ||
120 | |||
121 | out: | ||
122 | gpio_set_value(phy->gpio_en, !phy->en_polarity); | ||
123 | } | ||
124 | |||
125 | static int pn544_hci_i2c_enable(void *phy_id) | ||
126 | { | ||
127 | struct pn544_i2c_phy *phy = phy_id; | ||
128 | |||
129 | pr_info(DRIVER_DESC ": %s\n", __func__); | ||
130 | |||
131 | gpio_set_value(phy->gpio_fw, 0); | ||
132 | gpio_set_value(phy->gpio_en, phy->en_polarity); | ||
133 | usleep_range(10000, 15000); | ||
134 | |||
135 | phy->powered = 1; | ||
136 | |||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static void pn544_hci_i2c_disable(void *phy_id) | ||
141 | { | ||
142 | struct pn544_i2c_phy *phy = phy_id; | ||
143 | |||
144 | pr_info(DRIVER_DESC ": %s\n", __func__); | ||
145 | |||
146 | gpio_set_value(phy->gpio_fw, 0); | ||
147 | gpio_set_value(phy->gpio_en, !phy->en_polarity); | ||
148 | usleep_range(10000, 15000); | ||
149 | |||
150 | gpio_set_value(phy->gpio_en, phy->en_polarity); | ||
151 | usleep_range(10000, 15000); | ||
152 | |||
153 | gpio_set_value(phy->gpio_en, !phy->en_polarity); | ||
154 | usleep_range(10000, 15000); | ||
155 | |||
156 | phy->powered = 0; | ||
157 | } | ||
158 | |||
159 | static void pn544_hci_i2c_add_len_crc(struct sk_buff *skb) | ||
160 | { | ||
161 | u16 crc; | ||
162 | int len; | ||
163 | |||
164 | len = skb->len + 2; | ||
165 | *skb_push(skb, 1) = len; | ||
166 | |||
167 | crc = crc_ccitt(0xffff, skb->data, skb->len); | ||
168 | crc = ~crc; | ||
169 | *skb_put(skb, 1) = crc & 0xff; | ||
170 | *skb_put(skb, 1) = crc >> 8; | ||
171 | } | ||
172 | |||
173 | static void pn544_hci_i2c_remove_len_crc(struct sk_buff *skb) | ||
174 | { | ||
175 | skb_pull(skb, PN544_I2C_FRAME_HEADROOM); | ||
176 | skb_trim(skb, PN544_I2C_FRAME_TAILROOM); | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * Writing a frame must not return the number of written bytes. | ||
181 | * It must return either zero for success, or <0 for error. | ||
182 | * In addition, it must not alter the skb | ||
183 | */ | ||
184 | static int pn544_hci_i2c_write(void *phy_id, struct sk_buff *skb) | ||
185 | { | ||
186 | int r; | ||
187 | struct pn544_i2c_phy *phy = phy_id; | ||
188 | struct i2c_client *client = phy->i2c_dev; | ||
189 | |||
190 | if (phy->hard_fault != 0) | ||
191 | return phy->hard_fault; | ||
192 | |||
193 | usleep_range(3000, 6000); | ||
194 | |||
195 | pn544_hci_i2c_add_len_crc(skb); | ||
196 | |||
197 | I2C_DUMP_SKB("i2c frame written", skb); | ||
198 | |||
199 | r = i2c_master_send(client, skb->data, skb->len); | ||
200 | |||
201 | if (r == -EREMOTEIO) { /* Retry, chip was in standby */ | ||
202 | usleep_range(6000, 10000); | ||
203 | r = i2c_master_send(client, skb->data, skb->len); | ||
204 | } | ||
205 | |||
206 | if (r >= 0) { | ||
207 | if (r != skb->len) | ||
208 | r = -EREMOTEIO; | ||
209 | else | ||
210 | r = 0; | ||
211 | } | ||
212 | |||
213 | pn544_hci_i2c_remove_len_crc(skb); | ||
214 | |||
215 | return r; | ||
216 | } | ||
217 | |||
218 | static int check_crc(u8 *buf, int buflen) | ||
219 | { | ||
220 | int len; | ||
221 | u16 crc; | ||
222 | |||
223 | len = buf[0] + 1; | ||
224 | crc = crc_ccitt(0xffff, buf, len - 2); | ||
225 | crc = ~crc; | ||
226 | |||
227 | if (buf[len - 2] != (crc & 0xff) || buf[len - 1] != (crc >> 8)) { | ||
228 | pr_err(PN544_HCI_I2C_DRIVER_NAME | ||
229 | ": CRC error 0x%x != 0x%x 0x%x\n", | ||
230 | crc, buf[len - 1], buf[len - 2]); | ||
231 | |||
232 | pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__); | ||
233 | print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE, | ||
234 | 16, 2, buf, buflen, false); | ||
235 | return -EPERM; | ||
236 | } | ||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | /* | ||
241 | * Reads an shdlc frame and returns it in a newly allocated sk_buff. Guarantees | ||
242 | * that i2c bus will be flushed and that next read will start on a new frame. | ||
243 | * returned skb contains only LLC header and payload. | ||
244 | * returns: | ||
245 | * -EREMOTEIO : i2c read error (fatal) | ||
246 | * -EBADMSG : frame was incorrect and discarded | ||
247 | * -ENOMEM : cannot allocate skb, frame dropped | ||
248 | */ | ||
249 | static int pn544_hci_i2c_read(struct pn544_i2c_phy *phy, struct sk_buff **skb) | ||
250 | { | ||
251 | int r; | ||
252 | u8 len; | ||
253 | u8 tmp[PN544_HCI_I2C_LLC_MAX_SIZE - 1]; | ||
254 | struct i2c_client *client = phy->i2c_dev; | ||
255 | |||
256 | r = i2c_master_recv(client, &len, 1); | ||
257 | if (r != 1) { | ||
258 | dev_err(&client->dev, "cannot read len byte\n"); | ||
259 | return -EREMOTEIO; | ||
260 | } | ||
261 | |||
262 | if ((len < (PN544_HCI_I2C_LLC_MIN_SIZE - 1)) || | ||
263 | (len > (PN544_HCI_I2C_LLC_MAX_SIZE - 1))) { | ||
264 | dev_err(&client->dev, "invalid len byte\n"); | ||
265 | r = -EBADMSG; | ||
266 | goto flush; | ||
267 | } | ||
268 | |||
269 | *skb = alloc_skb(1 + len, GFP_KERNEL); | ||
270 | if (*skb == NULL) { | ||
271 | r = -ENOMEM; | ||
272 | goto flush; | ||
273 | } | ||
274 | |||
275 | *skb_put(*skb, 1) = len; | ||
276 | |||
277 | r = i2c_master_recv(client, skb_put(*skb, len), len); | ||
278 | if (r != len) { | ||
279 | kfree_skb(*skb); | ||
280 | return -EREMOTEIO; | ||
281 | } | ||
282 | |||
283 | I2C_DUMP_SKB("i2c frame read", *skb); | ||
284 | |||
285 | r = check_crc((*skb)->data, (*skb)->len); | ||
286 | if (r != 0) { | ||
287 | kfree_skb(*skb); | ||
288 | r = -EBADMSG; | ||
289 | goto flush; | ||
290 | } | ||
291 | |||
292 | skb_pull(*skb, 1); | ||
293 | skb_trim(*skb, (*skb)->len - 2); | ||
294 | |||
295 | usleep_range(3000, 6000); | ||
296 | |||
297 | return 0; | ||
298 | |||
299 | flush: | ||
300 | if (i2c_master_recv(client, tmp, sizeof(tmp)) < 0) | ||
301 | r = -EREMOTEIO; | ||
302 | |||
303 | usleep_range(3000, 6000); | ||
304 | |||
305 | return r; | ||
306 | } | ||
307 | |||
308 | /* | ||
309 | * Reads an shdlc frame from the chip. This is not as straightforward as it | ||
310 | * seems. There are cases where we could loose the frame start synchronization. | ||
311 | * The frame format is len-data-crc, and corruption can occur anywhere while | ||
312 | * transiting on i2c bus, such that we could read an invalid len. | ||
313 | * In order to recover synchronization with the next frame, we must be sure | ||
314 | * to read the real amount of data without using the len byte. We do this by | ||
315 | * assuming the following: | ||
316 | * - the chip will always present only one single complete frame on the bus | ||
317 | * before triggering the interrupt | ||
318 | * - the chip will not present a new frame until we have completely read | ||
319 | * the previous one (or until we have handled the interrupt). | ||
320 | * The tricky case is when we read a corrupted len that is less than the real | ||
321 | * len. We must detect this here in order to determine that we need to flush | ||
322 | * the bus. This is the reason why we check the crc here. | ||
323 | */ | ||
324 | static irqreturn_t pn544_hci_i2c_irq_thread_fn(int irq, void *phy_id) | ||
325 | { | ||
326 | struct pn544_i2c_phy *phy = phy_id; | ||
327 | struct i2c_client *client; | ||
328 | struct sk_buff *skb = NULL; | ||
329 | int r; | ||
330 | |||
331 | if (!phy || irq != phy->i2c_dev->irq) { | ||
332 | WARN_ON_ONCE(1); | ||
333 | return IRQ_NONE; | ||
334 | } | ||
335 | |||
336 | client = phy->i2c_dev; | ||
337 | dev_dbg(&client->dev, "IRQ\n"); | ||
338 | |||
339 | if (phy->hard_fault != 0) | ||
340 | return IRQ_HANDLED; | ||
341 | |||
342 | r = pn544_hci_i2c_read(phy, &skb); | ||
343 | if (r == -EREMOTEIO) { | ||
344 | phy->hard_fault = r; | ||
345 | |||
346 | nfc_hci_recv_frame(phy->hdev, NULL); | ||
347 | |||
348 | return IRQ_HANDLED; | ||
349 | } else if ((r == -ENOMEM) || (r == -EBADMSG)) { | ||
350 | return IRQ_HANDLED; | ||
351 | } | ||
352 | |||
353 | nfc_hci_recv_frame(phy->hdev, skb); | ||
354 | |||
355 | return IRQ_HANDLED; | ||
356 | } | ||
357 | |||
358 | static struct nfc_phy_ops i2c_phy_ops = { | ||
359 | .write = pn544_hci_i2c_write, | ||
360 | .enable = pn544_hci_i2c_enable, | ||
361 | .disable = pn544_hci_i2c_disable, | ||
362 | }; | ||
363 | |||
364 | static int __devinit pn544_hci_i2c_probe(struct i2c_client *client, | ||
365 | const struct i2c_device_id *id) | ||
366 | { | ||
367 | struct pn544_i2c_phy *phy; | ||
368 | struct pn544_nfc_platform_data *pdata; | ||
369 | int r = 0; | ||
370 | |||
371 | dev_dbg(&client->dev, "%s\n", __func__); | ||
372 | dev_dbg(&client->dev, "IRQ: %d\n", client->irq); | ||
373 | |||
374 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
375 | dev_err(&client->dev, "Need I2C_FUNC_I2C\n"); | ||
376 | return -ENODEV; | ||
377 | } | ||
378 | |||
379 | phy = kzalloc(sizeof(struct pn544_i2c_phy), GFP_KERNEL); | ||
380 | if (!phy) { | ||
381 | dev_err(&client->dev, | ||
382 | "Cannot allocate memory for pn544 i2c phy.\n"); | ||
383 | r = -ENOMEM; | ||
384 | goto err_phy_alloc; | ||
385 | } | ||
386 | |||
387 | phy->i2c_dev = client; | ||
388 | i2c_set_clientdata(client, phy); | ||
389 | |||
390 | pdata = client->dev.platform_data; | ||
391 | if (pdata == NULL) { | ||
392 | dev_err(&client->dev, "No platform data\n"); | ||
393 | r = -EINVAL; | ||
394 | goto err_pdata; | ||
395 | } | ||
396 | |||
397 | if (pdata->request_resources == NULL) { | ||
398 | dev_err(&client->dev, "request_resources() missing\n"); | ||
399 | r = -EINVAL; | ||
400 | goto err_pdata; | ||
401 | } | ||
402 | |||
403 | r = pdata->request_resources(client); | ||
404 | if (r) { | ||
405 | dev_err(&client->dev, "Cannot get platform resources\n"); | ||
406 | goto err_pdata; | ||
407 | } | ||
408 | |||
409 | phy->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE); | ||
410 | phy->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET); | ||
411 | phy->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ); | ||
412 | |||
413 | pn544_hci_i2c_platform_init(phy); | ||
414 | |||
415 | r = request_threaded_irq(client->irq, NULL, pn544_hci_i2c_irq_thread_fn, | ||
416 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | ||
417 | PN544_HCI_I2C_DRIVER_NAME, phy); | ||
418 | if (r < 0) { | ||
419 | dev_err(&client->dev, "Unable to register IRQ handler\n"); | ||
420 | goto err_rti; | ||
421 | } | ||
422 | |||
423 | r = pn544_hci_probe(phy, &i2c_phy_ops, LLC_SHDLC_NAME, | ||
424 | PN544_I2C_FRAME_HEADROOM, PN544_I2C_FRAME_TAILROOM, | ||
425 | PN544_HCI_I2C_LLC_MAX_PAYLOAD, &phy->hdev); | ||
426 | if (r < 0) | ||
427 | goto err_hci; | ||
428 | |||
429 | return 0; | ||
430 | |||
431 | err_hci: | ||
432 | free_irq(client->irq, phy); | ||
433 | |||
434 | err_rti: | ||
435 | if (pdata->free_resources != NULL) | ||
436 | pdata->free_resources(); | ||
437 | |||
438 | err_pdata: | ||
439 | kfree(phy); | ||
440 | |||
441 | err_phy_alloc: | ||
442 | return r; | ||
443 | } | ||
444 | |||
445 | static __devexit int pn544_hci_i2c_remove(struct i2c_client *client) | ||
446 | { | ||
447 | struct pn544_i2c_phy *phy = i2c_get_clientdata(client); | ||
448 | struct pn544_nfc_platform_data *pdata = client->dev.platform_data; | ||
449 | |||
450 | dev_dbg(&client->dev, "%s\n", __func__); | ||
451 | |||
452 | pn544_hci_remove(phy->hdev); | ||
453 | |||
454 | if (phy->powered) | ||
455 | pn544_hci_i2c_disable(phy); | ||
456 | |||
457 | free_irq(client->irq, phy); | ||
458 | if (pdata->free_resources) | ||
459 | pdata->free_resources(); | ||
460 | |||
461 | kfree(phy); | ||
462 | |||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | static struct i2c_driver pn544_hci_i2c_driver = { | ||
467 | .driver = { | ||
468 | .name = PN544_HCI_I2C_DRIVER_NAME, | ||
469 | }, | ||
470 | .probe = pn544_hci_i2c_probe, | ||
471 | .id_table = pn544_hci_i2c_id_table, | ||
472 | .remove = __devexit_p(pn544_hci_i2c_remove), | ||
473 | }; | ||
474 | |||
475 | static int __init pn544_hci_i2c_init(void) | ||
476 | { | ||
477 | int r; | ||
478 | |||
479 | pr_debug(DRIVER_DESC ": %s\n", __func__); | ||
480 | |||
481 | r = i2c_add_driver(&pn544_hci_i2c_driver); | ||
482 | if (r) { | ||
483 | pr_err(PN544_HCI_I2C_DRIVER_NAME | ||
484 | ": driver registration failed\n"); | ||
485 | return r; | ||
486 | } | ||
487 | |||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | static void __exit pn544_hci_i2c_exit(void) | ||
492 | { | ||
493 | i2c_del_driver(&pn544_hci_i2c_driver); | ||
494 | } | ||
495 | |||
496 | module_init(pn544_hci_i2c_init); | ||
497 | module_exit(pn544_hci_i2c_exit); | ||
498 | |||
499 | MODULE_LICENSE("GPL"); | ||
500 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
diff --git a/drivers/nfc/pn544_hci.c b/drivers/nfc/pn544/pn544.c index c9c8570273ab..cc666de3b8e5 100644 --- a/drivers/nfc/pn544_hci.c +++ b/drivers/nfc/pn544/pn544.c | |||
@@ -18,47 +18,21 @@ | |||
18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 18 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/crc-ccitt.h> | ||
22 | #include <linux/module.h> | ||
23 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
24 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
25 | #include <linux/miscdevice.h> | ||
26 | #include <linux/interrupt.h> | ||
27 | #include <linux/gpio.h> | ||
28 | #include <linux/i2c.h> | ||
29 | 23 | ||
30 | #include <linux/nfc.h> | 24 | #include <linux/nfc.h> |
31 | #include <net/nfc/hci.h> | 25 | #include <net/nfc/hci.h> |
32 | #include <net/nfc/llc.h> | 26 | #include <net/nfc/llc.h> |
33 | 27 | ||
34 | #include <linux/nfc/pn544.h> | 28 | #include "pn544.h" |
35 | |||
36 | #define DRIVER_DESC "HCI NFC driver for PN544" | ||
37 | |||
38 | #define PN544_HCI_DRIVER_NAME "pn544_hci" | ||
39 | 29 | ||
40 | /* Timing restrictions (ms) */ | 30 | /* Timing restrictions (ms) */ |
41 | #define PN544_HCI_RESETVEN_TIME 30 | 31 | #define PN544_HCI_RESETVEN_TIME 30 |
42 | 32 | ||
43 | static struct i2c_device_id pn544_hci_id_table[] = { | ||
44 | {"pn544", 0}, | ||
45 | {} | ||
46 | }; | ||
47 | |||
48 | MODULE_DEVICE_TABLE(i2c, pn544_hci_id_table); | ||
49 | |||
50 | #define HCI_MODE 0 | 33 | #define HCI_MODE 0 |
51 | #define FW_MODE 1 | 34 | #define FW_MODE 1 |
52 | 35 | ||
53 | /* framing in HCI mode */ | ||
54 | #define PN544_HCI_LLC_LEN 1 | ||
55 | #define PN544_HCI_LLC_CRC 2 | ||
56 | #define PN544_HCI_LLC_LEN_CRC (PN544_HCI_LLC_LEN + PN544_HCI_LLC_CRC) | ||
57 | #define PN544_HCI_LLC_MIN_SIZE (1 + PN544_HCI_LLC_LEN_CRC) | ||
58 | #define PN544_HCI_LLC_MAX_PAYLOAD 29 | ||
59 | #define PN544_HCI_LLC_MAX_SIZE (PN544_HCI_LLC_LEN_CRC + 1 + \ | ||
60 | PN544_HCI_LLC_MAX_PAYLOAD) | ||
61 | |||
62 | enum pn544_state { | 36 | enum pn544_state { |
63 | PN544_ST_COLD, | 37 | PN544_ST_COLD, |
64 | PN544_ST_FW_READY, | 38 | PN544_ST_FW_READY, |
@@ -100,6 +74,10 @@ enum pn544_state { | |||
100 | #define PN544_SYS_MGMT_INFO_NOTIFICATION 0x02 | 74 | #define PN544_SYS_MGMT_INFO_NOTIFICATION 0x02 |
101 | 75 | ||
102 | #define PN544_POLLING_LOOP_MGMT_GATE 0x94 | 76 | #define PN544_POLLING_LOOP_MGMT_GATE 0x94 |
77 | #define PN544_DEP_MODE 0x01 | ||
78 | #define PN544_DEP_ATR_REQ 0x02 | ||
79 | #define PN544_DEP_ATR_RES 0x03 | ||
80 | #define PN544_DEP_MERGE 0x0D | ||
103 | #define PN544_PL_RDPHASES 0x06 | 81 | #define PN544_PL_RDPHASES 0x06 |
104 | #define PN544_PL_EMULATION 0x07 | 82 | #define PN544_PL_EMULATION 0x07 |
105 | #define PN544_PL_NFCT_DEACTIVATED 0x09 | 83 | #define PN544_PL_NFCT_DEACTIVATED 0x09 |
@@ -108,6 +86,15 @@ enum pn544_state { | |||
108 | 86 | ||
109 | #define PN544_NFC_WI_MGMT_GATE 0xA1 | 87 | #define PN544_NFC_WI_MGMT_GATE 0xA1 |
110 | 88 | ||
89 | #define PN544_HCI_EVT_SND_DATA 0x01 | ||
90 | #define PN544_HCI_EVT_ACTIVATED 0x02 | ||
91 | #define PN544_HCI_EVT_DEACTIVATED 0x03 | ||
92 | #define PN544_HCI_EVT_RCV_DATA 0x04 | ||
93 | #define PN544_HCI_EVT_CONTINUE_MI 0x05 | ||
94 | |||
95 | #define PN544_HCI_CMD_ATTREQUEST 0x12 | ||
96 | #define PN544_HCI_CMD_CONTINUE_ACTIVATION 0x13 | ||
97 | |||
111 | static struct nfc_hci_gate pn544_gates[] = { | 98 | static struct nfc_hci_gate pn544_gates[] = { |
112 | {NFC_HCI_ADMIN_GATE, NFC_HCI_INVALID_PIPE}, | 99 | {NFC_HCI_ADMIN_GATE, NFC_HCI_INVALID_PIPE}, |
113 | {NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE}, | 100 | {NFC_HCI_LOOPBACK_GATE, NFC_HCI_INVALID_PIPE}, |
@@ -128,259 +115,22 @@ static struct nfc_hci_gate pn544_gates[] = { | |||
128 | 115 | ||
129 | /* Largest headroom needed for outgoing custom commands */ | 116 | /* Largest headroom needed for outgoing custom commands */ |
130 | #define PN544_CMDS_HEADROOM 2 | 117 | #define PN544_CMDS_HEADROOM 2 |
131 | #define PN544_FRAME_HEADROOM 1 | ||
132 | #define PN544_FRAME_TAILROOM 2 | ||
133 | 118 | ||
134 | struct pn544_hci_info { | 119 | struct pn544_hci_info { |
135 | struct i2c_client *i2c_dev; | 120 | struct nfc_phy_ops *phy_ops; |
121 | void *phy_id; | ||
122 | |||
136 | struct nfc_hci_dev *hdev; | 123 | struct nfc_hci_dev *hdev; |
137 | 124 | ||
138 | enum pn544_state state; | 125 | enum pn544_state state; |
139 | 126 | ||
140 | struct mutex info_lock; | 127 | struct mutex info_lock; |
141 | 128 | ||
142 | unsigned int gpio_en; | ||
143 | unsigned int gpio_irq; | ||
144 | unsigned int gpio_fw; | ||
145 | unsigned int en_polarity; | ||
146 | |||
147 | int hard_fault; /* | ||
148 | * < 0 if hardware error occured (e.g. i2c err) | ||
149 | * and prevents normal operation. | ||
150 | */ | ||
151 | int async_cb_type; | 129 | int async_cb_type; |
152 | data_exchange_cb_t async_cb; | 130 | data_exchange_cb_t async_cb; |
153 | void *async_cb_context; | 131 | void *async_cb_context; |
154 | }; | 132 | }; |
155 | 133 | ||
156 | static void pn544_hci_platform_init(struct pn544_hci_info *info) | ||
157 | { | ||
158 | int polarity, retry, ret; | ||
159 | char rset_cmd[] = { 0x05, 0xF9, 0x04, 0x00, 0xC3, 0xE5 }; | ||
160 | int count = sizeof(rset_cmd); | ||
161 | |||
162 | pr_info(DRIVER_DESC ": %s\n", __func__); | ||
163 | dev_info(&info->i2c_dev->dev, "Detecting nfc_en polarity\n"); | ||
164 | |||
165 | /* Disable fw download */ | ||
166 | gpio_set_value(info->gpio_fw, 0); | ||
167 | |||
168 | for (polarity = 0; polarity < 2; polarity++) { | ||
169 | info->en_polarity = polarity; | ||
170 | retry = 3; | ||
171 | while (retry--) { | ||
172 | /* power off */ | ||
173 | gpio_set_value(info->gpio_en, !info->en_polarity); | ||
174 | usleep_range(10000, 15000); | ||
175 | |||
176 | /* power on */ | ||
177 | gpio_set_value(info->gpio_en, info->en_polarity); | ||
178 | usleep_range(10000, 15000); | ||
179 | |||
180 | /* send reset */ | ||
181 | dev_dbg(&info->i2c_dev->dev, "Sending reset cmd\n"); | ||
182 | ret = i2c_master_send(info->i2c_dev, rset_cmd, count); | ||
183 | if (ret == count) { | ||
184 | dev_info(&info->i2c_dev->dev, | ||
185 | "nfc_en polarity : active %s\n", | ||
186 | (polarity == 0 ? "low" : "high")); | ||
187 | goto out; | ||
188 | } | ||
189 | } | ||
190 | } | ||
191 | |||
192 | dev_err(&info->i2c_dev->dev, | ||
193 | "Could not detect nfc_en polarity, fallback to active high\n"); | ||
194 | |||
195 | out: | ||
196 | gpio_set_value(info->gpio_en, !info->en_polarity); | ||
197 | } | ||
198 | |||
199 | static int pn544_hci_enable(struct pn544_hci_info *info, int mode) | ||
200 | { | ||
201 | pr_info(DRIVER_DESC ": %s\n", __func__); | ||
202 | |||
203 | gpio_set_value(info->gpio_fw, 0); | ||
204 | gpio_set_value(info->gpio_en, info->en_polarity); | ||
205 | usleep_range(10000, 15000); | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static void pn544_hci_disable(struct pn544_hci_info *info) | ||
211 | { | ||
212 | pr_info(DRIVER_DESC ": %s\n", __func__); | ||
213 | |||
214 | gpio_set_value(info->gpio_fw, 0); | ||
215 | gpio_set_value(info->gpio_en, !info->en_polarity); | ||
216 | usleep_range(10000, 15000); | ||
217 | |||
218 | gpio_set_value(info->gpio_en, info->en_polarity); | ||
219 | usleep_range(10000, 15000); | ||
220 | |||
221 | gpio_set_value(info->gpio_en, !info->en_polarity); | ||
222 | usleep_range(10000, 15000); | ||
223 | } | ||
224 | |||
225 | static int pn544_hci_i2c_write(struct i2c_client *client, u8 *buf, int len) | ||
226 | { | ||
227 | int r; | ||
228 | |||
229 | usleep_range(3000, 6000); | ||
230 | |||
231 | r = i2c_master_send(client, buf, len); | ||
232 | |||
233 | if (r == -EREMOTEIO) { /* Retry, chip was in standby */ | ||
234 | usleep_range(6000, 10000); | ||
235 | r = i2c_master_send(client, buf, len); | ||
236 | } | ||
237 | |||
238 | if (r >= 0) { | ||
239 | if (r != len) | ||
240 | return -EREMOTEIO; | ||
241 | else | ||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | return r; | ||
246 | } | ||
247 | |||
248 | static int check_crc(u8 *buf, int buflen) | ||
249 | { | ||
250 | int len; | ||
251 | u16 crc; | ||
252 | |||
253 | len = buf[0] + 1; | ||
254 | crc = crc_ccitt(0xffff, buf, len - 2); | ||
255 | crc = ~crc; | ||
256 | |||
257 | if (buf[len - 2] != (crc & 0xff) || buf[len - 1] != (crc >> 8)) { | ||
258 | pr_err(PN544_HCI_DRIVER_NAME ": CRC error 0x%x != 0x%x 0x%x\n", | ||
259 | crc, buf[len - 1], buf[len - 2]); | ||
260 | |||
261 | pr_info(DRIVER_DESC ": %s : BAD CRC\n", __func__); | ||
262 | print_hex_dump(KERN_DEBUG, "crc: ", DUMP_PREFIX_NONE, | ||
263 | 16, 2, buf, buflen, false); | ||
264 | return -EPERM; | ||
265 | } | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | /* | ||
270 | * Reads an shdlc frame and returns it in a newly allocated sk_buff. Guarantees | ||
271 | * that i2c bus will be flushed and that next read will start on a new frame. | ||
272 | * returned skb contains only LLC header and payload. | ||
273 | * returns: | ||
274 | * -EREMOTEIO : i2c read error (fatal) | ||
275 | * -EBADMSG : frame was incorrect and discarded | ||
276 | * -ENOMEM : cannot allocate skb, frame dropped | ||
277 | */ | ||
278 | static int pn544_hci_i2c_read(struct i2c_client *client, struct sk_buff **skb) | ||
279 | { | ||
280 | int r; | ||
281 | u8 len; | ||
282 | u8 tmp[PN544_HCI_LLC_MAX_SIZE - 1]; | ||
283 | |||
284 | r = i2c_master_recv(client, &len, 1); | ||
285 | if (r != 1) { | ||
286 | dev_err(&client->dev, "cannot read len byte\n"); | ||
287 | return -EREMOTEIO; | ||
288 | } | ||
289 | |||
290 | if ((len < (PN544_HCI_LLC_MIN_SIZE - 1)) || | ||
291 | (len > (PN544_HCI_LLC_MAX_SIZE - 1))) { | ||
292 | dev_err(&client->dev, "invalid len byte\n"); | ||
293 | r = -EBADMSG; | ||
294 | goto flush; | ||
295 | } | ||
296 | |||
297 | *skb = alloc_skb(1 + len, GFP_KERNEL); | ||
298 | if (*skb == NULL) { | ||
299 | r = -ENOMEM; | ||
300 | goto flush; | ||
301 | } | ||
302 | |||
303 | *skb_put(*skb, 1) = len; | ||
304 | |||
305 | r = i2c_master_recv(client, skb_put(*skb, len), len); | ||
306 | if (r != len) { | ||
307 | kfree_skb(*skb); | ||
308 | return -EREMOTEIO; | ||
309 | } | ||
310 | |||
311 | r = check_crc((*skb)->data, (*skb)->len); | ||
312 | if (r != 0) { | ||
313 | kfree_skb(*skb); | ||
314 | r = -EBADMSG; | ||
315 | goto flush; | ||
316 | } | ||
317 | |||
318 | skb_pull(*skb, 1); | ||
319 | skb_trim(*skb, (*skb)->len - 2); | ||
320 | |||
321 | usleep_range(3000, 6000); | ||
322 | |||
323 | return 0; | ||
324 | |||
325 | flush: | ||
326 | if (i2c_master_recv(client, tmp, sizeof(tmp)) < 0) | ||
327 | r = -EREMOTEIO; | ||
328 | |||
329 | usleep_range(3000, 6000); | ||
330 | |||
331 | return r; | ||
332 | } | ||
333 | |||
334 | /* | ||
335 | * Reads an shdlc frame from the chip. This is not as straightforward as it | ||
336 | * seems. There are cases where we could loose the frame start synchronization. | ||
337 | * The frame format is len-data-crc, and corruption can occur anywhere while | ||
338 | * transiting on i2c bus, such that we could read an invalid len. | ||
339 | * In order to recover synchronization with the next frame, we must be sure | ||
340 | * to read the real amount of data without using the len byte. We do this by | ||
341 | * assuming the following: | ||
342 | * - the chip will always present only one single complete frame on the bus | ||
343 | * before triggering the interrupt | ||
344 | * - the chip will not present a new frame until we have completely read | ||
345 | * the previous one (or until we have handled the interrupt). | ||
346 | * The tricky case is when we read a corrupted len that is less than the real | ||
347 | * len. We must detect this here in order to determine that we need to flush | ||
348 | * the bus. This is the reason why we check the crc here. | ||
349 | */ | ||
350 | static irqreturn_t pn544_hci_irq_thread_fn(int irq, void *dev_id) | ||
351 | { | ||
352 | struct pn544_hci_info *info = dev_id; | ||
353 | struct i2c_client *client; | ||
354 | struct sk_buff *skb = NULL; | ||
355 | int r; | ||
356 | |||
357 | if (!info || irq != info->i2c_dev->irq) { | ||
358 | WARN_ON_ONCE(1); | ||
359 | return IRQ_NONE; | ||
360 | } | ||
361 | |||
362 | client = info->i2c_dev; | ||
363 | dev_dbg(&client->dev, "IRQ\n"); | ||
364 | |||
365 | if (info->hard_fault != 0) | ||
366 | return IRQ_HANDLED; | ||
367 | |||
368 | r = pn544_hci_i2c_read(client, &skb); | ||
369 | if (r == -EREMOTEIO) { | ||
370 | info->hard_fault = r; | ||
371 | |||
372 | nfc_hci_recv_frame(info->hdev, NULL); | ||
373 | |||
374 | return IRQ_HANDLED; | ||
375 | } else if ((r == -ENOMEM) || (r == -EBADMSG)) { | ||
376 | return IRQ_HANDLED; | ||
377 | } | ||
378 | |||
379 | nfc_hci_recv_frame(info->hdev, skb); | ||
380 | |||
381 | return IRQ_HANDLED; | ||
382 | } | ||
383 | |||
384 | static int pn544_hci_open(struct nfc_hci_dev *hdev) | 134 | static int pn544_hci_open(struct nfc_hci_dev *hdev) |
385 | { | 135 | { |
386 | struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); | 136 | struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); |
@@ -393,7 +143,7 @@ static int pn544_hci_open(struct nfc_hci_dev *hdev) | |||
393 | goto out; | 143 | goto out; |
394 | } | 144 | } |
395 | 145 | ||
396 | r = pn544_hci_enable(info, HCI_MODE); | 146 | r = info->phy_ops->enable(info->phy_id); |
397 | 147 | ||
398 | if (r == 0) | 148 | if (r == 0) |
399 | info->state = PN544_ST_READY; | 149 | info->state = PN544_ST_READY; |
@@ -412,7 +162,7 @@ static void pn544_hci_close(struct nfc_hci_dev *hdev) | |||
412 | if (info->state == PN544_ST_COLD) | 162 | if (info->state == PN544_ST_COLD) |
413 | goto out; | 163 | goto out; |
414 | 164 | ||
415 | pn544_hci_disable(info); | 165 | info->phy_ops->disable(info->phy_id); |
416 | 166 | ||
417 | info->state = PN544_ST_COLD; | 167 | info->state = PN544_ST_COLD; |
418 | 168 | ||
@@ -587,40 +337,11 @@ static int pn544_hci_ready(struct nfc_hci_dev *hdev) | |||
587 | return 0; | 337 | return 0; |
588 | } | 338 | } |
589 | 339 | ||
590 | static void pn544_hci_add_len_crc(struct sk_buff *skb) | ||
591 | { | ||
592 | u16 crc; | ||
593 | int len; | ||
594 | |||
595 | len = skb->len + 2; | ||
596 | *skb_push(skb, 1) = len; | ||
597 | |||
598 | crc = crc_ccitt(0xffff, skb->data, skb->len); | ||
599 | crc = ~crc; | ||
600 | *skb_put(skb, 1) = crc & 0xff; | ||
601 | *skb_put(skb, 1) = crc >> 8; | ||
602 | } | ||
603 | |||
604 | static void pn544_hci_remove_len_crc(struct sk_buff *skb) | ||
605 | { | ||
606 | skb_pull(skb, PN544_FRAME_HEADROOM); | ||
607 | skb_trim(skb, PN544_FRAME_TAILROOM); | ||
608 | } | ||
609 | |||
610 | static int pn544_hci_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) | 340 | static int pn544_hci_xmit(struct nfc_hci_dev *hdev, struct sk_buff *skb) |
611 | { | 341 | { |
612 | struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); | 342 | struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); |
613 | struct i2c_client *client = info->i2c_dev; | ||
614 | int r; | ||
615 | 343 | ||
616 | if (info->hard_fault != 0) | 344 | return info->phy_ops->write(info->phy_id, skb); |
617 | return info->hard_fault; | ||
618 | |||
619 | pn544_hci_add_len_crc(skb); | ||
620 | r = pn544_hci_i2c_write(client, skb->data, skb->len); | ||
621 | pn544_hci_remove_len_crc(skb); | ||
622 | |||
623 | return r; | ||
624 | } | 345 | } |
625 | 346 | ||
626 | static int pn544_hci_start_poll(struct nfc_hci_dev *hdev, | 347 | static int pn544_hci_start_poll(struct nfc_hci_dev *hdev, |
@@ -630,6 +351,9 @@ static int pn544_hci_start_poll(struct nfc_hci_dev *hdev, | |||
630 | int r; | 351 | int r; |
631 | u8 duration[2]; | 352 | u8 duration[2]; |
632 | u8 activated; | 353 | u8 activated; |
354 | u8 i_mode = 0x3f; /* Enable all supported modes */ | ||
355 | u8 t_mode = 0x0f; | ||
356 | u8 t_merge = 0x01; /* Enable merge by default */ | ||
633 | 357 | ||
634 | pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n", | 358 | pr_info(DRIVER_DESC ": %s protocols 0x%x 0x%x\n", |
635 | __func__, im_protocols, tm_protocols); | 359 | __func__, im_protocols, tm_protocols); |
@@ -667,6 +391,61 @@ static int pn544_hci_start_poll(struct nfc_hci_dev *hdev, | |||
667 | if (r < 0) | 391 | if (r < 0) |
668 | return r; | 392 | return r; |
669 | 393 | ||
394 | if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) { | ||
395 | hdev->gb = nfc_get_local_general_bytes(hdev->ndev, | ||
396 | &hdev->gb_len); | ||
397 | pr_debug("generate local bytes %p", hdev->gb); | ||
398 | if (hdev->gb == NULL || hdev->gb_len == 0) { | ||
399 | im_protocols &= ~NFC_PROTO_NFC_DEP_MASK; | ||
400 | tm_protocols &= ~NFC_PROTO_NFC_DEP_MASK; | ||
401 | } | ||
402 | } | ||
403 | |||
404 | if (im_protocols & NFC_PROTO_NFC_DEP_MASK) { | ||
405 | r = nfc_hci_send_event(hdev, | ||
406 | PN544_RF_READER_NFCIP1_INITIATOR_GATE, | ||
407 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | ||
408 | if (r < 0) | ||
409 | return r; | ||
410 | |||
411 | r = nfc_hci_set_param(hdev, | ||
412 | PN544_RF_READER_NFCIP1_INITIATOR_GATE, | ||
413 | PN544_DEP_MODE, &i_mode, 1); | ||
414 | if (r < 0) | ||
415 | return r; | ||
416 | |||
417 | r = nfc_hci_set_param(hdev, | ||
418 | PN544_RF_READER_NFCIP1_INITIATOR_GATE, | ||
419 | PN544_DEP_ATR_REQ, hdev->gb, hdev->gb_len); | ||
420 | if (r < 0) | ||
421 | return r; | ||
422 | |||
423 | r = nfc_hci_send_event(hdev, | ||
424 | PN544_RF_READER_NFCIP1_INITIATOR_GATE, | ||
425 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); | ||
426 | if (r < 0) | ||
427 | nfc_hci_send_event(hdev, | ||
428 | PN544_RF_READER_NFCIP1_INITIATOR_GATE, | ||
429 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | ||
430 | } | ||
431 | |||
432 | if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) { | ||
433 | r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, | ||
434 | PN544_DEP_MODE, &t_mode, 1); | ||
435 | if (r < 0) | ||
436 | return r; | ||
437 | |||
438 | r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, | ||
439 | PN544_DEP_ATR_RES, hdev->gb, hdev->gb_len); | ||
440 | if (r < 0) | ||
441 | return r; | ||
442 | |||
443 | r = nfc_hci_set_param(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, | ||
444 | PN544_DEP_MERGE, &t_merge, 1); | ||
445 | if (r < 0) | ||
446 | return r; | ||
447 | } | ||
448 | |||
670 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | 449 | r = nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, |
671 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); | 450 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); |
672 | if (r < 0) | 451 | if (r < 0) |
@@ -676,6 +455,43 @@ static int pn544_hci_start_poll(struct nfc_hci_dev *hdev, | |||
676 | return r; | 455 | return r; |
677 | } | 456 | } |
678 | 457 | ||
458 | static int pn544_hci_dep_link_up(struct nfc_hci_dev *hdev, | ||
459 | struct nfc_target *target, u8 comm_mode, | ||
460 | u8 *gb, size_t gb_len) | ||
461 | { | ||
462 | struct sk_buff *rgb_skb = NULL; | ||
463 | int r; | ||
464 | |||
465 | r = nfc_hci_get_param(hdev, target->hci_reader_gate, | ||
466 | PN544_DEP_ATR_RES, &rgb_skb); | ||
467 | if (r < 0) | ||
468 | return r; | ||
469 | |||
470 | if (rgb_skb->len == 0 || rgb_skb->len > NFC_GB_MAXSIZE) { | ||
471 | r = -EPROTO; | ||
472 | goto exit; | ||
473 | } | ||
474 | print_hex_dump(KERN_DEBUG, "remote gb: ", DUMP_PREFIX_OFFSET, | ||
475 | 16, 1, rgb_skb->data, rgb_skb->len, true); | ||
476 | |||
477 | r = nfc_set_remote_general_bytes(hdev->ndev, rgb_skb->data, | ||
478 | rgb_skb->len); | ||
479 | |||
480 | if (r == 0) | ||
481 | r = nfc_dep_link_is_up(hdev->ndev, target->idx, comm_mode, | ||
482 | NFC_RF_INITIATOR); | ||
483 | exit: | ||
484 | kfree_skb(rgb_skb); | ||
485 | return r; | ||
486 | } | ||
487 | |||
488 | static int pn544_hci_dep_link_down(struct nfc_hci_dev *hdev) | ||
489 | { | ||
490 | |||
491 | return nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_INITIATOR_GATE, | ||
492 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | ||
493 | } | ||
494 | |||
679 | static int pn544_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, | 495 | static int pn544_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, |
680 | struct nfc_target *target) | 496 | struct nfc_target *target) |
681 | { | 497 | { |
@@ -687,6 +503,9 @@ static int pn544_hci_target_from_gate(struct nfc_hci_dev *hdev, u8 gate, | |||
687 | target->supported_protocols = NFC_PROTO_JEWEL_MASK; | 503 | target->supported_protocols = NFC_PROTO_JEWEL_MASK; |
688 | target->sens_res = 0x0c00; | 504 | target->sens_res = 0x0c00; |
689 | break; | 505 | break; |
506 | case PN544_RF_READER_NFCIP1_INITIATOR_GATE: | ||
507 | target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; | ||
508 | break; | ||
690 | default: | 509 | default: |
691 | return -EPROTO; | 510 | return -EPROTO; |
692 | } | 511 | } |
@@ -701,7 +520,18 @@ static int pn544_hci_complete_target_discovered(struct nfc_hci_dev *hdev, | |||
701 | struct sk_buff *uid_skb; | 520 | struct sk_buff *uid_skb; |
702 | int r = 0; | 521 | int r = 0; |
703 | 522 | ||
704 | if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) { | 523 | if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) |
524 | return r; | ||
525 | |||
526 | if (target->supported_protocols & NFC_PROTO_NFC_DEP_MASK) { | ||
527 | r = nfc_hci_send_cmd(hdev, | ||
528 | PN544_RF_READER_NFCIP1_INITIATOR_GATE, | ||
529 | PN544_HCI_CMD_CONTINUE_ACTIVATION, NULL, 0, NULL); | ||
530 | if (r < 0) | ||
531 | return r; | ||
532 | |||
533 | target->hci_reader_gate = PN544_RF_READER_NFCIP1_INITIATOR_GATE; | ||
534 | } else if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) { | ||
705 | if (target->nfcid1_len != 4 && target->nfcid1_len != 7 && | 535 | if (target->nfcid1_len != 4 && target->nfcid1_len != 7 && |
706 | target->nfcid1_len != 10) | 536 | target->nfcid1_len != 10) |
707 | return -EPROTO; | 537 | return -EPROTO; |
@@ -724,6 +554,16 @@ static int pn544_hci_complete_target_discovered(struct nfc_hci_dev *hdev, | |||
724 | PN544_RF_READER_CMD_ACTIVATE_NEXT, | 554 | PN544_RF_READER_CMD_ACTIVATE_NEXT, |
725 | uid_skb->data, uid_skb->len, NULL); | 555 | uid_skb->data, uid_skb->len, NULL); |
726 | kfree_skb(uid_skb); | 556 | kfree_skb(uid_skb); |
557 | |||
558 | r = nfc_hci_send_cmd(hdev, | ||
559 | PN544_RF_READER_NFCIP1_INITIATOR_GATE, | ||
560 | PN544_HCI_CMD_CONTINUE_ACTIVATION, | ||
561 | NULL, 0, NULL); | ||
562 | if (r < 0) | ||
563 | return r; | ||
564 | |||
565 | target->hci_reader_gate = PN544_RF_READER_NFCIP1_INITIATOR_GATE; | ||
566 | target->supported_protocols = NFC_PROTO_NFC_DEP_MASK; | ||
727 | } else if (target->supported_protocols & NFC_PROTO_ISO14443_MASK) { | 567 | } else if (target->supported_protocols & NFC_PROTO_ISO14443_MASK) { |
728 | /* | 568 | /* |
729 | * TODO: maybe other ISO 14443 require some kind of continue | 569 | * TODO: maybe other ISO 14443 require some kind of continue |
@@ -769,7 +609,7 @@ static void pn544_hci_data_exchange_cb(void *context, struct sk_buff *skb, | |||
769 | * <= 0: driver handled the data exchange | 609 | * <= 0: driver handled the data exchange |
770 | * 1: driver doesn't especially handle, please do standard processing | 610 | * 1: driver doesn't especially handle, please do standard processing |
771 | */ | 611 | */ |
772 | static int pn544_hci_data_exchange(struct nfc_hci_dev *hdev, | 612 | static int pn544_hci_im_transceive(struct nfc_hci_dev *hdev, |
773 | struct nfc_target *target, | 613 | struct nfc_target *target, |
774 | struct sk_buff *skb, data_exchange_cb_t cb, | 614 | struct sk_buff *skb, data_exchange_cb_t cb, |
775 | void *cb_context) | 615 | void *cb_context) |
@@ -822,17 +662,110 @@ static int pn544_hci_data_exchange(struct nfc_hci_dev *hdev, | |||
822 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, | 662 | return nfc_hci_send_cmd_async(hdev, target->hci_reader_gate, |
823 | PN544_JEWEL_RAW_CMD, skb->data, | 663 | PN544_JEWEL_RAW_CMD, skb->data, |
824 | skb->len, cb, cb_context); | 664 | skb->len, cb, cb_context); |
665 | case PN544_RF_READER_NFCIP1_INITIATOR_GATE: | ||
666 | *skb_push(skb, 1) = 0; | ||
667 | |||
668 | return nfc_hci_send_event(hdev, target->hci_reader_gate, | ||
669 | PN544_HCI_EVT_SND_DATA, skb->data, | ||
670 | skb->len); | ||
825 | default: | 671 | default: |
826 | return 1; | 672 | return 1; |
827 | } | 673 | } |
828 | } | 674 | } |
829 | 675 | ||
676 | static int pn544_hci_tm_send(struct nfc_hci_dev *hdev, struct sk_buff *skb) | ||
677 | { | ||
678 | /* Set default false for multiple information chaining */ | ||
679 | *skb_push(skb, 1) = 0; | ||
680 | |||
681 | return nfc_hci_send_event(hdev, PN544_RF_READER_NFCIP1_TARGET_GATE, | ||
682 | PN544_HCI_EVT_SND_DATA, skb->data, skb->len); | ||
683 | } | ||
684 | |||
830 | static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, | 685 | static int pn544_hci_check_presence(struct nfc_hci_dev *hdev, |
831 | struct nfc_target *target) | 686 | struct nfc_target *target) |
832 | { | 687 | { |
833 | return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | 688 | pr_debug("supported protocol %d", target->supported_protocols); |
834 | PN544_RF_READER_CMD_PRESENCE_CHECK, | 689 | if (target->supported_protocols & (NFC_PROTO_ISO14443_MASK | |
835 | NULL, 0, NULL); | 690 | NFC_PROTO_ISO14443_B_MASK)) { |
691 | return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | ||
692 | PN544_RF_READER_CMD_PRESENCE_CHECK, | ||
693 | NULL, 0, NULL); | ||
694 | } else if (target->supported_protocols & NFC_PROTO_MIFARE_MASK) { | ||
695 | if (target->nfcid1_len != 4 && target->nfcid1_len != 7 && | ||
696 | target->nfcid1_len != 10) | ||
697 | return -EOPNOTSUPP; | ||
698 | |||
699 | return nfc_hci_send_cmd(hdev, NFC_HCI_RF_READER_A_GATE, | ||
700 | PN544_RF_READER_CMD_ACTIVATE_NEXT, | ||
701 | target->nfcid1, target->nfcid1_len, NULL); | ||
702 | } else if (target->supported_protocols & NFC_PROTO_JEWEL_MASK) { | ||
703 | return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | ||
704 | PN544_JEWEL_RAW_CMD, NULL, 0, NULL); | ||
705 | } else if (target->supported_protocols & NFC_PROTO_FELICA_MASK) { | ||
706 | return nfc_hci_send_cmd(hdev, PN544_RF_READER_F_GATE, | ||
707 | PN544_FELICA_RAW, NULL, 0, NULL); | ||
708 | } else if (target->supported_protocols & NFC_PROTO_NFC_DEP_MASK) { | ||
709 | return nfc_hci_send_cmd(hdev, target->hci_reader_gate, | ||
710 | PN544_HCI_CMD_ATTREQUEST, | ||
711 | NULL, 0, NULL); | ||
712 | } | ||
713 | |||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | static void pn544_hci_event_received(struct nfc_hci_dev *hdev, u8 gate, | ||
718 | u8 event, struct sk_buff *skb) | ||
719 | { | ||
720 | struct sk_buff *rgb_skb = NULL; | ||
721 | int r = 0; | ||
722 | |||
723 | pr_debug("hci event %d", event); | ||
724 | switch (event) { | ||
725 | case PN544_HCI_EVT_ACTIVATED: | ||
726 | if (gate == PN544_RF_READER_NFCIP1_INITIATOR_GATE) | ||
727 | nfc_hci_target_discovered(hdev, gate); | ||
728 | else if (gate == PN544_RF_READER_NFCIP1_TARGET_GATE) { | ||
729 | r = nfc_hci_get_param(hdev, gate, PN544_DEP_ATR_REQ, | ||
730 | &rgb_skb); | ||
731 | |||
732 | if (r < 0) | ||
733 | goto exit; | ||
734 | |||
735 | nfc_tm_activated(hdev->ndev, NFC_PROTO_NFC_DEP_MASK, | ||
736 | NFC_COMM_PASSIVE, rgb_skb->data, | ||
737 | rgb_skb->len); | ||
738 | |||
739 | kfree_skb(rgb_skb); | ||
740 | } | ||
741 | |||
742 | break; | ||
743 | case PN544_HCI_EVT_DEACTIVATED: | ||
744 | nfc_hci_send_event(hdev, gate, | ||
745 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | ||
746 | break; | ||
747 | case PN544_HCI_EVT_RCV_DATA: | ||
748 | if (skb->len < 2) { | ||
749 | r = -EPROTO; | ||
750 | goto exit; | ||
751 | } | ||
752 | |||
753 | if (skb->data[0] != 0) { | ||
754 | pr_debug("data0 %d", skb->data[0]); | ||
755 | r = -EPROTO; | ||
756 | goto exit; | ||
757 | } | ||
758 | |||
759 | skb_pull(skb, 2); | ||
760 | nfc_tm_data_received(hdev->ndev, skb); | ||
761 | |||
762 | return; | ||
763 | default: | ||
764 | break; | ||
765 | } | ||
766 | |||
767 | exit: | ||
768 | kfree_skb(skb); | ||
836 | } | 769 | } |
837 | 770 | ||
838 | static struct nfc_hci_ops pn544_hci_ops = { | 771 | static struct nfc_hci_ops pn544_hci_ops = { |
@@ -841,74 +774,36 @@ static struct nfc_hci_ops pn544_hci_ops = { | |||
841 | .hci_ready = pn544_hci_ready, | 774 | .hci_ready = pn544_hci_ready, |
842 | .xmit = pn544_hci_xmit, | 775 | .xmit = pn544_hci_xmit, |
843 | .start_poll = pn544_hci_start_poll, | 776 | .start_poll = pn544_hci_start_poll, |
777 | .dep_link_up = pn544_hci_dep_link_up, | ||
778 | .dep_link_down = pn544_hci_dep_link_down, | ||
844 | .target_from_gate = pn544_hci_target_from_gate, | 779 | .target_from_gate = pn544_hci_target_from_gate, |
845 | .complete_target_discovered = pn544_hci_complete_target_discovered, | 780 | .complete_target_discovered = pn544_hci_complete_target_discovered, |
846 | .data_exchange = pn544_hci_data_exchange, | 781 | .im_transceive = pn544_hci_im_transceive, |
782 | .tm_send = pn544_hci_tm_send, | ||
847 | .check_presence = pn544_hci_check_presence, | 783 | .check_presence = pn544_hci_check_presence, |
784 | .event_received = pn544_hci_event_received, | ||
848 | }; | 785 | }; |
849 | 786 | ||
850 | static int __devinit pn544_hci_probe(struct i2c_client *client, | 787 | int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, |
851 | const struct i2c_device_id *id) | 788 | int phy_headroom, int phy_tailroom, int phy_payload, |
789 | struct nfc_hci_dev **hdev) | ||
852 | { | 790 | { |
853 | struct pn544_hci_info *info; | 791 | struct pn544_hci_info *info; |
854 | struct pn544_nfc_platform_data *pdata; | ||
855 | int r = 0; | ||
856 | u32 protocols; | 792 | u32 protocols; |
857 | struct nfc_hci_init_data init_data; | 793 | struct nfc_hci_init_data init_data; |
858 | 794 | int r; | |
859 | dev_dbg(&client->dev, "%s\n", __func__); | ||
860 | dev_dbg(&client->dev, "IRQ: %d\n", client->irq); | ||
861 | |||
862 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
863 | dev_err(&client->dev, "Need I2C_FUNC_I2C\n"); | ||
864 | return -ENODEV; | ||
865 | } | ||
866 | 795 | ||
867 | info = kzalloc(sizeof(struct pn544_hci_info), GFP_KERNEL); | 796 | info = kzalloc(sizeof(struct pn544_hci_info), GFP_KERNEL); |
868 | if (!info) { | 797 | if (!info) { |
869 | dev_err(&client->dev, | 798 | pr_err("Cannot allocate memory for pn544_hci_info.\n"); |
870 | "Cannot allocate memory for pn544_hci_info.\n"); | ||
871 | r = -ENOMEM; | 799 | r = -ENOMEM; |
872 | goto err_info_alloc; | 800 | goto err_info_alloc; |
873 | } | 801 | } |
874 | 802 | ||
875 | info->i2c_dev = client; | 803 | info->phy_ops = phy_ops; |
804 | info->phy_id = phy_id; | ||
876 | info->state = PN544_ST_COLD; | 805 | info->state = PN544_ST_COLD; |
877 | mutex_init(&info->info_lock); | 806 | mutex_init(&info->info_lock); |
878 | i2c_set_clientdata(client, info); | ||
879 | |||
880 | pdata = client->dev.platform_data; | ||
881 | if (pdata == NULL) { | ||
882 | dev_err(&client->dev, "No platform data\n"); | ||
883 | r = -EINVAL; | ||
884 | goto err_pdata; | ||
885 | } | ||
886 | |||
887 | if (pdata->request_resources == NULL) { | ||
888 | dev_err(&client->dev, "request_resources() missing\n"); | ||
889 | r = -EINVAL; | ||
890 | goto err_pdata; | ||
891 | } | ||
892 | |||
893 | r = pdata->request_resources(client); | ||
894 | if (r) { | ||
895 | dev_err(&client->dev, "Cannot get platform resources\n"); | ||
896 | goto err_pdata; | ||
897 | } | ||
898 | |||
899 | info->gpio_en = pdata->get_gpio(NFC_GPIO_ENABLE); | ||
900 | info->gpio_fw = pdata->get_gpio(NFC_GPIO_FW_RESET); | ||
901 | info->gpio_irq = pdata->get_gpio(NFC_GPIO_IRQ); | ||
902 | |||
903 | pn544_hci_platform_init(info); | ||
904 | |||
905 | r = request_threaded_irq(client->irq, NULL, pn544_hci_irq_thread_fn, | ||
906 | IRQF_TRIGGER_RISING | IRQF_ONESHOT, | ||
907 | PN544_HCI_DRIVER_NAME, info); | ||
908 | if (r < 0) { | ||
909 | dev_err(&client->dev, "Unable to register IRQ handler\n"); | ||
910 | goto err_rti; | ||
911 | } | ||
912 | 807 | ||
913 | init_data.gate_count = ARRAY_SIZE(pn544_gates); | 808 | init_data.gate_count = ARRAY_SIZE(pn544_gates); |
914 | 809 | ||
@@ -928,13 +823,11 @@ static int __devinit pn544_hci_probe(struct i2c_client *client, | |||
928 | NFC_PROTO_NFC_DEP_MASK; | 823 | NFC_PROTO_NFC_DEP_MASK; |
929 | 824 | ||
930 | info->hdev = nfc_hci_allocate_device(&pn544_hci_ops, &init_data, | 825 | info->hdev = nfc_hci_allocate_device(&pn544_hci_ops, &init_data, |
931 | protocols, LLC_SHDLC_NAME, | 826 | protocols, llc_name, |
932 | PN544_FRAME_HEADROOM + | 827 | phy_headroom + PN544_CMDS_HEADROOM, |
933 | PN544_CMDS_HEADROOM, | 828 | phy_tailroom, phy_payload); |
934 | PN544_FRAME_TAILROOM, | ||
935 | PN544_HCI_LLC_MAX_PAYLOAD); | ||
936 | if (!info->hdev) { | 829 | if (!info->hdev) { |
937 | dev_err(&client->dev, "Cannot allocate nfc hdev.\n"); | 830 | pr_err("Cannot allocate nfc hdev.\n"); |
938 | r = -ENOMEM; | 831 | r = -ENOMEM; |
939 | goto err_alloc_hdev; | 832 | goto err_alloc_hdev; |
940 | } | 833 | } |
@@ -945,79 +838,25 @@ static int __devinit pn544_hci_probe(struct i2c_client *client, | |||
945 | if (r) | 838 | if (r) |
946 | goto err_regdev; | 839 | goto err_regdev; |
947 | 840 | ||
841 | *hdev = info->hdev; | ||
842 | |||
948 | return 0; | 843 | return 0; |
949 | 844 | ||
950 | err_regdev: | 845 | err_regdev: |
951 | nfc_hci_free_device(info->hdev); | 846 | nfc_hci_free_device(info->hdev); |
952 | 847 | ||
953 | err_alloc_hdev: | 848 | err_alloc_hdev: |
954 | free_irq(client->irq, info); | ||
955 | |||
956 | err_rti: | ||
957 | if (pdata->free_resources != NULL) | ||
958 | pdata->free_resources(); | ||
959 | |||
960 | err_pdata: | ||
961 | kfree(info); | 849 | kfree(info); |
962 | 850 | ||
963 | err_info_alloc: | 851 | err_info_alloc: |
964 | return r; | 852 | return r; |
965 | } | 853 | } |
966 | 854 | ||
967 | static __devexit int pn544_hci_remove(struct i2c_client *client) | 855 | void pn544_hci_remove(struct nfc_hci_dev *hdev) |
968 | { | 856 | { |
969 | struct pn544_hci_info *info = i2c_get_clientdata(client); | 857 | struct pn544_hci_info *info = nfc_hci_get_clientdata(hdev); |
970 | struct pn544_nfc_platform_data *pdata = client->dev.platform_data; | ||
971 | |||
972 | dev_dbg(&client->dev, "%s\n", __func__); | ||
973 | |||
974 | nfc_hci_free_device(info->hdev); | ||
975 | |||
976 | if (info->state != PN544_ST_COLD) { | ||
977 | if (pdata->disable) | ||
978 | pdata->disable(); | ||
979 | } | ||
980 | |||
981 | free_irq(client->irq, info); | ||
982 | if (pdata->free_resources) | ||
983 | pdata->free_resources(); | ||
984 | 858 | ||
859 | nfc_hci_unregister_device(hdev); | ||
860 | nfc_hci_free_device(hdev); | ||
985 | kfree(info); | 861 | kfree(info); |
986 | |||
987 | return 0; | ||
988 | } | 862 | } |
989 | |||
990 | static struct i2c_driver pn544_hci_driver = { | ||
991 | .driver = { | ||
992 | .name = PN544_HCI_DRIVER_NAME, | ||
993 | }, | ||
994 | .probe = pn544_hci_probe, | ||
995 | .id_table = pn544_hci_id_table, | ||
996 | .remove = __devexit_p(pn544_hci_remove), | ||
997 | }; | ||
998 | |||
999 | static int __init pn544_hci_init(void) | ||
1000 | { | ||
1001 | int r; | ||
1002 | |||
1003 | pr_debug(DRIVER_DESC ": %s\n", __func__); | ||
1004 | |||
1005 | r = i2c_add_driver(&pn544_hci_driver); | ||
1006 | if (r) { | ||
1007 | pr_err(PN544_HCI_DRIVER_NAME ": driver registration failed\n"); | ||
1008 | return r; | ||
1009 | } | ||
1010 | |||
1011 | return 0; | ||
1012 | } | ||
1013 | |||
1014 | static void __exit pn544_hci_exit(void) | ||
1015 | { | ||
1016 | i2c_del_driver(&pn544_hci_driver); | ||
1017 | } | ||
1018 | |||
1019 | module_init(pn544_hci_init); | ||
1020 | module_exit(pn544_hci_exit); | ||
1021 | |||
1022 | MODULE_LICENSE("GPL"); | ||
1023 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
diff --git a/drivers/nfc/pn544/pn544.h b/drivers/nfc/pn544/pn544.h new file mode 100644 index 000000000000..f47c6454914b --- /dev/null +++ b/drivers/nfc/pn544/pn544.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2011 - 2012 Intel Corporation. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the | ||
16 | * Free Software Foundation, Inc., | ||
17 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | */ | ||
19 | |||
20 | #ifndef __LOCAL_PN544_H_ | ||
21 | #define __LOCAL_PN544_H_ | ||
22 | |||
23 | #include <net/nfc/hci.h> | ||
24 | |||
25 | #define DRIVER_DESC "HCI NFC driver for PN544" | ||
26 | |||
27 | int pn544_hci_probe(void *phy_id, struct nfc_phy_ops *phy_ops, char *llc_name, | ||
28 | int phy_headroom, int phy_tailroom, int phy_payload, | ||
29 | struct nfc_hci_dev **hdev); | ||
30 | void pn544_hci_remove(struct nfc_hci_dev *hdev); | ||
31 | |||
32 | #endif /* __LOCAL_PN544_H_ */ | ||
diff --git a/drivers/ssb/b43_pci_bridge.c b/drivers/ssb/b43_pci_bridge.c index 266aa1648a02..19396dc4ee47 100644 --- a/drivers/ssb/b43_pci_bridge.c +++ b/drivers/ssb/b43_pci_bridge.c | |||
@@ -37,6 +37,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = { | |||
37 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4329) }, | 37 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4329) }, |
38 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) }, | 38 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432b) }, |
39 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432c) }, | 39 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x432c) }, |
40 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4350) }, | ||
40 | { 0, }, | 41 | { 0, }, |
41 | }; | 42 | }; |
42 | MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl); | 43 | MODULE_DEVICE_TABLE(pci, b43_pci_bridge_tbl); |
diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c index b58fef780ea0..d7d58044b4bc 100644 --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c | |||
@@ -346,6 +346,8 @@ static void ssb_pmu_pll_init(struct ssb_chipcommon *cc) | |||
346 | chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, 0x380005C0); | 346 | chipco_write32(cc, SSB_CHIPCO_PLLCTL_DATA, 0x380005C0); |
347 | } | 347 | } |
348 | break; | 348 | break; |
349 | case 43222: | ||
350 | break; | ||
349 | default: | 351 | default: |
350 | ssb_printk(KERN_ERR PFX | 352 | ssb_printk(KERN_ERR PFX |
351 | "ERROR: PLL init unknown for device %04X\n", | 353 | "ERROR: PLL init unknown for device %04X\n", |
@@ -434,6 +436,7 @@ static void ssb_pmu_resources_init(struct ssb_chipcommon *cc) | |||
434 | min_msk = 0xCBB; | 436 | min_msk = 0xCBB; |
435 | break; | 437 | break; |
436 | case 0x4322: | 438 | case 0x4322: |
439 | case 43222: | ||
437 | /* We keep the default settings: | 440 | /* We keep the default settings: |
438 | * min_msk = 0xCBB | 441 | * min_msk = 0xCBB |
439 | * max_msk = 0x7FFFF | 442 | * max_msk = 0x7FFFF |
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c index c6250867a95d..b918ba922306 100644 --- a/drivers/ssb/driver_mipscore.c +++ b/drivers/ssb/driver_mipscore.c | |||
@@ -192,9 +192,10 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore) | |||
192 | 192 | ||
193 | /* When there is no chipcommon on the bus there is 4MB flash */ | 193 | /* When there is no chipcommon on the bus there is 4MB flash */ |
194 | if (!bus->chipco.dev) { | 194 | if (!bus->chipco.dev) { |
195 | mcore->flash_buswidth = 2; | 195 | mcore->pflash.present = true; |
196 | mcore->flash_window = SSB_FLASH1; | 196 | mcore->pflash.buswidth = 2; |
197 | mcore->flash_window_size = SSB_FLASH1_SZ; | 197 | mcore->pflash.window = SSB_FLASH1; |
198 | mcore->pflash.window_size = SSB_FLASH1_SZ; | ||
198 | return; | 199 | return; |
199 | } | 200 | } |
200 | 201 | ||
@@ -206,13 +207,14 @@ static void ssb_mips_flash_detect(struct ssb_mipscore *mcore) | |||
206 | break; | 207 | break; |
207 | case SSB_CHIPCO_FLASHT_PARA: | 208 | case SSB_CHIPCO_FLASHT_PARA: |
208 | pr_debug("Found parallel flash\n"); | 209 | pr_debug("Found parallel flash\n"); |
209 | mcore->flash_window = SSB_FLASH2; | 210 | mcore->pflash.present = true; |
210 | mcore->flash_window_size = SSB_FLASH2_SZ; | 211 | mcore->pflash.window = SSB_FLASH2; |
212 | mcore->pflash.window_size = SSB_FLASH2_SZ; | ||
211 | if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG) | 213 | if ((ssb_read32(bus->chipco.dev, SSB_CHIPCO_FLASH_CFG) |
212 | & SSB_CHIPCO_CFG_DS16) == 0) | 214 | & SSB_CHIPCO_CFG_DS16) == 0) |
213 | mcore->flash_buswidth = 1; | 215 | mcore->pflash.buswidth = 1; |
214 | else | 216 | else |
215 | mcore->flash_buswidth = 2; | 217 | mcore->pflash.buswidth = 2; |
216 | break; | 218 | break; |
217 | } | 219 | } |
218 | } | 220 | } |
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index 4180eb78d575..fd15d9829705 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h | |||
@@ -251,7 +251,7 @@ struct bcma_bus { | |||
251 | u8 num; | 251 | u8 num; |
252 | 252 | ||
253 | struct bcma_drv_cc drv_cc; | 253 | struct bcma_drv_cc drv_cc; |
254 | struct bcma_drv_pci drv_pci; | 254 | struct bcma_drv_pci drv_pci[2]; |
255 | struct bcma_drv_mips drv_mips; | 255 | struct bcma_drv_mips drv_mips; |
256 | struct bcma_drv_gmac_cmn drv_gmac_cmn; | 256 | struct bcma_drv_gmac_cmn drv_gmac_cmn; |
257 | 257 | ||
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h index 1cf1749440ac..145f3c56227f 100644 --- a/include/linux/bcma/bcma_driver_chipcommon.h +++ b/include/linux/bcma/bcma_driver_chipcommon.h | |||
@@ -510,6 +510,7 @@ struct bcma_chipcommon_pmu { | |||
510 | 510 | ||
511 | #ifdef CONFIG_BCMA_DRIVER_MIPS | 511 | #ifdef CONFIG_BCMA_DRIVER_MIPS |
512 | struct bcma_pflash { | 512 | struct bcma_pflash { |
513 | bool present; | ||
513 | u8 buswidth; | 514 | u8 buswidth; |
514 | u32 window; | 515 | u32 window; |
515 | u32 window_size; | 516 | u32 window_size; |
@@ -532,6 +533,7 @@ struct mtd_info; | |||
532 | 533 | ||
533 | struct bcma_nflash { | 534 | struct bcma_nflash { |
534 | bool present; | 535 | bool present; |
536 | bool boot; /* This is the flash the SoC boots from */ | ||
535 | 537 | ||
536 | struct mtd_info *mtd; | 538 | struct mtd_info *mtd; |
537 | }; | 539 | }; |
@@ -552,6 +554,7 @@ struct bcma_drv_cc { | |||
552 | u32 capabilities; | 554 | u32 capabilities; |
553 | u32 capabilities_ext; | 555 | u32 capabilities_ext; |
554 | u8 setup_done:1; | 556 | u8 setup_done:1; |
557 | u8 early_setup_done:1; | ||
555 | /* Fast Powerup Delay constant */ | 558 | /* Fast Powerup Delay constant */ |
556 | u16 fast_pwrup_delay; | 559 | u16 fast_pwrup_delay; |
557 | struct bcma_chipcommon_pmu pmu; | 560 | struct bcma_chipcommon_pmu pmu; |
@@ -583,6 +586,7 @@ struct bcma_drv_cc { | |||
583 | bcma_cc_write32(cc, offset, (bcma_cc_read32(cc, offset) & (mask)) | (set)) | 586 | bcma_cc_write32(cc, offset, (bcma_cc_read32(cc, offset) & (mask)) | (set)) |
584 | 587 | ||
585 | extern void bcma_core_chipcommon_init(struct bcma_drv_cc *cc); | 588 | extern void bcma_core_chipcommon_init(struct bcma_drv_cc *cc); |
589 | extern void bcma_core_chipcommon_early_init(struct bcma_drv_cc *cc); | ||
586 | 590 | ||
587 | extern void bcma_chipco_suspend(struct bcma_drv_cc *cc); | 591 | extern void bcma_chipco_suspend(struct bcma_drv_cc *cc); |
588 | extern void bcma_chipco_resume(struct bcma_drv_cc *cc); | 592 | extern void bcma_chipco_resume(struct bcma_drv_cc *cc); |
@@ -606,6 +610,7 @@ u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value); | |||
606 | 610 | ||
607 | /* PMU support */ | 611 | /* PMU support */ |
608 | extern void bcma_pmu_init(struct bcma_drv_cc *cc); | 612 | extern void bcma_pmu_init(struct bcma_drv_cc *cc); |
613 | extern void bcma_pmu_early_init(struct bcma_drv_cc *cc); | ||
609 | 614 | ||
610 | extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, | 615 | extern void bcma_chipco_pll_write(struct bcma_drv_cc *cc, u32 offset, |
611 | u32 value); | 616 | u32 value); |
diff --git a/include/linux/bcma/bcma_driver_mips.h b/include/linux/bcma/bcma_driver_mips.h index c0043645cdcb..0baf8a56b794 100644 --- a/include/linux/bcma/bcma_driver_mips.h +++ b/include/linux/bcma/bcma_driver_mips.h | |||
@@ -35,13 +35,16 @@ struct bcma_device; | |||
35 | struct bcma_drv_mips { | 35 | struct bcma_drv_mips { |
36 | struct bcma_device *core; | 36 | struct bcma_device *core; |
37 | u8 setup_done:1; | 37 | u8 setup_done:1; |
38 | u8 early_setup_done:1; | ||
38 | unsigned int assigned_irqs; | 39 | unsigned int assigned_irqs; |
39 | }; | 40 | }; |
40 | 41 | ||
41 | #ifdef CONFIG_BCMA_DRIVER_MIPS | 42 | #ifdef CONFIG_BCMA_DRIVER_MIPS |
42 | extern void bcma_core_mips_init(struct bcma_drv_mips *mcore); | 43 | extern void bcma_core_mips_init(struct bcma_drv_mips *mcore); |
44 | extern void bcma_core_mips_early_init(struct bcma_drv_mips *mcore); | ||
43 | #else | 45 | #else |
44 | static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { } | 46 | static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { } |
47 | static inline void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) { } | ||
45 | #endif | 48 | #endif |
46 | 49 | ||
47 | extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore); | 50 | extern u32 bcma_cpu_clock(struct bcma_drv_mips *mcore); |
diff --git a/include/linux/bcma/bcma_regs.h b/include/linux/bcma/bcma_regs.h index 6c9cb93ae3de..7e8104bb7a7e 100644 --- a/include/linux/bcma/bcma_regs.h +++ b/include/linux/bcma/bcma_regs.h | |||
@@ -85,6 +85,9 @@ | |||
85 | * (2 ZettaBytes), high 32 bits | 85 | * (2 ZettaBytes), high 32 bits |
86 | */ | 86 | */ |
87 | 87 | ||
88 | #define BCMA_SFLASH 0x1c000000 | 88 | #define BCMA_SOC_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */ |
89 | #define BCMA_SOC_FLASH1_SZ 0x00400000 /* MIPS Size of Flash Region 1 */ | ||
90 | #define BCMA_SOC_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */ | ||
91 | #define BCMA_SOC_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */ | ||
89 | 92 | ||
90 | #endif /* LINUX_BCMA_REGS_H_ */ | 93 | #endif /* LINUX_BCMA_REGS_H_ */ |
diff --git a/include/linux/ssb/ssb_driver_mips.h b/include/linux/ssb/ssb_driver_mips.h index 5f44e9740cd2..07a9c7a2e088 100644 --- a/include/linux/ssb/ssb_driver_mips.h +++ b/include/linux/ssb/ssb_driver_mips.h | |||
@@ -13,6 +13,12 @@ struct ssb_serial_port { | |||
13 | unsigned int reg_shift; | 13 | unsigned int reg_shift; |
14 | }; | 14 | }; |
15 | 15 | ||
16 | struct ssb_pflash { | ||
17 | bool present; | ||
18 | u8 buswidth; | ||
19 | u32 window; | ||
20 | u32 window_size; | ||
21 | }; | ||
16 | 22 | ||
17 | struct ssb_mipscore { | 23 | struct ssb_mipscore { |
18 | struct ssb_device *dev; | 24 | struct ssb_device *dev; |
@@ -20,9 +26,7 @@ struct ssb_mipscore { | |||
20 | int nr_serial_ports; | 26 | int nr_serial_ports; |
21 | struct ssb_serial_port serial_ports[4]; | 27 | struct ssb_serial_port serial_ports[4]; |
22 | 28 | ||
23 | u8 flash_buswidth; | 29 | struct ssb_pflash pflash; |
24 | u32 flash_window; | ||
25 | u32 flash_window_size; | ||
26 | }; | 30 | }; |
27 | 31 | ||
28 | extern void ssb_mipscore_init(struct ssb_mipscore *mcore); | 32 | extern void ssb_mipscore_init(struct ssb_mipscore *mcore); |
diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h index 6a76e0a0705e..42f21766c538 100644 --- a/include/net/bluetooth/a2mp.h +++ b/include/net/bluetooth/a2mp.h | |||
@@ -19,13 +19,25 @@ | |||
19 | 19 | ||
20 | #define A2MP_FEAT_EXT 0x8000 | 20 | #define A2MP_FEAT_EXT 0x8000 |
21 | 21 | ||
22 | enum amp_mgr_state { | ||
23 | READ_LOC_AMP_INFO, | ||
24 | READ_LOC_AMP_ASSOC, | ||
25 | READ_LOC_AMP_ASSOC_FINAL, | ||
26 | }; | ||
27 | |||
22 | struct amp_mgr { | 28 | struct amp_mgr { |
29 | struct list_head list; | ||
23 | struct l2cap_conn *l2cap_conn; | 30 | struct l2cap_conn *l2cap_conn; |
24 | struct l2cap_chan *a2mp_chan; | 31 | struct l2cap_chan *a2mp_chan; |
32 | struct l2cap_chan *bredr_chan; | ||
25 | struct kref kref; | 33 | struct kref kref; |
26 | __u8 ident; | 34 | __u8 ident; |
27 | __u8 handle; | 35 | __u8 handle; |
36 | enum amp_mgr_state state; | ||
28 | unsigned long flags; | 37 | unsigned long flags; |
38 | |||
39 | struct list_head amp_ctrls; | ||
40 | struct mutex amp_ctrls_lock; | ||
29 | }; | 41 | }; |
30 | 42 | ||
31 | struct a2mp_cmd { | 43 | struct a2mp_cmd { |
@@ -118,9 +130,19 @@ struct a2mp_physlink_rsp { | |||
118 | #define A2MP_STATUS_PHYS_LINK_EXISTS 0x05 | 130 | #define A2MP_STATUS_PHYS_LINK_EXISTS 0x05 |
119 | #define A2MP_STATUS_SECURITY_VIOLATION 0x06 | 131 | #define A2MP_STATUS_SECURITY_VIOLATION 0x06 |
120 | 132 | ||
121 | void amp_mgr_get(struct amp_mgr *mgr); | 133 | extern struct list_head amp_mgr_list; |
134 | extern struct mutex amp_mgr_list_lock; | ||
135 | |||
136 | struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr); | ||
122 | int amp_mgr_put(struct amp_mgr *mgr); | 137 | int amp_mgr_put(struct amp_mgr *mgr); |
138 | u8 __next_ident(struct amp_mgr *mgr); | ||
123 | struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, | 139 | struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, |
124 | struct sk_buff *skb); | 140 | struct sk_buff *skb); |
141 | struct amp_mgr *amp_mgr_lookup_by_state(u8 state); | ||
142 | void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data); | ||
143 | void a2mp_discover_amp(struct l2cap_chan *chan); | ||
144 | void a2mp_send_getinfo_rsp(struct hci_dev *hdev); | ||
145 | void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status); | ||
146 | void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status); | ||
125 | 147 | ||
126 | #endif /* __A2MP_H */ | 148 | #endif /* __A2MP_H */ |
diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h new file mode 100644 index 000000000000..2e7c79ea0463 --- /dev/null +++ b/include/net/bluetooth/amp.h | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | Copyright (c) 2011,2012 Intel Corp. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License version 2 and | ||
6 | only version 2 as published by the Free Software Foundation. | ||
7 | |||
8 | This program is distributed in the hope that it will be useful, | ||
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #ifndef __AMP_H | ||
15 | #define __AMP_H | ||
16 | |||
17 | struct amp_ctrl { | ||
18 | struct list_head list; | ||
19 | struct kref kref; | ||
20 | __u8 id; | ||
21 | __u16 assoc_len_so_far; | ||
22 | __u16 assoc_rem_len; | ||
23 | __u16 assoc_len; | ||
24 | __u8 *assoc; | ||
25 | }; | ||
26 | |||
27 | int amp_ctrl_put(struct amp_ctrl *ctrl); | ||
28 | void amp_ctrl_get(struct amp_ctrl *ctrl); | ||
29 | struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id); | ||
30 | struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id); | ||
31 | void amp_ctrl_list_flush(struct amp_mgr *mgr); | ||
32 | |||
33 | struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, | ||
34 | u8 remote_id, bool out); | ||
35 | |||
36 | int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type); | ||
37 | |||
38 | void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr); | ||
39 | void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle); | ||
40 | void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr); | ||
41 | void amp_read_loc_assoc_final_data(struct hci_dev *hdev, | ||
42 | struct hci_conn *hcon); | ||
43 | void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, | ||
44 | struct hci_conn *hcon); | ||
45 | void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, | ||
46 | struct hci_conn *hcon); | ||
47 | void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle); | ||
48 | void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle); | ||
49 | |||
50 | #endif /* __AMP_H */ | ||
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index ede036977ae8..2554b3f5222a 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h | |||
@@ -180,7 +180,6 @@ static inline void bacpy(bdaddr_t *dst, bdaddr_t *src) | |||
180 | } | 180 | } |
181 | 181 | ||
182 | void baswap(bdaddr_t *dst, bdaddr_t *src); | 182 | void baswap(bdaddr_t *dst, bdaddr_t *src); |
183 | char *batostr(bdaddr_t *ba); | ||
184 | 183 | ||
185 | /* Common socket structures and functions */ | 184 | /* Common socket structures and functions */ |
186 | 185 | ||
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 76b2b6bdcf36..88cbbda61027 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h | |||
@@ -33,6 +33,8 @@ | |||
33 | #define HCI_LINK_KEY_SIZE 16 | 33 | #define HCI_LINK_KEY_SIZE 16 |
34 | #define HCI_AMP_LINK_KEY_SIZE (2 * HCI_LINK_KEY_SIZE) | 34 | #define HCI_AMP_LINK_KEY_SIZE (2 * HCI_LINK_KEY_SIZE) |
35 | 35 | ||
36 | #define HCI_MAX_AMP_ASSOC_SIZE 672 | ||
37 | |||
36 | /* HCI dev events */ | 38 | /* HCI dev events */ |
37 | #define HCI_DEV_REG 1 | 39 | #define HCI_DEV_REG 1 |
38 | #define HCI_DEV_UNREG 2 | 40 | #define HCI_DEV_UNREG 2 |
@@ -196,6 +198,7 @@ enum { | |||
196 | #define ACL_START_NO_FLUSH 0x00 | 198 | #define ACL_START_NO_FLUSH 0x00 |
197 | #define ACL_CONT 0x01 | 199 | #define ACL_CONT 0x01 |
198 | #define ACL_START 0x02 | 200 | #define ACL_START 0x02 |
201 | #define ACL_COMPLETE 0x03 | ||
199 | #define ACL_ACTIVE_BCAST 0x04 | 202 | #define ACL_ACTIVE_BCAST 0x04 |
200 | #define ACL_PICO_BCAST 0x08 | 203 | #define ACL_PICO_BCAST 0x08 |
201 | 204 | ||
@@ -205,6 +208,7 @@ enum { | |||
205 | #define ESCO_LINK 0x02 | 208 | #define ESCO_LINK 0x02 |
206 | /* Low Energy links do not have defined link type. Use invented one */ | 209 | /* Low Energy links do not have defined link type. Use invented one */ |
207 | #define LE_LINK 0x80 | 210 | #define LE_LINK 0x80 |
211 | #define AMP_LINK 0x81 | ||
208 | 212 | ||
209 | /* LMP features */ | 213 | /* LMP features */ |
210 | #define LMP_3SLOT 0x01 | 214 | #define LMP_3SLOT 0x01 |
@@ -556,12 +560,46 @@ struct hci_cp_accept_phy_link { | |||
556 | __u8 key[HCI_AMP_LINK_KEY_SIZE]; | 560 | __u8 key[HCI_AMP_LINK_KEY_SIZE]; |
557 | } __packed; | 561 | } __packed; |
558 | 562 | ||
559 | #define HCI_OP_DISCONN_PHY_LINK 0x0437 | 563 | #define HCI_OP_DISCONN_PHY_LINK 0x0437 |
560 | struct hci_cp_disconn_phy_link { | 564 | struct hci_cp_disconn_phy_link { |
561 | __u8 phy_handle; | 565 | __u8 phy_handle; |
562 | __u8 reason; | 566 | __u8 reason; |
563 | } __packed; | 567 | } __packed; |
564 | 568 | ||
569 | struct ext_flow_spec { | ||
570 | __u8 id; | ||
571 | __u8 stype; | ||
572 | __le16 msdu; | ||
573 | __le32 sdu_itime; | ||
574 | __le32 acc_lat; | ||
575 | __le32 flush_to; | ||
576 | } __packed; | ||
577 | |||
578 | #define HCI_OP_CREATE_LOGICAL_LINK 0x0438 | ||
579 | #define HCI_OP_ACCEPT_LOGICAL_LINK 0x0439 | ||
580 | struct hci_cp_create_accept_logical_link { | ||
581 | __u8 phy_handle; | ||
582 | struct ext_flow_spec tx_flow_spec; | ||
583 | struct ext_flow_spec rx_flow_spec; | ||
584 | } __packed; | ||
585 | |||
586 | #define HCI_OP_DISCONN_LOGICAL_LINK 0x043a | ||
587 | struct hci_cp_disconn_logical_link { | ||
588 | __le16 log_handle; | ||
589 | } __packed; | ||
590 | |||
591 | #define HCI_OP_LOGICAL_LINK_CANCEL 0x043b | ||
592 | struct hci_cp_logical_link_cancel { | ||
593 | __u8 phy_handle; | ||
594 | __u8 flow_spec_id; | ||
595 | } __packed; | ||
596 | |||
597 | struct hci_rp_logical_link_cancel { | ||
598 | __u8 status; | ||
599 | __u8 phy_handle; | ||
600 | __u8 flow_spec_id; | ||
601 | } __packed; | ||
602 | |||
565 | #define HCI_OP_SNIFF_MODE 0x0803 | 603 | #define HCI_OP_SNIFF_MODE 0x0803 |
566 | struct hci_cp_sniff_mode { | 604 | struct hci_cp_sniff_mode { |
567 | __le16 handle; | 605 | __le16 handle; |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index e7d454609881..9fe8e2dec870 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -73,6 +73,7 @@ struct discovery_state { | |||
73 | struct hci_conn_hash { | 73 | struct hci_conn_hash { |
74 | struct list_head list; | 74 | struct list_head list; |
75 | unsigned int acl_num; | 75 | unsigned int acl_num; |
76 | unsigned int amp_num; | ||
76 | unsigned int sco_num; | 77 | unsigned int sco_num; |
77 | unsigned int le_num; | 78 | unsigned int le_num; |
78 | }; | 79 | }; |
@@ -124,6 +125,14 @@ struct le_scan_params { | |||
124 | 125 | ||
125 | #define HCI_MAX_SHORT_NAME_LENGTH 10 | 126 | #define HCI_MAX_SHORT_NAME_LENGTH 10 |
126 | 127 | ||
128 | struct amp_assoc { | ||
129 | __u16 len; | ||
130 | __u16 offset; | ||
131 | __u16 rem_len; | ||
132 | __u16 len_so_far; | ||
133 | __u8 data[HCI_MAX_AMP_ASSOC_SIZE]; | ||
134 | }; | ||
135 | |||
127 | #define NUM_REASSEMBLY 4 | 136 | #define NUM_REASSEMBLY 4 |
128 | struct hci_dev { | 137 | struct hci_dev { |
129 | struct list_head list; | 138 | struct list_head list; |
@@ -177,6 +186,8 @@ struct hci_dev { | |||
177 | __u32 amp_max_flush_to; | 186 | __u32 amp_max_flush_to; |
178 | __u32 amp_be_flush_to; | 187 | __u32 amp_be_flush_to; |
179 | 188 | ||
189 | struct amp_assoc loc_assoc; | ||
190 | |||
180 | __u8 flow_ctl_mode; | 191 | __u8 flow_ctl_mode; |
181 | 192 | ||
182 | unsigned int auto_accept_delay; | 193 | unsigned int auto_accept_delay; |
@@ -252,8 +263,6 @@ struct hci_dev { | |||
252 | 263 | ||
253 | struct sk_buff_head driver_init; | 264 | struct sk_buff_head driver_init; |
254 | 265 | ||
255 | void *core_data; | ||
256 | |||
257 | atomic_t promisc; | 266 | atomic_t promisc; |
258 | 267 | ||
259 | struct dentry *debugfs; | 268 | struct dentry *debugfs; |
@@ -277,6 +286,8 @@ struct hci_dev { | |||
277 | int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg); | 286 | int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg); |
278 | }; | 287 | }; |
279 | 288 | ||
289 | #define HCI_PHY_HANDLE(handle) (handle & 0xff) | ||
290 | |||
280 | struct hci_conn { | 291 | struct hci_conn { |
281 | struct list_head list; | 292 | struct list_head list; |
282 | 293 | ||
@@ -310,6 +321,7 @@ struct hci_conn { | |||
310 | 321 | ||
311 | __u8 remote_cap; | 322 | __u8 remote_cap; |
312 | __u8 remote_auth; | 323 | __u8 remote_auth; |
324 | __u8 remote_id; | ||
313 | bool flush_key; | 325 | bool flush_key; |
314 | 326 | ||
315 | unsigned int sent; | 327 | unsigned int sent; |
@@ -339,7 +351,7 @@ struct hci_conn { | |||
339 | 351 | ||
340 | struct hci_chan { | 352 | struct hci_chan { |
341 | struct list_head list; | 353 | struct list_head list; |
342 | 354 | __u16 handle; | |
343 | struct hci_conn *conn; | 355 | struct hci_conn *conn; |
344 | struct sk_buff_head data_q; | 356 | struct sk_buff_head data_q; |
345 | unsigned int sent; | 357 | unsigned int sent; |
@@ -438,6 +450,9 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) | |||
438 | case ACL_LINK: | 450 | case ACL_LINK: |
439 | h->acl_num++; | 451 | h->acl_num++; |
440 | break; | 452 | break; |
453 | case AMP_LINK: | ||
454 | h->amp_num++; | ||
455 | break; | ||
441 | case LE_LINK: | 456 | case LE_LINK: |
442 | h->le_num++; | 457 | h->le_num++; |
443 | break; | 458 | break; |
@@ -459,6 +474,9 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) | |||
459 | case ACL_LINK: | 474 | case ACL_LINK: |
460 | h->acl_num--; | 475 | h->acl_num--; |
461 | break; | 476 | break; |
477 | case AMP_LINK: | ||
478 | h->amp_num--; | ||
479 | break; | ||
462 | case LE_LINK: | 480 | case LE_LINK: |
463 | h->le_num--; | 481 | h->le_num--; |
464 | break; | 482 | break; |
@@ -475,6 +493,8 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type) | |||
475 | switch (type) { | 493 | switch (type) { |
476 | case ACL_LINK: | 494 | case ACL_LINK: |
477 | return h->acl_num; | 495 | return h->acl_num; |
496 | case AMP_LINK: | ||
497 | return h->amp_num; | ||
478 | case LE_LINK: | 498 | case LE_LINK: |
479 | return h->le_num; | 499 | return h->le_num; |
480 | case SCO_LINK: | 500 | case SCO_LINK: |
@@ -556,6 +576,7 @@ void hci_conn_check_pending(struct hci_dev *hdev); | |||
556 | struct hci_chan *hci_chan_create(struct hci_conn *conn); | 576 | struct hci_chan *hci_chan_create(struct hci_conn *conn); |
557 | void hci_chan_del(struct hci_chan *chan); | 577 | void hci_chan_del(struct hci_chan *chan); |
558 | void hci_chan_list_flush(struct hci_conn *conn); | 578 | void hci_chan_list_flush(struct hci_conn *conn); |
579 | struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle); | ||
559 | 580 | ||
560 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, | 581 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, |
561 | __u8 dst_type, __u8 sec_level, __u8 auth_type); | 582 | __u8 dst_type, __u8 sec_level, __u8 auth_type); |
@@ -584,7 +605,10 @@ static inline void hci_conn_put(struct hci_conn *conn) | |||
584 | 605 | ||
585 | if (atomic_dec_and_test(&conn->refcnt)) { | 606 | if (atomic_dec_and_test(&conn->refcnt)) { |
586 | unsigned long timeo; | 607 | unsigned long timeo; |
587 | if (conn->type == ACL_LINK || conn->type == LE_LINK) { | 608 | |
609 | switch (conn->type) { | ||
610 | case ACL_LINK: | ||
611 | case LE_LINK: | ||
588 | del_timer(&conn->idle_timer); | 612 | del_timer(&conn->idle_timer); |
589 | if (conn->state == BT_CONNECTED) { | 613 | if (conn->state == BT_CONNECTED) { |
590 | timeo = conn->disc_timeout; | 614 | timeo = conn->disc_timeout; |
@@ -593,12 +617,20 @@ static inline void hci_conn_put(struct hci_conn *conn) | |||
593 | } else { | 617 | } else { |
594 | timeo = msecs_to_jiffies(10); | 618 | timeo = msecs_to_jiffies(10); |
595 | } | 619 | } |
596 | } else { | 620 | break; |
621 | |||
622 | case AMP_LINK: | ||
623 | timeo = conn->disc_timeout; | ||
624 | break; | ||
625 | |||
626 | default: | ||
597 | timeo = msecs_to_jiffies(10); | 627 | timeo = msecs_to_jiffies(10); |
628 | break; | ||
598 | } | 629 | } |
630 | |||
599 | cancel_delayed_work(&conn->disc_work); | 631 | cancel_delayed_work(&conn->disc_work); |
600 | queue_delayed_work(conn->hdev->workqueue, | 632 | queue_delayed_work(conn->hdev->workqueue, |
601 | &conn->disc_work, timeo); | 633 | &conn->disc_work, timeo); |
602 | } | 634 | } |
603 | } | 635 | } |
604 | 636 | ||
@@ -789,6 +821,10 @@ static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason) | |||
789 | sco_disconn_cfm(conn, reason); | 821 | sco_disconn_cfm(conn, reason); |
790 | break; | 822 | break; |
791 | 823 | ||
824 | /* L2CAP would be handled for BREDR chan */ | ||
825 | case AMP_LINK: | ||
826 | break; | ||
827 | |||
792 | default: | 828 | default: |
793 | BT_ERR("unknown link type %d", conn->type); | 829 | BT_ERR("unknown link type %d", conn->type); |
794 | break; | 830 | break; |
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 7ed8e356425a..6e23afdf65c1 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -32,13 +32,14 @@ | |||
32 | /* L2CAP defaults */ | 32 | /* L2CAP defaults */ |
33 | #define L2CAP_DEFAULT_MTU 672 | 33 | #define L2CAP_DEFAULT_MTU 672 |
34 | #define L2CAP_DEFAULT_MIN_MTU 48 | 34 | #define L2CAP_DEFAULT_MIN_MTU 48 |
35 | #define L2CAP_DEFAULT_FLUSH_TO 0xffff | 35 | #define L2CAP_DEFAULT_FLUSH_TO 0xFFFF |
36 | #define L2CAP_EFS_DEFAULT_FLUSH_TO 0xFFFFFFFF | ||
36 | #define L2CAP_DEFAULT_TX_WINDOW 63 | 37 | #define L2CAP_DEFAULT_TX_WINDOW 63 |
37 | #define L2CAP_DEFAULT_EXT_WINDOW 0x3FFF | 38 | #define L2CAP_DEFAULT_EXT_WINDOW 0x3FFF |
38 | #define L2CAP_DEFAULT_MAX_TX 3 | 39 | #define L2CAP_DEFAULT_MAX_TX 3 |
39 | #define L2CAP_DEFAULT_RETRANS_TO 2000 /* 2 seconds */ | 40 | #define L2CAP_DEFAULT_RETRANS_TO 2000 /* 2 seconds */ |
40 | #define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */ | 41 | #define L2CAP_DEFAULT_MONITOR_TO 12000 /* 12 seconds */ |
41 | #define L2CAP_DEFAULT_MAX_PDU_SIZE 1009 /* Sized for 3-DH5 packet */ | 42 | #define L2CAP_DEFAULT_MAX_PDU_SIZE 1492 /* Sized for AMP packet */ |
42 | #define L2CAP_DEFAULT_ACK_TO 200 | 43 | #define L2CAP_DEFAULT_ACK_TO 200 |
43 | #define L2CAP_DEFAULT_MAX_SDU_SIZE 0xFFFF | 44 | #define L2CAP_DEFAULT_MAX_SDU_SIZE 0xFFFF |
44 | #define L2CAP_DEFAULT_SDU_ITIME 0xFFFFFFFF | 45 | #define L2CAP_DEFAULT_SDU_ITIME 0xFFFFFFFF |
@@ -508,6 +509,8 @@ struct l2cap_chan { | |||
508 | __u32 remote_acc_lat; | 509 | __u32 remote_acc_lat; |
509 | __u32 remote_flush_to; | 510 | __u32 remote_flush_to; |
510 | 511 | ||
512 | __u8 ctrl_id; | ||
513 | |||
511 | struct delayed_work chan_timer; | 514 | struct delayed_work chan_timer; |
512 | struct delayed_work retrans_timer; | 515 | struct delayed_work retrans_timer; |
513 | struct delayed_work monitor_timer; | 516 | struct delayed_work monitor_timer; |
@@ -538,6 +541,7 @@ struct l2cap_ops { | |||
538 | void (*state_change) (struct l2cap_chan *chan, | 541 | void (*state_change) (struct l2cap_chan *chan, |
539 | int state); | 542 | int state); |
540 | void (*ready) (struct l2cap_chan *chan); | 543 | void (*ready) (struct l2cap_chan *chan); |
544 | void (*defer) (struct l2cap_chan *chan); | ||
541 | struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, | 545 | struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, |
542 | unsigned long len, int nb); | 546 | unsigned long len, int nb); |
543 | }; | 547 | }; |
@@ -745,6 +749,10 @@ static inline void l2cap_chan_no_ready(struct l2cap_chan *chan) | |||
745 | { | 749 | { |
746 | } | 750 | } |
747 | 751 | ||
752 | static inline void l2cap_chan_no_defer(struct l2cap_chan *chan) | ||
753 | { | ||
754 | } | ||
755 | |||
748 | extern bool disable_ertm; | 756 | extern bool disable_ertm; |
749 | 757 | ||
750 | int l2cap_init_sockets(void); | 758 | int l2cap_init_sockets(void); |
@@ -767,6 +775,8 @@ int l2cap_chan_check_security(struct l2cap_chan *chan); | |||
767 | void l2cap_chan_set_defaults(struct l2cap_chan *chan); | 775 | void l2cap_chan_set_defaults(struct l2cap_chan *chan); |
768 | int l2cap_ertm_init(struct l2cap_chan *chan); | 776 | int l2cap_ertm_init(struct l2cap_chan *chan); |
769 | void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan); | 777 | void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan); |
778 | void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan); | ||
770 | void l2cap_chan_del(struct l2cap_chan *chan, int err); | 779 | void l2cap_chan_del(struct l2cap_chan *chan, int err); |
780 | void l2cap_send_conn_req(struct l2cap_chan *chan); | ||
771 | 781 | ||
772 | #endif /* __L2CAP_H */ | 782 | #endif /* __L2CAP_H */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index aa0e4a12308c..c6964572890f 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -1232,6 +1232,7 @@ struct cfg80211_deauth_request { | |||
1232 | const u8 *ie; | 1232 | const u8 *ie; |
1233 | size_t ie_len; | 1233 | size_t ie_len; |
1234 | u16 reason_code; | 1234 | u16 reason_code; |
1235 | bool local_state_change; | ||
1235 | }; | 1236 | }; |
1236 | 1237 | ||
1237 | /** | 1238 | /** |
@@ -2665,6 +2666,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); | |||
2665 | unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc); | 2666 | unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc); |
2666 | 2667 | ||
2667 | /** | 2668 | /** |
2669 | * ieee80211_get_mesh_hdrlen - get mesh extension header length | ||
2670 | * @meshhdr: the mesh extension header, only the flags field | ||
2671 | * (first byte) will be accessed | ||
2672 | * Returns the length of the extension header, which is always at | ||
2673 | * least 6 bytes and at most 18 if address 5 and 6 are present. | ||
2674 | */ | ||
2675 | unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); | ||
2676 | |||
2677 | /** | ||
2668 | * DOC: Data path helpers | 2678 | * DOC: Data path helpers |
2669 | * | 2679 | * |
2670 | * In addition to generic utilities, cfg80211 also offers | 2680 | * In addition to generic utilities, cfg80211 also offers |
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h index e900072950cb..639f50af42df 100644 --- a/include/net/nfc/hci.h +++ b/include/net/nfc/hci.h | |||
@@ -24,6 +24,12 @@ | |||
24 | 24 | ||
25 | #include <net/nfc/nfc.h> | 25 | #include <net/nfc/nfc.h> |
26 | 26 | ||
27 | struct nfc_phy_ops { | ||
28 | int (*write)(void *dev_id, struct sk_buff *skb); | ||
29 | int (*enable)(void *dev_id); | ||
30 | void (*disable)(void *dev_id); | ||
31 | }; | ||
32 | |||
27 | struct nfc_hci_dev; | 33 | struct nfc_hci_dev; |
28 | 34 | ||
29 | struct nfc_hci_ops { | 35 | struct nfc_hci_ops { |
@@ -38,15 +44,21 @@ struct nfc_hci_ops { | |||
38 | int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb); | 44 | int (*xmit) (struct nfc_hci_dev *hdev, struct sk_buff *skb); |
39 | int (*start_poll) (struct nfc_hci_dev *hdev, | 45 | int (*start_poll) (struct nfc_hci_dev *hdev, |
40 | u32 im_protocols, u32 tm_protocols); | 46 | u32 im_protocols, u32 tm_protocols); |
47 | int (*dep_link_up)(struct nfc_hci_dev *hdev, struct nfc_target *target, | ||
48 | u8 comm_mode, u8 *gb, size_t gb_len); | ||
49 | int (*dep_link_down)(struct nfc_hci_dev *hdev); | ||
41 | int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate, | 50 | int (*target_from_gate) (struct nfc_hci_dev *hdev, u8 gate, |
42 | struct nfc_target *target); | 51 | struct nfc_target *target); |
43 | int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate, | 52 | int (*complete_target_discovered) (struct nfc_hci_dev *hdev, u8 gate, |
44 | struct nfc_target *target); | 53 | struct nfc_target *target); |
45 | int (*data_exchange) (struct nfc_hci_dev *hdev, | 54 | int (*im_transceive) (struct nfc_hci_dev *hdev, |
46 | struct nfc_target *target, struct sk_buff *skb, | 55 | struct nfc_target *target, struct sk_buff *skb, |
47 | data_exchange_cb_t cb, void *cb_context); | 56 | data_exchange_cb_t cb, void *cb_context); |
57 | int (*tm_send)(struct nfc_hci_dev *hdev, struct sk_buff *skb); | ||
48 | int (*check_presence)(struct nfc_hci_dev *hdev, | 58 | int (*check_presence)(struct nfc_hci_dev *hdev, |
49 | struct nfc_target *target); | 59 | struct nfc_target *target); |
60 | void (*event_received)(struct nfc_hci_dev *hdev, u8 gate, u8 event, | ||
61 | struct sk_buff *skb); | ||
50 | }; | 62 | }; |
51 | 63 | ||
52 | /* Pipes */ | 64 | /* Pipes */ |
@@ -114,6 +126,9 @@ struct nfc_hci_dev { | |||
114 | int async_cb_type; | 126 | int async_cb_type; |
115 | data_exchange_cb_t async_cb; | 127 | data_exchange_cb_t async_cb; |
116 | void *async_cb_context; | 128 | void *async_cb_context; |
129 | |||
130 | u8 *gb; | ||
131 | size_t gb_len; | ||
117 | }; | 132 | }; |
118 | 133 | ||
119 | /* hci device allocation */ | 134 | /* hci device allocation */ |
@@ -219,5 +234,6 @@ int nfc_hci_send_response(struct nfc_hci_dev *hdev, u8 gate, u8 response, | |||
219 | const u8 *param, size_t param_len); | 234 | const u8 *param, size_t param_len); |
220 | int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event, | 235 | int nfc_hci_send_event(struct nfc_hci_dev *hdev, u8 gate, u8 event, |
221 | const u8 *param, size_t param_len); | 236 | const u8 *param, size_t param_len); |
237 | int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate); | ||
222 | 238 | ||
223 | #endif /* __NET_HCI_H */ | 239 | #endif /* __NET_HCI_H */ |
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h index f05b10682c9d..fce80b2f9be7 100644 --- a/include/net/nfc/nfc.h +++ b/include/net/nfc/nfc.h | |||
@@ -95,7 +95,7 @@ struct nfc_genl_data { | |||
95 | }; | 95 | }; |
96 | 96 | ||
97 | struct nfc_dev { | 97 | struct nfc_dev { |
98 | unsigned int idx; | 98 | int idx; |
99 | u32 target_next_idx; | 99 | u32 target_next_idx; |
100 | struct nfc_target *targets; | 100 | struct nfc_target *targets; |
101 | int n_targets; | 101 | int n_targets; |
diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h index d908d17da56d..0e63cee8d810 100644 --- a/include/uapi/linux/nfc.h +++ b/include/uapi/linux/nfc.h | |||
@@ -60,6 +60,13 @@ | |||
60 | * target mode. | 60 | * target mode. |
61 | * @NFC_EVENT_DEVICE_DEACTIVATED: event emitted when the adapter is deactivated | 61 | * @NFC_EVENT_DEVICE_DEACTIVATED: event emitted when the adapter is deactivated |
62 | * from target mode. | 62 | * from target mode. |
63 | * @NFC_CMD_LLC_GET_PARAMS: request LTO, RW, and MIUX parameters for a device | ||
64 | * @NFC_CMD_LLC_SET_PARAMS: set one or more of LTO, RW, and MIUX parameters for | ||
65 | * a device. LTO must be set before the link is up otherwise -EINPROGRESS | ||
66 | * is returned. RW and MIUX can be set at anytime and will be passed in | ||
67 | * subsequent CONNECT and CC messages. | ||
68 | * If one of the passed parameters is wrong none is set and -EINVAL is | ||
69 | * returned. | ||
63 | */ | 70 | */ |
64 | enum nfc_commands { | 71 | enum nfc_commands { |
65 | NFC_CMD_UNSPEC, | 72 | NFC_CMD_UNSPEC, |
@@ -77,6 +84,8 @@ enum nfc_commands { | |||
77 | NFC_EVENT_TARGET_LOST, | 84 | NFC_EVENT_TARGET_LOST, |
78 | NFC_EVENT_TM_ACTIVATED, | 85 | NFC_EVENT_TM_ACTIVATED, |
79 | NFC_EVENT_TM_DEACTIVATED, | 86 | NFC_EVENT_TM_DEACTIVATED, |
87 | NFC_CMD_LLC_GET_PARAMS, | ||
88 | NFC_CMD_LLC_SET_PARAMS, | ||
80 | /* private: internal use only */ | 89 | /* private: internal use only */ |
81 | __NFC_CMD_AFTER_LAST | 90 | __NFC_CMD_AFTER_LAST |
82 | }; | 91 | }; |
@@ -102,6 +111,9 @@ enum nfc_commands { | |||
102 | * @NFC_ATTR_RF_MODE: Initiator or target | 111 | * @NFC_ATTR_RF_MODE: Initiator or target |
103 | * @NFC_ATTR_IM_PROTOCOLS: Initiator mode protocols to poll for | 112 | * @NFC_ATTR_IM_PROTOCOLS: Initiator mode protocols to poll for |
104 | * @NFC_ATTR_TM_PROTOCOLS: Target mode protocols to listen for | 113 | * @NFC_ATTR_TM_PROTOCOLS: Target mode protocols to listen for |
114 | * @NFC_ATTR_LLC_PARAM_LTO: Link TimeOut parameter | ||
115 | * @NFC_ATTR_LLC_PARAM_RW: Receive Window size parameter | ||
116 | * @NFC_ATTR_LLC_PARAM_MIUX: MIU eXtension parameter | ||
105 | */ | 117 | */ |
106 | enum nfc_attrs { | 118 | enum nfc_attrs { |
107 | NFC_ATTR_UNSPEC, | 119 | NFC_ATTR_UNSPEC, |
@@ -119,6 +131,9 @@ enum nfc_attrs { | |||
119 | NFC_ATTR_DEVICE_POWERED, | 131 | NFC_ATTR_DEVICE_POWERED, |
120 | NFC_ATTR_IM_PROTOCOLS, | 132 | NFC_ATTR_IM_PROTOCOLS, |
121 | NFC_ATTR_TM_PROTOCOLS, | 133 | NFC_ATTR_TM_PROTOCOLS, |
134 | NFC_ATTR_LLC_PARAM_LTO, | ||
135 | NFC_ATTR_LLC_PARAM_RW, | ||
136 | NFC_ATTR_LLC_PARAM_MIUX, | ||
122 | /* private: internal use only */ | 137 | /* private: internal use only */ |
123 | __NFC_ATTR_AFTER_LAST | 138 | __NFC_ATTR_AFTER_LAST |
124 | }; | 139 | }; |
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index 3537d385035e..1c11d0dcd863 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig | |||
@@ -11,6 +11,7 @@ menuconfig BT | |||
11 | select CRYPTO_BLKCIPHER | 11 | select CRYPTO_BLKCIPHER |
12 | select CRYPTO_AES | 12 | select CRYPTO_AES |
13 | select CRYPTO_ECB | 13 | select CRYPTO_ECB |
14 | select CRYPTO_SHA256 | ||
14 | help | 15 | help |
15 | Bluetooth is low-cost, low-power, short-range wireless technology. | 16 | Bluetooth is low-cost, low-power, short-range wireless technology. |
16 | It was designed as a replacement for cables and other short-range | 17 | It was designed as a replacement for cables and other short-range |
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile index fa6d94a4602a..dea6a287daca 100644 --- a/net/bluetooth/Makefile +++ b/net/bluetooth/Makefile | |||
@@ -10,4 +10,4 @@ obj-$(CONFIG_BT_HIDP) += hidp/ | |||
10 | 10 | ||
11 | bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ | 11 | bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ |
12 | hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \ | 12 | hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \ |
13 | a2mp.o | 13 | a2mp.o amp.o |
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 0760d1fed6f0..d5136cfb57e2 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c | |||
@@ -16,6 +16,11 @@ | |||
16 | #include <net/bluetooth/hci_core.h> | 16 | #include <net/bluetooth/hci_core.h> |
17 | #include <net/bluetooth/l2cap.h> | 17 | #include <net/bluetooth/l2cap.h> |
18 | #include <net/bluetooth/a2mp.h> | 18 | #include <net/bluetooth/a2mp.h> |
19 | #include <net/bluetooth/amp.h> | ||
20 | |||
21 | /* Global AMP Manager list */ | ||
22 | LIST_HEAD(amp_mgr_list); | ||
23 | DEFINE_MUTEX(amp_mgr_list_lock); | ||
19 | 24 | ||
20 | /* A2MP build & send command helper functions */ | 25 | /* A2MP build & send command helper functions */ |
21 | static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data) | 26 | static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data) |
@@ -37,8 +42,7 @@ static struct a2mp_cmd *__a2mp_build(u8 code, u8 ident, u16 len, void *data) | |||
37 | return cmd; | 42 | return cmd; |
38 | } | 43 | } |
39 | 44 | ||
40 | static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, | 45 | void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data) |
41 | void *data) | ||
42 | { | 46 | { |
43 | struct l2cap_chan *chan = mgr->a2mp_chan; | 47 | struct l2cap_chan *chan = mgr->a2mp_chan; |
44 | struct a2mp_cmd *cmd; | 48 | struct a2mp_cmd *cmd; |
@@ -63,6 +67,14 @@ static void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, | |||
63 | kfree(cmd); | 67 | kfree(cmd); |
64 | } | 68 | } |
65 | 69 | ||
70 | u8 __next_ident(struct amp_mgr *mgr) | ||
71 | { | ||
72 | if (++mgr->ident == 0) | ||
73 | mgr->ident = 1; | ||
74 | |||
75 | return mgr->ident; | ||
76 | } | ||
77 | |||
66 | static inline void __a2mp_cl_bredr(struct a2mp_cl *cl) | 78 | static inline void __a2mp_cl_bredr(struct a2mp_cl *cl) |
67 | { | 79 | { |
68 | cl->id = 0; | 80 | cl->id = 0; |
@@ -161,6 +173,83 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
161 | return 0; | 173 | return 0; |
162 | } | 174 | } |
163 | 175 | ||
176 | static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | ||
177 | struct a2mp_cmd *hdr) | ||
178 | { | ||
179 | struct a2mp_discov_rsp *rsp = (void *) skb->data; | ||
180 | u16 len = le16_to_cpu(hdr->len); | ||
181 | struct a2mp_cl *cl; | ||
182 | u16 ext_feat; | ||
183 | bool found = false; | ||
184 | |||
185 | if (len < sizeof(*rsp)) | ||
186 | return -EINVAL; | ||
187 | |||
188 | len -= sizeof(*rsp); | ||
189 | skb_pull(skb, sizeof(*rsp)); | ||
190 | |||
191 | ext_feat = le16_to_cpu(rsp->ext_feat); | ||
192 | |||
193 | BT_DBG("mtu %d efm 0x%4.4x", le16_to_cpu(rsp->mtu), ext_feat); | ||
194 | |||
195 | /* check that packet is not broken for now */ | ||
196 | while (ext_feat & A2MP_FEAT_EXT) { | ||
197 | if (len < sizeof(ext_feat)) | ||
198 | return -EINVAL; | ||
199 | |||
200 | ext_feat = get_unaligned_le16(skb->data); | ||
201 | BT_DBG("efm 0x%4.4x", ext_feat); | ||
202 | len -= sizeof(ext_feat); | ||
203 | skb_pull(skb, sizeof(ext_feat)); | ||
204 | } | ||
205 | |||
206 | cl = (void *) skb->data; | ||
207 | while (len >= sizeof(*cl)) { | ||
208 | BT_DBG("Remote AMP id %d type %d status %d", cl->id, cl->type, | ||
209 | cl->status); | ||
210 | |||
211 | if (cl->id != HCI_BREDR_ID && cl->type == HCI_AMP) { | ||
212 | struct a2mp_info_req req; | ||
213 | |||
214 | found = true; | ||
215 | req.id = cl->id; | ||
216 | a2mp_send(mgr, A2MP_GETINFO_REQ, __next_ident(mgr), | ||
217 | sizeof(req), &req); | ||
218 | } | ||
219 | |||
220 | len -= sizeof(*cl); | ||
221 | cl = (void *) skb_pull(skb, sizeof(*cl)); | ||
222 | } | ||
223 | |||
224 | /* Fall back to L2CAP init sequence */ | ||
225 | if (!found) { | ||
226 | struct l2cap_conn *conn = mgr->l2cap_conn; | ||
227 | struct l2cap_chan *chan; | ||
228 | |||
229 | mutex_lock(&conn->chan_lock); | ||
230 | |||
231 | list_for_each_entry(chan, &conn->chan_l, list) { | ||
232 | |||
233 | BT_DBG("chan %p state %s", chan, | ||
234 | state_to_string(chan->state)); | ||
235 | |||
236 | if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) | ||
237 | continue; | ||
238 | |||
239 | l2cap_chan_lock(chan); | ||
240 | |||
241 | if (chan->state == BT_CONNECT) | ||
242 | l2cap_send_conn_req(chan); | ||
243 | |||
244 | l2cap_chan_unlock(chan); | ||
245 | } | ||
246 | |||
247 | mutex_unlock(&conn->chan_lock); | ||
248 | } | ||
249 | |||
250 | return 0; | ||
251 | } | ||
252 | |||
164 | static int a2mp_change_notify(struct amp_mgr *mgr, struct sk_buff *skb, | 253 | static int a2mp_change_notify(struct amp_mgr *mgr, struct sk_buff *skb, |
165 | struct a2mp_cmd *hdr) | 254 | struct a2mp_cmd *hdr) |
166 | { | 255 | { |
@@ -181,7 +270,6 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
181 | struct a2mp_cmd *hdr) | 270 | struct a2mp_cmd *hdr) |
182 | { | 271 | { |
183 | struct a2mp_info_req *req = (void *) skb->data; | 272 | struct a2mp_info_req *req = (void *) skb->data; |
184 | struct a2mp_info_rsp rsp; | ||
185 | struct hci_dev *hdev; | 273 | struct hci_dev *hdev; |
186 | 274 | ||
187 | if (le16_to_cpu(hdr->len) < sizeof(*req)) | 275 | if (le16_to_cpu(hdr->len) < sizeof(*req)) |
@@ -189,53 +277,93 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
189 | 277 | ||
190 | BT_DBG("id %d", req->id); | 278 | BT_DBG("id %d", req->id); |
191 | 279 | ||
192 | rsp.id = req->id; | ||
193 | rsp.status = A2MP_STATUS_INVALID_CTRL_ID; | ||
194 | |||
195 | hdev = hci_dev_get(req->id); | 280 | hdev = hci_dev_get(req->id); |
196 | if (hdev && hdev->amp_type != HCI_BREDR) { | 281 | if (!hdev || hdev->dev_type != HCI_AMP) { |
197 | rsp.status = 0; | 282 | struct a2mp_info_rsp rsp; |
198 | rsp.total_bw = cpu_to_le32(hdev->amp_total_bw); | 283 | |
199 | rsp.max_bw = cpu_to_le32(hdev->amp_max_bw); | 284 | rsp.id = req->id; |
200 | rsp.min_latency = cpu_to_le32(hdev->amp_min_latency); | 285 | rsp.status = A2MP_STATUS_INVALID_CTRL_ID; |
201 | rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap); | 286 | |
202 | rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size); | 287 | a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp), |
288 | &rsp); | ||
289 | |||
290 | goto done; | ||
203 | } | 291 | } |
204 | 292 | ||
293 | mgr->state = READ_LOC_AMP_INFO; | ||
294 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); | ||
295 | |||
296 | done: | ||
205 | if (hdev) | 297 | if (hdev) |
206 | hci_dev_put(hdev); | 298 | hci_dev_put(hdev); |
207 | 299 | ||
208 | a2mp_send(mgr, A2MP_GETINFO_RSP, hdr->ident, sizeof(rsp), &rsp); | ||
209 | |||
210 | skb_pull(skb, sizeof(*req)); | 300 | skb_pull(skb, sizeof(*req)); |
211 | return 0; | 301 | return 0; |
212 | } | 302 | } |
213 | 303 | ||
304 | static int a2mp_getinfo_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | ||
305 | struct a2mp_cmd *hdr) | ||
306 | { | ||
307 | struct a2mp_info_rsp *rsp = (struct a2mp_info_rsp *) skb->data; | ||
308 | struct a2mp_amp_assoc_req req; | ||
309 | struct amp_ctrl *ctrl; | ||
310 | |||
311 | if (le16_to_cpu(hdr->len) < sizeof(*rsp)) | ||
312 | return -EINVAL; | ||
313 | |||
314 | BT_DBG("id %d status 0x%2.2x", rsp->id, rsp->status); | ||
315 | |||
316 | if (rsp->status) | ||
317 | return -EINVAL; | ||
318 | |||
319 | ctrl = amp_ctrl_add(mgr, rsp->id); | ||
320 | if (!ctrl) | ||
321 | return -ENOMEM; | ||
322 | |||
323 | req.id = rsp->id; | ||
324 | a2mp_send(mgr, A2MP_GETAMPASSOC_REQ, __next_ident(mgr), sizeof(req), | ||
325 | &req); | ||
326 | |||
327 | skb_pull(skb, sizeof(*rsp)); | ||
328 | return 0; | ||
329 | } | ||
330 | |||
214 | static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb, | 331 | static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb, |
215 | struct a2mp_cmd *hdr) | 332 | struct a2mp_cmd *hdr) |
216 | { | 333 | { |
217 | struct a2mp_amp_assoc_req *req = (void *) skb->data; | 334 | struct a2mp_amp_assoc_req *req = (void *) skb->data; |
218 | struct hci_dev *hdev; | 335 | struct hci_dev *hdev; |
336 | struct amp_mgr *tmp; | ||
219 | 337 | ||
220 | if (le16_to_cpu(hdr->len) < sizeof(*req)) | 338 | if (le16_to_cpu(hdr->len) < sizeof(*req)) |
221 | return -EINVAL; | 339 | return -EINVAL; |
222 | 340 | ||
223 | BT_DBG("id %d", req->id); | 341 | BT_DBG("id %d", req->id); |
224 | 342 | ||
343 | /* Make sure that other request is not processed */ | ||
344 | tmp = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC); | ||
345 | |||
225 | hdev = hci_dev_get(req->id); | 346 | hdev = hci_dev_get(req->id); |
226 | if (!hdev || hdev->amp_type == HCI_BREDR) { | 347 | if (!hdev || hdev->amp_type == HCI_BREDR || tmp) { |
227 | struct a2mp_amp_assoc_rsp rsp; | 348 | struct a2mp_amp_assoc_rsp rsp; |
228 | rsp.id = req->id; | 349 | rsp.id = req->id; |
229 | rsp.status = A2MP_STATUS_INVALID_CTRL_ID; | 350 | |
351 | if (tmp) { | ||
352 | rsp.status = A2MP_STATUS_COLLISION_OCCURED; | ||
353 | amp_mgr_put(tmp); | ||
354 | } else { | ||
355 | rsp.status = A2MP_STATUS_INVALID_CTRL_ID; | ||
356 | } | ||
230 | 357 | ||
231 | a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, hdr->ident, sizeof(rsp), | 358 | a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, hdr->ident, sizeof(rsp), |
232 | &rsp); | 359 | &rsp); |
233 | goto clean; | 360 | |
361 | goto done; | ||
234 | } | 362 | } |
235 | 363 | ||
236 | /* Placeholder for HCI Read AMP Assoc */ | 364 | amp_read_loc_assoc(hdev, mgr); |
237 | 365 | ||
238 | clean: | 366 | done: |
239 | if (hdev) | 367 | if (hdev) |
240 | hci_dev_put(hdev); | 368 | hci_dev_put(hdev); |
241 | 369 | ||
@@ -243,6 +371,68 @@ clean: | |||
243 | return 0; | 371 | return 0; |
244 | } | 372 | } |
245 | 373 | ||
374 | static int a2mp_getampassoc_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | ||
375 | struct a2mp_cmd *hdr) | ||
376 | { | ||
377 | struct a2mp_amp_assoc_rsp *rsp = (void *) skb->data; | ||
378 | u16 len = le16_to_cpu(hdr->len); | ||
379 | struct hci_dev *hdev; | ||
380 | struct amp_ctrl *ctrl; | ||
381 | struct hci_conn *hcon; | ||
382 | size_t assoc_len; | ||
383 | |||
384 | if (len < sizeof(*rsp)) | ||
385 | return -EINVAL; | ||
386 | |||
387 | assoc_len = len - sizeof(*rsp); | ||
388 | |||
389 | BT_DBG("id %d status 0x%2.2x assoc len %zu", rsp->id, rsp->status, | ||
390 | assoc_len); | ||
391 | |||
392 | if (rsp->status) | ||
393 | return -EINVAL; | ||
394 | |||
395 | /* Save remote ASSOC data */ | ||
396 | ctrl = amp_ctrl_lookup(mgr, rsp->id); | ||
397 | if (ctrl) { | ||
398 | u8 *assoc; | ||
399 | |||
400 | assoc = kzalloc(assoc_len, GFP_KERNEL); | ||
401 | if (!assoc) { | ||
402 | amp_ctrl_put(ctrl); | ||
403 | return -ENOMEM; | ||
404 | } | ||
405 | |||
406 | memcpy(assoc, rsp->amp_assoc, assoc_len); | ||
407 | ctrl->assoc = assoc; | ||
408 | ctrl->assoc_len = assoc_len; | ||
409 | ctrl->assoc_rem_len = assoc_len; | ||
410 | ctrl->assoc_len_so_far = 0; | ||
411 | |||
412 | amp_ctrl_put(ctrl); | ||
413 | } | ||
414 | |||
415 | /* Create Phys Link */ | ||
416 | hdev = hci_dev_get(rsp->id); | ||
417 | if (!hdev) | ||
418 | return -EINVAL; | ||
419 | |||
420 | hcon = phylink_add(hdev, mgr, rsp->id, true); | ||
421 | if (!hcon) | ||
422 | goto done; | ||
423 | |||
424 | BT_DBG("Created hcon %p: loc:%d -> rem:%d", hcon, hdev->id, rsp->id); | ||
425 | |||
426 | mgr->bredr_chan->ctrl_id = rsp->id; | ||
427 | |||
428 | amp_create_phylink(hdev, mgr, hcon); | ||
429 | |||
430 | done: | ||
431 | hci_dev_put(hdev); | ||
432 | skb_pull(skb, len); | ||
433 | return 0; | ||
434 | } | ||
435 | |||
246 | static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, | 436 | static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, |
247 | struct a2mp_cmd *hdr) | 437 | struct a2mp_cmd *hdr) |
248 | { | 438 | { |
@@ -250,6 +440,8 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
250 | 440 | ||
251 | struct a2mp_physlink_rsp rsp; | 441 | struct a2mp_physlink_rsp rsp; |
252 | struct hci_dev *hdev; | 442 | struct hci_dev *hdev; |
443 | struct hci_conn *hcon; | ||
444 | struct amp_ctrl *ctrl; | ||
253 | 445 | ||
254 | if (le16_to_cpu(hdr->len) < sizeof(*req)) | 446 | if (le16_to_cpu(hdr->len) < sizeof(*req)) |
255 | return -EINVAL; | 447 | return -EINVAL; |
@@ -265,9 +457,43 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
265 | goto send_rsp; | 457 | goto send_rsp; |
266 | } | 458 | } |
267 | 459 | ||
268 | /* TODO process physlink create */ | 460 | ctrl = amp_ctrl_lookup(mgr, rsp.remote_id); |
461 | if (!ctrl) { | ||
462 | ctrl = amp_ctrl_add(mgr, rsp.remote_id); | ||
463 | if (ctrl) { | ||
464 | amp_ctrl_get(ctrl); | ||
465 | } else { | ||
466 | rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION; | ||
467 | goto send_rsp; | ||
468 | } | ||
469 | } | ||
269 | 470 | ||
270 | rsp.status = A2MP_STATUS_SUCCESS; | 471 | if (ctrl) { |
472 | size_t assoc_len = le16_to_cpu(hdr->len) - sizeof(*req); | ||
473 | u8 *assoc; | ||
474 | |||
475 | assoc = kzalloc(assoc_len, GFP_KERNEL); | ||
476 | if (!assoc) { | ||
477 | amp_ctrl_put(ctrl); | ||
478 | return -ENOMEM; | ||
479 | } | ||
480 | |||
481 | memcpy(assoc, req->amp_assoc, assoc_len); | ||
482 | ctrl->assoc = assoc; | ||
483 | ctrl->assoc_len = assoc_len; | ||
484 | ctrl->assoc_rem_len = assoc_len; | ||
485 | ctrl->assoc_len_so_far = 0; | ||
486 | |||
487 | amp_ctrl_put(ctrl); | ||
488 | } | ||
489 | |||
490 | hcon = phylink_add(hdev, mgr, req->local_id, false); | ||
491 | if (hcon) { | ||
492 | amp_accept_phylink(hdev, mgr, hcon); | ||
493 | rsp.status = A2MP_STATUS_SUCCESS; | ||
494 | } else { | ||
495 | rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION; | ||
496 | } | ||
271 | 497 | ||
272 | send_rsp: | 498 | send_rsp: |
273 | if (hdev) | 499 | if (hdev) |
@@ -286,6 +512,7 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
286 | struct a2mp_physlink_req *req = (void *) skb->data; | 512 | struct a2mp_physlink_req *req = (void *) skb->data; |
287 | struct a2mp_physlink_rsp rsp; | 513 | struct a2mp_physlink_rsp rsp; |
288 | struct hci_dev *hdev; | 514 | struct hci_dev *hdev; |
515 | struct hci_conn *hcon; | ||
289 | 516 | ||
290 | if (le16_to_cpu(hdr->len) < sizeof(*req)) | 517 | if (le16_to_cpu(hdr->len) < sizeof(*req)) |
291 | return -EINVAL; | 518 | return -EINVAL; |
@@ -296,14 +523,22 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
296 | rsp.remote_id = req->local_id; | 523 | rsp.remote_id = req->local_id; |
297 | rsp.status = A2MP_STATUS_SUCCESS; | 524 | rsp.status = A2MP_STATUS_SUCCESS; |
298 | 525 | ||
299 | hdev = hci_dev_get(req->local_id); | 526 | hdev = hci_dev_get(req->remote_id); |
300 | if (!hdev) { | 527 | if (!hdev) { |
301 | rsp.status = A2MP_STATUS_INVALID_CTRL_ID; | 528 | rsp.status = A2MP_STATUS_INVALID_CTRL_ID; |
302 | goto send_rsp; | 529 | goto send_rsp; |
303 | } | 530 | } |
304 | 531 | ||
532 | hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, mgr->l2cap_conn->dst); | ||
533 | if (!hcon) { | ||
534 | BT_ERR("No phys link exist"); | ||
535 | rsp.status = A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS; | ||
536 | goto clean; | ||
537 | } | ||
538 | |||
305 | /* TODO Disconnect Phys Link here */ | 539 | /* TODO Disconnect Phys Link here */ |
306 | 540 | ||
541 | clean: | ||
307 | hci_dev_put(hdev); | 542 | hci_dev_put(hdev); |
308 | 543 | ||
309 | send_rsp: | 544 | send_rsp: |
@@ -377,10 +612,19 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) | |||
377 | err = a2mp_discphyslink_req(mgr, skb, hdr); | 612 | err = a2mp_discphyslink_req(mgr, skb, hdr); |
378 | break; | 613 | break; |
379 | 614 | ||
380 | case A2MP_CHANGE_RSP: | ||
381 | case A2MP_DISCOVER_RSP: | 615 | case A2MP_DISCOVER_RSP: |
616 | err = a2mp_discover_rsp(mgr, skb, hdr); | ||
617 | break; | ||
618 | |||
382 | case A2MP_GETINFO_RSP: | 619 | case A2MP_GETINFO_RSP: |
620 | err = a2mp_getinfo_rsp(mgr, skb, hdr); | ||
621 | break; | ||
622 | |||
383 | case A2MP_GETAMPASSOC_RSP: | 623 | case A2MP_GETAMPASSOC_RSP: |
624 | err = a2mp_getampassoc_rsp(mgr, skb, hdr); | ||
625 | break; | ||
626 | |||
627 | case A2MP_CHANGE_RSP: | ||
384 | case A2MP_CREATEPHYSLINK_RSP: | 628 | case A2MP_CREATEPHYSLINK_RSP: |
385 | case A2MP_DISCONNPHYSLINK_RSP: | 629 | case A2MP_DISCONNPHYSLINK_RSP: |
386 | err = a2mp_cmd_rsp(mgr, skb, hdr); | 630 | err = a2mp_cmd_rsp(mgr, skb, hdr); |
@@ -455,9 +699,10 @@ static struct l2cap_ops a2mp_chan_ops = { | |||
455 | .new_connection = l2cap_chan_no_new_connection, | 699 | .new_connection = l2cap_chan_no_new_connection, |
456 | .teardown = l2cap_chan_no_teardown, | 700 | .teardown = l2cap_chan_no_teardown, |
457 | .ready = l2cap_chan_no_ready, | 701 | .ready = l2cap_chan_no_ready, |
702 | .defer = l2cap_chan_no_defer, | ||
458 | }; | 703 | }; |
459 | 704 | ||
460 | static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn) | 705 | static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) |
461 | { | 706 | { |
462 | struct l2cap_chan *chan; | 707 | struct l2cap_chan *chan; |
463 | int err; | 708 | int err; |
@@ -492,7 +737,10 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn) | |||
492 | 737 | ||
493 | chan->conf_state = 0; | 738 | chan->conf_state = 0; |
494 | 739 | ||
495 | l2cap_chan_add(conn, chan); | 740 | if (locked) |
741 | __l2cap_chan_add(conn, chan); | ||
742 | else | ||
743 | l2cap_chan_add(conn, chan); | ||
496 | 744 | ||
497 | chan->remote_mps = chan->omtu; | 745 | chan->remote_mps = chan->omtu; |
498 | chan->mps = chan->omtu; | 746 | chan->mps = chan->omtu; |
@@ -503,11 +751,13 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn) | |||
503 | } | 751 | } |
504 | 752 | ||
505 | /* AMP Manager functions */ | 753 | /* AMP Manager functions */ |
506 | void amp_mgr_get(struct amp_mgr *mgr) | 754 | struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr) |
507 | { | 755 | { |
508 | BT_DBG("mgr %p orig refcnt %d", mgr, atomic_read(&mgr->kref.refcount)); | 756 | BT_DBG("mgr %p orig refcnt %d", mgr, atomic_read(&mgr->kref.refcount)); |
509 | 757 | ||
510 | kref_get(&mgr->kref); | 758 | kref_get(&mgr->kref); |
759 | |||
760 | return mgr; | ||
511 | } | 761 | } |
512 | 762 | ||
513 | static void amp_mgr_destroy(struct kref *kref) | 763 | static void amp_mgr_destroy(struct kref *kref) |
@@ -516,6 +766,11 @@ static void amp_mgr_destroy(struct kref *kref) | |||
516 | 766 | ||
517 | BT_DBG("mgr %p", mgr); | 767 | BT_DBG("mgr %p", mgr); |
518 | 768 | ||
769 | mutex_lock(&_mgr_list_lock); | ||
770 | list_del(&mgr->list); | ||
771 | mutex_unlock(&_mgr_list_lock); | ||
772 | |||
773 | amp_ctrl_list_flush(mgr); | ||
519 | kfree(mgr); | 774 | kfree(mgr); |
520 | } | 775 | } |
521 | 776 | ||
@@ -526,7 +781,7 @@ int amp_mgr_put(struct amp_mgr *mgr) | |||
526 | return kref_put(&mgr->kref, &_mgr_destroy); | 781 | return kref_put(&mgr->kref, &_mgr_destroy); |
527 | } | 782 | } |
528 | 783 | ||
529 | static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn) | 784 | static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn, bool locked) |
530 | { | 785 | { |
531 | struct amp_mgr *mgr; | 786 | struct amp_mgr *mgr; |
532 | struct l2cap_chan *chan; | 787 | struct l2cap_chan *chan; |
@@ -539,7 +794,7 @@ static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn) | |||
539 | 794 | ||
540 | mgr->l2cap_conn = conn; | 795 | mgr->l2cap_conn = conn; |
541 | 796 | ||
542 | chan = a2mp_chan_open(conn); | 797 | chan = a2mp_chan_open(conn, locked); |
543 | if (!chan) { | 798 | if (!chan) { |
544 | kfree(mgr); | 799 | kfree(mgr); |
545 | return NULL; | 800 | return NULL; |
@@ -552,6 +807,14 @@ static struct amp_mgr *amp_mgr_create(struct l2cap_conn *conn) | |||
552 | 807 | ||
553 | kref_init(&mgr->kref); | 808 | kref_init(&mgr->kref); |
554 | 809 | ||
810 | /* Remote AMP ctrl list initialization */ | ||
811 | INIT_LIST_HEAD(&mgr->amp_ctrls); | ||
812 | mutex_init(&mgr->amp_ctrls_lock); | ||
813 | |||
814 | mutex_lock(&_mgr_list_lock); | ||
815 | list_add(&mgr->list, &_mgr_list); | ||
816 | mutex_unlock(&_mgr_list_lock); | ||
817 | |||
555 | return mgr; | 818 | return mgr; |
556 | } | 819 | } |
557 | 820 | ||
@@ -560,7 +823,7 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, | |||
560 | { | 823 | { |
561 | struct amp_mgr *mgr; | 824 | struct amp_mgr *mgr; |
562 | 825 | ||
563 | mgr = amp_mgr_create(conn); | 826 | mgr = amp_mgr_create(conn, false); |
564 | if (!mgr) { | 827 | if (!mgr) { |
565 | BT_ERR("Could not create AMP manager"); | 828 | BT_ERR("Could not create AMP manager"); |
566 | return NULL; | 829 | return NULL; |
@@ -570,3 +833,139 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, | |||
570 | 833 | ||
571 | return mgr->a2mp_chan; | 834 | return mgr->a2mp_chan; |
572 | } | 835 | } |
836 | |||
837 | struct amp_mgr *amp_mgr_lookup_by_state(u8 state) | ||
838 | { | ||
839 | struct amp_mgr *mgr; | ||
840 | |||
841 | mutex_lock(&_mgr_list_lock); | ||
842 | list_for_each_entry(mgr, &_mgr_list, list) { | ||
843 | if (mgr->state == state) { | ||
844 | amp_mgr_get(mgr); | ||
845 | mutex_unlock(&_mgr_list_lock); | ||
846 | return mgr; | ||
847 | } | ||
848 | } | ||
849 | mutex_unlock(&_mgr_list_lock); | ||
850 | |||
851 | return NULL; | ||
852 | } | ||
853 | |||
854 | void a2mp_send_getinfo_rsp(struct hci_dev *hdev) | ||
855 | { | ||
856 | struct amp_mgr *mgr; | ||
857 | struct a2mp_info_rsp rsp; | ||
858 | |||
859 | mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_INFO); | ||
860 | if (!mgr) | ||
861 | return; | ||
862 | |||
863 | BT_DBG("%s mgr %p", hdev->name, mgr); | ||
864 | |||
865 | rsp.id = hdev->id; | ||
866 | rsp.status = A2MP_STATUS_INVALID_CTRL_ID; | ||
867 | |||
868 | if (hdev->amp_type != HCI_BREDR) { | ||
869 | rsp.status = 0; | ||
870 | rsp.total_bw = cpu_to_le32(hdev->amp_total_bw); | ||
871 | rsp.max_bw = cpu_to_le32(hdev->amp_max_bw); | ||
872 | rsp.min_latency = cpu_to_le32(hdev->amp_min_latency); | ||
873 | rsp.pal_cap = cpu_to_le16(hdev->amp_pal_cap); | ||
874 | rsp.assoc_size = cpu_to_le16(hdev->amp_assoc_size); | ||
875 | } | ||
876 | |||
877 | a2mp_send(mgr, A2MP_GETINFO_RSP, mgr->ident, sizeof(rsp), &rsp); | ||
878 | amp_mgr_put(mgr); | ||
879 | } | ||
880 | |||
881 | void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status) | ||
882 | { | ||
883 | struct amp_mgr *mgr; | ||
884 | struct amp_assoc *loc_assoc = &hdev->loc_assoc; | ||
885 | struct a2mp_amp_assoc_rsp *rsp; | ||
886 | size_t len; | ||
887 | |||
888 | mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC); | ||
889 | if (!mgr) | ||
890 | return; | ||
891 | |||
892 | BT_DBG("%s mgr %p", hdev->name, mgr); | ||
893 | |||
894 | len = sizeof(struct a2mp_amp_assoc_rsp) + loc_assoc->len; | ||
895 | rsp = kzalloc(len, GFP_KERNEL); | ||
896 | if (!rsp) { | ||
897 | amp_mgr_put(mgr); | ||
898 | return; | ||
899 | } | ||
900 | |||
901 | rsp->id = hdev->id; | ||
902 | |||
903 | if (status) { | ||
904 | rsp->status = A2MP_STATUS_INVALID_CTRL_ID; | ||
905 | } else { | ||
906 | rsp->status = A2MP_STATUS_SUCCESS; | ||
907 | memcpy(rsp->amp_assoc, loc_assoc->data, loc_assoc->len); | ||
908 | } | ||
909 | |||
910 | a2mp_send(mgr, A2MP_GETAMPASSOC_RSP, mgr->ident, len, rsp); | ||
911 | amp_mgr_put(mgr); | ||
912 | kfree(rsp); | ||
913 | } | ||
914 | |||
915 | void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status) | ||
916 | { | ||
917 | struct amp_mgr *mgr; | ||
918 | struct amp_assoc *loc_assoc = &hdev->loc_assoc; | ||
919 | struct a2mp_physlink_req *req; | ||
920 | struct l2cap_chan *bredr_chan; | ||
921 | size_t len; | ||
922 | |||
923 | mgr = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC_FINAL); | ||
924 | if (!mgr) | ||
925 | return; | ||
926 | |||
927 | len = sizeof(*req) + loc_assoc->len; | ||
928 | |||
929 | BT_DBG("%s mgr %p assoc_len %zu", hdev->name, mgr, len); | ||
930 | |||
931 | req = kzalloc(len, GFP_KERNEL); | ||
932 | if (!req) { | ||
933 | amp_mgr_put(mgr); | ||
934 | return; | ||
935 | } | ||
936 | |||
937 | bredr_chan = mgr->bredr_chan; | ||
938 | if (!bredr_chan) | ||
939 | goto clean; | ||
940 | |||
941 | req->local_id = hdev->id; | ||
942 | req->remote_id = bredr_chan->ctrl_id; | ||
943 | memcpy(req->amp_assoc, loc_assoc->data, loc_assoc->len); | ||
944 | |||
945 | a2mp_send(mgr, A2MP_CREATEPHYSLINK_REQ, __next_ident(mgr), len, req); | ||
946 | |||
947 | clean: | ||
948 | amp_mgr_put(mgr); | ||
949 | kfree(req); | ||
950 | } | ||
951 | |||
952 | void a2mp_discover_amp(struct l2cap_chan *chan) | ||
953 | { | ||
954 | struct l2cap_conn *conn = chan->conn; | ||
955 | struct amp_mgr *mgr = conn->hcon->amp_mgr; | ||
956 | struct a2mp_discov_req req; | ||
957 | |||
958 | BT_DBG("chan %p conn %p mgr %p", chan, conn, mgr); | ||
959 | |||
960 | if (!mgr) { | ||
961 | mgr = amp_mgr_create(conn, true); | ||
962 | if (!mgr) | ||
963 | return; | ||
964 | } | ||
965 | |||
966 | mgr->bredr_chan = chan; | ||
967 | |||
968 | req.mtu = cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU); | ||
969 | req.ext_feat = 0; | ||
970 | a2mp_send(mgr, A2MP_DISCOVER_REQ, 1, sizeof(req), &req); | ||
971 | } | ||
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index ba033f09196e..5355df63d39b 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -569,7 +569,6 @@ static int bt_seq_show(struct seq_file *seq, void *v) | |||
569 | { | 569 | { |
570 | struct bt_seq_state *s = seq->private; | 570 | struct bt_seq_state *s = seq->private; |
571 | struct bt_sock_list *l = s->l; | 571 | struct bt_sock_list *l = s->l; |
572 | bdaddr_t src_baswapped, dst_baswapped; | ||
573 | 572 | ||
574 | if (v == SEQ_START_TOKEN) { | 573 | if (v == SEQ_START_TOKEN) { |
575 | seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent"); | 574 | seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent"); |
@@ -583,18 +582,17 @@ static int bt_seq_show(struct seq_file *seq, void *v) | |||
583 | } else { | 582 | } else { |
584 | struct sock *sk = sk_entry(v); | 583 | struct sock *sk = sk_entry(v); |
585 | struct bt_sock *bt = bt_sk(sk); | 584 | struct bt_sock *bt = bt_sk(sk); |
586 | baswap(&src_baswapped, &bt->src); | ||
587 | baswap(&dst_baswapped, &bt->dst); | ||
588 | 585 | ||
589 | seq_printf(seq, "%pK %-6d %-6u %-6u %-6u %-6lu %pM %pM %-6lu", | 586 | seq_printf(seq, |
587 | "%pK %-6d %-6u %-6u %-6u %-6lu %pMR %pMR %-6lu", | ||
590 | sk, | 588 | sk, |
591 | atomic_read(&sk->sk_refcnt), | 589 | atomic_read(&sk->sk_refcnt), |
592 | sk_rmem_alloc_get(sk), | 590 | sk_rmem_alloc_get(sk), |
593 | sk_wmem_alloc_get(sk), | 591 | sk_wmem_alloc_get(sk), |
594 | from_kuid(seq_user_ns(seq), sock_i_uid(sk)), | 592 | from_kuid(seq_user_ns(seq), sock_i_uid(sk)), |
595 | sock_i_ino(sk), | 593 | sock_i_ino(sk), |
596 | &src_baswapped, | 594 | &bt->src, |
597 | &dst_baswapped, | 595 | &bt->dst, |
598 | bt->parent? sock_i_ino(bt->parent): 0LU); | 596 | bt->parent? sock_i_ino(bt->parent): 0LU); |
599 | 597 | ||
600 | if (l->custom_seq_show) { | 598 | if (l->custom_seq_show) { |
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c new file mode 100644 index 000000000000..231d7ef53ecb --- /dev/null +++ b/net/bluetooth/amp.c | |||
@@ -0,0 +1,374 @@ | |||
1 | /* | ||
2 | Copyright (c) 2011,2012 Intel Corp. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License version 2 and | ||
6 | only version 2 as published by the Free Software Foundation. | ||
7 | |||
8 | This program is distributed in the hope that it will be useful, | ||
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #include <net/bluetooth/bluetooth.h> | ||
15 | #include <net/bluetooth/hci.h> | ||
16 | #include <net/bluetooth/hci_core.h> | ||
17 | #include <net/bluetooth/a2mp.h> | ||
18 | #include <net/bluetooth/amp.h> | ||
19 | #include <crypto/hash.h> | ||
20 | |||
21 | /* Remote AMP Controllers interface */ | ||
22 | void amp_ctrl_get(struct amp_ctrl *ctrl) | ||
23 | { | ||
24 | BT_DBG("ctrl %p orig refcnt %d", ctrl, | ||
25 | atomic_read(&ctrl->kref.refcount)); | ||
26 | |||
27 | kref_get(&ctrl->kref); | ||
28 | } | ||
29 | |||
30 | static void amp_ctrl_destroy(struct kref *kref) | ||
31 | { | ||
32 | struct amp_ctrl *ctrl = container_of(kref, struct amp_ctrl, kref); | ||
33 | |||
34 | BT_DBG("ctrl %p", ctrl); | ||
35 | |||
36 | kfree(ctrl->assoc); | ||
37 | kfree(ctrl); | ||
38 | } | ||
39 | |||
40 | int amp_ctrl_put(struct amp_ctrl *ctrl) | ||
41 | { | ||
42 | BT_DBG("ctrl %p orig refcnt %d", ctrl, | ||
43 | atomic_read(&ctrl->kref.refcount)); | ||
44 | |||
45 | return kref_put(&ctrl->kref, &_ctrl_destroy); | ||
46 | } | ||
47 | |||
48 | struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id) | ||
49 | { | ||
50 | struct amp_ctrl *ctrl; | ||
51 | |||
52 | ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL); | ||
53 | if (!ctrl) | ||
54 | return NULL; | ||
55 | |||
56 | kref_init(&ctrl->kref); | ||
57 | ctrl->id = id; | ||
58 | |||
59 | mutex_lock(&mgr->amp_ctrls_lock); | ||
60 | list_add(&ctrl->list, &mgr->amp_ctrls); | ||
61 | mutex_unlock(&mgr->amp_ctrls_lock); | ||
62 | |||
63 | BT_DBG("mgr %p ctrl %p", mgr, ctrl); | ||
64 | |||
65 | return ctrl; | ||
66 | } | ||
67 | |||
68 | void amp_ctrl_list_flush(struct amp_mgr *mgr) | ||
69 | { | ||
70 | struct amp_ctrl *ctrl, *n; | ||
71 | |||
72 | BT_DBG("mgr %p", mgr); | ||
73 | |||
74 | mutex_lock(&mgr->amp_ctrls_lock); | ||
75 | list_for_each_entry_safe(ctrl, n, &mgr->amp_ctrls, list) { | ||
76 | list_del(&ctrl->list); | ||
77 | amp_ctrl_put(ctrl); | ||
78 | } | ||
79 | mutex_unlock(&mgr->amp_ctrls_lock); | ||
80 | } | ||
81 | |||
82 | struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id) | ||
83 | { | ||
84 | struct amp_ctrl *ctrl; | ||
85 | |||
86 | BT_DBG("mgr %p id %d", mgr, id); | ||
87 | |||
88 | mutex_lock(&mgr->amp_ctrls_lock); | ||
89 | list_for_each_entry(ctrl, &mgr->amp_ctrls, list) { | ||
90 | if (ctrl->id == id) { | ||
91 | amp_ctrl_get(ctrl); | ||
92 | mutex_unlock(&mgr->amp_ctrls_lock); | ||
93 | return ctrl; | ||
94 | } | ||
95 | } | ||
96 | mutex_unlock(&mgr->amp_ctrls_lock); | ||
97 | |||
98 | return NULL; | ||
99 | } | ||
100 | |||
101 | /* Physical Link interface */ | ||
102 | static u8 __next_handle(struct amp_mgr *mgr) | ||
103 | { | ||
104 | if (++mgr->handle == 0) | ||
105 | mgr->handle = 1; | ||
106 | |||
107 | return mgr->handle; | ||
108 | } | ||
109 | |||
110 | struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, | ||
111 | u8 remote_id, bool out) | ||
112 | { | ||
113 | bdaddr_t *dst = mgr->l2cap_conn->dst; | ||
114 | struct hci_conn *hcon; | ||
115 | |||
116 | hcon = hci_conn_add(hdev, AMP_LINK, dst); | ||
117 | if (!hcon) | ||
118 | return NULL; | ||
119 | |||
120 | BT_DBG("hcon %p dst %pMR", hcon, dst); | ||
121 | |||
122 | hcon->state = BT_CONNECT; | ||
123 | hcon->attempt++; | ||
124 | hcon->handle = __next_handle(mgr); | ||
125 | hcon->remote_id = remote_id; | ||
126 | hcon->amp_mgr = amp_mgr_get(mgr); | ||
127 | hcon->out = out; | ||
128 | |||
129 | return hcon; | ||
130 | } | ||
131 | |||
132 | /* AMP crypto key generation interface */ | ||
133 | static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output) | ||
134 | { | ||
135 | int ret = 0; | ||
136 | struct crypto_shash *tfm; | ||
137 | |||
138 | if (!ksize) | ||
139 | return -EINVAL; | ||
140 | |||
141 | tfm = crypto_alloc_shash("hmac(sha256)", 0, 0); | ||
142 | if (IS_ERR(tfm)) { | ||
143 | BT_DBG("crypto_alloc_ahash failed: err %ld", PTR_ERR(tfm)); | ||
144 | return PTR_ERR(tfm); | ||
145 | } | ||
146 | |||
147 | ret = crypto_shash_setkey(tfm, key, ksize); | ||
148 | if (ret) { | ||
149 | BT_DBG("crypto_ahash_setkey failed: err %d", ret); | ||
150 | } else { | ||
151 | struct { | ||
152 | struct shash_desc shash; | ||
153 | char ctx[crypto_shash_descsize(tfm)]; | ||
154 | } desc; | ||
155 | |||
156 | desc.shash.tfm = tfm; | ||
157 | desc.shash.flags = CRYPTO_TFM_REQ_MAY_SLEEP; | ||
158 | |||
159 | ret = crypto_shash_digest(&desc.shash, plaintext, psize, | ||
160 | output); | ||
161 | } | ||
162 | |||
163 | crypto_free_shash(tfm); | ||
164 | return ret; | ||
165 | } | ||
166 | |||
167 | int phylink_gen_key(struct hci_conn *conn, u8 *data, u8 *len, u8 *type) | ||
168 | { | ||
169 | struct hci_dev *hdev = conn->hdev; | ||
170 | struct link_key *key; | ||
171 | u8 keybuf[HCI_AMP_LINK_KEY_SIZE]; | ||
172 | u8 gamp_key[HCI_AMP_LINK_KEY_SIZE]; | ||
173 | int err; | ||
174 | |||
175 | if (!hci_conn_check_link_mode(conn)) | ||
176 | return -EACCES; | ||
177 | |||
178 | BT_DBG("conn %p key_type %d", conn, conn->key_type); | ||
179 | |||
180 | /* Legacy key */ | ||
181 | if (conn->key_type < 3) { | ||
182 | BT_ERR("Legacy key type %d", conn->key_type); | ||
183 | return -EACCES; | ||
184 | } | ||
185 | |||
186 | *type = conn->key_type; | ||
187 | *len = HCI_AMP_LINK_KEY_SIZE; | ||
188 | |||
189 | key = hci_find_link_key(hdev, &conn->dst); | ||
190 | if (!key) { | ||
191 | BT_DBG("No Link key for conn %p dst %pMR", conn, &conn->dst); | ||
192 | return -EACCES; | ||
193 | } | ||
194 | |||
195 | /* BR/EDR Link Key concatenated together with itself */ | ||
196 | memcpy(&keybuf[0], key->val, HCI_LINK_KEY_SIZE); | ||
197 | memcpy(&keybuf[HCI_LINK_KEY_SIZE], key->val, HCI_LINK_KEY_SIZE); | ||
198 | |||
199 | /* Derive Generic AMP Link Key (gamp) */ | ||
200 | err = hmac_sha256(keybuf, HCI_AMP_LINK_KEY_SIZE, "gamp", 4, gamp_key); | ||
201 | if (err) { | ||
202 | BT_ERR("Could not derive Generic AMP Key: err %d", err); | ||
203 | return err; | ||
204 | } | ||
205 | |||
206 | if (conn->key_type == HCI_LK_DEBUG_COMBINATION) { | ||
207 | BT_DBG("Use Generic AMP Key (gamp)"); | ||
208 | memcpy(data, gamp_key, HCI_AMP_LINK_KEY_SIZE); | ||
209 | return err; | ||
210 | } | ||
211 | |||
212 | /* Derive Dedicated AMP Link Key: "802b" is 802.11 PAL keyID */ | ||
213 | return hmac_sha256(gamp_key, HCI_AMP_LINK_KEY_SIZE, "802b", 4, data); | ||
214 | } | ||
215 | |||
216 | void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle) | ||
217 | { | ||
218 | struct hci_cp_read_local_amp_assoc cp; | ||
219 | struct amp_assoc *loc_assoc = &hdev->loc_assoc; | ||
220 | |||
221 | BT_DBG("%s handle %d", hdev->name, phy_handle); | ||
222 | |||
223 | cp.phy_handle = phy_handle; | ||
224 | cp.max_len = cpu_to_le16(hdev->amp_assoc_size); | ||
225 | cp.len_so_far = cpu_to_le16(loc_assoc->offset); | ||
226 | |||
227 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp); | ||
228 | } | ||
229 | |||
230 | void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr) | ||
231 | { | ||
232 | struct hci_cp_read_local_amp_assoc cp; | ||
233 | |||
234 | memset(&hdev->loc_assoc, 0, sizeof(struct amp_assoc)); | ||
235 | memset(&cp, 0, sizeof(cp)); | ||
236 | |||
237 | cp.max_len = cpu_to_le16(hdev->amp_assoc_size); | ||
238 | |||
239 | mgr->state = READ_LOC_AMP_ASSOC; | ||
240 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp); | ||
241 | } | ||
242 | |||
243 | void amp_read_loc_assoc_final_data(struct hci_dev *hdev, | ||
244 | struct hci_conn *hcon) | ||
245 | { | ||
246 | struct hci_cp_read_local_amp_assoc cp; | ||
247 | struct amp_mgr *mgr = hcon->amp_mgr; | ||
248 | |||
249 | cp.phy_handle = hcon->handle; | ||
250 | cp.len_so_far = cpu_to_le16(0); | ||
251 | cp.max_len = cpu_to_le16(hdev->amp_assoc_size); | ||
252 | |||
253 | mgr->state = READ_LOC_AMP_ASSOC_FINAL; | ||
254 | |||
255 | /* Read Local AMP Assoc final link information data */ | ||
256 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_ASSOC, sizeof(cp), &cp); | ||
257 | } | ||
258 | |||
259 | /* Write AMP Assoc data fragments, returns true with last fragment written*/ | ||
260 | static bool amp_write_rem_assoc_frag(struct hci_dev *hdev, | ||
261 | struct hci_conn *hcon) | ||
262 | { | ||
263 | struct hci_cp_write_remote_amp_assoc *cp; | ||
264 | struct amp_mgr *mgr = hcon->amp_mgr; | ||
265 | struct amp_ctrl *ctrl; | ||
266 | u16 frag_len, len; | ||
267 | |||
268 | ctrl = amp_ctrl_lookup(mgr, hcon->remote_id); | ||
269 | if (!ctrl) | ||
270 | return false; | ||
271 | |||
272 | if (!ctrl->assoc_rem_len) { | ||
273 | BT_DBG("all fragments are written"); | ||
274 | ctrl->assoc_rem_len = ctrl->assoc_len; | ||
275 | ctrl->assoc_len_so_far = 0; | ||
276 | |||
277 | amp_ctrl_put(ctrl); | ||
278 | return true; | ||
279 | } | ||
280 | |||
281 | frag_len = min_t(u16, 248, ctrl->assoc_rem_len); | ||
282 | len = frag_len + sizeof(*cp); | ||
283 | |||
284 | cp = kzalloc(len, GFP_KERNEL); | ||
285 | if (!cp) { | ||
286 | amp_ctrl_put(ctrl); | ||
287 | return false; | ||
288 | } | ||
289 | |||
290 | BT_DBG("hcon %p ctrl %p frag_len %u assoc_len %u rem_len %u", | ||
291 | hcon, ctrl, frag_len, ctrl->assoc_len, ctrl->assoc_rem_len); | ||
292 | |||
293 | cp->phy_handle = hcon->handle; | ||
294 | cp->len_so_far = cpu_to_le16(ctrl->assoc_len_so_far); | ||
295 | cp->rem_len = cpu_to_le16(ctrl->assoc_rem_len); | ||
296 | memcpy(cp->frag, ctrl->assoc, frag_len); | ||
297 | |||
298 | ctrl->assoc_len_so_far += frag_len; | ||
299 | ctrl->assoc_rem_len -= frag_len; | ||
300 | |||
301 | amp_ctrl_put(ctrl); | ||
302 | |||
303 | hci_send_cmd(hdev, HCI_OP_WRITE_REMOTE_AMP_ASSOC, len, cp); | ||
304 | |||
305 | kfree(cp); | ||
306 | |||
307 | return false; | ||
308 | } | ||
309 | |||
310 | void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle) | ||
311 | { | ||
312 | struct hci_conn *hcon; | ||
313 | |||
314 | BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle); | ||
315 | |||
316 | hcon = hci_conn_hash_lookup_handle(hdev, handle); | ||
317 | if (!hcon) | ||
318 | return; | ||
319 | |||
320 | amp_write_rem_assoc_frag(hdev, hcon); | ||
321 | } | ||
322 | |||
323 | void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle) | ||
324 | { | ||
325 | struct hci_conn *hcon; | ||
326 | |||
327 | BT_DBG("%s phy handle 0x%2.2x", hdev->name, handle); | ||
328 | |||
329 | hcon = hci_conn_hash_lookup_handle(hdev, handle); | ||
330 | if (!hcon) | ||
331 | return; | ||
332 | |||
333 | BT_DBG("%s phy handle 0x%2.2x hcon %p", hdev->name, handle, hcon); | ||
334 | |||
335 | amp_write_rem_assoc_frag(hdev, hcon); | ||
336 | } | ||
337 | |||
338 | void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, | ||
339 | struct hci_conn *hcon) | ||
340 | { | ||
341 | struct hci_cp_create_phy_link cp; | ||
342 | |||
343 | cp.phy_handle = hcon->handle; | ||
344 | |||
345 | BT_DBG("%s hcon %p phy handle 0x%2.2x", hdev->name, hcon, | ||
346 | hcon->handle); | ||
347 | |||
348 | if (phylink_gen_key(mgr->l2cap_conn->hcon, cp.key, &cp.key_len, | ||
349 | &cp.key_type)) { | ||
350 | BT_DBG("Cannot create link key"); | ||
351 | return; | ||
352 | } | ||
353 | |||
354 | hci_send_cmd(hdev, HCI_OP_CREATE_PHY_LINK, sizeof(cp), &cp); | ||
355 | } | ||
356 | |||
357 | void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, | ||
358 | struct hci_conn *hcon) | ||
359 | { | ||
360 | struct hci_cp_accept_phy_link cp; | ||
361 | |||
362 | cp.phy_handle = hcon->handle; | ||
363 | |||
364 | BT_DBG("%s hcon %p phy handle 0x%2.2x", hdev->name, hcon, | ||
365 | hcon->handle); | ||
366 | |||
367 | if (phylink_gen_key(mgr->l2cap_conn->hcon, cp.key, &cp.key_len, | ||
368 | &cp.key_type)) { | ||
369 | BT_DBG("Cannot create link key"); | ||
370 | return; | ||
371 | } | ||
372 | |||
373 | hci_send_cmd(hdev, HCI_OP_ACCEPT_PHY_LINK, sizeof(cp), &cp); | ||
374 | } | ||
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index 4a6620bc1570..a5b639702637 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
@@ -182,8 +182,7 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len) | |||
182 | a2 = data; | 182 | a2 = data; |
183 | data += ETH_ALEN; | 183 | data += ETH_ALEN; |
184 | 184 | ||
185 | BT_DBG("mc filter %s -> %s", | 185 | BT_DBG("mc filter %pMR -> %pMR", a1, a2); |
186 | batostr((void *) a1), batostr((void *) a2)); | ||
187 | 186 | ||
188 | /* Iterate from a1 to a2 */ | 187 | /* Iterate from a1 to a2 */ |
189 | set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter); | 188 | set_bit(bnep_mc_hash(a1), (ulong *) &s->mc_filter); |
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index 6c9c1fd601ca..e0a6ebf2baa6 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c | |||
@@ -353,7 +353,7 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) | |||
353 | 353 | ||
354 | BT_DBG("mtu %d", session->mtu); | 354 | BT_DBG("mtu %d", session->mtu); |
355 | 355 | ||
356 | sprintf(session->name, "%s", batostr(&bt_sk(sock->sk)->dst)); | 356 | sprintf(session->name, "%pMR", &bt_sk(sock->sk)->dst); |
357 | 357 | ||
358 | session->sock = sock; | 358 | session->sock = sock; |
359 | session->state = BT_CONFIG; | 359 | session->state = BT_CONFIG; |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index b9196a44f759..fe646211c61f 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -130,6 +130,20 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason) | |||
130 | hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp); | 130 | hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp); |
131 | } | 131 | } |
132 | 132 | ||
133 | static void hci_amp_disconn(struct hci_conn *conn, __u8 reason) | ||
134 | { | ||
135 | struct hci_cp_disconn_phy_link cp; | ||
136 | |||
137 | BT_DBG("hcon %p", conn); | ||
138 | |||
139 | conn->state = BT_DISCONN; | ||
140 | |||
141 | cp.phy_handle = HCI_PHY_HANDLE(conn->handle); | ||
142 | cp.reason = reason; | ||
143 | hci_send_cmd(conn->hdev, HCI_OP_DISCONN_PHY_LINK, | ||
144 | sizeof(cp), &cp); | ||
145 | } | ||
146 | |||
133 | static void hci_add_sco(struct hci_conn *conn, __u16 handle) | 147 | static void hci_add_sco(struct hci_conn *conn, __u16 handle) |
134 | { | 148 | { |
135 | struct hci_dev *hdev = conn->hdev; | 149 | struct hci_dev *hdev = conn->hdev; |
@@ -230,11 +244,24 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status) | |||
230 | } | 244 | } |
231 | } | 245 | } |
232 | 246 | ||
247 | static void hci_conn_disconnect(struct hci_conn *conn) | ||
248 | { | ||
249 | __u8 reason = hci_proto_disconn_ind(conn); | ||
250 | |||
251 | switch (conn->type) { | ||
252 | case ACL_LINK: | ||
253 | hci_acl_disconn(conn, reason); | ||
254 | break; | ||
255 | case AMP_LINK: | ||
256 | hci_amp_disconn(conn, reason); | ||
257 | break; | ||
258 | } | ||
259 | } | ||
260 | |||
233 | static void hci_conn_timeout(struct work_struct *work) | 261 | static void hci_conn_timeout(struct work_struct *work) |
234 | { | 262 | { |
235 | struct hci_conn *conn = container_of(work, struct hci_conn, | 263 | struct hci_conn *conn = container_of(work, struct hci_conn, |
236 | disc_work.work); | 264 | disc_work.work); |
237 | __u8 reason; | ||
238 | 265 | ||
239 | BT_DBG("hcon %p state %s", conn, state_to_string(conn->state)); | 266 | BT_DBG("hcon %p state %s", conn, state_to_string(conn->state)); |
240 | 267 | ||
@@ -253,8 +280,7 @@ static void hci_conn_timeout(struct work_struct *work) | |||
253 | break; | 280 | break; |
254 | case BT_CONFIG: | 281 | case BT_CONFIG: |
255 | case BT_CONNECTED: | 282 | case BT_CONNECTED: |
256 | reason = hci_proto_disconn_ind(conn); | 283 | hci_conn_disconnect(conn); |
257 | hci_acl_disconn(conn, reason); | ||
258 | break; | 284 | break; |
259 | default: | 285 | default: |
260 | conn->state = BT_CLOSED; | 286 | conn->state = BT_CLOSED; |
@@ -320,7 +346,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
320 | { | 346 | { |
321 | struct hci_conn *conn; | 347 | struct hci_conn *conn; |
322 | 348 | ||
323 | BT_DBG("%s dst %s", hdev->name, batostr(dst)); | 349 | BT_DBG("%s dst %pMR", hdev->name, dst); |
324 | 350 | ||
325 | conn = kzalloc(sizeof(struct hci_conn), GFP_KERNEL); | 351 | conn = kzalloc(sizeof(struct hci_conn), GFP_KERNEL); |
326 | if (!conn) | 352 | if (!conn) |
@@ -437,7 +463,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) | |||
437 | int use_src = bacmp(src, BDADDR_ANY); | 463 | int use_src = bacmp(src, BDADDR_ANY); |
438 | struct hci_dev *hdev = NULL, *d; | 464 | struct hci_dev *hdev = NULL, *d; |
439 | 465 | ||
440 | BT_DBG("%s -> %s", batostr(src), batostr(dst)); | 466 | BT_DBG("%pMR -> %pMR", src, dst); |
441 | 467 | ||
442 | read_lock(&hci_dev_list_lock); | 468 | read_lock(&hci_dev_list_lock); |
443 | 469 | ||
@@ -567,7 +593,7 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, | |||
567 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, | 593 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, |
568 | __u8 dst_type, __u8 sec_level, __u8 auth_type) | 594 | __u8 dst_type, __u8 sec_level, __u8 auth_type) |
569 | { | 595 | { |
570 | BT_DBG("%s dst %s type 0x%x", hdev->name, batostr(dst), type); | 596 | BT_DBG("%s dst %pMR type 0x%x", hdev->name, dst, type); |
571 | 597 | ||
572 | switch (type) { | 598 | switch (type) { |
573 | case LE_LINK: | 599 | case LE_LINK: |
@@ -963,3 +989,35 @@ void hci_chan_list_flush(struct hci_conn *conn) | |||
963 | list_for_each_entry_safe(chan, n, &conn->chan_list, list) | 989 | list_for_each_entry_safe(chan, n, &conn->chan_list, list) |
964 | hci_chan_del(chan); | 990 | hci_chan_del(chan); |
965 | } | 991 | } |
992 | |||
993 | static struct hci_chan *__hci_chan_lookup_handle(struct hci_conn *hcon, | ||
994 | __u16 handle) | ||
995 | { | ||
996 | struct hci_chan *hchan; | ||
997 | |||
998 | list_for_each_entry(hchan, &hcon->chan_list, list) { | ||
999 | if (hchan->handle == handle) | ||
1000 | return hchan; | ||
1001 | } | ||
1002 | |||
1003 | return NULL; | ||
1004 | } | ||
1005 | |||
1006 | struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle) | ||
1007 | { | ||
1008 | struct hci_conn_hash *h = &hdev->conn_hash; | ||
1009 | struct hci_conn *hcon; | ||
1010 | struct hci_chan *hchan = NULL; | ||
1011 | |||
1012 | rcu_read_lock(); | ||
1013 | |||
1014 | list_for_each_entry_rcu(hcon, &h->list, list) { | ||
1015 | hchan = __hci_chan_lookup_handle(hcon, handle); | ||
1016 | if (hchan) | ||
1017 | break; | ||
1018 | } | ||
1019 | |||
1020 | rcu_read_unlock(); | ||
1021 | |||
1022 | return hchan; | ||
1023 | } | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 8a0ce706aebd..5a3f941b610f 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -405,7 +405,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, | |||
405 | struct discovery_state *cache = &hdev->discovery; | 405 | struct discovery_state *cache = &hdev->discovery; |
406 | struct inquiry_entry *e; | 406 | struct inquiry_entry *e; |
407 | 407 | ||
408 | BT_DBG("cache %p, %s", cache, batostr(bdaddr)); | 408 | BT_DBG("cache %p, %pMR", cache, bdaddr); |
409 | 409 | ||
410 | list_for_each_entry(e, &cache->all, all) { | 410 | list_for_each_entry(e, &cache->all, all) { |
411 | if (!bacmp(&e->data.bdaddr, bdaddr)) | 411 | if (!bacmp(&e->data.bdaddr, bdaddr)) |
@@ -421,7 +421,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup_unknown(struct hci_dev *hdev, | |||
421 | struct discovery_state *cache = &hdev->discovery; | 421 | struct discovery_state *cache = &hdev->discovery; |
422 | struct inquiry_entry *e; | 422 | struct inquiry_entry *e; |
423 | 423 | ||
424 | BT_DBG("cache %p, %s", cache, batostr(bdaddr)); | 424 | BT_DBG("cache %p, %pMR", cache, bdaddr); |
425 | 425 | ||
426 | list_for_each_entry(e, &cache->unknown, list) { | 426 | list_for_each_entry(e, &cache->unknown, list) { |
427 | if (!bacmp(&e->data.bdaddr, bdaddr)) | 427 | if (!bacmp(&e->data.bdaddr, bdaddr)) |
@@ -438,7 +438,7 @@ struct inquiry_entry *hci_inquiry_cache_lookup_resolve(struct hci_dev *hdev, | |||
438 | struct discovery_state *cache = &hdev->discovery; | 438 | struct discovery_state *cache = &hdev->discovery; |
439 | struct inquiry_entry *e; | 439 | struct inquiry_entry *e; |
440 | 440 | ||
441 | BT_DBG("cache %p bdaddr %s state %d", cache, batostr(bdaddr), state); | 441 | BT_DBG("cache %p bdaddr %pMR state %d", cache, bdaddr, state); |
442 | 442 | ||
443 | list_for_each_entry(e, &cache->resolve, list) { | 443 | list_for_each_entry(e, &cache->resolve, list) { |
444 | if (!bacmp(bdaddr, BDADDR_ANY) && e->name_state == state) | 444 | if (!bacmp(bdaddr, BDADDR_ANY) && e->name_state == state) |
@@ -475,7 +475,7 @@ bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, | |||
475 | struct discovery_state *cache = &hdev->discovery; | 475 | struct discovery_state *cache = &hdev->discovery; |
476 | struct inquiry_entry *ie; | 476 | struct inquiry_entry *ie; |
477 | 477 | ||
478 | BT_DBG("cache %p, %s", cache, batostr(&data->bdaddr)); | 478 | BT_DBG("cache %p, %pMR", cache, &data->bdaddr); |
479 | 479 | ||
480 | if (ssp) | 480 | if (ssp) |
481 | *ssp = data->ssp_mode; | 481 | *ssp = data->ssp_mode; |
@@ -1259,7 +1259,7 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, | |||
1259 | list_add(&key->list, &hdev->link_keys); | 1259 | list_add(&key->list, &hdev->link_keys); |
1260 | } | 1260 | } |
1261 | 1261 | ||
1262 | BT_DBG("%s key for %s type %u", hdev->name, batostr(bdaddr), type); | 1262 | BT_DBG("%s key for %pMR type %u", hdev->name, bdaddr, type); |
1263 | 1263 | ||
1264 | /* Some buggy controller combinations generate a changed | 1264 | /* Some buggy controller combinations generate a changed |
1265 | * combination key for legacy pairing even when there's no | 1265 | * combination key for legacy pairing even when there's no |
@@ -1338,7 +1338,7 @@ int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
1338 | if (!key) | 1338 | if (!key) |
1339 | return -ENOENT; | 1339 | return -ENOENT; |
1340 | 1340 | ||
1341 | BT_DBG("%s removing %s", hdev->name, batostr(bdaddr)); | 1341 | BT_DBG("%s removing %pMR", hdev->name, bdaddr); |
1342 | 1342 | ||
1343 | list_del(&key->list); | 1343 | list_del(&key->list); |
1344 | kfree(key); | 1344 | kfree(key); |
@@ -1354,7 +1354,7 @@ int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
1354 | if (bacmp(bdaddr, &k->bdaddr)) | 1354 | if (bacmp(bdaddr, &k->bdaddr)) |
1355 | continue; | 1355 | continue; |
1356 | 1356 | ||
1357 | BT_DBG("%s removing %s", hdev->name, batostr(bdaddr)); | 1357 | BT_DBG("%s removing %pMR", hdev->name, bdaddr); |
1358 | 1358 | ||
1359 | list_del(&k->list); | 1359 | list_del(&k->list); |
1360 | kfree(k); | 1360 | kfree(k); |
@@ -1401,7 +1401,7 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
1401 | if (!data) | 1401 | if (!data) |
1402 | return -ENOENT; | 1402 | return -ENOENT; |
1403 | 1403 | ||
1404 | BT_DBG("%s removing %s", hdev->name, batostr(bdaddr)); | 1404 | BT_DBG("%s removing %pMR", hdev->name, bdaddr); |
1405 | 1405 | ||
1406 | list_del(&data->list); | 1406 | list_del(&data->list); |
1407 | kfree(data); | 1407 | kfree(data); |
@@ -1440,7 +1440,7 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, | |||
1440 | memcpy(data->hash, hash, sizeof(data->hash)); | 1440 | memcpy(data->hash, hash, sizeof(data->hash)); |
1441 | memcpy(data->randomizer, randomizer, sizeof(data->randomizer)); | 1441 | memcpy(data->randomizer, randomizer, sizeof(data->randomizer)); |
1442 | 1442 | ||
1443 | BT_DBG("%s for %s", hdev->name, batostr(bdaddr)); | 1443 | BT_DBG("%s for %pMR", hdev->name, bdaddr); |
1444 | 1444 | ||
1445 | return 0; | 1445 | return 0; |
1446 | } | 1446 | } |
@@ -2153,9 +2153,10 @@ static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags) | |||
2153 | hdr->dlen = cpu_to_le16(len); | 2153 | hdr->dlen = cpu_to_le16(len); |
2154 | } | 2154 | } |
2155 | 2155 | ||
2156 | static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue, | 2156 | static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue, |
2157 | struct sk_buff *skb, __u16 flags) | 2157 | struct sk_buff *skb, __u16 flags) |
2158 | { | 2158 | { |
2159 | struct hci_conn *conn = chan->conn; | ||
2159 | struct hci_dev *hdev = conn->hdev; | 2160 | struct hci_dev *hdev = conn->hdev; |
2160 | struct sk_buff *list; | 2161 | struct sk_buff *list; |
2161 | 2162 | ||
@@ -2163,7 +2164,18 @@ static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue, | |||
2163 | skb->data_len = 0; | 2164 | skb->data_len = 0; |
2164 | 2165 | ||
2165 | bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; | 2166 | bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; |
2166 | hci_add_acl_hdr(skb, conn->handle, flags); | 2167 | |
2168 | switch (hdev->dev_type) { | ||
2169 | case HCI_BREDR: | ||
2170 | hci_add_acl_hdr(skb, conn->handle, flags); | ||
2171 | break; | ||
2172 | case HCI_AMP: | ||
2173 | hci_add_acl_hdr(skb, chan->handle, flags); | ||
2174 | break; | ||
2175 | default: | ||
2176 | BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type); | ||
2177 | return; | ||
2178 | } | ||
2167 | 2179 | ||
2168 | list = skb_shinfo(skb)->frag_list; | 2180 | list = skb_shinfo(skb)->frag_list; |
2169 | if (!list) { | 2181 | if (!list) { |
@@ -2202,14 +2214,13 @@ static void hci_queue_acl(struct hci_conn *conn, struct sk_buff_head *queue, | |||
2202 | 2214 | ||
2203 | void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags) | 2215 | void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags) |
2204 | { | 2216 | { |
2205 | struct hci_conn *conn = chan->conn; | 2217 | struct hci_dev *hdev = chan->conn->hdev; |
2206 | struct hci_dev *hdev = conn->hdev; | ||
2207 | 2218 | ||
2208 | BT_DBG("%s chan %p flags 0x%4.4x", hdev->name, chan, flags); | 2219 | BT_DBG("%s chan %p flags 0x%4.4x", hdev->name, chan, flags); |
2209 | 2220 | ||
2210 | skb->dev = (void *) hdev; | 2221 | skb->dev = (void *) hdev; |
2211 | 2222 | ||
2212 | hci_queue_acl(conn, &chan->data_q, skb, flags); | 2223 | hci_queue_acl(chan, &chan->data_q, skb, flags); |
2213 | 2224 | ||
2214 | queue_work(hdev->workqueue, &hdev->tx_work); | 2225 | queue_work(hdev->workqueue, &hdev->tx_work); |
2215 | } | 2226 | } |
@@ -2311,8 +2322,8 @@ static void hci_link_tx_to(struct hci_dev *hdev, __u8 type) | |||
2311 | /* Kill stalled connections */ | 2322 | /* Kill stalled connections */ |
2312 | list_for_each_entry_rcu(c, &h->list, list) { | 2323 | list_for_each_entry_rcu(c, &h->list, list) { |
2313 | if (c->type == type && c->sent) { | 2324 | if (c->type == type && c->sent) { |
2314 | BT_ERR("%s killing stalled connection %s", | 2325 | BT_ERR("%s killing stalled connection %pMR", |
2315 | hdev->name, batostr(&c->dst)); | 2326 | hdev->name, &c->dst); |
2316 | hci_acl_disconn(c, HCI_ERROR_REMOTE_USER_TERM); | 2327 | hci_acl_disconn(c, HCI_ERROR_REMOTE_USER_TERM); |
2317 | } | 2328 | } |
2318 | } | 2329 | } |
@@ -2381,6 +2392,9 @@ static struct hci_chan *hci_chan_sent(struct hci_dev *hdev, __u8 type, | |||
2381 | case ACL_LINK: | 2392 | case ACL_LINK: |
2382 | cnt = hdev->acl_cnt; | 2393 | cnt = hdev->acl_cnt; |
2383 | break; | 2394 | break; |
2395 | case AMP_LINK: | ||
2396 | cnt = hdev->block_cnt; | ||
2397 | break; | ||
2384 | case SCO_LINK: | 2398 | case SCO_LINK: |
2385 | case ESCO_LINK: | 2399 | case ESCO_LINK: |
2386 | cnt = hdev->sco_cnt; | 2400 | cnt = hdev->sco_cnt; |
@@ -2510,11 +2524,19 @@ static void hci_sched_acl_blk(struct hci_dev *hdev) | |||
2510 | struct hci_chan *chan; | 2524 | struct hci_chan *chan; |
2511 | struct sk_buff *skb; | 2525 | struct sk_buff *skb; |
2512 | int quote; | 2526 | int quote; |
2527 | u8 type; | ||
2513 | 2528 | ||
2514 | __check_timeout(hdev, cnt); | 2529 | __check_timeout(hdev, cnt); |
2515 | 2530 | ||
2531 | BT_DBG("%s", hdev->name); | ||
2532 | |||
2533 | if (hdev->dev_type == HCI_AMP) | ||
2534 | type = AMP_LINK; | ||
2535 | else | ||
2536 | type = ACL_LINK; | ||
2537 | |||
2516 | while (hdev->block_cnt > 0 && | 2538 | while (hdev->block_cnt > 0 && |
2517 | (chan = hci_chan_sent(hdev, ACL_LINK, "e))) { | 2539 | (chan = hci_chan_sent(hdev, type, "e))) { |
2518 | u32 priority = (skb_peek(&chan->data_q))->priority; | 2540 | u32 priority = (skb_peek(&chan->data_q))->priority; |
2519 | while (quote > 0 && (skb = skb_peek(&chan->data_q))) { | 2541 | while (quote > 0 && (skb = skb_peek(&chan->data_q))) { |
2520 | int blocks; | 2542 | int blocks; |
@@ -2547,14 +2569,19 @@ static void hci_sched_acl_blk(struct hci_dev *hdev) | |||
2547 | } | 2569 | } |
2548 | 2570 | ||
2549 | if (cnt != hdev->block_cnt) | 2571 | if (cnt != hdev->block_cnt) |
2550 | hci_prio_recalculate(hdev, ACL_LINK); | 2572 | hci_prio_recalculate(hdev, type); |
2551 | } | 2573 | } |
2552 | 2574 | ||
2553 | static void hci_sched_acl(struct hci_dev *hdev) | 2575 | static void hci_sched_acl(struct hci_dev *hdev) |
2554 | { | 2576 | { |
2555 | BT_DBG("%s", hdev->name); | 2577 | BT_DBG("%s", hdev->name); |
2556 | 2578 | ||
2557 | if (!hci_conn_num(hdev, ACL_LINK)) | 2579 | /* No ACL link over BR/EDR controller */ |
2580 | if (!hci_conn_num(hdev, ACL_LINK) && hdev->dev_type == HCI_BREDR) | ||
2581 | return; | ||
2582 | |||
2583 | /* No AMP link over AMP controller */ | ||
2584 | if (!hci_conn_num(hdev, AMP_LINK) && hdev->dev_type == HCI_AMP) | ||
2558 | return; | 2585 | return; |
2559 | 2586 | ||
2560 | switch (hdev->flow_ctl_mode) { | 2587 | switch (hdev->flow_ctl_mode) { |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 2022b43c7353..0383635f91fb 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <net/bluetooth/bluetooth.h> | 30 | #include <net/bluetooth/bluetooth.h> |
31 | #include <net/bluetooth/hci_core.h> | 31 | #include <net/bluetooth/hci_core.h> |
32 | #include <net/bluetooth/mgmt.h> | 32 | #include <net/bluetooth/mgmt.h> |
33 | #include <net/bluetooth/a2mp.h> | ||
34 | #include <net/bluetooth/amp.h> | ||
33 | 35 | ||
34 | /* Handle HCI Event packets */ | 36 | /* Handle HCI Event packets */ |
35 | 37 | ||
@@ -846,7 +848,7 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev, | |||
846 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 848 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
847 | 849 | ||
848 | if (rp->status) | 850 | if (rp->status) |
849 | return; | 851 | goto a2mp_rsp; |
850 | 852 | ||
851 | hdev->amp_status = rp->amp_status; | 853 | hdev->amp_status = rp->amp_status; |
852 | hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); | 854 | hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); |
@@ -860,6 +862,46 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev, | |||
860 | hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); | 862 | hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); |
861 | 863 | ||
862 | hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); | 864 | hci_req_complete(hdev, HCI_OP_READ_LOCAL_AMP_INFO, rp->status); |
865 | |||
866 | a2mp_rsp: | ||
867 | a2mp_send_getinfo_rsp(hdev); | ||
868 | } | ||
869 | |||
870 | static void hci_cc_read_local_amp_assoc(struct hci_dev *hdev, | ||
871 | struct sk_buff *skb) | ||
872 | { | ||
873 | struct hci_rp_read_local_amp_assoc *rp = (void *) skb->data; | ||
874 | struct amp_assoc *assoc = &hdev->loc_assoc; | ||
875 | size_t rem_len, frag_len; | ||
876 | |||
877 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | ||
878 | |||
879 | if (rp->status) | ||
880 | goto a2mp_rsp; | ||
881 | |||
882 | frag_len = skb->len - sizeof(*rp); | ||
883 | rem_len = __le16_to_cpu(rp->rem_len); | ||
884 | |||
885 | if (rem_len > frag_len) { | ||
886 | BT_DBG("frag_len %zu rem_len %zu", frag_len, rem_len); | ||
887 | |||
888 | memcpy(assoc->data + assoc->offset, rp->frag, frag_len); | ||
889 | assoc->offset += frag_len; | ||
890 | |||
891 | /* Read other fragments */ | ||
892 | amp_read_loc_assoc_frag(hdev, rp->phy_handle); | ||
893 | |||
894 | return; | ||
895 | } | ||
896 | |||
897 | memcpy(assoc->data + assoc->offset, rp->frag, rem_len); | ||
898 | assoc->len = assoc->offset + rem_len; | ||
899 | assoc->offset = 0; | ||
900 | |||
901 | a2mp_rsp: | ||
902 | /* Send A2MP Rsp when all fragments are received */ | ||
903 | a2mp_send_getampassoc_rsp(hdev, rp->status); | ||
904 | a2mp_send_create_phy_link_req(hdev, rp->status); | ||
863 | } | 905 | } |
864 | 906 | ||
865 | static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, | 907 | static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, |
@@ -1174,6 +1216,20 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, | |||
1174 | hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status); | 1216 | hci_req_complete(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED, status); |
1175 | } | 1217 | } |
1176 | 1218 | ||
1219 | static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, | ||
1220 | struct sk_buff *skb) | ||
1221 | { | ||
1222 | struct hci_rp_write_remote_amp_assoc *rp = (void *) skb->data; | ||
1223 | |||
1224 | BT_DBG("%s status 0x%2.2x phy_handle 0x%2.2x", | ||
1225 | hdev->name, rp->status, rp->phy_handle); | ||
1226 | |||
1227 | if (rp->status) | ||
1228 | return; | ||
1229 | |||
1230 | amp_write_rem_assoc_continue(hdev, rp->phy_handle); | ||
1231 | } | ||
1232 | |||
1177 | static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) | 1233 | static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) |
1178 | { | 1234 | { |
1179 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1235 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
@@ -1210,7 +1266,7 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) | |||
1210 | 1266 | ||
1211 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); | 1267 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); |
1212 | 1268 | ||
1213 | BT_DBG("%s bdaddr %s hcon %p", hdev->name, batostr(&cp->bdaddr), conn); | 1269 | BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn); |
1214 | 1270 | ||
1215 | if (status) { | 1271 | if (status) { |
1216 | if (conn && conn->state == BT_CONNECT) { | 1272 | if (conn && conn->state == BT_CONNECT) { |
@@ -1639,8 +1695,7 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) | |||
1639 | return; | 1695 | return; |
1640 | } | 1696 | } |
1641 | 1697 | ||
1642 | BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst), | 1698 | BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn); |
1643 | conn); | ||
1644 | 1699 | ||
1645 | conn->state = BT_CLOSED; | 1700 | conn->state = BT_CLOSED; |
1646 | mgmt_connect_failed(hdev, &conn->dst, conn->type, | 1701 | mgmt_connect_failed(hdev, &conn->dst, conn->type, |
@@ -1657,6 +1712,38 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) | |||
1657 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1712 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
1658 | } | 1713 | } |
1659 | 1714 | ||
1715 | static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) | ||
1716 | { | ||
1717 | struct hci_cp_create_phy_link *cp; | ||
1718 | |||
1719 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1720 | |||
1721 | if (status) | ||
1722 | return; | ||
1723 | |||
1724 | cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_PHY_LINK); | ||
1725 | if (!cp) | ||
1726 | return; | ||
1727 | |||
1728 | amp_write_remote_assoc(hdev, cp->phy_handle); | ||
1729 | } | ||
1730 | |||
1731 | static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) | ||
1732 | { | ||
1733 | struct hci_cp_accept_phy_link *cp; | ||
1734 | |||
1735 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
1736 | |||
1737 | if (status) | ||
1738 | return; | ||
1739 | |||
1740 | cp = hci_sent_cmd_data(hdev, HCI_OP_ACCEPT_PHY_LINK); | ||
1741 | if (!cp) | ||
1742 | return; | ||
1743 | |||
1744 | amp_write_remote_assoc(hdev, cp->phy_handle); | ||
1745 | } | ||
1746 | |||
1660 | static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1747 | static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1661 | { | 1748 | { |
1662 | __u8 status = *((__u8 *) skb->data); | 1749 | __u8 status = *((__u8 *) skb->data); |
@@ -1822,7 +1909,7 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
1822 | struct hci_ev_conn_request *ev = (void *) skb->data; | 1909 | struct hci_ev_conn_request *ev = (void *) skb->data; |
1823 | int mask = hdev->link_mode; | 1910 | int mask = hdev->link_mode; |
1824 | 1911 | ||
1825 | BT_DBG("%s bdaddr %s type 0x%x", hdev->name, batostr(&ev->bdaddr), | 1912 | BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, |
1826 | ev->link_type); | 1913 | ev->link_type); |
1827 | 1914 | ||
1828 | mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); | 1915 | mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type); |
@@ -2314,6 +2401,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2314 | hci_cc_read_local_amp_info(hdev, skb); | 2401 | hci_cc_read_local_amp_info(hdev, skb); |
2315 | break; | 2402 | break; |
2316 | 2403 | ||
2404 | case HCI_OP_READ_LOCAL_AMP_ASSOC: | ||
2405 | hci_cc_read_local_amp_assoc(hdev, skb); | ||
2406 | break; | ||
2407 | |||
2317 | case HCI_OP_DELETE_STORED_LINK_KEY: | 2408 | case HCI_OP_DELETE_STORED_LINK_KEY: |
2318 | hci_cc_delete_stored_link_key(hdev, skb); | 2409 | hci_cc_delete_stored_link_key(hdev, skb); |
2319 | break; | 2410 | break; |
@@ -2386,6 +2477,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2386 | hci_cc_write_le_host_supported(hdev, skb); | 2477 | hci_cc_write_le_host_supported(hdev, skb); |
2387 | break; | 2478 | break; |
2388 | 2479 | ||
2480 | case HCI_OP_WRITE_REMOTE_AMP_ASSOC: | ||
2481 | hci_cc_write_remote_amp_assoc(hdev, skb); | ||
2482 | break; | ||
2483 | |||
2389 | default: | 2484 | default: |
2390 | BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); | 2485 | BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); |
2391 | break; | 2486 | break; |
@@ -2467,6 +2562,14 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2467 | hci_cs_le_start_enc(hdev, ev->status); | 2562 | hci_cs_le_start_enc(hdev, ev->status); |
2468 | break; | 2563 | break; |
2469 | 2564 | ||
2565 | case HCI_OP_CREATE_PHY_LINK: | ||
2566 | hci_cs_create_phylink(hdev, ev->status); | ||
2567 | break; | ||
2568 | |||
2569 | case HCI_OP_ACCEPT_PHY_LINK: | ||
2570 | hci_cs_accept_phylink(hdev, ev->status); | ||
2571 | break; | ||
2572 | |||
2470 | default: | 2573 | default: |
2471 | BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); | 2574 | BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); |
2472 | break; | 2575 | break; |
@@ -2574,6 +2677,27 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2574 | queue_work(hdev->workqueue, &hdev->tx_work); | 2677 | queue_work(hdev->workqueue, &hdev->tx_work); |
2575 | } | 2678 | } |
2576 | 2679 | ||
2680 | static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, | ||
2681 | __u16 handle) | ||
2682 | { | ||
2683 | struct hci_chan *chan; | ||
2684 | |||
2685 | switch (hdev->dev_type) { | ||
2686 | case HCI_BREDR: | ||
2687 | return hci_conn_hash_lookup_handle(hdev, handle); | ||
2688 | case HCI_AMP: | ||
2689 | chan = hci_chan_lookup_handle(hdev, handle); | ||
2690 | if (chan) | ||
2691 | return chan->conn; | ||
2692 | break; | ||
2693 | default: | ||
2694 | BT_ERR("%s unknown dev_type %d", hdev->name, hdev->dev_type); | ||
2695 | break; | ||
2696 | } | ||
2697 | |||
2698 | return NULL; | ||
2699 | } | ||
2700 | |||
2577 | static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2701 | static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2578 | { | 2702 | { |
2579 | struct hci_ev_num_comp_blocks *ev = (void *) skb->data; | 2703 | struct hci_ev_num_comp_blocks *ev = (void *) skb->data; |
@@ -2595,13 +2719,13 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2595 | 2719 | ||
2596 | for (i = 0; i < ev->num_hndl; i++) { | 2720 | for (i = 0; i < ev->num_hndl; i++) { |
2597 | struct hci_comp_blocks_info *info = &ev->handles[i]; | 2721 | struct hci_comp_blocks_info *info = &ev->handles[i]; |
2598 | struct hci_conn *conn; | 2722 | struct hci_conn *conn = NULL; |
2599 | __u16 handle, block_count; | 2723 | __u16 handle, block_count; |
2600 | 2724 | ||
2601 | handle = __le16_to_cpu(info->handle); | 2725 | handle = __le16_to_cpu(info->handle); |
2602 | block_count = __le16_to_cpu(info->blocks); | 2726 | block_count = __le16_to_cpu(info->blocks); |
2603 | 2727 | ||
2604 | conn = hci_conn_hash_lookup_handle(hdev, handle); | 2728 | conn = __hci_conn_lookup_handle(hdev, handle); |
2605 | if (!conn) | 2729 | if (!conn) |
2606 | continue; | 2730 | continue; |
2607 | 2731 | ||
@@ -2609,6 +2733,7 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2609 | 2733 | ||
2610 | switch (conn->type) { | 2734 | switch (conn->type) { |
2611 | case ACL_LINK: | 2735 | case ACL_LINK: |
2736 | case AMP_LINK: | ||
2612 | hdev->block_cnt += block_count; | 2737 | hdev->block_cnt += block_count; |
2613 | if (hdev->block_cnt > hdev->num_blocks) | 2738 | if (hdev->block_cnt > hdev->num_blocks) |
2614 | hdev->block_cnt = hdev->num_blocks; | 2739 | hdev->block_cnt = hdev->num_blocks; |
@@ -2705,13 +2830,13 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2705 | 2830 | ||
2706 | key = hci_find_link_key(hdev, &ev->bdaddr); | 2831 | key = hci_find_link_key(hdev, &ev->bdaddr); |
2707 | if (!key) { | 2832 | if (!key) { |
2708 | BT_DBG("%s link key not found for %s", hdev->name, | 2833 | BT_DBG("%s link key not found for %pMR", hdev->name, |
2709 | batostr(&ev->bdaddr)); | 2834 | &ev->bdaddr); |
2710 | goto not_found; | 2835 | goto not_found; |
2711 | } | 2836 | } |
2712 | 2837 | ||
2713 | BT_DBG("%s found key type %u for %s", hdev->name, key->type, | 2838 | BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, |
2714 | batostr(&ev->bdaddr)); | 2839 | &ev->bdaddr); |
2715 | 2840 | ||
2716 | if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && | 2841 | if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && |
2717 | key->type == HCI_LK_DEBUG_COMBINATION) { | 2842 | key->type == HCI_LK_DEBUG_COMBINATION) { |
@@ -3558,6 +3683,22 @@ static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3558 | } | 3683 | } |
3559 | } | 3684 | } |
3560 | 3685 | ||
3686 | static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) | ||
3687 | { | ||
3688 | struct hci_ev_channel_selected *ev = (void *) skb->data; | ||
3689 | struct hci_conn *hcon; | ||
3690 | |||
3691 | BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); | ||
3692 | |||
3693 | skb_pull(skb, sizeof(*ev)); | ||
3694 | |||
3695 | hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); | ||
3696 | if (!hcon) | ||
3697 | return; | ||
3698 | |||
3699 | amp_read_loc_assoc_final_data(hdev, hcon); | ||
3700 | } | ||
3701 | |||
3561 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | 3702 | void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) |
3562 | { | 3703 | { |
3563 | struct hci_event_hdr *hdr = (void *) skb->data; | 3704 | struct hci_event_hdr *hdr = (void *) skb->data; |
@@ -3722,6 +3863,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
3722 | hci_le_meta_evt(hdev, skb); | 3863 | hci_le_meta_evt(hdev, skb); |
3723 | break; | 3864 | break; |
3724 | 3865 | ||
3866 | case HCI_EV_CHANNEL_SELECTED: | ||
3867 | hci_chan_selected_evt(hdev, skb); | ||
3868 | break; | ||
3869 | |||
3725 | case HCI_EV_REMOTE_OOB_DATA_REQUEST: | 3870 | case HCI_EV_REMOTE_OOB_DATA_REQUEST: |
3726 | hci_remote_oob_data_request_evt(hdev, skb); | 3871 | hci_remote_oob_data_request_evt(hdev, skb); |
3727 | break; | 3872 | break; |
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index a20e61c3653d..55cceee02a84 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
@@ -38,7 +38,7 @@ static ssize_t show_link_address(struct device *dev, | |||
38 | struct device_attribute *attr, char *buf) | 38 | struct device_attribute *attr, char *buf) |
39 | { | 39 | { |
40 | struct hci_conn *conn = to_hci_conn(dev); | 40 | struct hci_conn *conn = to_hci_conn(dev); |
41 | return sprintf(buf, "%s\n", batostr(&conn->dst)); | 41 | return sprintf(buf, "%pMR\n", &conn->dst); |
42 | } | 42 | } |
43 | 43 | ||
44 | static ssize_t show_link_features(struct device *dev, | 44 | static ssize_t show_link_features(struct device *dev, |
@@ -224,7 +224,7 @@ static ssize_t show_address(struct device *dev, | |||
224 | struct device_attribute *attr, char *buf) | 224 | struct device_attribute *attr, char *buf) |
225 | { | 225 | { |
226 | struct hci_dev *hdev = to_hci_dev(dev); | 226 | struct hci_dev *hdev = to_hci_dev(dev); |
227 | return sprintf(buf, "%s\n", batostr(&hdev->bdaddr)); | 227 | return sprintf(buf, "%pMR\n", &hdev->bdaddr); |
228 | } | 228 | } |
229 | 229 | ||
230 | static ssize_t show_features(struct device *dev, | 230 | static ssize_t show_features(struct device *dev, |
@@ -406,8 +406,8 @@ static int inquiry_cache_show(struct seq_file *f, void *p) | |||
406 | 406 | ||
407 | list_for_each_entry(e, &cache->all, all) { | 407 | list_for_each_entry(e, &cache->all, all) { |
408 | struct inquiry_data *data = &e->data; | 408 | struct inquiry_data *data = &e->data; |
409 | seq_printf(f, "%s %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", | 409 | seq_printf(f, "%pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n", |
410 | batostr(&data->bdaddr), | 410 | &data->bdaddr, |
411 | data->pscan_rep_mode, data->pscan_period_mode, | 411 | data->pscan_rep_mode, data->pscan_period_mode, |
412 | data->pscan_mode, data->dev_class[2], | 412 | data->pscan_mode, data->dev_class[2], |
413 | data->dev_class[1], data->dev_class[0], | 413 | data->dev_class[1], data->dev_class[0], |
@@ -440,7 +440,7 @@ static int blacklist_show(struct seq_file *f, void *p) | |||
440 | hci_dev_lock(hdev); | 440 | hci_dev_lock(hdev); |
441 | 441 | ||
442 | list_for_each_entry(b, &hdev->blacklist, list) | 442 | list_for_each_entry(b, &hdev->blacklist, list) |
443 | seq_printf(f, "%s\n", batostr(&b->bdaddr)); | 443 | seq_printf(f, "%pMR\n", &b->bdaddr); |
444 | 444 | ||
445 | hci_dev_unlock(hdev); | 445 | hci_dev_unlock(hdev); |
446 | 446 | ||
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index ccd985da6518..0c0028463fa3 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -932,8 +932,12 @@ static int hidp_setup_hid(struct hidp_session *session, | |||
932 | hid->country = req->country; | 932 | hid->country = req->country; |
933 | 933 | ||
934 | strncpy(hid->name, req->name, 128); | 934 | strncpy(hid->name, req->name, 128); |
935 | strncpy(hid->phys, batostr(&bt_sk(session->ctrl_sock->sk)->src), 64); | 935 | |
936 | strncpy(hid->uniq, batostr(&bt_sk(session->ctrl_sock->sk)->dst), 64); | 936 | snprintf(hid->phys, sizeof(hid->phys), "%pMR", |
937 | &bt_sk(session->ctrl_sock->sk)->src); | ||
938 | |||
939 | snprintf(hid->uniq, sizeof(hid->uniq), "%pMR", | ||
940 | &bt_sk(session->ctrl_sock->sk)->dst); | ||
937 | 941 | ||
938 | hid->dev.parent = &session->conn->dev; | 942 | hid->dev.parent = &session->conn->dev; |
939 | hid->ll_driver = &hidp_hid_driver; | 943 | hid->ll_driver = &hidp_hid_driver; |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a91239dcda41..08efc256c931 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -48,19 +48,20 @@ static LIST_HEAD(chan_list); | |||
48 | static DEFINE_RWLOCK(chan_list_lock); | 48 | static DEFINE_RWLOCK(chan_list_lock); |
49 | 49 | ||
50 | static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, | 50 | static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, |
51 | u8 code, u8 ident, u16 dlen, void *data); | 51 | u8 code, u8 ident, u16 dlen, void *data); |
52 | static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, | 52 | static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, |
53 | void *data); | 53 | void *data); |
54 | static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); | 54 | static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data); |
55 | static void l2cap_send_disconn_req(struct l2cap_conn *conn, | 55 | static void l2cap_send_disconn_req(struct l2cap_conn *conn, |
56 | struct l2cap_chan *chan, int err); | 56 | struct l2cap_chan *chan, int err); |
57 | 57 | ||
58 | static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, | 58 | static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, |
59 | struct sk_buff_head *skbs, u8 event); | 59 | struct sk_buff_head *skbs, u8 event); |
60 | 60 | ||
61 | /* ---- L2CAP channels ---- */ | 61 | /* ---- L2CAP channels ---- */ |
62 | 62 | ||
63 | static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid) | 63 | static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, |
64 | u16 cid) | ||
64 | { | 65 | { |
65 | struct l2cap_chan *c; | 66 | struct l2cap_chan *c; |
66 | 67 | ||
@@ -71,7 +72,8 @@ static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 | |||
71 | return NULL; | 72 | return NULL; |
72 | } | 73 | } |
73 | 74 | ||
74 | static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) | 75 | static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, |
76 | u16 cid) | ||
75 | { | 77 | { |
76 | struct l2cap_chan *c; | 78 | struct l2cap_chan *c; |
77 | 79 | ||
@@ -84,7 +86,8 @@ static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 | |||
84 | 86 | ||
85 | /* Find channel with given SCID. | 87 | /* Find channel with given SCID. |
86 | * Returns locked channel. */ | 88 | * Returns locked channel. */ |
87 | static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) | 89 | static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, |
90 | u16 cid) | ||
88 | { | 91 | { |
89 | struct l2cap_chan *c; | 92 | struct l2cap_chan *c; |
90 | 93 | ||
@@ -97,7 +100,8 @@ static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 ci | |||
97 | return c; | 100 | return c; |
98 | } | 101 | } |
99 | 102 | ||
100 | static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) | 103 | static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, |
104 | u8 ident) | ||
101 | { | 105 | { |
102 | struct l2cap_chan *c; | 106 | struct l2cap_chan *c; |
103 | 107 | ||
@@ -178,7 +182,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn) | |||
178 | static void __l2cap_state_change(struct l2cap_chan *chan, int state) | 182 | static void __l2cap_state_change(struct l2cap_chan *chan, int state) |
179 | { | 183 | { |
180 | BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), | 184 | BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), |
181 | state_to_string(state)); | 185 | state_to_string(state)); |
182 | 186 | ||
183 | chan->state = state; | 187 | chan->state = state; |
184 | chan->ops->state_change(chan, state); | 188 | chan->ops->state_change(chan, state); |
@@ -361,7 +365,7 @@ static void l2cap_seq_list_append(struct l2cap_seq_list *seq_list, u16 seq) | |||
361 | static void l2cap_chan_timeout(struct work_struct *work) | 365 | static void l2cap_chan_timeout(struct work_struct *work) |
362 | { | 366 | { |
363 | struct l2cap_chan *chan = container_of(work, struct l2cap_chan, | 367 | struct l2cap_chan *chan = container_of(work, struct l2cap_chan, |
364 | chan_timer.work); | 368 | chan_timer.work); |
365 | struct l2cap_conn *conn = chan->conn; | 369 | struct l2cap_conn *conn = chan->conn; |
366 | int reason; | 370 | int reason; |
367 | 371 | ||
@@ -373,7 +377,7 @@ static void l2cap_chan_timeout(struct work_struct *work) | |||
373 | if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) | 377 | if (chan->state == BT_CONNECTED || chan->state == BT_CONFIG) |
374 | reason = ECONNREFUSED; | 378 | reason = ECONNREFUSED; |
375 | else if (chan->state == BT_CONNECT && | 379 | else if (chan->state == BT_CONNECT && |
376 | chan->sec_level != BT_SECURITY_SDP) | 380 | chan->sec_level != BT_SECURITY_SDP) |
377 | reason = ECONNREFUSED; | 381 | reason = ECONNREFUSED; |
378 | else | 382 | else |
379 | reason = ETIMEDOUT; | 383 | reason = ETIMEDOUT; |
@@ -455,7 +459,7 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan) | |||
455 | set_bit(FLAG_FORCE_ACTIVE, &chan->flags); | 459 | set_bit(FLAG_FORCE_ACTIVE, &chan->flags); |
456 | } | 460 | } |
457 | 461 | ||
458 | static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | 462 | void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) |
459 | { | 463 | { |
460 | BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, | 464 | BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, |
461 | __le16_to_cpu(chan->psm), chan->dcid); | 465 | __le16_to_cpu(chan->psm), chan->dcid); |
@@ -504,7 +508,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | |||
504 | chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; | 508 | chan->local_msdu = L2CAP_DEFAULT_MAX_SDU_SIZE; |
505 | chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; | 509 | chan->local_sdu_itime = L2CAP_DEFAULT_SDU_ITIME; |
506 | chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; | 510 | chan->local_acc_lat = L2CAP_DEFAULT_ACC_LAT; |
507 | chan->local_flush_to = L2CAP_DEFAULT_FLUSH_TO; | 511 | chan->local_flush_to = L2CAP_EFS_DEFAULT_FLUSH_TO; |
508 | 512 | ||
509 | l2cap_chan_hold(chan); | 513 | l2cap_chan_hold(chan); |
510 | 514 | ||
@@ -527,6 +531,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
527 | BT_DBG("chan %p, conn %p, err %d", chan, conn, err); | 531 | BT_DBG("chan %p, conn %p, err %d", chan, conn, err); |
528 | 532 | ||
529 | if (conn) { | 533 | if (conn) { |
534 | struct amp_mgr *mgr = conn->hcon->amp_mgr; | ||
530 | /* Delete from channel list */ | 535 | /* Delete from channel list */ |
531 | list_del(&chan->list); | 536 | list_del(&chan->list); |
532 | 537 | ||
@@ -536,10 +541,12 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
536 | 541 | ||
537 | if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP) | 542 | if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP) |
538 | hci_conn_put(conn->hcon); | 543 | hci_conn_put(conn->hcon); |
544 | |||
545 | if (mgr && mgr->bredr_chan == chan) | ||
546 | mgr->bredr_chan = NULL; | ||
539 | } | 547 | } |
540 | 548 | ||
541 | if (chan->ops->teardown) | 549 | chan->ops->teardown(chan, err); |
542 | chan->ops->teardown(chan, err); | ||
543 | 550 | ||
544 | if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) | 551 | if (test_bit(CONF_NOT_COMPLETE, &chan->conf_state)) |
545 | return; | 552 | return; |
@@ -573,19 +580,18 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
573 | struct l2cap_conn *conn = chan->conn; | 580 | struct l2cap_conn *conn = chan->conn; |
574 | struct sock *sk = chan->sk; | 581 | struct sock *sk = chan->sk; |
575 | 582 | ||
576 | BT_DBG("chan %p state %s sk %p", chan, | 583 | BT_DBG("chan %p state %s sk %p", chan, state_to_string(chan->state), |
577 | state_to_string(chan->state), sk); | 584 | sk); |
578 | 585 | ||
579 | switch (chan->state) { | 586 | switch (chan->state) { |
580 | case BT_LISTEN: | 587 | case BT_LISTEN: |
581 | if (chan->ops->teardown) | 588 | chan->ops->teardown(chan, 0); |
582 | chan->ops->teardown(chan, 0); | ||
583 | break; | 589 | break; |
584 | 590 | ||
585 | case BT_CONNECTED: | 591 | case BT_CONNECTED: |
586 | case BT_CONFIG: | 592 | case BT_CONFIG: |
587 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && | 593 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && |
588 | conn->hcon->type == ACL_LINK) { | 594 | conn->hcon->type == ACL_LINK) { |
589 | __set_chan_timer(chan, sk->sk_sndtimeo); | 595 | __set_chan_timer(chan, sk->sk_sndtimeo); |
590 | l2cap_send_disconn_req(conn, chan, reason); | 596 | l2cap_send_disconn_req(conn, chan, reason); |
591 | } else | 597 | } else |
@@ -594,7 +600,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
594 | 600 | ||
595 | case BT_CONNECT2: | 601 | case BT_CONNECT2: |
596 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && | 602 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && |
597 | conn->hcon->type == ACL_LINK) { | 603 | conn->hcon->type == ACL_LINK) { |
598 | struct l2cap_conn_rsp rsp; | 604 | struct l2cap_conn_rsp rsp; |
599 | __u16 result; | 605 | __u16 result; |
600 | 606 | ||
@@ -609,7 +615,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
609 | rsp.result = cpu_to_le16(result); | 615 | rsp.result = cpu_to_le16(result); |
610 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | 616 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); |
611 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, | 617 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, |
612 | sizeof(rsp), &rsp); | 618 | sizeof(rsp), &rsp); |
613 | } | 619 | } |
614 | 620 | ||
615 | l2cap_chan_del(chan, reason); | 621 | l2cap_chan_del(chan, reason); |
@@ -621,8 +627,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
621 | break; | 627 | break; |
622 | 628 | ||
623 | default: | 629 | default: |
624 | if (chan->ops->teardown) | 630 | chan->ops->teardown(chan, 0); |
625 | chan->ops->teardown(chan, 0); | ||
626 | break; | 631 | break; |
627 | } | 632 | } |
628 | } | 633 | } |
@@ -691,7 +696,8 @@ static u8 l2cap_get_ident(struct l2cap_conn *conn) | |||
691 | return id; | 696 | return id; |
692 | } | 697 | } |
693 | 698 | ||
694 | static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data) | 699 | static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, |
700 | void *data) | ||
695 | { | 701 | { |
696 | struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); | 702 | struct sk_buff *skb = l2cap_build_cmd(conn, code, ident, len, data); |
697 | u8 flags; | 703 | u8 flags; |
@@ -718,10 +724,10 @@ static void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb) | |||
718 | u16 flags; | 724 | u16 flags; |
719 | 725 | ||
720 | BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, | 726 | BT_DBG("chan %p, skb %p len %d priority %u", chan, skb, skb->len, |
721 | skb->priority); | 727 | skb->priority); |
722 | 728 | ||
723 | if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && | 729 | if (!test_bit(FLAG_FLUSHABLE, &chan->flags) && |
724 | lmp_no_flush_capable(hcon->hdev)) | 730 | lmp_no_flush_capable(hcon->hdev)) |
725 | flags = ACL_START_NO_FLUSH; | 731 | flags = ACL_START_NO_FLUSH; |
726 | else | 732 | else |
727 | flags = ACL_START; | 733 | flags = ACL_START; |
@@ -946,7 +952,19 @@ static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) | |||
946 | return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); | 952 | return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); |
947 | } | 953 | } |
948 | 954 | ||
949 | static void l2cap_send_conn_req(struct l2cap_chan *chan) | 955 | static bool __amp_capable(struct l2cap_chan *chan) |
956 | { | ||
957 | struct l2cap_conn *conn = chan->conn; | ||
958 | |||
959 | if (enable_hs && | ||
960 | chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED && | ||
961 | conn->fixed_chan_mask & L2CAP_FC_A2MP) | ||
962 | return true; | ||
963 | else | ||
964 | return false; | ||
965 | } | ||
966 | |||
967 | void l2cap_send_conn_req(struct l2cap_chan *chan) | ||
950 | { | 968 | { |
951 | struct l2cap_conn *conn = chan->conn; | 969 | struct l2cap_conn *conn = chan->conn; |
952 | struct l2cap_conn_req req; | 970 | struct l2cap_conn_req req; |
@@ -972,6 +990,16 @@ static void l2cap_chan_ready(struct l2cap_chan *chan) | |||
972 | chan->ops->ready(chan); | 990 | chan->ops->ready(chan); |
973 | } | 991 | } |
974 | 992 | ||
993 | static void l2cap_start_connection(struct l2cap_chan *chan) | ||
994 | { | ||
995 | if (__amp_capable(chan)) { | ||
996 | BT_DBG("chan %p AMP capable: discover AMPs", chan); | ||
997 | a2mp_discover_amp(chan); | ||
998 | } else { | ||
999 | l2cap_send_conn_req(chan); | ||
1000 | } | ||
1001 | } | ||
1002 | |||
975 | static void l2cap_do_start(struct l2cap_chan *chan) | 1003 | static void l2cap_do_start(struct l2cap_chan *chan) |
976 | { | 1004 | { |
977 | struct l2cap_conn *conn = chan->conn; | 1005 | struct l2cap_conn *conn = chan->conn; |
@@ -986,8 +1014,9 @@ static void l2cap_do_start(struct l2cap_chan *chan) | |||
986 | return; | 1014 | return; |
987 | 1015 | ||
988 | if (l2cap_chan_check_security(chan) && | 1016 | if (l2cap_chan_check_security(chan) && |
989 | __l2cap_no_conn_pending(chan)) | 1017 | __l2cap_no_conn_pending(chan)) { |
990 | l2cap_send_conn_req(chan); | 1018 | l2cap_start_connection(chan); |
1019 | } | ||
991 | } else { | 1020 | } else { |
992 | struct l2cap_info_req req; | 1021 | struct l2cap_info_req req; |
993 | req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); | 1022 | req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); |
@@ -997,8 +1026,8 @@ static void l2cap_do_start(struct l2cap_chan *chan) | |||
997 | 1026 | ||
998 | schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); | 1027 | schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); |
999 | 1028 | ||
1000 | l2cap_send_cmd(conn, conn->info_ident, | 1029 | l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, |
1001 | L2CAP_INFO_REQ, sizeof(req), &req); | 1030 | sizeof(req), &req); |
1002 | } | 1031 | } |
1003 | } | 1032 | } |
1004 | 1033 | ||
@@ -1018,7 +1047,8 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) | |||
1018 | } | 1047 | } |
1019 | } | 1048 | } |
1020 | 1049 | ||
1021 | static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err) | 1050 | static void l2cap_send_disconn_req(struct l2cap_conn *conn, |
1051 | struct l2cap_chan *chan, int err) | ||
1022 | { | 1052 | { |
1023 | struct sock *sk = chan->sk; | 1053 | struct sock *sk = chan->sk; |
1024 | struct l2cap_disconn_req req; | 1054 | struct l2cap_disconn_req req; |
@@ -1033,14 +1063,14 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c | |||
1033 | } | 1063 | } |
1034 | 1064 | ||
1035 | if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { | 1065 | if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { |
1036 | __l2cap_state_change(chan, BT_DISCONN); | 1066 | l2cap_state_change(chan, BT_DISCONN); |
1037 | return; | 1067 | return; |
1038 | } | 1068 | } |
1039 | 1069 | ||
1040 | req.dcid = cpu_to_le16(chan->dcid); | 1070 | req.dcid = cpu_to_le16(chan->dcid); |
1041 | req.scid = cpu_to_le16(chan->scid); | 1071 | req.scid = cpu_to_le16(chan->scid); |
1042 | l2cap_send_cmd(conn, l2cap_get_ident(conn), | 1072 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, |
1043 | L2CAP_DISCONN_REQ, sizeof(req), &req); | 1073 | sizeof(req), &req); |
1044 | 1074 | ||
1045 | lock_sock(sk); | 1075 | lock_sock(sk); |
1046 | __l2cap_state_change(chan, BT_DISCONN); | 1076 | __l2cap_state_change(chan, BT_DISCONN); |
@@ -1069,20 +1099,20 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
1069 | 1099 | ||
1070 | if (chan->state == BT_CONNECT) { | 1100 | if (chan->state == BT_CONNECT) { |
1071 | if (!l2cap_chan_check_security(chan) || | 1101 | if (!l2cap_chan_check_security(chan) || |
1072 | !__l2cap_no_conn_pending(chan)) { | 1102 | !__l2cap_no_conn_pending(chan)) { |
1073 | l2cap_chan_unlock(chan); | 1103 | l2cap_chan_unlock(chan); |
1074 | continue; | 1104 | continue; |
1075 | } | 1105 | } |
1076 | 1106 | ||
1077 | if (!l2cap_mode_supported(chan->mode, conn->feat_mask) | 1107 | if (!l2cap_mode_supported(chan->mode, conn->feat_mask) |
1078 | && test_bit(CONF_STATE2_DEVICE, | 1108 | && test_bit(CONF_STATE2_DEVICE, |
1079 | &chan->conf_state)) { | 1109 | &chan->conf_state)) { |
1080 | l2cap_chan_close(chan, ECONNRESET); | 1110 | l2cap_chan_close(chan, ECONNRESET); |
1081 | l2cap_chan_unlock(chan); | 1111 | l2cap_chan_unlock(chan); |
1082 | continue; | 1112 | continue; |
1083 | } | 1113 | } |
1084 | 1114 | ||
1085 | l2cap_send_conn_req(chan); | 1115 | l2cap_start_connection(chan); |
1086 | 1116 | ||
1087 | } else if (chan->state == BT_CONNECT2) { | 1117 | } else if (chan->state == BT_CONNECT2) { |
1088 | struct l2cap_conn_rsp rsp; | 1118 | struct l2cap_conn_rsp rsp; |
@@ -1094,11 +1124,9 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
1094 | lock_sock(sk); | 1124 | lock_sock(sk); |
1095 | if (test_bit(BT_SK_DEFER_SETUP, | 1125 | if (test_bit(BT_SK_DEFER_SETUP, |
1096 | &bt_sk(sk)->flags)) { | 1126 | &bt_sk(sk)->flags)) { |
1097 | struct sock *parent = bt_sk(sk)->parent; | ||
1098 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); | 1127 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); |
1099 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); | 1128 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); |
1100 | if (parent) | 1129 | chan->ops->defer(chan); |
1101 | parent->sk_data_ready(parent, 0); | ||
1102 | 1130 | ||
1103 | } else { | 1131 | } else { |
1104 | __l2cap_state_change(chan, BT_CONFIG); | 1132 | __l2cap_state_change(chan, BT_CONFIG); |
@@ -1112,17 +1140,17 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
1112 | } | 1140 | } |
1113 | 1141 | ||
1114 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, | 1142 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, |
1115 | sizeof(rsp), &rsp); | 1143 | sizeof(rsp), &rsp); |
1116 | 1144 | ||
1117 | if (test_bit(CONF_REQ_SENT, &chan->conf_state) || | 1145 | if (test_bit(CONF_REQ_SENT, &chan->conf_state) || |
1118 | rsp.result != L2CAP_CR_SUCCESS) { | 1146 | rsp.result != L2CAP_CR_SUCCESS) { |
1119 | l2cap_chan_unlock(chan); | 1147 | l2cap_chan_unlock(chan); |
1120 | continue; | 1148 | continue; |
1121 | } | 1149 | } |
1122 | 1150 | ||
1123 | set_bit(CONF_REQ_SENT, &chan->conf_state); | 1151 | set_bit(CONF_REQ_SENT, &chan->conf_state); |
1124 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, | 1152 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, |
1125 | l2cap_build_conf_req(chan, buf), buf); | 1153 | l2cap_build_conf_req(chan, buf), buf); |
1126 | chan->num_conf_req++; | 1154 | chan->num_conf_req++; |
1127 | } | 1155 | } |
1128 | 1156 | ||
@@ -1204,8 +1232,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
1204 | bacpy(&bt_sk(sk)->src, conn->src); | 1232 | bacpy(&bt_sk(sk)->src, conn->src); |
1205 | bacpy(&bt_sk(sk)->dst, conn->dst); | 1233 | bacpy(&bt_sk(sk)->dst, conn->dst); |
1206 | 1234 | ||
1207 | bt_accept_enqueue(parent, sk); | ||
1208 | |||
1209 | l2cap_chan_add(conn, chan); | 1235 | l2cap_chan_add(conn, chan); |
1210 | 1236 | ||
1211 | l2cap_chan_ready(chan); | 1237 | l2cap_chan_ready(chan); |
@@ -1270,7 +1296,7 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) | |||
1270 | 1296 | ||
1271 | list_for_each_entry(chan, &conn->chan_l, list) { | 1297 | list_for_each_entry(chan, &conn->chan_l, list) { |
1272 | if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) | 1298 | if (test_bit(FLAG_FORCE_RELIABLE, &chan->flags)) |
1273 | __l2cap_chan_set_err(chan, err); | 1299 | l2cap_chan_set_err(chan, err); |
1274 | } | 1300 | } |
1275 | 1301 | ||
1276 | mutex_unlock(&conn->chan_lock); | 1302 | mutex_unlock(&conn->chan_lock); |
@@ -1279,7 +1305,7 @@ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) | |||
1279 | static void l2cap_info_timeout(struct work_struct *work) | 1305 | static void l2cap_info_timeout(struct work_struct *work) |
1280 | { | 1306 | { |
1281 | struct l2cap_conn *conn = container_of(work, struct l2cap_conn, | 1307 | struct l2cap_conn *conn = container_of(work, struct l2cap_conn, |
1282 | info_timer.work); | 1308 | info_timer.work); |
1283 | 1309 | ||
1284 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; | 1310 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; |
1285 | conn->info_ident = 0; | 1311 | conn->info_ident = 0; |
@@ -1333,7 +1359,7 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) | |||
1333 | static void security_timeout(struct work_struct *work) | 1359 | static void security_timeout(struct work_struct *work) |
1334 | { | 1360 | { |
1335 | struct l2cap_conn *conn = container_of(work, struct l2cap_conn, | 1361 | struct l2cap_conn *conn = container_of(work, struct l2cap_conn, |
1336 | security_timer.work); | 1362 | security_timer.work); |
1337 | 1363 | ||
1338 | BT_DBG("conn %p", conn); | 1364 | BT_DBG("conn %p", conn); |
1339 | 1365 | ||
@@ -1355,7 +1381,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) | |||
1355 | if (!hchan) | 1381 | if (!hchan) |
1356 | return NULL; | 1382 | return NULL; |
1357 | 1383 | ||
1358 | conn = kzalloc(sizeof(struct l2cap_conn), GFP_ATOMIC); | 1384 | conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL); |
1359 | if (!conn) { | 1385 | if (!conn) { |
1360 | hci_chan_del(hchan); | 1386 | hci_chan_del(hchan); |
1361 | return NULL; | 1387 | return NULL; |
@@ -1367,10 +1393,22 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) | |||
1367 | 1393 | ||
1368 | BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); | 1394 | BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); |
1369 | 1395 | ||
1370 | if (hcon->hdev->le_mtu && hcon->type == LE_LINK) | 1396 | switch (hcon->type) { |
1371 | conn->mtu = hcon->hdev->le_mtu; | 1397 | case AMP_LINK: |
1372 | else | 1398 | conn->mtu = hcon->hdev->block_mtu; |
1399 | break; | ||
1400 | |||
1401 | case LE_LINK: | ||
1402 | if (hcon->hdev->le_mtu) { | ||
1403 | conn->mtu = hcon->hdev->le_mtu; | ||
1404 | break; | ||
1405 | } | ||
1406 | /* fall through */ | ||
1407 | |||
1408 | default: | ||
1373 | conn->mtu = hcon->hdev->acl_mtu; | 1409 | conn->mtu = hcon->hdev->acl_mtu; |
1410 | break; | ||
1411 | } | ||
1374 | 1412 | ||
1375 | conn->src = &hcon->hdev->bdaddr; | 1413 | conn->src = &hcon->hdev->bdaddr; |
1376 | conn->dst = &hcon->dst; | 1414 | conn->dst = &hcon->dst; |
@@ -1448,7 +1486,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
1448 | __u8 auth_type; | 1486 | __u8 auth_type; |
1449 | int err; | 1487 | int err; |
1450 | 1488 | ||
1451 | BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst), | 1489 | BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", src, dst, |
1452 | dst_type, __le16_to_cpu(psm)); | 1490 | dst_type, __le16_to_cpu(psm)); |
1453 | 1491 | ||
1454 | hdev = hci_get_route(dst, src); | 1492 | hdev = hci_get_route(dst, src); |
@@ -1461,7 +1499,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
1461 | 1499 | ||
1462 | /* PSM must be odd and lsb of upper byte must be 0 */ | 1500 | /* PSM must be odd and lsb of upper byte must be 0 */ |
1463 | if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid && | 1501 | if ((__le16_to_cpu(psm) & 0x0101) != 0x0001 && !cid && |
1464 | chan->chan_type != L2CAP_CHAN_RAW) { | 1502 | chan->chan_type != L2CAP_CHAN_RAW) { |
1465 | err = -EINVAL; | 1503 | err = -EINVAL; |
1466 | goto done; | 1504 | goto done; |
1467 | } | 1505 | } |
@@ -1770,7 +1808,7 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan) | |||
1770 | skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); | 1808 | skb = l2cap_ertm_seq_in_queue(&chan->tx_q, seq); |
1771 | if (!skb) { | 1809 | if (!skb) { |
1772 | BT_DBG("Error: Can't retransmit seq %d, frame missing", | 1810 | BT_DBG("Error: Can't retransmit seq %d, frame missing", |
1773 | seq); | 1811 | seq); |
1774 | continue; | 1812 | continue; |
1775 | } | 1813 | } |
1776 | 1814 | ||
@@ -1795,9 +1833,9 @@ static void l2cap_ertm_resend(struct l2cap_chan *chan) | |||
1795 | /* Cloned sk_buffs are read-only, so we need a | 1833 | /* Cloned sk_buffs are read-only, so we need a |
1796 | * writeable copy | 1834 | * writeable copy |
1797 | */ | 1835 | */ |
1798 | tx_skb = skb_copy(skb, GFP_ATOMIC); | 1836 | tx_skb = skb_copy(skb, GFP_KERNEL); |
1799 | } else { | 1837 | } else { |
1800 | tx_skb = skb_clone(skb, GFP_ATOMIC); | 1838 | tx_skb = skb_clone(skb, GFP_KERNEL); |
1801 | } | 1839 | } |
1802 | 1840 | ||
1803 | if (!tx_skb) { | 1841 | if (!tx_skb) { |
@@ -1855,7 +1893,7 @@ static void l2cap_retransmit_all(struct l2cap_chan *chan, | |||
1855 | if (chan->unacked_frames) { | 1893 | if (chan->unacked_frames) { |
1856 | skb_queue_walk(&chan->tx_q, skb) { | 1894 | skb_queue_walk(&chan->tx_q, skb) { |
1857 | if (bt_cb(skb)->control.txseq == control->reqseq || | 1895 | if (bt_cb(skb)->control.txseq == control->reqseq || |
1858 | skb == chan->tx_send_head) | 1896 | skb == chan->tx_send_head) |
1859 | break; | 1897 | break; |
1860 | } | 1898 | } |
1861 | 1899 | ||
@@ -2156,7 +2194,7 @@ static int l2cap_segment_sdu(struct l2cap_chan *chan, | |||
2156 | } | 2194 | } |
2157 | 2195 | ||
2158 | int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, | 2196 | int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, |
2159 | u32 priority) | 2197 | u32 priority) |
2160 | { | 2198 | { |
2161 | struct sk_buff *skb; | 2199 | struct sk_buff *skb; |
2162 | int err; | 2200 | int err; |
@@ -2543,7 +2581,7 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) | |||
2543 | /* Don't send frame to the socket it came from */ | 2581 | /* Don't send frame to the socket it came from */ |
2544 | if (skb->sk == sk) | 2582 | if (skb->sk == sk) |
2545 | continue; | 2583 | continue; |
2546 | nskb = skb_clone(skb, GFP_ATOMIC); | 2584 | nskb = skb_clone(skb, GFP_KERNEL); |
2547 | if (!nskb) | 2585 | if (!nskb) |
2548 | continue; | 2586 | continue; |
2549 | 2587 | ||
@@ -2569,7 +2607,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, | |||
2569 | len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; | 2607 | len = L2CAP_HDR_SIZE + L2CAP_CMD_HDR_SIZE + dlen; |
2570 | count = min_t(unsigned int, conn->mtu, len); | 2608 | count = min_t(unsigned int, conn->mtu, len); |
2571 | 2609 | ||
2572 | skb = bt_skb_alloc(count, GFP_ATOMIC); | 2610 | skb = bt_skb_alloc(count, GFP_KERNEL); |
2573 | if (!skb) | 2611 | if (!skb) |
2574 | return NULL; | 2612 | return NULL; |
2575 | 2613 | ||
@@ -2599,7 +2637,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, | |||
2599 | while (len) { | 2637 | while (len) { |
2600 | count = min_t(unsigned int, conn->mtu, len); | 2638 | count = min_t(unsigned int, conn->mtu, len); |
2601 | 2639 | ||
2602 | *frag = bt_skb_alloc(count, GFP_ATOMIC); | 2640 | *frag = bt_skb_alloc(count, GFP_KERNEL); |
2603 | if (!*frag) | 2641 | if (!*frag) |
2604 | goto fail; | 2642 | goto fail; |
2605 | 2643 | ||
@@ -2618,7 +2656,8 @@ fail: | |||
2618 | return NULL; | 2656 | return NULL; |
2619 | } | 2657 | } |
2620 | 2658 | ||
2621 | static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, unsigned long *val) | 2659 | static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen, |
2660 | unsigned long *val) | ||
2622 | { | 2661 | { |
2623 | struct l2cap_conf_opt *opt = *ptr; | 2662 | struct l2cap_conf_opt *opt = *ptr; |
2624 | int len; | 2663 | int len; |
@@ -2692,7 +2731,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) | |||
2692 | efs.msdu = cpu_to_le16(chan->local_msdu); | 2731 | efs.msdu = cpu_to_le16(chan->local_msdu); |
2693 | efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); | 2732 | efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); |
2694 | efs.acc_lat = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); | 2733 | efs.acc_lat = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); |
2695 | efs.flush_to = __constant_cpu_to_le32(L2CAP_DEFAULT_FLUSH_TO); | 2734 | efs.flush_to = __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO); |
2696 | break; | 2735 | break; |
2697 | 2736 | ||
2698 | case L2CAP_MODE_STREAMING: | 2737 | case L2CAP_MODE_STREAMING: |
@@ -2709,7 +2748,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) | |||
2709 | } | 2748 | } |
2710 | 2749 | ||
2711 | l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), | 2750 | l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs), |
2712 | (unsigned long) &efs); | 2751 | (unsigned long) &efs); |
2713 | } | 2752 | } |
2714 | 2753 | ||
2715 | static void l2cap_ack_timeout(struct work_struct *work) | 2754 | static void l2cap_ack_timeout(struct work_struct *work) |
@@ -2798,13 +2837,13 @@ static inline bool __l2cap_efs_supported(struct l2cap_chan *chan) | |||
2798 | static inline void l2cap_txwin_setup(struct l2cap_chan *chan) | 2837 | static inline void l2cap_txwin_setup(struct l2cap_chan *chan) |
2799 | { | 2838 | { |
2800 | if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && | 2839 | if (chan->tx_win > L2CAP_DEFAULT_TX_WINDOW && |
2801 | __l2cap_ews_supported(chan)) { | 2840 | __l2cap_ews_supported(chan)) { |
2802 | /* use extended control field */ | 2841 | /* use extended control field */ |
2803 | set_bit(FLAG_EXT_CTRL, &chan->flags); | 2842 | set_bit(FLAG_EXT_CTRL, &chan->flags); |
2804 | chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; | 2843 | chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; |
2805 | } else { | 2844 | } else { |
2806 | chan->tx_win = min_t(u16, chan->tx_win, | 2845 | chan->tx_win = min_t(u16, chan->tx_win, |
2807 | L2CAP_DEFAULT_TX_WINDOW); | 2846 | L2CAP_DEFAULT_TX_WINDOW); |
2808 | chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; | 2847 | chan->tx_win_max = L2CAP_DEFAULT_TX_WINDOW; |
2809 | } | 2848 | } |
2810 | chan->ack_win = chan->tx_win; | 2849 | chan->ack_win = chan->tx_win; |
@@ -2844,7 +2883,7 @@ done: | |||
2844 | switch (chan->mode) { | 2883 | switch (chan->mode) { |
2845 | case L2CAP_MODE_BASIC: | 2884 | case L2CAP_MODE_BASIC: |
2846 | if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && | 2885 | if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && |
2847 | !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) | 2886 | !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) |
2848 | break; | 2887 | break; |
2849 | 2888 | ||
2850 | rfc.mode = L2CAP_MODE_BASIC; | 2889 | rfc.mode = L2CAP_MODE_BASIC; |
@@ -2855,7 +2894,7 @@ done: | |||
2855 | rfc.max_pdu_size = 0; | 2894 | rfc.max_pdu_size = 0; |
2856 | 2895 | ||
2857 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), | 2896 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), |
2858 | (unsigned long) &rfc); | 2897 | (unsigned long) &rfc); |
2859 | break; | 2898 | break; |
2860 | 2899 | ||
2861 | case L2CAP_MODE_ERTM: | 2900 | case L2CAP_MODE_ERTM: |
@@ -2865,18 +2904,17 @@ done: | |||
2865 | rfc.monitor_timeout = 0; | 2904 | rfc.monitor_timeout = 0; |
2866 | 2905 | ||
2867 | size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - | 2906 | size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - |
2868 | L2CAP_EXT_HDR_SIZE - | 2907 | L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - |
2869 | L2CAP_SDULEN_SIZE - | 2908 | L2CAP_FCS_SIZE); |
2870 | L2CAP_FCS_SIZE); | ||
2871 | rfc.max_pdu_size = cpu_to_le16(size); | 2909 | rfc.max_pdu_size = cpu_to_le16(size); |
2872 | 2910 | ||
2873 | l2cap_txwin_setup(chan); | 2911 | l2cap_txwin_setup(chan); |
2874 | 2912 | ||
2875 | rfc.txwin_size = min_t(u16, chan->tx_win, | 2913 | rfc.txwin_size = min_t(u16, chan->tx_win, |
2876 | L2CAP_DEFAULT_TX_WINDOW); | 2914 | L2CAP_DEFAULT_TX_WINDOW); |
2877 | 2915 | ||
2878 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), | 2916 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), |
2879 | (unsigned long) &rfc); | 2917 | (unsigned long) &rfc); |
2880 | 2918 | ||
2881 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) | 2919 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) |
2882 | l2cap_add_opt_efs(&ptr, chan); | 2920 | l2cap_add_opt_efs(&ptr, chan); |
@@ -2885,14 +2923,14 @@ done: | |||
2885 | break; | 2923 | break; |
2886 | 2924 | ||
2887 | if (chan->fcs == L2CAP_FCS_NONE || | 2925 | if (chan->fcs == L2CAP_FCS_NONE || |
2888 | test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { | 2926 | test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { |
2889 | chan->fcs = L2CAP_FCS_NONE; | 2927 | chan->fcs = L2CAP_FCS_NONE; |
2890 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); | 2928 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); |
2891 | } | 2929 | } |
2892 | 2930 | ||
2893 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) | 2931 | if (test_bit(FLAG_EXT_CTRL, &chan->flags)) |
2894 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, | 2932 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, |
2895 | chan->tx_win); | 2933 | chan->tx_win); |
2896 | break; | 2934 | break; |
2897 | 2935 | ||
2898 | case L2CAP_MODE_STREAMING: | 2936 | case L2CAP_MODE_STREAMING: |
@@ -2904,13 +2942,12 @@ done: | |||
2904 | rfc.monitor_timeout = 0; | 2942 | rfc.monitor_timeout = 0; |
2905 | 2943 | ||
2906 | size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - | 2944 | size = min_t(u16, L2CAP_DEFAULT_MAX_PDU_SIZE, chan->conn->mtu - |
2907 | L2CAP_EXT_HDR_SIZE - | 2945 | L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - |
2908 | L2CAP_SDULEN_SIZE - | 2946 | L2CAP_FCS_SIZE); |
2909 | L2CAP_FCS_SIZE); | ||
2910 | rfc.max_pdu_size = cpu_to_le16(size); | 2947 | rfc.max_pdu_size = cpu_to_le16(size); |
2911 | 2948 | ||
2912 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), | 2949 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), |
2913 | (unsigned long) &rfc); | 2950 | (unsigned long) &rfc); |
2914 | 2951 | ||
2915 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) | 2952 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) |
2916 | l2cap_add_opt_efs(&ptr, chan); | 2953 | l2cap_add_opt_efs(&ptr, chan); |
@@ -2919,7 +2956,7 @@ done: | |||
2919 | break; | 2956 | break; |
2920 | 2957 | ||
2921 | if (chan->fcs == L2CAP_FCS_NONE || | 2958 | if (chan->fcs == L2CAP_FCS_NONE || |
2922 | test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { | 2959 | test_bit(CONF_NO_FCS_RECV, &chan->conf_state)) { |
2923 | chan->fcs = L2CAP_FCS_NONE; | 2960 | chan->fcs = L2CAP_FCS_NONE; |
2924 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); | 2961 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, chan->fcs); |
2925 | } | 2962 | } |
@@ -3011,7 +3048,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data) | |||
3011 | case L2CAP_MODE_ERTM: | 3048 | case L2CAP_MODE_ERTM: |
3012 | if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { | 3049 | if (!test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { |
3013 | chan->mode = l2cap_select_mode(rfc.mode, | 3050 | chan->mode = l2cap_select_mode(rfc.mode, |
3014 | chan->conn->feat_mask); | 3051 | chan->conn->feat_mask); |
3015 | break; | 3052 | break; |
3016 | } | 3053 | } |
3017 | 3054 | ||
@@ -3036,8 +3073,8 @@ done: | |||
3036 | if (chan->num_conf_rsp == 1) | 3073 | if (chan->num_conf_rsp == 1) |
3037 | return -ECONNREFUSED; | 3074 | return -ECONNREFUSED; |
3038 | 3075 | ||
3039 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, | 3076 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), |
3040 | sizeof(rfc), (unsigned long) &rfc); | 3077 | (unsigned long) &rfc); |
3041 | } | 3078 | } |
3042 | 3079 | ||
3043 | if (result == L2CAP_CONF_SUCCESS) { | 3080 | if (result == L2CAP_CONF_SUCCESS) { |
@@ -3054,8 +3091,8 @@ done: | |||
3054 | 3091 | ||
3055 | if (remote_efs) { | 3092 | if (remote_efs) { |
3056 | if (chan->local_stype != L2CAP_SERV_NOTRAFIC && | 3093 | if (chan->local_stype != L2CAP_SERV_NOTRAFIC && |
3057 | efs.stype != L2CAP_SERV_NOTRAFIC && | 3094 | efs.stype != L2CAP_SERV_NOTRAFIC && |
3058 | efs.stype != chan->local_stype) { | 3095 | efs.stype != chan->local_stype) { |
3059 | 3096 | ||
3060 | result = L2CAP_CONF_UNACCEPT; | 3097 | result = L2CAP_CONF_UNACCEPT; |
3061 | 3098 | ||
@@ -3063,8 +3100,8 @@ done: | |||
3063 | return -ECONNREFUSED; | 3100 | return -ECONNREFUSED; |
3064 | 3101 | ||
3065 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, | 3102 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, |
3066 | sizeof(efs), | 3103 | sizeof(efs), |
3067 | (unsigned long) &efs); | 3104 | (unsigned long) &efs); |
3068 | } else { | 3105 | } else { |
3069 | /* Send PENDING Conf Rsp */ | 3106 | /* Send PENDING Conf Rsp */ |
3070 | result = L2CAP_CONF_PENDING; | 3107 | result = L2CAP_CONF_PENDING; |
@@ -3087,10 +3124,8 @@ done: | |||
3087 | chan->remote_max_tx = rfc.max_transmit; | 3124 | chan->remote_max_tx = rfc.max_transmit; |
3088 | 3125 | ||
3089 | size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), | 3126 | size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), |
3090 | chan->conn->mtu - | 3127 | chan->conn->mtu - L2CAP_EXT_HDR_SIZE - |
3091 | L2CAP_EXT_HDR_SIZE - | 3128 | L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); |
3092 | L2CAP_SDULEN_SIZE - | ||
3093 | L2CAP_FCS_SIZE); | ||
3094 | rfc.max_pdu_size = cpu_to_le16(size); | 3129 | rfc.max_pdu_size = cpu_to_le16(size); |
3095 | chan->remote_mps = size; | 3130 | chan->remote_mps = size; |
3096 | 3131 | ||
@@ -3102,36 +3137,35 @@ done: | |||
3102 | set_bit(CONF_MODE_DONE, &chan->conf_state); | 3137 | set_bit(CONF_MODE_DONE, &chan->conf_state); |
3103 | 3138 | ||
3104 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, | 3139 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, |
3105 | sizeof(rfc), (unsigned long) &rfc); | 3140 | sizeof(rfc), (unsigned long) &rfc); |
3106 | 3141 | ||
3107 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { | 3142 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { |
3108 | chan->remote_id = efs.id; | 3143 | chan->remote_id = efs.id; |
3109 | chan->remote_stype = efs.stype; | 3144 | chan->remote_stype = efs.stype; |
3110 | chan->remote_msdu = le16_to_cpu(efs.msdu); | 3145 | chan->remote_msdu = le16_to_cpu(efs.msdu); |
3111 | chan->remote_flush_to = | 3146 | chan->remote_flush_to = |
3112 | le32_to_cpu(efs.flush_to); | 3147 | le32_to_cpu(efs.flush_to); |
3113 | chan->remote_acc_lat = | 3148 | chan->remote_acc_lat = |
3114 | le32_to_cpu(efs.acc_lat); | 3149 | le32_to_cpu(efs.acc_lat); |
3115 | chan->remote_sdu_itime = | 3150 | chan->remote_sdu_itime = |
3116 | le32_to_cpu(efs.sdu_itime); | 3151 | le32_to_cpu(efs.sdu_itime); |
3117 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, | 3152 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, |
3118 | sizeof(efs), (unsigned long) &efs); | 3153 | sizeof(efs), |
3154 | (unsigned long) &efs); | ||
3119 | } | 3155 | } |
3120 | break; | 3156 | break; |
3121 | 3157 | ||
3122 | case L2CAP_MODE_STREAMING: | 3158 | case L2CAP_MODE_STREAMING: |
3123 | size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), | 3159 | size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), |
3124 | chan->conn->mtu - | 3160 | chan->conn->mtu - L2CAP_EXT_HDR_SIZE - |
3125 | L2CAP_EXT_HDR_SIZE - | 3161 | L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); |
3126 | L2CAP_SDULEN_SIZE - | ||
3127 | L2CAP_FCS_SIZE); | ||
3128 | rfc.max_pdu_size = cpu_to_le16(size); | 3162 | rfc.max_pdu_size = cpu_to_le16(size); |
3129 | chan->remote_mps = size; | 3163 | chan->remote_mps = size; |
3130 | 3164 | ||
3131 | set_bit(CONF_MODE_DONE, &chan->conf_state); | 3165 | set_bit(CONF_MODE_DONE, &chan->conf_state); |
3132 | 3166 | ||
3133 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, | 3167 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), |
3134 | sizeof(rfc), (unsigned long) &rfc); | 3168 | (unsigned long) &rfc); |
3135 | 3169 | ||
3136 | break; | 3170 | break; |
3137 | 3171 | ||
@@ -3152,7 +3186,8 @@ done: | |||
3152 | return ptr - data; | 3186 | return ptr - data; |
3153 | } | 3187 | } |
3154 | 3188 | ||
3155 | static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, void *data, u16 *result) | 3189 | static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, |
3190 | void *data, u16 *result) | ||
3156 | { | 3191 | { |
3157 | struct l2cap_conf_req *req = data; | 3192 | struct l2cap_conf_req *req = data; |
3158 | void *ptr = req->data; | 3193 | void *ptr = req->data; |
@@ -3179,7 +3214,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi | |||
3179 | case L2CAP_CONF_FLUSH_TO: | 3214 | case L2CAP_CONF_FLUSH_TO: |
3180 | chan->flush_to = val; | 3215 | chan->flush_to = val; |
3181 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, | 3216 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, |
3182 | 2, chan->flush_to); | 3217 | 2, chan->flush_to); |
3183 | break; | 3218 | break; |
3184 | 3219 | ||
3185 | case L2CAP_CONF_RFC: | 3220 | case L2CAP_CONF_RFC: |
@@ -3187,13 +3222,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi | |||
3187 | memcpy(&rfc, (void *)val, olen); | 3222 | memcpy(&rfc, (void *)val, olen); |
3188 | 3223 | ||
3189 | if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && | 3224 | if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && |
3190 | rfc.mode != chan->mode) | 3225 | rfc.mode != chan->mode) |
3191 | return -ECONNREFUSED; | 3226 | return -ECONNREFUSED; |
3192 | 3227 | ||
3193 | chan->fcs = 0; | 3228 | chan->fcs = 0; |
3194 | 3229 | ||
3195 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, | 3230 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, |
3196 | sizeof(rfc), (unsigned long) &rfc); | 3231 | sizeof(rfc), (unsigned long) &rfc); |
3197 | break; | 3232 | break; |
3198 | 3233 | ||
3199 | case L2CAP_CONF_EWS: | 3234 | case L2CAP_CONF_EWS: |
@@ -3207,12 +3242,12 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi | |||
3207 | memcpy(&efs, (void *)val, olen); | 3242 | memcpy(&efs, (void *)val, olen); |
3208 | 3243 | ||
3209 | if (chan->local_stype != L2CAP_SERV_NOTRAFIC && | 3244 | if (chan->local_stype != L2CAP_SERV_NOTRAFIC && |
3210 | efs.stype != L2CAP_SERV_NOTRAFIC && | 3245 | efs.stype != L2CAP_SERV_NOTRAFIC && |
3211 | efs.stype != chan->local_stype) | 3246 | efs.stype != chan->local_stype) |
3212 | return -ECONNREFUSED; | 3247 | return -ECONNREFUSED; |
3213 | 3248 | ||
3214 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, | 3249 | l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), |
3215 | sizeof(efs), (unsigned long) &efs); | 3250 | (unsigned long) &efs); |
3216 | break; | 3251 | break; |
3217 | } | 3252 | } |
3218 | } | 3253 | } |
@@ -3235,10 +3270,10 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi | |||
3235 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { | 3270 | if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) { |
3236 | chan->local_msdu = le16_to_cpu(efs.msdu); | 3271 | chan->local_msdu = le16_to_cpu(efs.msdu); |
3237 | chan->local_sdu_itime = | 3272 | chan->local_sdu_itime = |
3238 | le32_to_cpu(efs.sdu_itime); | 3273 | le32_to_cpu(efs.sdu_itime); |
3239 | chan->local_acc_lat = le32_to_cpu(efs.acc_lat); | 3274 | chan->local_acc_lat = le32_to_cpu(efs.acc_lat); |
3240 | chan->local_flush_to = | 3275 | chan->local_flush_to = |
3241 | le32_to_cpu(efs.flush_to); | 3276 | le32_to_cpu(efs.flush_to); |
3242 | } | 3277 | } |
3243 | break; | 3278 | break; |
3244 | 3279 | ||
@@ -3253,7 +3288,8 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, voi | |||
3253 | return ptr - data; | 3288 | return ptr - data; |
3254 | } | 3289 | } |
3255 | 3290 | ||
3256 | static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, u16 result, u16 flags) | 3291 | static int l2cap_build_conf_rsp(struct l2cap_chan *chan, void *data, |
3292 | u16 result, u16 flags) | ||
3257 | { | 3293 | { |
3258 | struct l2cap_conf_rsp *rsp = data; | 3294 | struct l2cap_conf_rsp *rsp = data; |
3259 | void *ptr = rsp->data; | 3295 | void *ptr = rsp->data; |
@@ -3277,14 +3313,13 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) | |||
3277 | rsp.dcid = cpu_to_le16(chan->scid); | 3313 | rsp.dcid = cpu_to_le16(chan->scid); |
3278 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); | 3314 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); |
3279 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | 3315 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); |
3280 | l2cap_send_cmd(conn, chan->ident, | 3316 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); |
3281 | L2CAP_CONN_RSP, sizeof(rsp), &rsp); | ||
3282 | 3317 | ||
3283 | if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) | 3318 | if (test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) |
3284 | return; | 3319 | return; |
3285 | 3320 | ||
3286 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, | 3321 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, |
3287 | l2cap_build_conf_req(chan, buf), buf); | 3322 | l2cap_build_conf_req(chan, buf), buf); |
3288 | chan->num_conf_req++; | 3323 | chan->num_conf_req++; |
3289 | } | 3324 | } |
3290 | 3325 | ||
@@ -3339,7 +3374,8 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) | |||
3339 | } | 3374 | } |
3340 | } | 3375 | } |
3341 | 3376 | ||
3342 | static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | 3377 | static inline int l2cap_command_rej(struct l2cap_conn *conn, |
3378 | struct l2cap_cmd_hdr *cmd, u8 *data) | ||
3343 | { | 3379 | { |
3344 | struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; | 3380 | struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; |
3345 | 3381 | ||
@@ -3347,7 +3383,7 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
3347 | return 0; | 3383 | return 0; |
3348 | 3384 | ||
3349 | if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && | 3385 | if ((conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_SENT) && |
3350 | cmd->ident == conn->info_ident) { | 3386 | cmd->ident == conn->info_ident) { |
3351 | cancel_delayed_work(&conn->info_timer); | 3387 | cancel_delayed_work(&conn->info_timer); |
3352 | 3388 | ||
3353 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; | 3389 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; |
@@ -3359,7 +3395,8 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
3359 | return 0; | 3395 | return 0; |
3360 | } | 3396 | } |
3361 | 3397 | ||
3362 | static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | 3398 | static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, |
3399 | u8 *data, u8 rsp_code, u8 amp_id) | ||
3363 | { | 3400 | { |
3364 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; | 3401 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; |
3365 | struct l2cap_conn_rsp rsp; | 3402 | struct l2cap_conn_rsp rsp; |
@@ -3386,7 +3423,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
3386 | 3423 | ||
3387 | /* Check if the ACL is secure enough (if not SDP) */ | 3424 | /* Check if the ACL is secure enough (if not SDP) */ |
3388 | if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && | 3425 | if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && |
3389 | !hci_conn_check_link_mode(conn->hcon)) { | 3426 | !hci_conn_check_link_mode(conn->hcon)) { |
3390 | conn->disc_reason = HCI_ERROR_AUTH_FAILURE; | 3427 | conn->disc_reason = HCI_ERROR_AUTH_FAILURE; |
3391 | result = L2CAP_CR_SEC_BLOCK; | 3428 | result = L2CAP_CR_SEC_BLOCK; |
3392 | goto response; | 3429 | goto response; |
@@ -3411,8 +3448,6 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
3411 | chan->psm = psm; | 3448 | chan->psm = psm; |
3412 | chan->dcid = scid; | 3449 | chan->dcid = scid; |
3413 | 3450 | ||
3414 | bt_accept_enqueue(parent, sk); | ||
3415 | |||
3416 | __l2cap_chan_add(conn, chan); | 3451 | __l2cap_chan_add(conn, chan); |
3417 | 3452 | ||
3418 | dcid = chan->scid; | 3453 | dcid = chan->scid; |
@@ -3427,7 +3462,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
3427 | __l2cap_state_change(chan, BT_CONNECT2); | 3462 | __l2cap_state_change(chan, BT_CONNECT2); |
3428 | result = L2CAP_CR_PEND; | 3463 | result = L2CAP_CR_PEND; |
3429 | status = L2CAP_CS_AUTHOR_PEND; | 3464 | status = L2CAP_CS_AUTHOR_PEND; |
3430 | parent->sk_data_ready(parent, 0); | 3465 | chan->ops->defer(chan); |
3431 | } else { | 3466 | } else { |
3432 | __l2cap_state_change(chan, BT_CONFIG); | 3467 | __l2cap_state_change(chan, BT_CONFIG); |
3433 | result = L2CAP_CR_SUCCESS; | 3468 | result = L2CAP_CR_SUCCESS; |
@@ -3453,7 +3488,7 @@ sendresp: | |||
3453 | rsp.dcid = cpu_to_le16(dcid); | 3488 | rsp.dcid = cpu_to_le16(dcid); |
3454 | rsp.result = cpu_to_le16(result); | 3489 | rsp.result = cpu_to_le16(result); |
3455 | rsp.status = cpu_to_le16(status); | 3490 | rsp.status = cpu_to_le16(status); |
3456 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 3491 | l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp); |
3457 | 3492 | ||
3458 | if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { | 3493 | if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { |
3459 | struct l2cap_info_req info; | 3494 | struct l2cap_info_req info; |
@@ -3464,23 +3499,29 @@ sendresp: | |||
3464 | 3499 | ||
3465 | schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); | 3500 | schedule_delayed_work(&conn->info_timer, L2CAP_INFO_TIMEOUT); |
3466 | 3501 | ||
3467 | l2cap_send_cmd(conn, conn->info_ident, | 3502 | l2cap_send_cmd(conn, conn->info_ident, L2CAP_INFO_REQ, |
3468 | L2CAP_INFO_REQ, sizeof(info), &info); | 3503 | sizeof(info), &info); |
3469 | } | 3504 | } |
3470 | 3505 | ||
3471 | if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && | 3506 | if (chan && !test_bit(CONF_REQ_SENT, &chan->conf_state) && |
3472 | result == L2CAP_CR_SUCCESS) { | 3507 | result == L2CAP_CR_SUCCESS) { |
3473 | u8 buf[128]; | 3508 | u8 buf[128]; |
3474 | set_bit(CONF_REQ_SENT, &chan->conf_state); | 3509 | set_bit(CONF_REQ_SENT, &chan->conf_state); |
3475 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, | 3510 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, |
3476 | l2cap_build_conf_req(chan, buf), buf); | 3511 | l2cap_build_conf_req(chan, buf), buf); |
3477 | chan->num_conf_req++; | 3512 | chan->num_conf_req++; |
3478 | } | 3513 | } |
3514 | } | ||
3479 | 3515 | ||
3516 | static int l2cap_connect_req(struct l2cap_conn *conn, | ||
3517 | struct l2cap_cmd_hdr *cmd, u8 *data) | ||
3518 | { | ||
3519 | l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0); | ||
3480 | return 0; | 3520 | return 0; |
3481 | } | 3521 | } |
3482 | 3522 | ||
3483 | static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | 3523 | static inline int l2cap_connect_rsp(struct l2cap_conn *conn, |
3524 | struct l2cap_cmd_hdr *cmd, u8 *data) | ||
3484 | { | 3525 | { |
3485 | struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; | 3526 | struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; |
3486 | u16 scid, dcid, result, status; | 3527 | u16 scid, dcid, result, status; |
@@ -3494,7 +3535,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
3494 | status = __le16_to_cpu(rsp->status); | 3535 | status = __le16_to_cpu(rsp->status); |
3495 | 3536 | ||
3496 | BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", | 3537 | BT_DBG("dcid 0x%4.4x scid 0x%4.4x result 0x%2.2x status 0x%2.2x", |
3497 | dcid, scid, result, status); | 3538 | dcid, scid, result, status); |
3498 | 3539 | ||
3499 | mutex_lock(&conn->chan_lock); | 3540 | mutex_lock(&conn->chan_lock); |
3500 | 3541 | ||
@@ -3527,7 +3568,7 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
3527 | break; | 3568 | break; |
3528 | 3569 | ||
3529 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, | 3570 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, |
3530 | l2cap_build_conf_req(chan, req), req); | 3571 | l2cap_build_conf_req(chan, req), req); |
3531 | chan->num_conf_req++; | 3572 | chan->num_conf_req++; |
3532 | break; | 3573 | break; |
3533 | 3574 | ||
@@ -3559,7 +3600,25 @@ static inline void set_default_fcs(struct l2cap_chan *chan) | |||
3559 | chan->fcs = L2CAP_FCS_CRC16; | 3600 | chan->fcs = L2CAP_FCS_CRC16; |
3560 | } | 3601 | } |
3561 | 3602 | ||
3562 | static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) | 3603 | static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data, |
3604 | u8 ident, u16 flags) | ||
3605 | { | ||
3606 | struct l2cap_conn *conn = chan->conn; | ||
3607 | |||
3608 | BT_DBG("conn %p chan %p ident %d flags 0x%4.4x", conn, chan, ident, | ||
3609 | flags); | ||
3610 | |||
3611 | clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); | ||
3612 | set_bit(CONF_OUTPUT_DONE, &chan->conf_state); | ||
3613 | |||
3614 | l2cap_send_cmd(conn, ident, L2CAP_CONF_RSP, | ||
3615 | l2cap_build_conf_rsp(chan, data, | ||
3616 | L2CAP_CONF_SUCCESS, flags), data); | ||
3617 | } | ||
3618 | |||
3619 | static inline int l2cap_config_req(struct l2cap_conn *conn, | ||
3620 | struct l2cap_cmd_hdr *cmd, u16 cmd_len, | ||
3621 | u8 *data) | ||
3563 | { | 3622 | { |
3564 | struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; | 3623 | struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; |
3565 | u16 dcid, flags; | 3624 | u16 dcid, flags; |
@@ -3584,7 +3643,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
3584 | rej.dcid = cpu_to_le16(chan->dcid); | 3643 | rej.dcid = cpu_to_le16(chan->dcid); |
3585 | 3644 | ||
3586 | l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, | 3645 | l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, |
3587 | sizeof(rej), &rej); | 3646 | sizeof(rej), &rej); |
3588 | goto unlock; | 3647 | goto unlock; |
3589 | } | 3648 | } |
3590 | 3649 | ||
@@ -3592,8 +3651,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
3592 | len = cmd_len - sizeof(*req); | 3651 | len = cmd_len - sizeof(*req); |
3593 | if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) { | 3652 | if (len < 0 || chan->conf_len + len > sizeof(chan->conf_req)) { |
3594 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, | 3653 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, |
3595 | l2cap_build_conf_rsp(chan, rsp, | 3654 | l2cap_build_conf_rsp(chan, rsp, |
3596 | L2CAP_CONF_REJECT, flags), rsp); | 3655 | L2CAP_CONF_REJECT, flags), rsp); |
3597 | goto unlock; | 3656 | goto unlock; |
3598 | } | 3657 | } |
3599 | 3658 | ||
@@ -3604,8 +3663,8 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
3604 | if (flags & L2CAP_CONF_FLAG_CONTINUATION) { | 3663 | if (flags & L2CAP_CONF_FLAG_CONTINUATION) { |
3605 | /* Incomplete config. Send empty response. */ | 3664 | /* Incomplete config. Send empty response. */ |
3606 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, | 3665 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, |
3607 | l2cap_build_conf_rsp(chan, rsp, | 3666 | l2cap_build_conf_rsp(chan, rsp, |
3608 | L2CAP_CONF_SUCCESS, flags), rsp); | 3667 | L2CAP_CONF_SUCCESS, flags), rsp); |
3609 | goto unlock; | 3668 | goto unlock; |
3610 | } | 3669 | } |
3611 | 3670 | ||
@@ -3643,23 +3702,22 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
3643 | if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { | 3702 | if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { |
3644 | u8 buf[64]; | 3703 | u8 buf[64]; |
3645 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, | 3704 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ, |
3646 | l2cap_build_conf_req(chan, buf), buf); | 3705 | l2cap_build_conf_req(chan, buf), buf); |
3647 | chan->num_conf_req++; | 3706 | chan->num_conf_req++; |
3648 | } | 3707 | } |
3649 | 3708 | ||
3650 | /* Got Conf Rsp PENDING from remote side and asume we sent | 3709 | /* Got Conf Rsp PENDING from remote side and asume we sent |
3651 | Conf Rsp PENDING in the code above */ | 3710 | Conf Rsp PENDING in the code above */ |
3652 | if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && | 3711 | if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) && |
3653 | test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { | 3712 | test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) { |
3654 | 3713 | ||
3655 | /* check compatibility */ | 3714 | /* check compatibility */ |
3656 | 3715 | ||
3657 | clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); | 3716 | /* Send rsp for BR/EDR channel */ |
3658 | set_bit(CONF_OUTPUT_DONE, &chan->conf_state); | 3717 | if (!chan->ctrl_id) |
3659 | 3718 | l2cap_send_efs_conf_rsp(chan, rsp, cmd->ident, flags); | |
3660 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, | 3719 | else |
3661 | l2cap_build_conf_rsp(chan, rsp, | 3720 | chan->ident = cmd->ident; |
3662 | L2CAP_CONF_SUCCESS, flags), rsp); | ||
3663 | } | 3721 | } |
3664 | 3722 | ||
3665 | unlock: | 3723 | unlock: |
@@ -3667,7 +3725,8 @@ unlock: | |||
3667 | return err; | 3725 | return err; |
3668 | } | 3726 | } |
3669 | 3727 | ||
3670 | static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | 3728 | static inline int l2cap_config_rsp(struct l2cap_conn *conn, |
3729 | struct l2cap_cmd_hdr *cmd, u8 *data) | ||
3671 | { | 3730 | { |
3672 | struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; | 3731 | struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; |
3673 | u16 scid, flags, result; | 3732 | u16 scid, flags, result; |
@@ -3699,7 +3758,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
3699 | char buf[64]; | 3758 | char buf[64]; |
3700 | 3759 | ||
3701 | len = l2cap_parse_conf_rsp(chan, rsp->data, len, | 3760 | len = l2cap_parse_conf_rsp(chan, rsp->data, len, |
3702 | buf, &result); | 3761 | buf, &result); |
3703 | if (len < 0) { | 3762 | if (len < 0) { |
3704 | l2cap_send_disconn_req(conn, chan, ECONNRESET); | 3763 | l2cap_send_disconn_req(conn, chan, ECONNRESET); |
3705 | goto done; | 3764 | goto done; |
@@ -3707,12 +3766,11 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
3707 | 3766 | ||
3708 | /* check compatibility */ | 3767 | /* check compatibility */ |
3709 | 3768 | ||
3710 | clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); | 3769 | if (!chan->ctrl_id) |
3711 | set_bit(CONF_OUTPUT_DONE, &chan->conf_state); | 3770 | l2cap_send_efs_conf_rsp(chan, buf, cmd->ident, |
3712 | 3771 | 0); | |
3713 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONF_RSP, | 3772 | else |
3714 | l2cap_build_conf_rsp(chan, buf, | 3773 | chan->ident = cmd->ident; |
3715 | L2CAP_CONF_SUCCESS, 0x0000), buf); | ||
3716 | } | 3774 | } |
3717 | goto done; | 3775 | goto done; |
3718 | 3776 | ||
@@ -3728,14 +3786,14 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr | |||
3728 | /* throw out any old stored conf requests */ | 3786 | /* throw out any old stored conf requests */ |
3729 | result = L2CAP_CONF_SUCCESS; | 3787 | result = L2CAP_CONF_SUCCESS; |
3730 | len = l2cap_parse_conf_rsp(chan, rsp->data, len, | 3788 | len = l2cap_parse_conf_rsp(chan, rsp->data, len, |
3731 | req, &result); | 3789 | req, &result); |
3732 | if (len < 0) { | 3790 | if (len < 0) { |
3733 | l2cap_send_disconn_req(conn, chan, ECONNRESET); | 3791 | l2cap_send_disconn_req(conn, chan, ECONNRESET); |
3734 | goto done; | 3792 | goto done; |
3735 | } | 3793 | } |
3736 | 3794 | ||
3737 | l2cap_send_cmd(conn, l2cap_get_ident(conn), | 3795 | l2cap_send_cmd(conn, l2cap_get_ident(conn), |
3738 | L2CAP_CONF_REQ, len, req); | 3796 | L2CAP_CONF_REQ, len, req); |
3739 | chan->num_conf_req++; | 3797 | chan->num_conf_req++; |
3740 | if (result != L2CAP_CONF_SUCCESS) | 3798 | if (result != L2CAP_CONF_SUCCESS) |
3741 | goto done; | 3799 | goto done; |
@@ -3773,7 +3831,8 @@ done: | |||
3773 | return err; | 3831 | return err; |
3774 | } | 3832 | } |
3775 | 3833 | ||
3776 | static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | 3834 | static inline int l2cap_disconnect_req(struct l2cap_conn *conn, |
3835 | struct l2cap_cmd_hdr *cmd, u8 *data) | ||
3777 | { | 3836 | { |
3778 | struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; | 3837 | struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; |
3779 | struct l2cap_disconn_rsp rsp; | 3838 | struct l2cap_disconn_rsp rsp; |
@@ -3819,7 +3878,8 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd | |||
3819 | return 0; | 3878 | return 0; |
3820 | } | 3879 | } |
3821 | 3880 | ||
3822 | static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | 3881 | static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, |
3882 | struct l2cap_cmd_hdr *cmd, u8 *data) | ||
3823 | { | 3883 | { |
3824 | struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; | 3884 | struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; |
3825 | u16 dcid, scid; | 3885 | u16 dcid, scid; |
@@ -3853,7 +3913,8 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd | |||
3853 | return 0; | 3913 | return 0; |
3854 | } | 3914 | } |
3855 | 3915 | ||
3856 | static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | 3916 | static inline int l2cap_information_req(struct l2cap_conn *conn, |
3917 | struct l2cap_cmd_hdr *cmd, u8 *data) | ||
3857 | { | 3918 | { |
3858 | struct l2cap_info_req *req = (struct l2cap_info_req *) data; | 3919 | struct l2cap_info_req *req = (struct l2cap_info_req *) data; |
3859 | u16 type; | 3920 | u16 type; |
@@ -3870,14 +3931,14 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm | |||
3870 | rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); | 3931 | rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); |
3871 | if (!disable_ertm) | 3932 | if (!disable_ertm) |
3872 | feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING | 3933 | feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING |
3873 | | L2CAP_FEAT_FCS; | 3934 | | L2CAP_FEAT_FCS; |
3874 | if (enable_hs) | 3935 | if (enable_hs) |
3875 | feat_mask |= L2CAP_FEAT_EXT_FLOW | 3936 | feat_mask |= L2CAP_FEAT_EXT_FLOW |
3876 | | L2CAP_FEAT_EXT_WINDOW; | 3937 | | L2CAP_FEAT_EXT_WINDOW; |
3877 | 3938 | ||
3878 | put_unaligned_le32(feat_mask, rsp->data); | 3939 | put_unaligned_le32(feat_mask, rsp->data); |
3879 | l2cap_send_cmd(conn, cmd->ident, | 3940 | l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), |
3880 | L2CAP_INFO_RSP, sizeof(buf), buf); | 3941 | buf); |
3881 | } else if (type == L2CAP_IT_FIXED_CHAN) { | 3942 | } else if (type == L2CAP_IT_FIXED_CHAN) { |
3882 | u8 buf[12]; | 3943 | u8 buf[12]; |
3883 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; | 3944 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; |
@@ -3890,20 +3951,21 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, struct l2cap_cm | |||
3890 | rsp->type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); | 3951 | rsp->type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); |
3891 | rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); | 3952 | rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); |
3892 | memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); | 3953 | memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); |
3893 | l2cap_send_cmd(conn, cmd->ident, | 3954 | l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), |
3894 | L2CAP_INFO_RSP, sizeof(buf), buf); | 3955 | buf); |
3895 | } else { | 3956 | } else { |
3896 | struct l2cap_info_rsp rsp; | 3957 | struct l2cap_info_rsp rsp; |
3897 | rsp.type = cpu_to_le16(type); | 3958 | rsp.type = cpu_to_le16(type); |
3898 | rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP); | 3959 | rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP); |
3899 | l2cap_send_cmd(conn, cmd->ident, | 3960 | l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), |
3900 | L2CAP_INFO_RSP, sizeof(rsp), &rsp); | 3961 | &rsp); |
3901 | } | 3962 | } |
3902 | 3963 | ||
3903 | return 0; | 3964 | return 0; |
3904 | } | 3965 | } |
3905 | 3966 | ||
3906 | static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data) | 3967 | static inline int l2cap_information_rsp(struct l2cap_conn *conn, |
3968 | struct l2cap_cmd_hdr *cmd, u8 *data) | ||
3907 | { | 3969 | { |
3908 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; | 3970 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; |
3909 | u16 type, result; | 3971 | u16 type, result; |
@@ -3915,7 +3977,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm | |||
3915 | 3977 | ||
3916 | /* L2CAP Info req/rsp are unbound to channels, add extra checks */ | 3978 | /* L2CAP Info req/rsp are unbound to channels, add extra checks */ |
3917 | if (cmd->ident != conn->info_ident || | 3979 | if (cmd->ident != conn->info_ident || |
3918 | conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) | 3980 | conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) |
3919 | return 0; | 3981 | return 0; |
3920 | 3982 | ||
3921 | cancel_delayed_work(&conn->info_timer); | 3983 | cancel_delayed_work(&conn->info_timer); |
@@ -3940,7 +4002,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm | |||
3940 | conn->info_ident = l2cap_get_ident(conn); | 4002 | conn->info_ident = l2cap_get_ident(conn); |
3941 | 4003 | ||
3942 | l2cap_send_cmd(conn, conn->info_ident, | 4004 | l2cap_send_cmd(conn, conn->info_ident, |
3943 | L2CAP_INFO_REQ, sizeof(req), &req); | 4005 | L2CAP_INFO_REQ, sizeof(req), &req); |
3944 | } else { | 4006 | } else { |
3945 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; | 4007 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE; |
3946 | conn->info_ident = 0; | 4008 | conn->info_ident = 0; |
@@ -3962,8 +4024,8 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cm | |||
3962 | } | 4024 | } |
3963 | 4025 | ||
3964 | static inline int l2cap_create_channel_req(struct l2cap_conn *conn, | 4026 | static inline int l2cap_create_channel_req(struct l2cap_conn *conn, |
3965 | struct l2cap_cmd_hdr *cmd, u16 cmd_len, | 4027 | struct l2cap_cmd_hdr *cmd, |
3966 | void *data) | 4028 | u16 cmd_len, void *data) |
3967 | { | 4029 | { |
3968 | struct l2cap_create_chan_req *req = data; | 4030 | struct l2cap_create_chan_req *req = data; |
3969 | struct l2cap_create_chan_rsp rsp; | 4031 | struct l2cap_create_chan_rsp rsp; |
@@ -3993,7 +4055,8 @@ static inline int l2cap_create_channel_req(struct l2cap_conn *conn, | |||
3993 | } | 4055 | } |
3994 | 4056 | ||
3995 | static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn, | 4057 | static inline int l2cap_create_channel_rsp(struct l2cap_conn *conn, |
3996 | struct l2cap_cmd_hdr *cmd, void *data) | 4058 | struct l2cap_cmd_hdr *cmd, |
4059 | void *data) | ||
3997 | { | 4060 | { |
3998 | BT_DBG("conn %p", conn); | 4061 | BT_DBG("conn %p", conn); |
3999 | 4062 | ||
@@ -4126,7 +4189,7 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, | |||
4126 | } | 4189 | } |
4127 | 4190 | ||
4128 | static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, | 4191 | static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, |
4129 | u16 to_multiplier) | 4192 | u16 to_multiplier) |
4130 | { | 4193 | { |
4131 | u16 max_latency; | 4194 | u16 max_latency; |
4132 | 4195 | ||
@@ -4147,7 +4210,8 @@ static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, | |||
4147 | } | 4210 | } |
4148 | 4211 | ||
4149 | static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, | 4212 | static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, |
4150 | struct l2cap_cmd_hdr *cmd, u8 *data) | 4213 | struct l2cap_cmd_hdr *cmd, |
4214 | u8 *data) | ||
4151 | { | 4215 | { |
4152 | struct hci_conn *hcon = conn->hcon; | 4216 | struct hci_conn *hcon = conn->hcon; |
4153 | struct l2cap_conn_param_update_req *req; | 4217 | struct l2cap_conn_param_update_req *req; |
@@ -4169,7 +4233,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, | |||
4169 | to_multiplier = __le16_to_cpu(req->to_multiplier); | 4233 | to_multiplier = __le16_to_cpu(req->to_multiplier); |
4170 | 4234 | ||
4171 | BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", | 4235 | BT_DBG("min 0x%4.4x max 0x%4.4x latency: 0x%4.4x Timeout: 0x%4.4x", |
4172 | min, max, latency, to_multiplier); | 4236 | min, max, latency, to_multiplier); |
4173 | 4237 | ||
4174 | memset(&rsp, 0, sizeof(rsp)); | 4238 | memset(&rsp, 0, sizeof(rsp)); |
4175 | 4239 | ||
@@ -4180,7 +4244,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, | |||
4180 | rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); | 4244 | rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); |
4181 | 4245 | ||
4182 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, | 4246 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, |
4183 | sizeof(rsp), &rsp); | 4247 | sizeof(rsp), &rsp); |
4184 | 4248 | ||
4185 | if (!err) | 4249 | if (!err) |
4186 | hci_le_conn_update(hcon, min, max, latency, to_multiplier); | 4250 | hci_le_conn_update(hcon, min, max, latency, to_multiplier); |
@@ -4189,7 +4253,8 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, | |||
4189 | } | 4253 | } |
4190 | 4254 | ||
4191 | static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, | 4255 | static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, |
4192 | struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) | 4256 | struct l2cap_cmd_hdr *cmd, u16 cmd_len, |
4257 | u8 *data) | ||
4193 | { | 4258 | { |
4194 | int err = 0; | 4259 | int err = 0; |
4195 | 4260 | ||
@@ -4203,6 +4268,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, | |||
4203 | break; | 4268 | break; |
4204 | 4269 | ||
4205 | case L2CAP_CONN_RSP: | 4270 | case L2CAP_CONN_RSP: |
4271 | case L2CAP_CREATE_CHAN_RSP: | ||
4206 | err = l2cap_connect_rsp(conn, cmd, data); | 4272 | err = l2cap_connect_rsp(conn, cmd, data); |
4207 | break; | 4273 | break; |
4208 | 4274 | ||
@@ -4241,10 +4307,6 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, | |||
4241 | err = l2cap_create_channel_req(conn, cmd, cmd_len, data); | 4307 | err = l2cap_create_channel_req(conn, cmd, cmd_len, data); |
4242 | break; | 4308 | break; |
4243 | 4309 | ||
4244 | case L2CAP_CREATE_CHAN_RSP: | ||
4245 | err = l2cap_create_channel_rsp(conn, cmd, data); | ||
4246 | break; | ||
4247 | |||
4248 | case L2CAP_MOVE_CHAN_REQ: | 4310 | case L2CAP_MOVE_CHAN_REQ: |
4249 | err = l2cap_move_channel_req(conn, cmd, cmd_len, data); | 4311 | err = l2cap_move_channel_req(conn, cmd, cmd_len, data); |
4250 | break; | 4312 | break; |
@@ -4271,7 +4333,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, | |||
4271 | } | 4333 | } |
4272 | 4334 | ||
4273 | static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, | 4335 | static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, |
4274 | struct l2cap_cmd_hdr *cmd, u8 *data) | 4336 | struct l2cap_cmd_hdr *cmd, u8 *data) |
4275 | { | 4337 | { |
4276 | switch (cmd->code) { | 4338 | switch (cmd->code) { |
4277 | case L2CAP_COMMAND_REJ: | 4339 | case L2CAP_COMMAND_REJ: |
@@ -4290,7 +4352,7 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, | |||
4290 | } | 4352 | } |
4291 | 4353 | ||
4292 | static inline void l2cap_sig_channel(struct l2cap_conn *conn, | 4354 | static inline void l2cap_sig_channel(struct l2cap_conn *conn, |
4293 | struct sk_buff *skb) | 4355 | struct sk_buff *skb) |
4294 | { | 4356 | { |
4295 | u8 *data = skb->data; | 4357 | u8 *data = skb->data; |
4296 | int len = skb->len; | 4358 | int len = skb->len; |
@@ -4307,7 +4369,8 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, | |||
4307 | 4369 | ||
4308 | cmd_len = le16_to_cpu(cmd.len); | 4370 | cmd_len = le16_to_cpu(cmd.len); |
4309 | 4371 | ||
4310 | BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, cmd.ident); | 4372 | BT_DBG("code 0x%2.2x len %d id 0x%2.2x", cmd.code, cmd_len, |
4373 | cmd.ident); | ||
4311 | 4374 | ||
4312 | if (cmd_len > len || !cmd.ident) { | 4375 | if (cmd_len > len || !cmd.ident) { |
4313 | BT_DBG("corrupted command"); | 4376 | BT_DBG("corrupted command"); |
@@ -4326,7 +4389,8 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, | |||
4326 | 4389 | ||
4327 | /* FIXME: Map err to a valid reason */ | 4390 | /* FIXME: Map err to a valid reason */ |
4328 | rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); | 4391 | rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); |
4329 | l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej); | 4392 | l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, |
4393 | sizeof(rej), &rej); | ||
4330 | } | 4394 | } |
4331 | 4395 | ||
4332 | data += cmd_len; | 4396 | data += cmd_len; |
@@ -4391,8 +4455,8 @@ static void l2cap_send_i_or_rr_or_rnr(struct l2cap_chan *chan) | |||
4391 | } | 4455 | } |
4392 | } | 4456 | } |
4393 | 4457 | ||
4394 | static void append_skb_frag(struct sk_buff *skb, | 4458 | static void append_skb_frag(struct sk_buff *skb, struct sk_buff *new_frag, |
4395 | struct sk_buff *new_frag, struct sk_buff **last_frag) | 4459 | struct sk_buff **last_frag) |
4396 | { | 4460 | { |
4397 | /* skb->len reflects data in skb as well as all fragments | 4461 | /* skb->len reflects data in skb as well as all fragments |
4398 | * skb->data_len reflects only data in fragments | 4462 | * skb->data_len reflects only data in fragments |
@@ -4641,7 +4705,7 @@ static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) | |||
4641 | 4705 | ||
4642 | if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { | 4706 | if (chan->rx_state == L2CAP_RX_STATE_SREJ_SENT) { |
4643 | if (__seq_offset(chan, txseq, chan->last_acked_seq) >= | 4707 | if (__seq_offset(chan, txseq, chan->last_acked_seq) >= |
4644 | chan->tx_win) { | 4708 | chan->tx_win) { |
4645 | /* See notes below regarding "double poll" and | 4709 | /* See notes below regarding "double poll" and |
4646 | * invalid packets. | 4710 | * invalid packets. |
4647 | */ | 4711 | */ |
@@ -4682,8 +4746,7 @@ static u8 l2cap_classify_txseq(struct l2cap_chan *chan, u16 txseq) | |||
4682 | } | 4746 | } |
4683 | 4747 | ||
4684 | if (__seq_offset(chan, txseq, chan->last_acked_seq) < | 4748 | if (__seq_offset(chan, txseq, chan->last_acked_seq) < |
4685 | __seq_offset(chan, chan->expected_tx_seq, | 4749 | __seq_offset(chan, chan->expected_tx_seq, chan->last_acked_seq)) { |
4686 | chan->last_acked_seq)){ | ||
4687 | BT_DBG("Duplicate - expected_tx_seq later than txseq"); | 4750 | BT_DBG("Duplicate - expected_tx_seq later than txseq"); |
4688 | return L2CAP_TXSEQ_DUPLICATE; | 4751 | return L2CAP_TXSEQ_DUPLICATE; |
4689 | } | 4752 | } |
@@ -5323,7 +5386,7 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
5323 | int exact = 0, lm1 = 0, lm2 = 0; | 5386 | int exact = 0, lm1 = 0, lm2 = 0; |
5324 | struct l2cap_chan *c; | 5387 | struct l2cap_chan *c; |
5325 | 5388 | ||
5326 | BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); | 5389 | BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr); |
5327 | 5390 | ||
5328 | /* Find listening sockets and check their link_mode */ | 5391 | /* Find listening sockets and check their link_mode */ |
5329 | read_lock(&chan_list_lock); | 5392 | read_lock(&chan_list_lock); |
@@ -5353,7 +5416,7 @@ void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) | |||
5353 | { | 5416 | { |
5354 | struct l2cap_conn *conn; | 5417 | struct l2cap_conn *conn; |
5355 | 5418 | ||
5356 | BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); | 5419 | BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); |
5357 | 5420 | ||
5358 | if (!status) { | 5421 | if (!status) { |
5359 | conn = l2cap_conn_add(hcon, status); | 5422 | conn = l2cap_conn_add(hcon, status); |
@@ -5443,7 +5506,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
5443 | } | 5506 | } |
5444 | 5507 | ||
5445 | if (!status && (chan->state == BT_CONNECTED || | 5508 | if (!status && (chan->state == BT_CONNECTED || |
5446 | chan->state == BT_CONFIG)) { | 5509 | chan->state == BT_CONFIG)) { |
5447 | struct sock *sk = chan->sk; | 5510 | struct sock *sk = chan->sk; |
5448 | 5511 | ||
5449 | clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); | 5512 | clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); |
@@ -5456,7 +5519,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
5456 | 5519 | ||
5457 | if (chan->state == BT_CONNECT) { | 5520 | if (chan->state == BT_CONNECT) { |
5458 | if (!status) { | 5521 | if (!status) { |
5459 | l2cap_send_conn_req(chan); | 5522 | l2cap_start_connection(chan); |
5460 | } else { | 5523 | } else { |
5461 | __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); | 5524 | __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); |
5462 | } | 5525 | } |
@@ -5470,11 +5533,9 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
5470 | if (!status) { | 5533 | if (!status) { |
5471 | if (test_bit(BT_SK_DEFER_SETUP, | 5534 | if (test_bit(BT_SK_DEFER_SETUP, |
5472 | &bt_sk(sk)->flags)) { | 5535 | &bt_sk(sk)->flags)) { |
5473 | struct sock *parent = bt_sk(sk)->parent; | ||
5474 | res = L2CAP_CR_PEND; | 5536 | res = L2CAP_CR_PEND; |
5475 | stat = L2CAP_CS_AUTHOR_PEND; | 5537 | stat = L2CAP_CS_AUTHOR_PEND; |
5476 | if (parent) | 5538 | chan->ops->defer(chan); |
5477 | parent->sk_data_ready(parent, 0); | ||
5478 | } else { | 5539 | } else { |
5479 | __l2cap_state_change(chan, BT_CONFIG); | 5540 | __l2cap_state_change(chan, BT_CONFIG); |
5480 | res = L2CAP_CR_SUCCESS; | 5541 | res = L2CAP_CR_SUCCESS; |
@@ -5494,7 +5555,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
5494 | rsp.result = cpu_to_le16(res); | 5555 | rsp.result = cpu_to_le16(res); |
5495 | rsp.status = cpu_to_le16(stat); | 5556 | rsp.status = cpu_to_le16(stat); |
5496 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, | 5557 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, |
5497 | sizeof(rsp), &rsp); | 5558 | sizeof(rsp), &rsp); |
5498 | 5559 | ||
5499 | if (!test_bit(CONF_REQ_SENT, &chan->conf_state) && | 5560 | if (!test_bit(CONF_REQ_SENT, &chan->conf_state) && |
5500 | res == L2CAP_CR_SUCCESS) { | 5561 | res == L2CAP_CR_SUCCESS) { |
@@ -5519,6 +5580,12 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
5519 | int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) | 5580 | int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) |
5520 | { | 5581 | { |
5521 | struct l2cap_conn *conn = hcon->l2cap_data; | 5582 | struct l2cap_conn *conn = hcon->l2cap_data; |
5583 | struct l2cap_hdr *hdr; | ||
5584 | int len; | ||
5585 | |||
5586 | /* For AMP controller do not create l2cap conn */ | ||
5587 | if (!conn && hcon->hdev->dev_type != HCI_BREDR) | ||
5588 | goto drop; | ||
5522 | 5589 | ||
5523 | if (!conn) | 5590 | if (!conn) |
5524 | conn = l2cap_conn_add(hcon, 0); | 5591 | conn = l2cap_conn_add(hcon, 0); |
@@ -5528,10 +5595,10 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) | |||
5528 | 5595 | ||
5529 | BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); | 5596 | BT_DBG("conn %p len %d flags 0x%x", conn, skb->len, flags); |
5530 | 5597 | ||
5531 | if (!(flags & ACL_CONT)) { | 5598 | switch (flags) { |
5532 | struct l2cap_hdr *hdr; | 5599 | case ACL_START: |
5533 | int len; | 5600 | case ACL_START_NO_FLUSH: |
5534 | 5601 | case ACL_COMPLETE: | |
5535 | if (conn->rx_len) { | 5602 | if (conn->rx_len) { |
5536 | BT_ERR("Unexpected start frame (len %d)", skb->len); | 5603 | BT_ERR("Unexpected start frame (len %d)", skb->len); |
5537 | kfree_skb(conn->rx_skb); | 5604 | kfree_skb(conn->rx_skb); |
@@ -5560,20 +5627,22 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) | |||
5560 | 5627 | ||
5561 | if (skb->len > len) { | 5628 | if (skb->len > len) { |
5562 | BT_ERR("Frame is too long (len %d, expected len %d)", | 5629 | BT_ERR("Frame is too long (len %d, expected len %d)", |
5563 | skb->len, len); | 5630 | skb->len, len); |
5564 | l2cap_conn_unreliable(conn, ECOMM); | 5631 | l2cap_conn_unreliable(conn, ECOMM); |
5565 | goto drop; | 5632 | goto drop; |
5566 | } | 5633 | } |
5567 | 5634 | ||
5568 | /* Allocate skb for the complete frame (with header) */ | 5635 | /* Allocate skb for the complete frame (with header) */ |
5569 | conn->rx_skb = bt_skb_alloc(len, GFP_ATOMIC); | 5636 | conn->rx_skb = bt_skb_alloc(len, GFP_KERNEL); |
5570 | if (!conn->rx_skb) | 5637 | if (!conn->rx_skb) |
5571 | goto drop; | 5638 | goto drop; |
5572 | 5639 | ||
5573 | skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), | 5640 | skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), |
5574 | skb->len); | 5641 | skb->len); |
5575 | conn->rx_len = len - skb->len; | 5642 | conn->rx_len = len - skb->len; |
5576 | } else { | 5643 | break; |
5644 | |||
5645 | case ACL_CONT: | ||
5577 | BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); | 5646 | BT_DBG("Cont: frag len %d (expecting %d)", skb->len, conn->rx_len); |
5578 | 5647 | ||
5579 | if (!conn->rx_len) { | 5648 | if (!conn->rx_len) { |
@@ -5584,7 +5653,7 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) | |||
5584 | 5653 | ||
5585 | if (skb->len > conn->rx_len) { | 5654 | if (skb->len > conn->rx_len) { |
5586 | BT_ERR("Fragment is too long (len %d, expected %d)", | 5655 | BT_ERR("Fragment is too long (len %d, expected %d)", |
5587 | skb->len, conn->rx_len); | 5656 | skb->len, conn->rx_len); |
5588 | kfree_skb(conn->rx_skb); | 5657 | kfree_skb(conn->rx_skb); |
5589 | conn->rx_skb = NULL; | 5658 | conn->rx_skb = NULL; |
5590 | conn->rx_len = 0; | 5659 | conn->rx_len = 0; |
@@ -5593,7 +5662,7 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) | |||
5593 | } | 5662 | } |
5594 | 5663 | ||
5595 | skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), | 5664 | skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), |
5596 | skb->len); | 5665 | skb->len); |
5597 | conn->rx_len -= skb->len; | 5666 | conn->rx_len -= skb->len; |
5598 | 5667 | ||
5599 | if (!conn->rx_len) { | 5668 | if (!conn->rx_len) { |
@@ -5601,6 +5670,7 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) | |||
5601 | l2cap_recv_frame(conn, conn->rx_skb); | 5670 | l2cap_recv_frame(conn, conn->rx_skb); |
5602 | conn->rx_skb = NULL; | 5671 | conn->rx_skb = NULL; |
5603 | } | 5672 | } |
5673 | break; | ||
5604 | } | 5674 | } |
5605 | 5675 | ||
5606 | drop: | 5676 | drop: |
@@ -5617,12 +5687,11 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p) | |||
5617 | list_for_each_entry(c, &chan_list, global_l) { | 5687 | list_for_each_entry(c, &chan_list, global_l) { |
5618 | struct sock *sk = c->sk; | 5688 | struct sock *sk = c->sk; |
5619 | 5689 | ||
5620 | seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", | 5690 | seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", |
5621 | batostr(&bt_sk(sk)->src), | 5691 | &bt_sk(sk)->src, &bt_sk(sk)->dst, |
5622 | batostr(&bt_sk(sk)->dst), | 5692 | c->state, __le16_to_cpu(c->psm), |
5623 | c->state, __le16_to_cpu(c->psm), | 5693 | c->scid, c->dcid, c->imtu, c->omtu, |
5624 | c->scid, c->dcid, c->imtu, c->omtu, | 5694 | c->sec_level, c->mode); |
5625 | c->sec_level, c->mode); | ||
5626 | } | 5695 | } |
5627 | 5696 | ||
5628 | read_unlock(&chan_list_lock); | 5697 | read_unlock(&chan_list_lock); |
@@ -5653,8 +5722,8 @@ int __init l2cap_init(void) | |||
5653 | return err; | 5722 | return err; |
5654 | 5723 | ||
5655 | if (bt_debugfs) { | 5724 | if (bt_debugfs) { |
5656 | l2cap_debugfs = debugfs_create_file("l2cap", 0444, | 5725 | l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, |
5657 | bt_debugfs, NULL, &l2cap_debugfs_fops); | 5726 | NULL, &l2cap_debugfs_fops); |
5658 | if (!l2cap_debugfs) | 5727 | if (!l2cap_debugfs) |
5659 | BT_ERR("Failed to create L2CAP debug file"); | 5728 | BT_ERR("Failed to create L2CAP debug file"); |
5660 | } | 5729 | } |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 083f2bf065d4..89f1472939ec 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -40,7 +40,8 @@ static struct bt_sock_list l2cap_sk_list = { | |||
40 | 40 | ||
41 | static const struct proto_ops l2cap_sock_ops; | 41 | static const struct proto_ops l2cap_sock_ops; |
42 | static void l2cap_sock_init(struct sock *sk, struct sock *parent); | 42 | static void l2cap_sock_init(struct sock *sk, struct sock *parent); |
43 | static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); | 43 | static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, |
44 | int proto, gfp_t prio); | ||
44 | 45 | ||
45 | static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | 46 | static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) |
46 | { | 47 | { |
@@ -106,7 +107,8 @@ done: | |||
106 | return err; | 107 | return err; |
107 | } | 108 | } |
108 | 109 | ||
109 | static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags) | 110 | static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, |
111 | int alen, int flags) | ||
110 | { | 112 | { |
111 | struct sock *sk = sock->sk; | 113 | struct sock *sk = sock->sk; |
112 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 114 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
@@ -134,7 +136,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, int al | |||
134 | lock_sock(sk); | 136 | lock_sock(sk); |
135 | 137 | ||
136 | err = bt_sock_wait_state(sk, BT_CONNECTED, | 138 | err = bt_sock_wait_state(sk, BT_CONNECTED, |
137 | sock_sndtimeo(sk, flags & O_NONBLOCK)); | 139 | sock_sndtimeo(sk, flags & O_NONBLOCK)); |
138 | 140 | ||
139 | release_sock(sk); | 141 | release_sock(sk); |
140 | 142 | ||
@@ -185,7 +187,8 @@ done: | |||
185 | return err; | 187 | return err; |
186 | } | 188 | } |
187 | 189 | ||
188 | static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags) | 190 | static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, |
191 | int flags) | ||
189 | { | 192 | { |
190 | DECLARE_WAITQUEUE(wait, current); | 193 | DECLARE_WAITQUEUE(wait, current); |
191 | struct sock *sk = sock->sk, *nsk; | 194 | struct sock *sk = sock->sk, *nsk; |
@@ -241,7 +244,8 @@ done: | |||
241 | return err; | 244 | return err; |
242 | } | 245 | } |
243 | 246 | ||
244 | static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *len, int peer) | 247 | static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, |
248 | int *len, int peer) | ||
245 | { | 249 | { |
246 | struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr; | 250 | struct sockaddr_l2 *la = (struct sockaddr_l2 *) addr; |
247 | struct sock *sk = sock->sk; | 251 | struct sock *sk = sock->sk; |
@@ -266,7 +270,8 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l | |||
266 | return 0; | 270 | return 0; |
267 | } | 271 | } |
268 | 272 | ||
269 | static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __user *optval, int __user *optlen) | 273 | static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, |
274 | char __user *optval, int __user *optlen) | ||
270 | { | 275 | { |
271 | struct sock *sk = sock->sk; | 276 | struct sock *sk = sock->sk; |
272 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 277 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
@@ -309,7 +314,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us | |||
309 | break; | 314 | break; |
310 | case BT_SECURITY_HIGH: | 315 | case BT_SECURITY_HIGH: |
311 | opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT | | 316 | opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT | |
312 | L2CAP_LM_SECURE; | 317 | L2CAP_LM_SECURE; |
313 | break; | 318 | break; |
314 | default: | 319 | default: |
315 | opt = 0; | 320 | opt = 0; |
@@ -353,7 +358,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, char __us | |||
353 | return err; | 358 | return err; |
354 | } | 359 | } |
355 | 360 | ||
356 | static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen) | 361 | static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, |
362 | char __user *optval, int __user *optlen) | ||
357 | { | 363 | { |
358 | struct sock *sk = sock->sk; | 364 | struct sock *sk = sock->sk; |
359 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 365 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
@@ -377,19 +383,20 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch | |||
377 | switch (optname) { | 383 | switch (optname) { |
378 | case BT_SECURITY: | 384 | case BT_SECURITY: |
379 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && | 385 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && |
380 | chan->chan_type != L2CAP_CHAN_RAW) { | 386 | chan->chan_type != L2CAP_CHAN_RAW) { |
381 | err = -EINVAL; | 387 | err = -EINVAL; |
382 | break; | 388 | break; |
383 | } | 389 | } |
384 | 390 | ||
385 | memset(&sec, 0, sizeof(sec)); | 391 | memset(&sec, 0, sizeof(sec)); |
386 | if (chan->conn) | 392 | if (chan->conn) { |
387 | sec.level = chan->conn->hcon->sec_level; | 393 | sec.level = chan->conn->hcon->sec_level; |
388 | else | ||
389 | sec.level = chan->sec_level; | ||
390 | 394 | ||
391 | if (sk->sk_state == BT_CONNECTED) | 395 | if (sk->sk_state == BT_CONNECTED) |
392 | sec.key_size = chan->conn->hcon->enc_key_size; | 396 | sec.key_size = chan->conn->hcon->enc_key_size; |
397 | } else { | ||
398 | sec.level = chan->sec_level; | ||
399 | } | ||
393 | 400 | ||
394 | len = min_t(unsigned int, len, sizeof(sec)); | 401 | len = min_t(unsigned int, len, sizeof(sec)); |
395 | if (copy_to_user(optval, (char *) &sec, len)) | 402 | if (copy_to_user(optval, (char *) &sec, len)) |
@@ -411,14 +418,14 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, ch | |||
411 | 418 | ||
412 | case BT_FLUSHABLE: | 419 | case BT_FLUSHABLE: |
413 | if (put_user(test_bit(FLAG_FLUSHABLE, &chan->flags), | 420 | if (put_user(test_bit(FLAG_FLUSHABLE, &chan->flags), |
414 | (u32 __user *) optval)) | 421 | (u32 __user *) optval)) |
415 | err = -EFAULT; | 422 | err = -EFAULT; |
416 | 423 | ||
417 | break; | 424 | break; |
418 | 425 | ||
419 | case BT_POWER: | 426 | case BT_POWER: |
420 | if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM | 427 | if (sk->sk_type != SOCK_SEQPACKET && sk->sk_type != SOCK_STREAM |
421 | && sk->sk_type != SOCK_RAW) { | 428 | && sk->sk_type != SOCK_RAW) { |
422 | err = -EINVAL; | 429 | err = -EINVAL; |
423 | break; | 430 | break; |
424 | } | 431 | } |
@@ -466,7 +473,8 @@ static bool l2cap_valid_mtu(struct l2cap_chan *chan, u16 mtu) | |||
466 | return true; | 473 | return true; |
467 | } | 474 | } |
468 | 475 | ||
469 | static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __user *optval, unsigned int optlen) | 476 | static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, |
477 | char __user *optval, unsigned int optlen) | ||
470 | { | 478 | { |
471 | struct sock *sk = sock->sk; | 479 | struct sock *sk = sock->sk; |
472 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 480 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
@@ -529,6 +537,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us | |||
529 | chan->fcs = opts.fcs; | 537 | chan->fcs = opts.fcs; |
530 | chan->max_tx = opts.max_tx; | 538 | chan->max_tx = opts.max_tx; |
531 | chan->tx_win = opts.txwin_size; | 539 | chan->tx_win = opts.txwin_size; |
540 | chan->flush_to = opts.flush_to; | ||
532 | break; | 541 | break; |
533 | 542 | ||
534 | case L2CAP_LM: | 543 | case L2CAP_LM: |
@@ -564,7 +573,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, char __us | |||
564 | return err; | 573 | return err; |
565 | } | 574 | } |
566 | 575 | ||
567 | static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, char __user *optval, unsigned int optlen) | 576 | static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, |
577 | char __user *optval, unsigned int optlen) | ||
568 | { | 578 | { |
569 | struct sock *sk = sock->sk; | 579 | struct sock *sk = sock->sk; |
570 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 580 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
@@ -587,7 +597,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
587 | switch (optname) { | 597 | switch (optname) { |
588 | case BT_SECURITY: | 598 | case BT_SECURITY: |
589 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && | 599 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && |
590 | chan->chan_type != L2CAP_CHAN_RAW) { | 600 | chan->chan_type != L2CAP_CHAN_RAW) { |
591 | err = -EINVAL; | 601 | err = -EINVAL; |
592 | break; | 602 | break; |
593 | } | 603 | } |
@@ -601,7 +611,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
601 | } | 611 | } |
602 | 612 | ||
603 | if (sec.level < BT_SECURITY_LOW || | 613 | if (sec.level < BT_SECURITY_LOW || |
604 | sec.level > BT_SECURITY_HIGH) { | 614 | sec.level > BT_SECURITY_HIGH) { |
605 | err = -EINVAL; | 615 | err = -EINVAL; |
606 | break; | 616 | break; |
607 | } | 617 | } |
@@ -627,7 +637,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
627 | 637 | ||
628 | /* or for ACL link */ | 638 | /* or for ACL link */ |
629 | } else if ((sk->sk_state == BT_CONNECT2 && | 639 | } else if ((sk->sk_state == BT_CONNECT2 && |
630 | test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) || | 640 | test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) || |
631 | sk->sk_state == BT_CONNECTED) { | 641 | sk->sk_state == BT_CONNECTED) { |
632 | if (!l2cap_chan_check_security(chan)) | 642 | if (!l2cap_chan_check_security(chan)) |
633 | set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); | 643 | set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); |
@@ -684,7 +694,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
684 | 694 | ||
685 | case BT_POWER: | 695 | case BT_POWER: |
686 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && | 696 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && |
687 | chan->chan_type != L2CAP_CHAN_RAW) { | 697 | chan->chan_type != L2CAP_CHAN_RAW) { |
688 | err = -EINVAL; | 698 | err = -EINVAL; |
689 | break; | 699 | break; |
690 | } | 700 | } |
@@ -720,7 +730,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
720 | } | 730 | } |
721 | 731 | ||
722 | if (chan->mode != L2CAP_MODE_ERTM && | 732 | if (chan->mode != L2CAP_MODE_ERTM && |
723 | chan->mode != L2CAP_MODE_STREAMING) { | 733 | chan->mode != L2CAP_MODE_STREAMING) { |
724 | err = -EOPNOTSUPP; | 734 | err = -EOPNOTSUPP; |
725 | break; | 735 | break; |
726 | } | 736 | } |
@@ -737,7 +747,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
737 | return err; | 747 | return err; |
738 | } | 748 | } |
739 | 749 | ||
740 | static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len) | 750 | static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, |
751 | struct msghdr *msg, size_t len) | ||
741 | { | 752 | { |
742 | struct sock *sk = sock->sk; | 753 | struct sock *sk = sock->sk; |
743 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 754 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; |
@@ -762,7 +773,8 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, struct ms | |||
762 | return err; | 773 | return err; |
763 | } | 774 | } |
764 | 775 | ||
765 | static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, size_t len, int flags) | 776 | static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, |
777 | struct msghdr *msg, size_t len, int flags) | ||
766 | { | 778 | { |
767 | struct sock *sk = sock->sk; | 779 | struct sock *sk = sock->sk; |
768 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 780 | struct l2cap_pinfo *pi = l2cap_pi(sk); |
@@ -866,7 +878,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) | |||
866 | 878 | ||
867 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) | 879 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) |
868 | err = bt_sock_wait_state(sk, BT_CLOSED, | 880 | err = bt_sock_wait_state(sk, BT_CLOSED, |
869 | sk->sk_lingertime); | 881 | sk->sk_lingertime); |
870 | } | 882 | } |
871 | 883 | ||
872 | if (!err && sk->sk_err) | 884 | if (!err && sk->sk_err) |
@@ -930,7 +942,7 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) | |||
930 | } | 942 | } |
931 | 943 | ||
932 | sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, | 944 | sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP, |
933 | GFP_ATOMIC); | 945 | GFP_ATOMIC); |
934 | if (!sk) | 946 | if (!sk) |
935 | return NULL; | 947 | return NULL; |
936 | 948 | ||
@@ -938,6 +950,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) | |||
938 | 950 | ||
939 | l2cap_sock_init(sk, parent); | 951 | l2cap_sock_init(sk, parent); |
940 | 952 | ||
953 | bt_accept_enqueue(parent, sk); | ||
954 | |||
941 | return l2cap_pi(sk)->chan; | 955 | return l2cap_pi(sk)->chan; |
942 | } | 956 | } |
943 | 957 | ||
@@ -1068,6 +1082,15 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan) | |||
1068 | release_sock(sk); | 1082 | release_sock(sk); |
1069 | } | 1083 | } |
1070 | 1084 | ||
1085 | static void l2cap_sock_defer_cb(struct l2cap_chan *chan) | ||
1086 | { | ||
1087 | struct sock *sk = chan->data; | ||
1088 | struct sock *parent = bt_sk(sk)->parent; | ||
1089 | |||
1090 | if (parent) | ||
1091 | parent->sk_data_ready(parent, 0); | ||
1092 | } | ||
1093 | |||
1071 | static struct l2cap_ops l2cap_chan_ops = { | 1094 | static struct l2cap_ops l2cap_chan_ops = { |
1072 | .name = "L2CAP Socket Interface", | 1095 | .name = "L2CAP Socket Interface", |
1073 | .new_connection = l2cap_sock_new_connection_cb, | 1096 | .new_connection = l2cap_sock_new_connection_cb, |
@@ -1076,6 +1099,7 @@ static struct l2cap_ops l2cap_chan_ops = { | |||
1076 | .teardown = l2cap_sock_teardown_cb, | 1099 | .teardown = l2cap_sock_teardown_cb, |
1077 | .state_change = l2cap_sock_state_change_cb, | 1100 | .state_change = l2cap_sock_state_change_cb, |
1078 | .ready = l2cap_sock_ready_cb, | 1101 | .ready = l2cap_sock_ready_cb, |
1102 | .defer = l2cap_sock_defer_cb, | ||
1079 | .alloc_skb = l2cap_sock_alloc_skb_cb, | 1103 | .alloc_skb = l2cap_sock_alloc_skb_cb, |
1080 | }; | 1104 | }; |
1081 | 1105 | ||
@@ -1083,7 +1107,8 @@ static void l2cap_sock_destruct(struct sock *sk) | |||
1083 | { | 1107 | { |
1084 | BT_DBG("sk %p", sk); | 1108 | BT_DBG("sk %p", sk); |
1085 | 1109 | ||
1086 | l2cap_chan_put(l2cap_pi(sk)->chan); | 1110 | if (l2cap_pi(sk)->chan) |
1111 | l2cap_chan_put(l2cap_pi(sk)->chan); | ||
1087 | if (l2cap_pi(sk)->rx_busy_skb) { | 1112 | if (l2cap_pi(sk)->rx_busy_skb) { |
1088 | kfree_skb(l2cap_pi(sk)->rx_busy_skb); | 1113 | kfree_skb(l2cap_pi(sk)->rx_busy_skb); |
1089 | l2cap_pi(sk)->rx_busy_skb = NULL; | 1114 | l2cap_pi(sk)->rx_busy_skb = NULL; |
@@ -1159,7 +1184,8 @@ static struct proto l2cap_proto = { | |||
1159 | .obj_size = sizeof(struct l2cap_pinfo) | 1184 | .obj_size = sizeof(struct l2cap_pinfo) |
1160 | }; | 1185 | }; |
1161 | 1186 | ||
1162 | static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio) | 1187 | static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, |
1188 | int proto, gfp_t prio) | ||
1163 | { | 1189 | { |
1164 | struct sock *sk; | 1190 | struct sock *sk; |
1165 | struct l2cap_chan *chan; | 1191 | struct l2cap_chan *chan; |
@@ -1204,7 +1230,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, | |||
1204 | sock->state = SS_UNCONNECTED; | 1230 | sock->state = SS_UNCONNECTED; |
1205 | 1231 | ||
1206 | if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM && | 1232 | if (sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM && |
1207 | sock->type != SOCK_DGRAM && sock->type != SOCK_RAW) | 1233 | sock->type != SOCK_DGRAM && sock->type != SOCK_RAW) |
1208 | return -ESOCKTNOSUPPORT; | 1234 | return -ESOCKTNOSUPPORT; |
1209 | 1235 | ||
1210 | if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) | 1236 | if (sock->type == SOCK_RAW && !kern && !capable(CAP_NET_RAW)) |
@@ -1261,7 +1287,8 @@ int __init l2cap_init_sockets(void) | |||
1261 | goto error; | 1287 | goto error; |
1262 | } | 1288 | } |
1263 | 1289 | ||
1264 | err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list, NULL); | 1290 | err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list, |
1291 | NULL); | ||
1265 | if (err < 0) { | 1292 | if (err < 0) { |
1266 | BT_ERR("Failed to create L2CAP proc file"); | 1293 | BT_ERR("Failed to create L2CAP proc file"); |
1267 | bt_sock_unregister(BTPROTO_L2CAP); | 1294 | bt_sock_unregister(BTPROTO_L2CAP); |
diff --git a/net/bluetooth/lib.c b/net/bluetooth/lib.c index e1c97527e16c..b3fbc73516c4 100644 --- a/net/bluetooth/lib.c +++ b/net/bluetooth/lib.c | |||
@@ -41,20 +41,6 @@ void baswap(bdaddr_t *dst, bdaddr_t *src) | |||
41 | } | 41 | } |
42 | EXPORT_SYMBOL(baswap); | 42 | EXPORT_SYMBOL(baswap); |
43 | 43 | ||
44 | char *batostr(bdaddr_t *ba) | ||
45 | { | ||
46 | static char str[2][18]; | ||
47 | static int i = 1; | ||
48 | |||
49 | i ^= 1; | ||
50 | sprintf(str[i], "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", | ||
51 | ba->b[5], ba->b[4], ba->b[3], | ||
52 | ba->b[2], ba->b[1], ba->b[0]); | ||
53 | |||
54 | return str[i]; | ||
55 | } | ||
56 | EXPORT_SYMBOL(batostr); | ||
57 | |||
58 | /* Bluetooth error codes to Unix errno mapping */ | 44 | /* Bluetooth error codes to Unix errno mapping */ |
59 | int bt_to_errno(__u16 code) | 45 | int bt_to_errno(__u16 code) |
60 | { | 46 | { |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index aa2ea0a8142c..399e5024b5bd 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -3125,6 +3125,9 @@ int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
3125 | struct pending_cmd *cmd; | 3125 | struct pending_cmd *cmd; |
3126 | int err; | 3126 | int err; |
3127 | 3127 | ||
3128 | mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp, | ||
3129 | hdev); | ||
3130 | |||
3128 | cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev); | 3131 | cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev); |
3129 | if (!cmd) | 3132 | if (!cmd) |
3130 | return -ENOENT; | 3133 | return -ENOENT; |
@@ -3137,8 +3140,6 @@ int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
3137 | 3140 | ||
3138 | mgmt_pending_remove(cmd); | 3141 | mgmt_pending_remove(cmd); |
3139 | 3142 | ||
3140 | mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp, | ||
3141 | hdev); | ||
3142 | return err; | 3143 | return err; |
3143 | } | 3144 | } |
3144 | 3145 | ||
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index c75107ef8920..201fdf737209 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -377,8 +377,8 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, | |||
377 | int err = 0; | 377 | int err = 0; |
378 | u8 dlci; | 378 | u8 dlci; |
379 | 379 | ||
380 | BT_DBG("dlc %p state %ld %s %s channel %d", | 380 | BT_DBG("dlc %p state %ld %pMR -> %pMR channel %d", |
381 | d, d->state, batostr(src), batostr(dst), channel); | 381 | d, d->state, src, dst, channel); |
382 | 382 | ||
383 | if (channel < 1 || channel > 30) | 383 | if (channel < 1 || channel > 30) |
384 | return -EINVAL; | 384 | return -EINVAL; |
@@ -676,7 +676,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, | |||
676 | struct socket *sock; | 676 | struct socket *sock; |
677 | struct sock *sk; | 677 | struct sock *sk; |
678 | 678 | ||
679 | BT_DBG("%s %s", batostr(src), batostr(dst)); | 679 | BT_DBG("%pMR -> %pMR", src, dst); |
680 | 680 | ||
681 | *err = rfcomm_l2sock_create(&sock); | 681 | *err = rfcomm_l2sock_create(&sock); |
682 | if (*err < 0) | 682 | if (*err < 0) |
@@ -709,7 +709,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, | |||
709 | 709 | ||
710 | bacpy(&addr.l2_bdaddr, dst); | 710 | bacpy(&addr.l2_bdaddr, dst); |
711 | addr.l2_family = AF_BLUETOOTH; | 711 | addr.l2_family = AF_BLUETOOTH; |
712 | addr.l2_psm = cpu_to_le16(RFCOMM_PSM); | 712 | addr.l2_psm = __constant_cpu_to_le16(RFCOMM_PSM); |
713 | addr.l2_cid = 0; | 713 | addr.l2_cid = 0; |
714 | *err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK); | 714 | *err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK); |
715 | if (*err == 0 || *err == -EINPROGRESS) | 715 | if (*err == 0 || *err == -EINPROGRESS) |
@@ -1987,7 +1987,7 @@ static int rfcomm_add_listener(bdaddr_t *ba) | |||
1987 | /* Bind socket */ | 1987 | /* Bind socket */ |
1988 | bacpy(&addr.l2_bdaddr, ba); | 1988 | bacpy(&addr.l2_bdaddr, ba); |
1989 | addr.l2_family = AF_BLUETOOTH; | 1989 | addr.l2_family = AF_BLUETOOTH; |
1990 | addr.l2_psm = cpu_to_le16(RFCOMM_PSM); | 1990 | addr.l2_psm = __constant_cpu_to_le16(RFCOMM_PSM); |
1991 | addr.l2_cid = 0; | 1991 | addr.l2_cid = 0; |
1992 | err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr)); | 1992 | err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr)); |
1993 | if (err < 0) { | 1993 | if (err < 0) { |
@@ -2125,11 +2125,10 @@ static int rfcomm_dlc_debugfs_show(struct seq_file *f, void *x) | |||
2125 | list_for_each_entry(d, &s->dlcs, list) { | 2125 | list_for_each_entry(d, &s->dlcs, list) { |
2126 | struct sock *sk = s->sock->sk; | 2126 | struct sock *sk = s->sock->sk; |
2127 | 2127 | ||
2128 | seq_printf(f, "%s %s %ld %d %d %d %d\n", | 2128 | seq_printf(f, "%pMR %pMR %ld %d %d %d %d\n", |
2129 | batostr(&bt_sk(sk)->src), | 2129 | &bt_sk(sk)->src, &bt_sk(sk)->dst, |
2130 | batostr(&bt_sk(sk)->dst), | 2130 | d->state, d->dlci, d->mtu, |
2131 | d->state, d->dlci, d->mtu, | 2131 | d->rx_credits, d->tx_credits); |
2132 | d->rx_credits, d->tx_credits); | ||
2133 | } | 2132 | } |
2134 | } | 2133 | } |
2135 | 2134 | ||
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index b3226f3658cf..4ddef57d03a7 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -334,7 +334,7 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr | |||
334 | struct sock *sk = sock->sk; | 334 | struct sock *sk = sock->sk; |
335 | int err = 0; | 335 | int err = 0; |
336 | 336 | ||
337 | BT_DBG("sk %p %s", sk, batostr(&sa->rc_bdaddr)); | 337 | BT_DBG("sk %p %pMR", sk, &sa->rc_bdaddr); |
338 | 338 | ||
339 | if (!addr || addr->sa_family != AF_BLUETOOTH) | 339 | if (!addr || addr->sa_family != AF_BLUETOOTH) |
340 | return -EINVAL; | 340 | return -EINVAL; |
@@ -975,10 +975,9 @@ static int rfcomm_sock_debugfs_show(struct seq_file *f, void *p) | |||
975 | read_lock(&rfcomm_sk_list.lock); | 975 | read_lock(&rfcomm_sk_list.lock); |
976 | 976 | ||
977 | sk_for_each(sk, node, &rfcomm_sk_list.head) { | 977 | sk_for_each(sk, node, &rfcomm_sk_list.head) { |
978 | seq_printf(f, "%s %s %d %d\n", | 978 | seq_printf(f, "%pMR %pMR %d %d\n", |
979 | batostr(&bt_sk(sk)->src), | 979 | &bt_sk(sk)->src, &bt_sk(sk)->dst, |
980 | batostr(&bt_sk(sk)->dst), | 980 | sk->sk_state, rfcomm_pi(sk)->channel); |
981 | sk->sk_state, rfcomm_pi(sk)->channel); | ||
982 | } | 981 | } |
983 | 982 | ||
984 | read_unlock(&rfcomm_sk_list.lock); | 983 | read_unlock(&rfcomm_sk_list.lock); |
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index ccc248791d50..bd6fd0f43d2b 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -166,7 +166,7 @@ static struct device *rfcomm_get_device(struct rfcomm_dev *dev) | |||
166 | static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf) | 166 | static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf) |
167 | { | 167 | { |
168 | struct rfcomm_dev *dev = dev_get_drvdata(tty_dev); | 168 | struct rfcomm_dev *dev = dev_get_drvdata(tty_dev); |
169 | return sprintf(buf, "%s\n", batostr(&dev->dst)); | 169 | return sprintf(buf, "%pMR\n", &dev->dst); |
170 | } | 170 | } |
171 | 171 | ||
172 | static ssize_t show_channel(struct device *tty_dev, struct device_attribute *attr, char *buf) | 172 | static ssize_t show_channel(struct device *tty_dev, struct device_attribute *attr, char *buf) |
@@ -663,8 +663,8 @@ static int rfcomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
663 | if (!dev) | 663 | if (!dev) |
664 | return -ENODEV; | 664 | return -ENODEV; |
665 | 665 | ||
666 | BT_DBG("dev %p dst %s channel %d opened %d", dev, batostr(&dev->dst), | 666 | BT_DBG("dev %p dst %pMR channel %d opened %d", dev, &dev->dst, |
667 | dev->channel, dev->port.count); | 667 | dev->channel, dev->port.count); |
668 | 668 | ||
669 | spin_lock_irqsave(&dev->port.lock, flags); | 669 | spin_lock_irqsave(&dev->port.lock, flags); |
670 | if (++dev->port.count > 1) { | 670 | if (++dev->port.count > 1) { |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index dc42b917aaaf..450cdcd88e5c 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -172,7 +172,7 @@ static int sco_connect(struct sock *sk) | |||
172 | struct hci_dev *hdev; | 172 | struct hci_dev *hdev; |
173 | int err, type; | 173 | int err, type; |
174 | 174 | ||
175 | BT_DBG("%s -> %s", batostr(src), batostr(dst)); | 175 | BT_DBG("%pMR -> %pMR", src, dst); |
176 | 176 | ||
177 | hdev = hci_get_route(dst, src); | 177 | hdev = hci_get_route(dst, src); |
178 | if (!hdev) | 178 | if (!hdev) |
@@ -460,7 +460,7 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le | |||
460 | struct sock *sk = sock->sk; | 460 | struct sock *sk = sock->sk; |
461 | int err = 0; | 461 | int err = 0; |
462 | 462 | ||
463 | BT_DBG("sk %p %s", sk, batostr(&sa->sco_bdaddr)); | 463 | BT_DBG("sk %p %pMR", sk, &sa->sco_bdaddr); |
464 | 464 | ||
465 | if (!addr || addr->sa_family != AF_BLUETOOTH) | 465 | if (!addr || addr->sa_family != AF_BLUETOOTH) |
466 | return -EINVAL; | 466 | return -EINVAL; |
@@ -893,7 +893,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
893 | struct hlist_node *node; | 893 | struct hlist_node *node; |
894 | int lm = 0; | 894 | int lm = 0; |
895 | 895 | ||
896 | BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); | 896 | BT_DBG("hdev %s, bdaddr %pMR", hdev->name, bdaddr); |
897 | 897 | ||
898 | /* Find listening sockets */ | 898 | /* Find listening sockets */ |
899 | read_lock(&sco_sk_list.lock); | 899 | read_lock(&sco_sk_list.lock); |
@@ -914,7 +914,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
914 | 914 | ||
915 | void sco_connect_cfm(struct hci_conn *hcon, __u8 status) | 915 | void sco_connect_cfm(struct hci_conn *hcon, __u8 status) |
916 | { | 916 | { |
917 | BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); | 917 | BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status); |
918 | if (!status) { | 918 | if (!status) { |
919 | struct sco_conn *conn; | 919 | struct sco_conn *conn; |
920 | 920 | ||
@@ -959,8 +959,8 @@ static int sco_debugfs_show(struct seq_file *f, void *p) | |||
959 | read_lock(&sco_sk_list.lock); | 959 | read_lock(&sco_sk_list.lock); |
960 | 960 | ||
961 | sk_for_each(sk, node, &sco_sk_list.head) { | 961 | sk_for_each(sk, node, &sco_sk_list.head) { |
962 | seq_printf(f, "%s %s %d\n", batostr(&bt_sk(sk)->src), | 962 | seq_printf(f, "%pMR %pMR %d\n", &bt_sk(sk)->src, |
963 | batostr(&bt_sk(sk)->dst), sk->sk_state); | 963 | &bt_sk(sk)->dst, sk->sk_state); |
964 | } | 964 | } |
965 | 965 | ||
966 | read_unlock(&sco_sk_list.lock); | 966 | read_unlock(&sco_sk_list.lock); |
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 8c225ef349cd..9176bc17595c 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -32,6 +32,8 @@ | |||
32 | 32 | ||
33 | #define SMP_TIMEOUT msecs_to_jiffies(30000) | 33 | #define SMP_TIMEOUT msecs_to_jiffies(30000) |
34 | 34 | ||
35 | #define AUTH_REQ_MASK 0x07 | ||
36 | |||
35 | static inline void swap128(u8 src[16], u8 dst[16]) | 37 | static inline void swap128(u8 src[16], u8 dst[16]) |
36 | { | 38 | { |
37 | int i; | 39 | int i; |
@@ -165,7 +167,7 @@ static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code, | |||
165 | 167 | ||
166 | lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); | 168 | lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); |
167 | lh->len = cpu_to_le16(sizeof(code) + dlen); | 169 | lh->len = cpu_to_le16(sizeof(code) + dlen); |
168 | lh->cid = cpu_to_le16(L2CAP_CID_SMP); | 170 | lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP); |
169 | 171 | ||
170 | memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code)); | 172 | memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code)); |
171 | 173 | ||
@@ -230,7 +232,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, | |||
230 | req->max_key_size = SMP_MAX_ENC_KEY_SIZE; | 232 | req->max_key_size = SMP_MAX_ENC_KEY_SIZE; |
231 | req->init_key_dist = 0; | 233 | req->init_key_dist = 0; |
232 | req->resp_key_dist = dist_keys; | 234 | req->resp_key_dist = dist_keys; |
233 | req->auth_req = authreq; | 235 | req->auth_req = (authreq & AUTH_REQ_MASK); |
234 | return; | 236 | return; |
235 | } | 237 | } |
236 | 238 | ||
@@ -239,7 +241,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, | |||
239 | rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE; | 241 | rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE; |
240 | rsp->init_key_dist = 0; | 242 | rsp->init_key_dist = 0; |
241 | rsp->resp_key_dist = req->resp_key_dist & dist_keys; | 243 | rsp->resp_key_dist = req->resp_key_dist & dist_keys; |
242 | rsp->auth_req = authreq; | 244 | rsp->auth_req = (authreq & AUTH_REQ_MASK); |
243 | } | 245 | } |
244 | 246 | ||
245 | static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) | 247 | static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 3d5332e367f8..c7386b2b767e 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -1110,7 +1110,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1110 | sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; | 1110 | sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; |
1111 | sdata->u.ibss.ibss_join_req = jiffies; | 1111 | sdata->u.ibss.ibss_join_req = jiffies; |
1112 | 1112 | ||
1113 | memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); | 1113 | memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len); |
1114 | sdata->u.ibss.ssid_len = params->ssid_len; | 1114 | sdata->u.ibss.ssid_len = params->ssid_len; |
1115 | 1115 | ||
1116 | mutex_unlock(&sdata->u.ibss.mtx); | 1116 | mutex_unlock(&sdata->u.ibss.mtx); |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 944c6cf53eb7..1a6fe135f201 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -840,7 +840,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
840 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 840 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
841 | if (info->control.vif == &sdata->vif) { | 841 | if (info->control.vif == &sdata->vif) { |
842 | __skb_unlink(skb, &local->pending[i]); | 842 | __skb_unlink(skb, &local->pending[i]); |
843 | dev_kfree_skb_irq(skb); | 843 | ieee80211_free_txskb(&local->hw, skb); |
844 | } | 844 | } |
845 | } | 845 | } |
846 | } | 846 | } |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 2bdf7769506f..1d1fdf0791f0 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -3177,26 +3177,37 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
3177 | ht_cfreq, ht_oper->primary_chan, | 3177 | ht_cfreq, ht_oper->primary_chan, |
3178 | cbss->channel->band); | 3178 | cbss->channel->band); |
3179 | ht_oper = NULL; | 3179 | ht_oper = NULL; |
3180 | } else { | ||
3181 | channel_type = NL80211_CHAN_HT20; | ||
3180 | } | 3182 | } |
3181 | } | 3183 | } |
3182 | 3184 | ||
3183 | if (ht_oper) { | 3185 | if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { |
3186 | /* | ||
3187 | * cfg80211 already verified that the channel itself can | ||
3188 | * be used, but it didn't check that we can do the right | ||
3189 | * HT type, so do that here as well. If HT40 isn't allowed | ||
3190 | * on this channel, disable 40 MHz operation. | ||
3191 | */ | ||
3184 | const u8 *ht_cap_ie; | 3192 | const u8 *ht_cap_ie; |
3185 | const struct ieee80211_ht_cap *ht_cap; | 3193 | const struct ieee80211_ht_cap *ht_cap; |
3186 | u8 chains = 1; | 3194 | u8 chains = 1; |
3187 | 3195 | ||
3188 | channel_type = NL80211_CHAN_HT20; | 3196 | channel_type = NL80211_CHAN_HT20; |
3189 | 3197 | ||
3190 | if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { | 3198 | switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
3191 | switch (ht_oper->ht_param & | 3199 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
3192 | IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 3200 | if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS) |
3193 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 3201 | ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; |
3202 | else | ||
3194 | channel_type = NL80211_CHAN_HT40PLUS; | 3203 | channel_type = NL80211_CHAN_HT40PLUS; |
3195 | break; | 3204 | break; |
3196 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | 3205 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: |
3206 | if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS) | ||
3207 | ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; | ||
3208 | else | ||
3197 | channel_type = NL80211_CHAN_HT40MINUS; | 3209 | channel_type = NL80211_CHAN_HT40MINUS; |
3198 | break; | 3210 | break; |
3199 | } | ||
3200 | } | 3211 | } |
3201 | 3212 | ||
3202 | ht_cap_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, | 3213 | ht_cap_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, |
@@ -3648,6 +3659,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
3648 | { | 3659 | { |
3649 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3660 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
3650 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; | 3661 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; |
3662 | bool tx = !req->local_state_change; | ||
3651 | 3663 | ||
3652 | mutex_lock(&ifmgd->mtx); | 3664 | mutex_lock(&ifmgd->mtx); |
3653 | 3665 | ||
@@ -3664,12 +3676,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
3664 | if (ifmgd->associated && | 3676 | if (ifmgd->associated && |
3665 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { | 3677 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { |
3666 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 3678 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
3667 | req->reason_code, true, frame_buf); | 3679 | req->reason_code, tx, frame_buf); |
3668 | } else { | 3680 | } else { |
3669 | drv_mgd_prepare_tx(sdata->local, sdata); | 3681 | drv_mgd_prepare_tx(sdata->local, sdata); |
3670 | ieee80211_send_deauth_disassoc(sdata, req->bssid, | 3682 | ieee80211_send_deauth_disassoc(sdata, req->bssid, |
3671 | IEEE80211_STYPE_DEAUTH, | 3683 | IEEE80211_STYPE_DEAUTH, |
3672 | req->reason_code, true, | 3684 | req->reason_code, tx, |
3673 | frame_buf); | 3685 | frame_buf); |
3674 | } | 3686 | } |
3675 | 3687 | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c0a1f53e68ab..38b382682cae 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -525,6 +525,11 @@ static ieee80211_rx_result ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
525 | 525 | ||
526 | if (ieee80211_is_action(hdr->frame_control)) { | 526 | if (ieee80211_is_action(hdr->frame_control)) { |
527 | u8 category; | 527 | u8 category; |
528 | |||
529 | /* make sure category field is present */ | ||
530 | if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE) | ||
531 | return RX_DROP_MONITOR; | ||
532 | |||
528 | mgmt = (struct ieee80211_mgmt *)hdr; | 533 | mgmt = (struct ieee80211_mgmt *)hdr; |
529 | category = mgmt->u.action.category; | 534 | category = mgmt->u.action.category; |
530 | if (category != WLAN_CATEGORY_MESH_ACTION && | 535 | if (category != WLAN_CATEGORY_MESH_ACTION && |
@@ -875,14 +880,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
875 | */ | 880 | */ |
876 | if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && | 881 | if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && |
877 | ieee80211_is_data_present(hdr->frame_control)) { | 882 | ieee80211_is_data_present(hdr->frame_control)) { |
878 | u16 ethertype; | 883 | unsigned int hdrlen; |
879 | u8 *payload; | 884 | __be16 ethertype; |
880 | 885 | ||
881 | payload = rx->skb->data + | 886 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
882 | ieee80211_hdrlen(hdr->frame_control); | 887 | |
883 | ethertype = (payload[6] << 8) | payload[7]; | 888 | if (rx->skb->len < hdrlen + 8) |
884 | if (cpu_to_be16(ethertype) == | 889 | return RX_DROP_MONITOR; |
885 | rx->sdata->control_port_protocol) | 890 | |
891 | skb_copy_bits(rx->skb, hdrlen + 6, ðertype, 2); | ||
892 | if (ethertype == rx->sdata->control_port_protocol) | ||
886 | return RX_CONTINUE; | 893 | return RX_CONTINUE; |
887 | } | 894 | } |
888 | 895 | ||
@@ -1459,11 +1466,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1459 | 1466 | ||
1460 | hdr = (struct ieee80211_hdr *)rx->skb->data; | 1467 | hdr = (struct ieee80211_hdr *)rx->skb->data; |
1461 | fc = hdr->frame_control; | 1468 | fc = hdr->frame_control; |
1469 | |||
1470 | if (ieee80211_is_ctl(fc)) | ||
1471 | return RX_CONTINUE; | ||
1472 | |||
1462 | sc = le16_to_cpu(hdr->seq_ctrl); | 1473 | sc = le16_to_cpu(hdr->seq_ctrl); |
1463 | frag = sc & IEEE80211_SCTL_FRAG; | 1474 | frag = sc & IEEE80211_SCTL_FRAG; |
1464 | 1475 | ||
1465 | if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || | 1476 | if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || |
1466 | (rx->skb)->len < 24 || | ||
1467 | is_multicast_ether_addr(hdr->addr1))) { | 1477 | is_multicast_ether_addr(hdr->addr1))) { |
1468 | /* not fragmented */ | 1478 | /* not fragmented */ |
1469 | goto out; | 1479 | goto out; |
@@ -1882,6 +1892,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1882 | 1892 | ||
1883 | hdr = (struct ieee80211_hdr *) skb->data; | 1893 | hdr = (struct ieee80211_hdr *) skb->data; |
1884 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1894 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1895 | |||
1896 | /* make sure fixed part of mesh header is there, also checks skb len */ | ||
1897 | if (!pskb_may_pull(rx->skb, hdrlen + 6)) | ||
1898 | return RX_DROP_MONITOR; | ||
1899 | |||
1900 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); | ||
1901 | |||
1902 | /* make sure full mesh header is there, also checks skb len */ | ||
1903 | if (!pskb_may_pull(rx->skb, | ||
1904 | hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr))) | ||
1905 | return RX_DROP_MONITOR; | ||
1906 | |||
1907 | /* reload pointers */ | ||
1908 | hdr = (struct ieee80211_hdr *) skb->data; | ||
1885 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); | 1909 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); |
1886 | 1910 | ||
1887 | /* frame is in RMC, don't forward */ | 1911 | /* frame is in RMC, don't forward */ |
@@ -1890,7 +1914,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1890 | mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) | 1914 | mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) |
1891 | return RX_DROP_MONITOR; | 1915 | return RX_DROP_MONITOR; |
1892 | 1916 | ||
1893 | if (!ieee80211_is_data(hdr->frame_control)) | 1917 | if (!ieee80211_is_data(hdr->frame_control) || |
1918 | !(status->rx_flags & IEEE80211_RX_RA_MATCH)) | ||
1894 | return RX_CONTINUE; | 1919 | return RX_CONTINUE; |
1895 | 1920 | ||
1896 | if (!mesh_hdr->ttl) | 1921 | if (!mesh_hdr->ttl) |
@@ -1904,9 +1929,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1904 | if (is_multicast_ether_addr(hdr->addr1)) { | 1929 | if (is_multicast_ether_addr(hdr->addr1)) { |
1905 | mpp_addr = hdr->addr3; | 1930 | mpp_addr = hdr->addr3; |
1906 | proxied_addr = mesh_hdr->eaddr1; | 1931 | proxied_addr = mesh_hdr->eaddr1; |
1907 | } else { | 1932 | } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) { |
1933 | /* has_a4 already checked in ieee80211_rx_mesh_check */ | ||
1908 | mpp_addr = hdr->addr4; | 1934 | mpp_addr = hdr->addr4; |
1909 | proxied_addr = mesh_hdr->eaddr2; | 1935 | proxied_addr = mesh_hdr->eaddr2; |
1936 | } else { | ||
1937 | return RX_DROP_MONITOR; | ||
1910 | } | 1938 | } |
1911 | 1939 | ||
1912 | rcu_read_lock(); | 1940 | rcu_read_lock(); |
@@ -1934,12 +1962,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1934 | } | 1962 | } |
1935 | skb_set_queue_mapping(skb, q); | 1963 | skb_set_queue_mapping(skb, q); |
1936 | 1964 | ||
1937 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) | ||
1938 | goto out; | ||
1939 | |||
1940 | if (!--mesh_hdr->ttl) { | 1965 | if (!--mesh_hdr->ttl) { |
1941 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); | 1966 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); |
1942 | return RX_DROP_MONITOR; | 1967 | goto out; |
1943 | } | 1968 | } |
1944 | 1969 | ||
1945 | if (!ifmsh->mshcfg.dot11MeshForwarding) | 1970 | if (!ifmsh->mshcfg.dot11MeshForwarding) |
@@ -2346,6 +2371,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2346 | } | 2371 | } |
2347 | break; | 2372 | break; |
2348 | case WLAN_CATEGORY_SELF_PROTECTED: | 2373 | case WLAN_CATEGORY_SELF_PROTECTED: |
2374 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
2375 | sizeof(mgmt->u.action.u.self_prot.action_code))) | ||
2376 | break; | ||
2377 | |||
2349 | switch (mgmt->u.action.u.self_prot.action_code) { | 2378 | switch (mgmt->u.action.u.self_prot.action_code) { |
2350 | case WLAN_SP_MESH_PEERING_OPEN: | 2379 | case WLAN_SP_MESH_PEERING_OPEN: |
2351 | case WLAN_SP_MESH_PEERING_CLOSE: | 2380 | case WLAN_SP_MESH_PEERING_CLOSE: |
@@ -2364,6 +2393,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2364 | } | 2393 | } |
2365 | break; | 2394 | break; |
2366 | case WLAN_CATEGORY_MESH_ACTION: | 2395 | case WLAN_CATEGORY_MESH_ACTION: |
2396 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
2397 | sizeof(mgmt->u.action.u.mesh_action.action_code))) | ||
2398 | break; | ||
2399 | |||
2367 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | 2400 | if (!ieee80211_vif_is_mesh(&sdata->vif)) |
2368 | break; | 2401 | break; |
2369 | if (mesh_action_is_path_sel(mgmt) && | 2402 | if (mesh_action_is_path_sel(mgmt) && |
@@ -2905,10 +2938,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2905 | if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) | 2938 | if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) |
2906 | local->dot11ReceivedFragmentCount++; | 2939 | local->dot11ReceivedFragmentCount++; |
2907 | 2940 | ||
2908 | if (ieee80211_is_mgmt(fc)) | 2941 | if (ieee80211_is_mgmt(fc)) { |
2909 | err = skb_linearize(skb); | 2942 | /* drop frame if too short for header */ |
2910 | else | 2943 | if (skb->len < ieee80211_hdrlen(fc)) |
2944 | err = -ENOBUFS; | ||
2945 | else | ||
2946 | err = skb_linearize(skb); | ||
2947 | } else { | ||
2911 | err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); | 2948 | err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); |
2949 | } | ||
2912 | 2950 | ||
2913 | if (err) { | 2951 | if (err) { |
2914 | dev_kfree_skb(skb); | 2952 | dev_kfree_skb(skb); |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index daf55e1e0fd3..f7bb54f9ab72 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -664,7 +664,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, | |||
664 | */ | 664 | */ |
665 | if (!skb) | 665 | if (!skb) |
666 | break; | 666 | break; |
667 | dev_kfree_skb(skb); | 667 | ieee80211_free_txskb(&local->hw, skb); |
668 | } | 668 | } |
669 | 669 | ||
670 | /* | 670 | /* |
@@ -693,7 +693,7 @@ static bool sta_info_cleanup_expire_buffered_ac(struct ieee80211_local *local, | |||
693 | local->total_ps_buffered--; | 693 | local->total_ps_buffered--; |
694 | ps_dbg(sta->sdata, "Buffered frame expired (STA %pM)\n", | 694 | ps_dbg(sta->sdata, "Buffered frame expired (STA %pM)\n", |
695 | sta->sta.addr); | 695 | sta->sta.addr); |
696 | dev_kfree_skb(skb); | 696 | ieee80211_free_txskb(&local->hw, skb); |
697 | } | 697 | } |
698 | 698 | ||
699 | /* | 699 | /* |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index dd0e6f20fc51..6636d3962317 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -406,7 +406,7 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, | |||
406 | int queue = info->hw_queue; | 406 | int queue = info->hw_queue; |
407 | 407 | ||
408 | if (WARN_ON(!info->control.vif)) { | 408 | if (WARN_ON(!info->control.vif)) { |
409 | kfree_skb(skb); | 409 | ieee80211_free_txskb(&local->hw, skb); |
410 | return; | 410 | return; |
411 | } | 411 | } |
412 | 412 | ||
@@ -431,7 +431,7 @@ void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local, | |||
431 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 431 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
432 | 432 | ||
433 | if (WARN_ON(!info->control.vif)) { | 433 | if (WARN_ON(!info->control.vif)) { |
434 | kfree_skb(skb); | 434 | ieee80211_free_txskb(&local->hw, skb); |
435 | continue; | 435 | continue; |
436 | } | 436 | } |
437 | 437 | ||
@@ -643,13 +643,41 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
643 | break; | 643 | break; |
644 | } | 644 | } |
645 | 645 | ||
646 | if (id != WLAN_EID_VENDOR_SPECIFIC && | 646 | switch (id) { |
647 | id != WLAN_EID_QUIET && | 647 | case WLAN_EID_SSID: |
648 | test_bit(id, seen_elems)) { | 648 | case WLAN_EID_SUPP_RATES: |
649 | elems->parse_error = true; | 649 | case WLAN_EID_FH_PARAMS: |
650 | left -= elen; | 650 | case WLAN_EID_DS_PARAMS: |
651 | pos += elen; | 651 | case WLAN_EID_CF_PARAMS: |
652 | continue; | 652 | case WLAN_EID_TIM: |
653 | case WLAN_EID_IBSS_PARAMS: | ||
654 | case WLAN_EID_CHALLENGE: | ||
655 | case WLAN_EID_RSN: | ||
656 | case WLAN_EID_ERP_INFO: | ||
657 | case WLAN_EID_EXT_SUPP_RATES: | ||
658 | case WLAN_EID_HT_CAPABILITY: | ||
659 | case WLAN_EID_HT_OPERATION: | ||
660 | case WLAN_EID_VHT_CAPABILITY: | ||
661 | case WLAN_EID_VHT_OPERATION: | ||
662 | case WLAN_EID_MESH_ID: | ||
663 | case WLAN_EID_MESH_CONFIG: | ||
664 | case WLAN_EID_PEER_MGMT: | ||
665 | case WLAN_EID_PREQ: | ||
666 | case WLAN_EID_PREP: | ||
667 | case WLAN_EID_PERR: | ||
668 | case WLAN_EID_RANN: | ||
669 | case WLAN_EID_CHANNEL_SWITCH: | ||
670 | case WLAN_EID_EXT_CHANSWITCH_ANN: | ||
671 | case WLAN_EID_COUNTRY: | ||
672 | case WLAN_EID_PWR_CONSTRAINT: | ||
673 | case WLAN_EID_TIMEOUT_INTERVAL: | ||
674 | if (test_bit(id, seen_elems)) { | ||
675 | elems->parse_error = true; | ||
676 | left -= elen; | ||
677 | pos += elen; | ||
678 | continue; | ||
679 | } | ||
680 | break; | ||
653 | } | 681 | } |
654 | 682 | ||
655 | if (calc_crc && id < 64 && (filter & (1ULL << id))) | 683 | if (calc_crc && id < 64 && (filter & (1ULL << id))) |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index bdb53aba888e..8bd2f5c6a56e 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -106,7 +106,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) | |||
106 | if (status->flag & RX_FLAG_MMIC_ERROR) | 106 | if (status->flag & RX_FLAG_MMIC_ERROR) |
107 | goto mic_fail; | 107 | goto mic_fail; |
108 | 108 | ||
109 | if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key) | 109 | if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key && |
110 | rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP) | ||
110 | goto update_iv; | 111 | goto update_iv; |
111 | 112 | ||
112 | return RX_CONTINUE; | 113 | return RX_CONTINUE; |
@@ -545,14 +546,19 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
545 | 546 | ||
546 | static void bip_aad(struct sk_buff *skb, u8 *aad) | 547 | static void bip_aad(struct sk_buff *skb, u8 *aad) |
547 | { | 548 | { |
549 | __le16 mask_fc; | ||
550 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
551 | |||
548 | /* BIP AAD: FC(masked) || A1 || A2 || A3 */ | 552 | /* BIP AAD: FC(masked) || A1 || A2 || A3 */ |
549 | 553 | ||
550 | /* FC type/subtype */ | 554 | /* FC type/subtype */ |
551 | aad[0] = skb->data[0]; | ||
552 | /* Mask FC Retry, PwrMgt, MoreData flags to zero */ | 555 | /* Mask FC Retry, PwrMgt, MoreData flags to zero */ |
553 | aad[1] = skb->data[1] & ~(BIT(4) | BIT(5) | BIT(6)); | 556 | mask_fc = hdr->frame_control; |
557 | mask_fc &= ~cpu_to_le16(IEEE80211_FCTL_RETRY | IEEE80211_FCTL_PM | | ||
558 | IEEE80211_FCTL_MOREDATA); | ||
559 | put_unaligned(mask_fc, (__le16 *) &aad[0]); | ||
554 | /* A1 || A2 || A3 */ | 560 | /* A1 || A2 || A3 */ |
555 | memcpy(aad + 2, skb->data + 4, 3 * ETH_ALEN); | 561 | memcpy(aad + 2, &hdr->addr1, 3 * ETH_ALEN); |
556 | } | 562 | } |
557 | 563 | ||
558 | 564 | ||
diff --git a/net/nfc/Kconfig b/net/nfc/Kconfig index 8d8d9bc4b6ff..60c3bbb63e8e 100644 --- a/net/nfc/Kconfig +++ b/net/nfc/Kconfig | |||
@@ -3,8 +3,8 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | menuconfig NFC | 5 | menuconfig NFC |
6 | depends on NET && EXPERIMENTAL | 6 | depends on NET |
7 | tristate "NFC subsystem support (EXPERIMENTAL)" | 7 | tristate "NFC subsystem support" |
8 | default n | 8 | default n |
9 | help | 9 | help |
10 | Say Y here if you want to build support for NFC (Near field | 10 | Say Y here if you want to build support for NFC (Near field |
diff --git a/net/nfc/core.c b/net/nfc/core.c index 479bee36dc3e..aa64ea441676 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
@@ -40,6 +40,9 @@ | |||
40 | int nfc_devlist_generation; | 40 | int nfc_devlist_generation; |
41 | DEFINE_MUTEX(nfc_devlist_mutex); | 41 | DEFINE_MUTEX(nfc_devlist_mutex); |
42 | 42 | ||
43 | /* NFC device ID bitmap */ | ||
44 | static DEFINE_IDA(nfc_index_ida); | ||
45 | |||
43 | /** | 46 | /** |
44 | * nfc_dev_up - turn on the NFC device | 47 | * nfc_dev_up - turn on the NFC device |
45 | * | 48 | * |
@@ -181,6 +184,7 @@ int nfc_stop_poll(struct nfc_dev *dev) | |||
181 | 184 | ||
182 | dev->ops->stop_poll(dev); | 185 | dev->ops->stop_poll(dev); |
183 | dev->polling = false; | 186 | dev->polling = false; |
187 | dev->rf_mode = NFC_RF_NONE; | ||
184 | 188 | ||
185 | error: | 189 | error: |
186 | device_unlock(&dev->dev); | 190 | device_unlock(&dev->dev); |
@@ -194,7 +198,7 @@ static struct nfc_target *nfc_find_target(struct nfc_dev *dev, u32 target_idx) | |||
194 | if (dev->n_targets == 0) | 198 | if (dev->n_targets == 0) |
195 | return NULL; | 199 | return NULL; |
196 | 200 | ||
197 | for (i = 0; i < dev->n_targets ; i++) { | 201 | for (i = 0; i < dev->n_targets; i++) { |
198 | if (dev->targets[i].idx == target_idx) | 202 | if (dev->targets[i].idx == target_idx) |
199 | return &dev->targets[i]; | 203 | return &dev->targets[i]; |
200 | } | 204 | } |
@@ -274,12 +278,14 @@ int nfc_dep_link_down(struct nfc_dev *dev) | |||
274 | if (!rc) { | 278 | if (!rc) { |
275 | dev->dep_link_up = false; | 279 | dev->dep_link_up = false; |
276 | dev->active_target = NULL; | 280 | dev->active_target = NULL; |
281 | dev->rf_mode = NFC_RF_NONE; | ||
277 | nfc_llcp_mac_is_down(dev); | 282 | nfc_llcp_mac_is_down(dev); |
278 | nfc_genl_dep_link_down_event(dev); | 283 | nfc_genl_dep_link_down_event(dev); |
279 | } | 284 | } |
280 | 285 | ||
281 | error: | 286 | error: |
282 | device_unlock(&dev->dev); | 287 | device_unlock(&dev->dev); |
288 | |||
283 | return rc; | 289 | return rc; |
284 | } | 290 | } |
285 | 291 | ||
@@ -503,6 +509,7 @@ EXPORT_SYMBOL(nfc_tm_activated); | |||
503 | int nfc_tm_deactivated(struct nfc_dev *dev) | 509 | int nfc_tm_deactivated(struct nfc_dev *dev) |
504 | { | 510 | { |
505 | dev->dep_link_up = false; | 511 | dev->dep_link_up = false; |
512 | dev->rf_mode = NFC_RF_NONE; | ||
506 | 513 | ||
507 | return nfc_genl_tm_deactivated(dev); | 514 | return nfc_genl_tm_deactivated(dev); |
508 | } | 515 | } |
@@ -697,6 +704,8 @@ static void nfc_check_pres_work(struct work_struct *work) | |||
697 | 704 | ||
698 | if (dev->active_target && timer_pending(&dev->check_pres_timer) == 0) { | 705 | if (dev->active_target && timer_pending(&dev->check_pres_timer) == 0) { |
699 | rc = dev->ops->check_presence(dev, dev->active_target); | 706 | rc = dev->ops->check_presence(dev, dev->active_target); |
707 | if (rc == -EOPNOTSUPP) | ||
708 | goto exit; | ||
700 | if (!rc) { | 709 | if (!rc) { |
701 | mod_timer(&dev->check_pres_timer, jiffies + | 710 | mod_timer(&dev->check_pres_timer, jiffies + |
702 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); | 711 | msecs_to_jiffies(NFC_CHECK_PRES_FREQ_MS)); |
@@ -708,6 +717,7 @@ static void nfc_check_pres_work(struct work_struct *work) | |||
708 | } | 717 | } |
709 | } | 718 | } |
710 | 719 | ||
720 | exit: | ||
711 | device_unlock(&dev->dev); | 721 | device_unlock(&dev->dev); |
712 | } | 722 | } |
713 | 723 | ||
@@ -753,7 +763,6 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | |||
753 | u32 supported_protocols, | 763 | u32 supported_protocols, |
754 | int tx_headroom, int tx_tailroom) | 764 | int tx_headroom, int tx_tailroom) |
755 | { | 765 | { |
756 | static atomic_t dev_no = ATOMIC_INIT(0); | ||
757 | struct nfc_dev *dev; | 766 | struct nfc_dev *dev; |
758 | 767 | ||
759 | if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || | 768 | if (!ops->start_poll || !ops->stop_poll || !ops->activate_target || |
@@ -767,11 +776,6 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | |||
767 | if (!dev) | 776 | if (!dev) |
768 | return NULL; | 777 | return NULL; |
769 | 778 | ||
770 | dev->dev.class = &nfc_class; | ||
771 | dev->idx = atomic_inc_return(&dev_no) - 1; | ||
772 | dev_set_name(&dev->dev, "nfc%d", dev->idx); | ||
773 | device_initialize(&dev->dev); | ||
774 | |||
775 | dev->ops = ops; | 779 | dev->ops = ops; |
776 | dev->supported_protocols = supported_protocols; | 780 | dev->supported_protocols = supported_protocols; |
777 | dev->tx_headroom = tx_headroom; | 781 | dev->tx_headroom = tx_headroom; |
@@ -779,6 +783,7 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops, | |||
779 | 783 | ||
780 | nfc_genl_data_init(&dev->genl_data); | 784 | nfc_genl_data_init(&dev->genl_data); |
781 | 785 | ||
786 | dev->rf_mode = NFC_RF_NONE; | ||
782 | 787 | ||
783 | /* first generation must not be 0 */ | 788 | /* first generation must not be 0 */ |
784 | dev->targets_generation = 1; | 789 | dev->targets_generation = 1; |
@@ -806,6 +811,14 @@ int nfc_register_device(struct nfc_dev *dev) | |||
806 | 811 | ||
807 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); | 812 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); |
808 | 813 | ||
814 | dev->idx = ida_simple_get(&nfc_index_ida, 0, 0, GFP_KERNEL); | ||
815 | if (dev->idx < 0) | ||
816 | return dev->idx; | ||
817 | |||
818 | dev->dev.class = &nfc_class; | ||
819 | dev_set_name(&dev->dev, "nfc%d", dev->idx); | ||
820 | device_initialize(&dev->dev); | ||
821 | |||
809 | mutex_lock(&nfc_devlist_mutex); | 822 | mutex_lock(&nfc_devlist_mutex); |
810 | nfc_devlist_generation++; | 823 | nfc_devlist_generation++; |
811 | rc = device_add(&dev->dev); | 824 | rc = device_add(&dev->dev); |
@@ -834,10 +847,12 @@ EXPORT_SYMBOL(nfc_register_device); | |||
834 | */ | 847 | */ |
835 | void nfc_unregister_device(struct nfc_dev *dev) | 848 | void nfc_unregister_device(struct nfc_dev *dev) |
836 | { | 849 | { |
837 | int rc; | 850 | int rc, id; |
838 | 851 | ||
839 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); | 852 | pr_debug("dev_name=%s\n", dev_name(&dev->dev)); |
840 | 853 | ||
854 | id = dev->idx; | ||
855 | |||
841 | mutex_lock(&nfc_devlist_mutex); | 856 | mutex_lock(&nfc_devlist_mutex); |
842 | nfc_devlist_generation++; | 857 | nfc_devlist_generation++; |
843 | 858 | ||
@@ -856,6 +871,8 @@ void nfc_unregister_device(struct nfc_dev *dev) | |||
856 | pr_debug("The userspace won't be notified that the device %s was removed\n", | 871 | pr_debug("The userspace won't be notified that the device %s was removed\n", |
857 | dev_name(&dev->dev)); | 872 | dev_name(&dev->dev)); |
858 | 873 | ||
874 | ida_simple_remove(&nfc_index_ida, id); | ||
875 | |||
859 | } | 876 | } |
860 | EXPORT_SYMBOL(nfc_unregister_device); | 877 | EXPORT_SYMBOL(nfc_unregister_device); |
861 | 878 | ||
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c index 71c6a7086b8f..07659cfd6d7b 100644 --- a/net/nfc/hci/command.c +++ b/net/nfc/hci/command.c | |||
@@ -257,16 +257,16 @@ static u8 nfc_hci_create_pipe(struct nfc_hci_dev *hdev, u8 dest_host, | |||
257 | *result = nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, | 257 | *result = nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, |
258 | NFC_HCI_ADM_CREATE_PIPE, | 258 | NFC_HCI_ADM_CREATE_PIPE, |
259 | (u8 *) ¶ms, sizeof(params), &skb); | 259 | (u8 *) ¶ms, sizeof(params), &skb); |
260 | if (*result == 0) { | 260 | if (*result < 0) |
261 | resp = (struct hci_create_pipe_resp *)skb->data; | 261 | return NFC_HCI_INVALID_PIPE; |
262 | pipe = resp->pipe; | ||
263 | kfree_skb(skb); | ||
264 | 262 | ||
265 | pr_debug("pipe created=%d\n", pipe); | 263 | resp = (struct hci_create_pipe_resp *)skb->data; |
264 | pipe = resp->pipe; | ||
265 | kfree_skb(skb); | ||
266 | 266 | ||
267 | return pipe; | 267 | pr_debug("pipe created=%d\n", pipe); |
268 | } else | 268 | |
269 | return NFC_HCI_INVALID_PIPE; | 269 | return pipe; |
270 | } | 270 | } |
271 | 271 | ||
272 | static int nfc_hci_delete_pipe(struct nfc_hci_dev *hdev, u8 pipe) | 272 | static int nfc_hci_delete_pipe(struct nfc_hci_dev *hdev, u8 pipe) |
@@ -279,8 +279,6 @@ static int nfc_hci_delete_pipe(struct nfc_hci_dev *hdev, u8 pipe) | |||
279 | 279 | ||
280 | static int nfc_hci_clear_all_pipes(struct nfc_hci_dev *hdev) | 280 | static int nfc_hci_clear_all_pipes(struct nfc_hci_dev *hdev) |
281 | { | 281 | { |
282 | int r; | ||
283 | |||
284 | u8 param[2]; | 282 | u8 param[2]; |
285 | 283 | ||
286 | /* TODO: Find out what the identity reference data is | 284 | /* TODO: Find out what the identity reference data is |
@@ -288,10 +286,8 @@ static int nfc_hci_clear_all_pipes(struct nfc_hci_dev *hdev) | |||
288 | 286 | ||
289 | pr_debug("\n"); | 287 | pr_debug("\n"); |
290 | 288 | ||
291 | r = nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, | 289 | return nfc_hci_execute_cmd(hdev, NFC_HCI_ADMIN_PIPE, |
292 | NFC_HCI_ADM_CLEAR_ALL_PIPE, param, 2, NULL); | 290 | NFC_HCI_ADM_CLEAR_ALL_PIPE, param, 2, NULL); |
293 | |||
294 | return 0; | ||
295 | } | 291 | } |
296 | 292 | ||
297 | int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate) | 293 | int nfc_hci_disconnect_gate(struct nfc_hci_dev *hdev, u8 gate) |
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 5fbb6e40793e..bc571b0efb92 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c | |||
@@ -65,8 +65,9 @@ static void nfc_hci_msg_tx_work(struct work_struct *work) | |||
65 | -ETIME); | 65 | -ETIME); |
66 | kfree(hdev->cmd_pending_msg); | 66 | kfree(hdev->cmd_pending_msg); |
67 | hdev->cmd_pending_msg = NULL; | 67 | hdev->cmd_pending_msg = NULL; |
68 | } else | 68 | } else { |
69 | goto exit; | 69 | goto exit; |
70 | } | ||
70 | } | 71 | } |
71 | 72 | ||
72 | next_msg: | 73 | next_msg: |
@@ -182,7 +183,7 @@ static u32 nfc_hci_sak_to_protocol(u8 sak) | |||
182 | } | 183 | } |
183 | } | 184 | } |
184 | 185 | ||
185 | static int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) | 186 | int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) |
186 | { | 187 | { |
187 | struct nfc_target *targets; | 188 | struct nfc_target *targets; |
188 | struct sk_buff *atqa_skb = NULL; | 189 | struct sk_buff *atqa_skb = NULL; |
@@ -263,7 +264,9 @@ static int nfc_hci_target_discovered(struct nfc_hci_dev *hdev, u8 gate) | |||
263 | break; | 264 | break; |
264 | } | 265 | } |
265 | 266 | ||
266 | targets->hci_reader_gate = gate; | 267 | /* if driver set the new gate, we will skip the old one */ |
268 | if (targets->hci_reader_gate == 0x00) | ||
269 | targets->hci_reader_gate = gate; | ||
267 | 270 | ||
268 | r = nfc_targets_found(hdev->ndev, targets, 1); | 271 | r = nfc_targets_found(hdev->ndev, targets, 1); |
269 | 272 | ||
@@ -275,6 +278,7 @@ exit: | |||
275 | 278 | ||
276 | return r; | 279 | return r; |
277 | } | 280 | } |
281 | EXPORT_SYMBOL(nfc_hci_target_discovered); | ||
278 | 282 | ||
279 | void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, | 283 | void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, |
280 | struct sk_buff *skb) | 284 | struct sk_buff *skb) |
@@ -307,8 +311,13 @@ void nfc_hci_event_received(struct nfc_hci_dev *hdev, u8 pipe, u8 event, | |||
307 | nfc_hci_pipe2gate(hdev, pipe)); | 311 | nfc_hci_pipe2gate(hdev, pipe)); |
308 | break; | 312 | break; |
309 | default: | 313 | default: |
310 | /* TODO: Unknown events are hardware specific | 314 | if (hdev->ops->event_received) { |
311 | * pass them to the driver (needs a new hci_ops) */ | 315 | hdev->ops->event_received(hdev, |
316 | nfc_hci_pipe2gate(hdev, pipe), | ||
317 | event, skb); | ||
318 | return; | ||
319 | } | ||
320 | |||
312 | break; | 321 | break; |
313 | } | 322 | } |
314 | 323 | ||
@@ -527,7 +536,8 @@ static int hci_start_poll(struct nfc_dev *nfc_dev, | |||
527 | return hdev->ops->start_poll(hdev, im_protocols, tm_protocols); | 536 | return hdev->ops->start_poll(hdev, im_protocols, tm_protocols); |
528 | else | 537 | else |
529 | return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | 538 | return nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, |
530 | NFC_HCI_EVT_READER_REQUESTED, NULL, 0); | 539 | NFC_HCI_EVT_READER_REQUESTED, |
540 | NULL, 0); | ||
531 | } | 541 | } |
532 | 542 | ||
533 | static void hci_stop_poll(struct nfc_dev *nfc_dev) | 543 | static void hci_stop_poll(struct nfc_dev *nfc_dev) |
@@ -538,6 +548,28 @@ static void hci_stop_poll(struct nfc_dev *nfc_dev) | |||
538 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | 548 | NFC_HCI_EVT_END_OPERATION, NULL, 0); |
539 | } | 549 | } |
540 | 550 | ||
551 | static int hci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | ||
552 | __u8 comm_mode, __u8 *gb, size_t gb_len) | ||
553 | { | ||
554 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | ||
555 | |||
556 | if (hdev->ops->dep_link_up) | ||
557 | return hdev->ops->dep_link_up(hdev, target, comm_mode, | ||
558 | gb, gb_len); | ||
559 | |||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | static int hci_dep_link_down(struct nfc_dev *nfc_dev) | ||
564 | { | ||
565 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | ||
566 | |||
567 | if (hdev->ops->dep_link_down) | ||
568 | return hdev->ops->dep_link_down(hdev); | ||
569 | |||
570 | return 0; | ||
571 | } | ||
572 | |||
541 | static int hci_activate_target(struct nfc_dev *nfc_dev, | 573 | static int hci_activate_target(struct nfc_dev *nfc_dev, |
542 | struct nfc_target *target, u32 protocol) | 574 | struct nfc_target *target, u32 protocol) |
543 | { | 575 | { |
@@ -586,8 +618,8 @@ static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
586 | switch (target->hci_reader_gate) { | 618 | switch (target->hci_reader_gate) { |
587 | case NFC_HCI_RF_READER_A_GATE: | 619 | case NFC_HCI_RF_READER_A_GATE: |
588 | case NFC_HCI_RF_READER_B_GATE: | 620 | case NFC_HCI_RF_READER_B_GATE: |
589 | if (hdev->ops->data_exchange) { | 621 | if (hdev->ops->im_transceive) { |
590 | r = hdev->ops->data_exchange(hdev, target, skb, cb, | 622 | r = hdev->ops->im_transceive(hdev, target, skb, cb, |
591 | cb_context); | 623 | cb_context); |
592 | if (r <= 0) /* handled */ | 624 | if (r <= 0) /* handled */ |
593 | break; | 625 | break; |
@@ -604,14 +636,14 @@ static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
604 | skb->len, hci_transceive_cb, hdev); | 636 | skb->len, hci_transceive_cb, hdev); |
605 | break; | 637 | break; |
606 | default: | 638 | default: |
607 | if (hdev->ops->data_exchange) { | 639 | if (hdev->ops->im_transceive) { |
608 | r = hdev->ops->data_exchange(hdev, target, skb, cb, | 640 | r = hdev->ops->im_transceive(hdev, target, skb, cb, |
609 | cb_context); | 641 | cb_context); |
610 | if (r == 1) | 642 | if (r == 1) |
611 | r = -ENOTSUPP; | 643 | r = -ENOTSUPP; |
612 | } | 644 | } else { |
613 | else | ||
614 | r = -ENOTSUPP; | 645 | r = -ENOTSUPP; |
646 | } | ||
615 | break; | 647 | break; |
616 | } | 648 | } |
617 | 649 | ||
@@ -620,6 +652,16 @@ static int hci_transceive(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
620 | return r; | 652 | return r; |
621 | } | 653 | } |
622 | 654 | ||
655 | static int hci_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb) | ||
656 | { | ||
657 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | ||
658 | |||
659 | if (hdev->ops->tm_send) | ||
660 | return hdev->ops->tm_send(hdev, skb); | ||
661 | else | ||
662 | return -ENOTSUPP; | ||
663 | } | ||
664 | |||
623 | static int hci_check_presence(struct nfc_dev *nfc_dev, | 665 | static int hci_check_presence(struct nfc_dev *nfc_dev, |
624 | struct nfc_target *target) | 666 | struct nfc_target *target) |
625 | { | 667 | { |
@@ -723,9 +765,12 @@ static struct nfc_ops hci_nfc_ops = { | |||
723 | .dev_down = hci_dev_down, | 765 | .dev_down = hci_dev_down, |
724 | .start_poll = hci_start_poll, | 766 | .start_poll = hci_start_poll, |
725 | .stop_poll = hci_stop_poll, | 767 | .stop_poll = hci_stop_poll, |
768 | .dep_link_up = hci_dep_link_up, | ||
769 | .dep_link_down = hci_dep_link_down, | ||
726 | .activate_target = hci_activate_target, | 770 | .activate_target = hci_activate_target, |
727 | .deactivate_target = hci_deactivate_target, | 771 | .deactivate_target = hci_deactivate_target, |
728 | .im_transceive = hci_transceive, | 772 | .im_transceive = hci_transceive, |
773 | .tm_send = hci_tm_send, | ||
729 | .check_presence = hci_check_presence, | 774 | .check_presence = hci_check_presence, |
730 | }; | 775 | }; |
731 | 776 | ||
@@ -848,7 +893,7 @@ void nfc_hci_driver_failure(struct nfc_hci_dev *hdev, int err) | |||
848 | } | 893 | } |
849 | EXPORT_SYMBOL(nfc_hci_driver_failure); | 894 | EXPORT_SYMBOL(nfc_hci_driver_failure); |
850 | 895 | ||
851 | void inline nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) | 896 | void nfc_hci_recv_frame(struct nfc_hci_dev *hdev, struct sk_buff *skb) |
852 | { | 897 | { |
853 | nfc_llc_rcv_from_drv(hdev->llc, skb); | 898 | nfc_llc_rcv_from_drv(hdev->llc, skb); |
854 | } | 899 | } |
diff --git a/net/nfc/hci/llc.c b/net/nfc/hci/llc.c index ae1205ded87f..fe5e966e5b88 100644 --- a/net/nfc/hci/llc.c +++ b/net/nfc/hci/llc.c | |||
@@ -72,7 +72,7 @@ int nfc_llc_register(const char *name, struct nfc_llc_ops *ops) | |||
72 | llc_engine->ops = ops; | 72 | llc_engine->ops = ops; |
73 | 73 | ||
74 | INIT_LIST_HEAD(&llc_engine->entry); | 74 | INIT_LIST_HEAD(&llc_engine->entry); |
75 | list_add_tail (&llc_engine->entry, &llc_engines); | 75 | list_add_tail(&llc_engine->entry, &llc_engines); |
76 | 76 | ||
77 | return 0; | 77 | return 0; |
78 | } | 78 | } |
diff --git a/net/nfc/hci/llc_shdlc.c b/net/nfc/hci/llc_shdlc.c index 01cbc72943cd..27b313befc35 100644 --- a/net/nfc/hci/llc_shdlc.c +++ b/net/nfc/hci/llc_shdlc.c | |||
@@ -634,9 +634,9 @@ static void llc_shdlc_sm_work(struct work_struct *work) | |||
634 | r = llc_shdlc_connect_initiate(shdlc); | 634 | r = llc_shdlc_connect_initiate(shdlc); |
635 | else | 635 | else |
636 | r = -ETIME; | 636 | r = -ETIME; |
637 | if (r < 0) | 637 | if (r < 0) { |
638 | llc_shdlc_connect_complete(shdlc, r); | 638 | llc_shdlc_connect_complete(shdlc, r); |
639 | else { | 639 | } else { |
640 | mod_timer(&shdlc->connect_timer, jiffies + | 640 | mod_timer(&shdlc->connect_timer, jiffies + |
641 | msecs_to_jiffies(SHDLC_CONNECT_VALUE_MS)); | 641 | msecs_to_jiffies(SHDLC_CONNECT_VALUE_MS)); |
642 | 642 | ||
@@ -682,9 +682,8 @@ static void llc_shdlc_sm_work(struct work_struct *work) | |||
682 | llc_shdlc_handle_send_queue(shdlc); | 682 | llc_shdlc_handle_send_queue(shdlc); |
683 | } | 683 | } |
684 | 684 | ||
685 | if (shdlc->hard_fault) { | 685 | if (shdlc->hard_fault) |
686 | shdlc->llc_failure(shdlc->hdev, shdlc->hard_fault); | 686 | shdlc->llc_failure(shdlc->hdev, shdlc->hard_fault); |
687 | } | ||
688 | break; | 687 | break; |
689 | default: | 688 | default: |
690 | break; | 689 | break; |
diff --git a/net/nfc/llcp/Kconfig b/net/nfc/llcp/Kconfig index fbf5e8150908..a1a41cd68255 100644 --- a/net/nfc/llcp/Kconfig +++ b/net/nfc/llcp/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config NFC_LLCP | 1 | config NFC_LLCP |
2 | depends on NFC && EXPERIMENTAL | 2 | depends on NFC |
3 | bool "NFC LLCP support (EXPERIMENTAL)" | 3 | bool "NFC LLCP support" |
4 | default n | 4 | default n |
5 | help | 5 | help |
6 | Say Y here if you want to build support for a kernel NFC LLCP | 6 | Say Y here if you want to build support for a kernel NFC LLCP |
diff --git a/net/nfc/llcp/commands.c b/net/nfc/llcp/commands.c index c45ccd6c094c..ed2d17312d61 100644 --- a/net/nfc/llcp/commands.c +++ b/net/nfc/llcp/commands.c | |||
@@ -261,7 +261,6 @@ int nfc_llcp_disconnect(struct nfc_llcp_sock *sock) | |||
261 | struct sk_buff *skb; | 261 | struct sk_buff *skb; |
262 | struct nfc_dev *dev; | 262 | struct nfc_dev *dev; |
263 | struct nfc_llcp_local *local; | 263 | struct nfc_llcp_local *local; |
264 | u16 size = 0; | ||
265 | 264 | ||
266 | pr_debug("Sending DISC\n"); | 265 | pr_debug("Sending DISC\n"); |
267 | 266 | ||
@@ -273,17 +272,10 @@ int nfc_llcp_disconnect(struct nfc_llcp_sock *sock) | |||
273 | if (dev == NULL) | 272 | if (dev == NULL) |
274 | return -ENODEV; | 273 | return -ENODEV; |
275 | 274 | ||
276 | size += LLCP_HEADER_SIZE; | 275 | skb = llcp_allocate_pdu(sock, LLCP_PDU_DISC, 0); |
277 | size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE; | ||
278 | |||
279 | skb = alloc_skb(size, GFP_ATOMIC); | ||
280 | if (skb == NULL) | 276 | if (skb == NULL) |
281 | return -ENOMEM; | 277 | return -ENOMEM; |
282 | 278 | ||
283 | skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); | ||
284 | |||
285 | skb = llcp_add_header(skb, sock->dsap, sock->ssap, LLCP_PDU_DISC); | ||
286 | |||
287 | skb_queue_tail(&local->tx_queue, skb); | 279 | skb_queue_tail(&local->tx_queue, skb); |
288 | 280 | ||
289 | return 0; | 281 | return 0; |
@@ -324,8 +316,7 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) | |||
324 | struct sk_buff *skb; | 316 | struct sk_buff *skb; |
325 | u8 *service_name_tlv = NULL, service_name_tlv_length; | 317 | u8 *service_name_tlv = NULL, service_name_tlv_length; |
326 | u8 *miux_tlv = NULL, miux_tlv_length; | 318 | u8 *miux_tlv = NULL, miux_tlv_length; |
327 | u8 *rw_tlv = NULL, rw_tlv_length, rw; | 319 | u8 *rw_tlv = NULL, rw_tlv_length; |
328 | __be16 miux; | ||
329 | int err; | 320 | int err; |
330 | u16 size = 0; | 321 | u16 size = 0; |
331 | 322 | ||
@@ -343,13 +334,11 @@ int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) | |||
343 | size += service_name_tlv_length; | 334 | size += service_name_tlv_length; |
344 | } | 335 | } |
345 | 336 | ||
346 | miux = cpu_to_be16(LLCP_MAX_MIUX); | 337 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0, |
347 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, | ||
348 | &miux_tlv_length); | 338 | &miux_tlv_length); |
349 | size += miux_tlv_length; | 339 | size += miux_tlv_length; |
350 | 340 | ||
351 | rw = LLCP_MAX_RW; | 341 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length); |
352 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length); | ||
353 | size += rw_tlv_length; | 342 | size += rw_tlv_length; |
354 | 343 | ||
355 | pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len); | 344 | pr_debug("SKB size %d SN length %zu\n", size, sock->service_name_len); |
@@ -386,8 +375,7 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock) | |||
386 | struct nfc_llcp_local *local; | 375 | struct nfc_llcp_local *local; |
387 | struct sk_buff *skb; | 376 | struct sk_buff *skb; |
388 | u8 *miux_tlv = NULL, miux_tlv_length; | 377 | u8 *miux_tlv = NULL, miux_tlv_length; |
389 | u8 *rw_tlv = NULL, rw_tlv_length, rw; | 378 | u8 *rw_tlv = NULL, rw_tlv_length; |
390 | __be16 miux; | ||
391 | int err; | 379 | int err; |
392 | u16 size = 0; | 380 | u16 size = 0; |
393 | 381 | ||
@@ -397,13 +385,11 @@ int nfc_llcp_send_cc(struct nfc_llcp_sock *sock) | |||
397 | if (local == NULL) | 385 | if (local == NULL) |
398 | return -ENODEV; | 386 | return -ENODEV; |
399 | 387 | ||
400 | miux = cpu_to_be16(LLCP_MAX_MIUX); | 388 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0, |
401 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, | ||
402 | &miux_tlv_length); | 389 | &miux_tlv_length); |
403 | size += miux_tlv_length; | 390 | size += miux_tlv_length; |
404 | 391 | ||
405 | rw = LLCP_MAX_RW; | 392 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &local->rw, 0, &rw_tlv_length); |
406 | rw_tlv = nfc_llcp_build_tlv(LLCP_TLV_RW, &rw, 0, &rw_tlv_length); | ||
407 | size += rw_tlv_length; | 393 | size += rw_tlv_length; |
408 | 394 | ||
409 | skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size); | 395 | skb = llcp_allocate_pdu(sock, LLCP_PDU_CC, size); |
@@ -428,6 +414,52 @@ error_tlv: | |||
428 | return err; | 414 | return err; |
429 | } | 415 | } |
430 | 416 | ||
417 | int nfc_llcp_send_snl(struct nfc_llcp_local *local, u8 tid, u8 sap) | ||
418 | { | ||
419 | struct sk_buff *skb; | ||
420 | struct nfc_dev *dev; | ||
421 | u8 *sdres_tlv = NULL, sdres_tlv_length, sdres[2]; | ||
422 | u16 size = 0; | ||
423 | |||
424 | pr_debug("Sending SNL tid 0x%x sap 0x%x\n", tid, sap); | ||
425 | |||
426 | if (local == NULL) | ||
427 | return -ENODEV; | ||
428 | |||
429 | dev = local->dev; | ||
430 | if (dev == NULL) | ||
431 | return -ENODEV; | ||
432 | |||
433 | sdres[0] = tid; | ||
434 | sdres[1] = sap; | ||
435 | sdres_tlv = nfc_llcp_build_tlv(LLCP_TLV_SDRES, sdres, 0, | ||
436 | &sdres_tlv_length); | ||
437 | if (sdres_tlv == NULL) | ||
438 | return -ENOMEM; | ||
439 | |||
440 | size += LLCP_HEADER_SIZE; | ||
441 | size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE; | ||
442 | size += sdres_tlv_length; | ||
443 | |||
444 | skb = alloc_skb(size, GFP_KERNEL); | ||
445 | if (skb == NULL) { | ||
446 | kfree(sdres_tlv); | ||
447 | return -ENOMEM; | ||
448 | } | ||
449 | |||
450 | skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); | ||
451 | |||
452 | skb = llcp_add_header(skb, LLCP_SAP_SDP, LLCP_SAP_SDP, LLCP_PDU_SNL); | ||
453 | |||
454 | memcpy(skb_put(skb, sdres_tlv_length), sdres_tlv, sdres_tlv_length); | ||
455 | |||
456 | skb_queue_tail(&local->tx_queue, skb); | ||
457 | |||
458 | kfree(sdres_tlv); | ||
459 | |||
460 | return 0; | ||
461 | } | ||
462 | |||
431 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason) | 463 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason) |
432 | { | 464 | { |
433 | struct sk_buff *skb; | 465 | struct sk_buff *skb; |
@@ -541,6 +573,52 @@ int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | |||
541 | return len; | 573 | return len; |
542 | } | 574 | } |
543 | 575 | ||
576 | int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, | ||
577 | struct msghdr *msg, size_t len) | ||
578 | { | ||
579 | struct sk_buff *pdu; | ||
580 | struct nfc_llcp_local *local; | ||
581 | size_t frag_len = 0, remaining_len; | ||
582 | u8 *msg_ptr; | ||
583 | int err; | ||
584 | |||
585 | pr_debug("Send UI frame len %zd\n", len); | ||
586 | |||
587 | local = sock->local; | ||
588 | if (local == NULL) | ||
589 | return -ENODEV; | ||
590 | |||
591 | remaining_len = len; | ||
592 | msg_ptr = (u8 *) msg->msg_iov; | ||
593 | |||
594 | while (remaining_len > 0) { | ||
595 | |||
596 | frag_len = min_t(size_t, sock->miu, remaining_len); | ||
597 | |||
598 | pr_debug("Fragment %zd bytes remaining %zd", | ||
599 | frag_len, remaining_len); | ||
600 | |||
601 | pdu = nfc_alloc_send_skb(sock->dev, &sock->sk, MSG_DONTWAIT, | ||
602 | frag_len + LLCP_HEADER_SIZE, &err); | ||
603 | if (pdu == NULL) { | ||
604 | pr_err("Could not allocate PDU\n"); | ||
605 | continue; | ||
606 | } | ||
607 | |||
608 | pdu = llcp_add_header(pdu, dsap, ssap, LLCP_PDU_UI); | ||
609 | |||
610 | memcpy(skb_put(pdu, frag_len), msg_ptr, frag_len); | ||
611 | |||
612 | /* No need to check for the peer RW for UI frames */ | ||
613 | skb_queue_tail(&local->tx_queue, pdu); | ||
614 | |||
615 | remaining_len -= frag_len; | ||
616 | msg_ptr += frag_len; | ||
617 | } | ||
618 | |||
619 | return len; | ||
620 | } | ||
621 | |||
544 | int nfc_llcp_send_rr(struct nfc_llcp_sock *sock) | 622 | int nfc_llcp_send_rr(struct nfc_llcp_sock *sock) |
545 | { | 623 | { |
546 | struct sk_buff *skb; | 624 | struct sk_buff *skb; |
diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index cc10d073c338..f6804532047a 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c | |||
@@ -45,12 +45,38 @@ void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *sk) | |||
45 | write_unlock(&l->lock); | 45 | write_unlock(&l->lock); |
46 | } | 46 | } |
47 | 47 | ||
48 | static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock) | ||
49 | { | ||
50 | struct nfc_llcp_local *local = sock->local; | ||
51 | struct sk_buff *s, *tmp; | ||
52 | |||
53 | pr_debug("%p\n", &sock->sk); | ||
54 | |||
55 | skb_queue_purge(&sock->tx_queue); | ||
56 | skb_queue_purge(&sock->tx_pending_queue); | ||
57 | skb_queue_purge(&sock->tx_backlog_queue); | ||
58 | |||
59 | if (local == NULL) | ||
60 | return; | ||
61 | |||
62 | /* Search for local pending SKBs that are related to this socket */ | ||
63 | skb_queue_walk_safe(&local->tx_queue, s, tmp) { | ||
64 | if (s->sk != &sock->sk) | ||
65 | continue; | ||
66 | |||
67 | skb_unlink(s, &local->tx_queue); | ||
68 | kfree_skb(s); | ||
69 | } | ||
70 | } | ||
71 | |||
48 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) | 72 | static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) |
49 | { | 73 | { |
50 | struct sock *sk; | 74 | struct sock *sk; |
51 | struct hlist_node *node, *tmp; | 75 | struct hlist_node *node, *tmp; |
52 | struct nfc_llcp_sock *llcp_sock; | 76 | struct nfc_llcp_sock *llcp_sock; |
53 | 77 | ||
78 | skb_queue_purge(&local->tx_queue); | ||
79 | |||
54 | write_lock(&local->sockets.lock); | 80 | write_lock(&local->sockets.lock); |
55 | 81 | ||
56 | sk_for_each_safe(sk, node, tmp, &local->sockets.head) { | 82 | sk_for_each_safe(sk, node, tmp, &local->sockets.head) { |
@@ -58,6 +84,8 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) | |||
58 | 84 | ||
59 | bh_lock_sock(sk); | 85 | bh_lock_sock(sk); |
60 | 86 | ||
87 | nfc_llcp_socket_purge(llcp_sock); | ||
88 | |||
61 | if (sk->sk_state == LLCP_CONNECTED) | 89 | if (sk->sk_state == LLCP_CONNECTED) |
62 | nfc_put_device(llcp_sock->dev); | 90 | nfc_put_device(llcp_sock->dev); |
63 | 91 | ||
@@ -65,7 +93,8 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) | |||
65 | struct nfc_llcp_sock *lsk, *n; | 93 | struct nfc_llcp_sock *lsk, *n; |
66 | struct sock *accept_sk; | 94 | struct sock *accept_sk; |
67 | 95 | ||
68 | list_for_each_entry_safe(lsk, n, &llcp_sock->accept_queue, | 96 | list_for_each_entry_safe(lsk, n, |
97 | &llcp_sock->accept_queue, | ||
69 | accept_queue) { | 98 | accept_queue) { |
70 | accept_sk = &lsk->sk; | 99 | accept_sk = &lsk->sk; |
71 | bh_lock_sock(accept_sk); | 100 | bh_lock_sock(accept_sk); |
@@ -85,6 +114,16 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen) | |||
85 | } | 114 | } |
86 | } | 115 | } |
87 | 116 | ||
117 | /* | ||
118 | * If we have a connection less socket bound, we keep it alive | ||
119 | * if the device is still present. | ||
120 | */ | ||
121 | if (sk->sk_state == LLCP_BOUND && sk->sk_type == SOCK_DGRAM && | ||
122 | listen == true) { | ||
123 | bh_unlock_sock(sk); | ||
124 | continue; | ||
125 | } | ||
126 | |||
88 | sk->sk_state = LLCP_CLOSED; | 127 | sk->sk_state = LLCP_CLOSED; |
89 | 128 | ||
90 | bh_unlock_sock(sk); | 129 | bh_unlock_sock(sk); |
@@ -134,7 +173,7 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, | |||
134 | { | 173 | { |
135 | struct sock *sk; | 174 | struct sock *sk; |
136 | struct hlist_node *node; | 175 | struct hlist_node *node; |
137 | struct nfc_llcp_sock *llcp_sock; | 176 | struct nfc_llcp_sock *llcp_sock, *tmp_sock; |
138 | 177 | ||
139 | pr_debug("ssap dsap %d %d\n", ssap, dsap); | 178 | pr_debug("ssap dsap %d %d\n", ssap, dsap); |
140 | 179 | ||
@@ -146,10 +185,12 @@ static struct nfc_llcp_sock *nfc_llcp_sock_get(struct nfc_llcp_local *local, | |||
146 | llcp_sock = NULL; | 185 | llcp_sock = NULL; |
147 | 186 | ||
148 | sk_for_each(sk, node, &local->sockets.head) { | 187 | sk_for_each(sk, node, &local->sockets.head) { |
149 | llcp_sock = nfc_llcp_sock(sk); | 188 | tmp_sock = nfc_llcp_sock(sk); |
150 | 189 | ||
151 | if (llcp_sock->ssap == ssap && llcp_sock->dsap == dsap) | 190 | if (tmp_sock->ssap == ssap && tmp_sock->dsap == dsap) { |
191 | llcp_sock = tmp_sock; | ||
152 | break; | 192 | break; |
193 | } | ||
153 | } | 194 | } |
154 | 195 | ||
155 | read_unlock(&local->sockets.lock); | 196 | read_unlock(&local->sockets.lock); |
@@ -249,7 +290,12 @@ struct nfc_llcp_sock *nfc_llcp_sock_from_sn(struct nfc_llcp_local *local, | |||
249 | 290 | ||
250 | pr_debug("llcp sock %p\n", tmp_sock); | 291 | pr_debug("llcp sock %p\n", tmp_sock); |
251 | 292 | ||
252 | if (tmp_sock->sk.sk_state != LLCP_LISTEN) | 293 | if (tmp_sock->sk.sk_type == SOCK_STREAM && |
294 | tmp_sock->sk.sk_state != LLCP_LISTEN) | ||
295 | continue; | ||
296 | |||
297 | if (tmp_sock->sk.sk_type == SOCK_DGRAM && | ||
298 | tmp_sock->sk.sk_state != LLCP_BOUND) | ||
253 | continue; | 299 | continue; |
254 | 300 | ||
255 | if (tmp_sock->service_name == NULL || | 301 | if (tmp_sock->service_name == NULL || |
@@ -421,10 +467,9 @@ static u8 nfc_llcp_reserve_sdp_ssap(struct nfc_llcp_local *local) | |||
421 | static int nfc_llcp_build_gb(struct nfc_llcp_local *local) | 467 | static int nfc_llcp_build_gb(struct nfc_llcp_local *local) |
422 | { | 468 | { |
423 | u8 *gb_cur, *version_tlv, version, version_length; | 469 | u8 *gb_cur, *version_tlv, version, version_length; |
424 | u8 *lto_tlv, lto, lto_length; | 470 | u8 *lto_tlv, lto_length; |
425 | u8 *wks_tlv, wks_length; | 471 | u8 *wks_tlv, wks_length; |
426 | u8 *miux_tlv, miux_length; | 472 | u8 *miux_tlv, miux_length; |
427 | __be16 miux; | ||
428 | u8 gb_len = 0; | 473 | u8 gb_len = 0; |
429 | int ret = 0; | 474 | int ret = 0; |
430 | 475 | ||
@@ -433,9 +478,7 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) | |||
433 | 1, &version_length); | 478 | 1, &version_length); |
434 | gb_len += version_length; | 479 | gb_len += version_length; |
435 | 480 | ||
436 | /* 1500 ms */ | 481 | lto_tlv = nfc_llcp_build_tlv(LLCP_TLV_LTO, &local->lto, 1, <o_length); |
437 | lto = 150; | ||
438 | lto_tlv = nfc_llcp_build_tlv(LLCP_TLV_LTO, <o, 1, <o_length); | ||
439 | gb_len += lto_length; | 482 | gb_len += lto_length; |
440 | 483 | ||
441 | pr_debug("Local wks 0x%lx\n", local->local_wks); | 484 | pr_debug("Local wks 0x%lx\n", local->local_wks); |
@@ -443,8 +486,7 @@ static int nfc_llcp_build_gb(struct nfc_llcp_local *local) | |||
443 | &wks_length); | 486 | &wks_length); |
444 | gb_len += wks_length; | 487 | gb_len += wks_length; |
445 | 488 | ||
446 | miux = cpu_to_be16(LLCP_MAX_MIUX); | 489 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&local->miux, 0, |
447 | miux_tlv = nfc_llcp_build_tlv(LLCP_TLV_MIUX, (u8 *)&miux, 0, | ||
448 | &miux_length); | 490 | &miux_length); |
449 | gb_len += miux_length; | 491 | gb_len += miux_length; |
450 | 492 | ||
@@ -610,7 +652,10 @@ static void nfc_llcp_tx_work(struct work_struct *work) | |||
610 | if (skb != NULL) { | 652 | if (skb != NULL) { |
611 | sk = skb->sk; | 653 | sk = skb->sk; |
612 | llcp_sock = nfc_llcp_sock(sk); | 654 | llcp_sock = nfc_llcp_sock(sk); |
613 | if (llcp_sock != NULL) { | 655 | |
656 | if (llcp_sock == NULL && nfc_llcp_ptype(skb) == LLCP_PDU_I) { | ||
657 | nfc_llcp_send_symm(local->dev); | ||
658 | } else { | ||
614 | int ret; | 659 | int ret; |
615 | 660 | ||
616 | pr_debug("Sending pending skb\n"); | 661 | pr_debug("Sending pending skb\n"); |
@@ -629,8 +674,6 @@ static void nfc_llcp_tx_work(struct work_struct *work) | |||
629 | skb_queue_tail(&llcp_sock->tx_pending_queue, | 674 | skb_queue_tail(&llcp_sock->tx_pending_queue, |
630 | skb); | 675 | skb); |
631 | } | 676 | } |
632 | } else { | ||
633 | nfc_llcp_send_symm(local->dev); | ||
634 | } | 677 | } |
635 | } else { | 678 | } else { |
636 | nfc_llcp_send_symm(local->dev); | 679 | nfc_llcp_send_symm(local->dev); |
@@ -704,6 +747,39 @@ static u8 *nfc_llcp_connect_sn(struct sk_buff *skb, size_t *sn_len) | |||
704 | return NULL; | 747 | return NULL; |
705 | } | 748 | } |
706 | 749 | ||
750 | static void nfc_llcp_recv_ui(struct nfc_llcp_local *local, | ||
751 | struct sk_buff *skb) | ||
752 | { | ||
753 | struct nfc_llcp_sock *llcp_sock; | ||
754 | struct nfc_llcp_ui_cb *ui_cb; | ||
755 | u8 dsap, ssap; | ||
756 | |||
757 | dsap = nfc_llcp_dsap(skb); | ||
758 | ssap = nfc_llcp_ssap(skb); | ||
759 | |||
760 | ui_cb = nfc_llcp_ui_skb_cb(skb); | ||
761 | ui_cb->dsap = dsap; | ||
762 | ui_cb->ssap = ssap; | ||
763 | |||
764 | printk("%s %d %d\n", __func__, dsap, ssap); | ||
765 | |||
766 | pr_debug("%d %d\n", dsap, ssap); | ||
767 | |||
768 | /* We're looking for a bound socket, not a client one */ | ||
769 | llcp_sock = nfc_llcp_sock_get(local, dsap, LLCP_SAP_SDP); | ||
770 | if (llcp_sock == NULL || llcp_sock->sk.sk_type != SOCK_DGRAM) | ||
771 | return; | ||
772 | |||
773 | /* There is no sequence with UI frames */ | ||
774 | skb_pull(skb, LLCP_HEADER_SIZE); | ||
775 | if (sock_queue_rcv_skb(&llcp_sock->sk, skb)) { | ||
776 | pr_err("receive queue is full\n"); | ||
777 | skb_queue_head(&llcp_sock->tx_backlog_queue, skb); | ||
778 | } | ||
779 | |||
780 | nfc_llcp_sock_put(llcp_sock); | ||
781 | } | ||
782 | |||
707 | static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | 783 | static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, |
708 | struct sk_buff *skb) | 784 | struct sk_buff *skb) |
709 | { | 785 | { |
@@ -823,9 +899,6 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
823 | fail: | 899 | fail: |
824 | /* Send DM */ | 900 | /* Send DM */ |
825 | nfc_llcp_send_dm(local, dsap, ssap, reason); | 901 | nfc_llcp_send_dm(local, dsap, ssap, reason); |
826 | |||
827 | return; | ||
828 | |||
829 | } | 902 | } |
830 | 903 | ||
831 | int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) | 904 | int nfc_llcp_queue_i_frames(struct nfc_llcp_sock *sock) |
@@ -953,6 +1026,9 @@ static void nfc_llcp_recv_disc(struct nfc_llcp_local *local, | |||
953 | 1026 | ||
954 | sk = &llcp_sock->sk; | 1027 | sk = &llcp_sock->sk; |
955 | lock_sock(sk); | 1028 | lock_sock(sk); |
1029 | |||
1030 | nfc_llcp_socket_purge(llcp_sock); | ||
1031 | |||
956 | if (sk->sk_state == LLCP_CLOSED) { | 1032 | if (sk->sk_state == LLCP_CLOSED) { |
957 | release_sock(sk); | 1033 | release_sock(sk); |
958 | nfc_llcp_sock_put(llcp_sock); | 1034 | nfc_llcp_sock_put(llcp_sock); |
@@ -1027,7 +1103,7 @@ static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, struct sk_buff *skb) | |||
1027 | } | 1103 | } |
1028 | 1104 | ||
1029 | if (llcp_sock == NULL) { | 1105 | if (llcp_sock == NULL) { |
1030 | pr_err("Invalid DM\n"); | 1106 | pr_debug("Already closed\n"); |
1031 | return; | 1107 | return; |
1032 | } | 1108 | } |
1033 | 1109 | ||
@@ -1038,8 +1114,100 @@ static void nfc_llcp_recv_dm(struct nfc_llcp_local *local, struct sk_buff *skb) | |||
1038 | sk->sk_state_change(sk); | 1114 | sk->sk_state_change(sk); |
1039 | 1115 | ||
1040 | nfc_llcp_sock_put(llcp_sock); | 1116 | nfc_llcp_sock_put(llcp_sock); |
1117 | } | ||
1041 | 1118 | ||
1042 | return; | 1119 | static void nfc_llcp_recv_snl(struct nfc_llcp_local *local, |
1120 | struct sk_buff *skb) | ||
1121 | { | ||
1122 | struct nfc_llcp_sock *llcp_sock; | ||
1123 | u8 dsap, ssap, *tlv, type, length, tid, sap; | ||
1124 | u16 tlv_len, offset; | ||
1125 | char *service_name; | ||
1126 | size_t service_name_len; | ||
1127 | |||
1128 | dsap = nfc_llcp_dsap(skb); | ||
1129 | ssap = nfc_llcp_ssap(skb); | ||
1130 | |||
1131 | pr_debug("%d %d\n", dsap, ssap); | ||
1132 | |||
1133 | if (dsap != LLCP_SAP_SDP || ssap != LLCP_SAP_SDP) { | ||
1134 | pr_err("Wrong SNL SAP\n"); | ||
1135 | return; | ||
1136 | } | ||
1137 | |||
1138 | tlv = &skb->data[LLCP_HEADER_SIZE]; | ||
1139 | tlv_len = skb->len - LLCP_HEADER_SIZE; | ||
1140 | offset = 0; | ||
1141 | |||
1142 | while (offset < tlv_len) { | ||
1143 | type = tlv[0]; | ||
1144 | length = tlv[1]; | ||
1145 | |||
1146 | switch (type) { | ||
1147 | case LLCP_TLV_SDREQ: | ||
1148 | tid = tlv[2]; | ||
1149 | service_name = (char *) &tlv[3]; | ||
1150 | service_name_len = length - 1; | ||
1151 | |||
1152 | pr_debug("Looking for %.16s\n", service_name); | ||
1153 | |||
1154 | if (service_name_len == strlen("urn:nfc:sn:sdp") && | ||
1155 | !strncmp(service_name, "urn:nfc:sn:sdp", | ||
1156 | service_name_len)) { | ||
1157 | sap = 1; | ||
1158 | goto send_snl; | ||
1159 | } | ||
1160 | |||
1161 | llcp_sock = nfc_llcp_sock_from_sn(local, service_name, | ||
1162 | service_name_len); | ||
1163 | if (!llcp_sock) { | ||
1164 | sap = 0; | ||
1165 | goto send_snl; | ||
1166 | } | ||
1167 | |||
1168 | /* | ||
1169 | * We found a socket but its ssap has not been reserved | ||
1170 | * yet. We need to assign it for good and send a reply. | ||
1171 | * The ssap will be freed when the socket is closed. | ||
1172 | */ | ||
1173 | if (llcp_sock->ssap == LLCP_SDP_UNBOUND) { | ||
1174 | atomic_t *client_count; | ||
1175 | |||
1176 | sap = nfc_llcp_reserve_sdp_ssap(local); | ||
1177 | |||
1178 | pr_debug("Reserving %d\n", sap); | ||
1179 | |||
1180 | if (sap == LLCP_SAP_MAX) { | ||
1181 | sap = 0; | ||
1182 | goto send_snl; | ||
1183 | } | ||
1184 | |||
1185 | client_count = | ||
1186 | &local->local_sdp_cnt[sap - | ||
1187 | LLCP_WKS_NUM_SAP]; | ||
1188 | |||
1189 | atomic_inc(client_count); | ||
1190 | |||
1191 | llcp_sock->ssap = sap; | ||
1192 | llcp_sock->reserved_ssap = sap; | ||
1193 | } else { | ||
1194 | sap = llcp_sock->ssap; | ||
1195 | } | ||
1196 | |||
1197 | pr_debug("%p %d\n", llcp_sock, sap); | ||
1198 | |||
1199 | send_snl: | ||
1200 | nfc_llcp_send_snl(local, tid, sap); | ||
1201 | break; | ||
1202 | |||
1203 | default: | ||
1204 | pr_err("Invalid SNL tlv value 0x%x\n", type); | ||
1205 | break; | ||
1206 | } | ||
1207 | |||
1208 | offset += length + 2; | ||
1209 | tlv += length + 2; | ||
1210 | } | ||
1043 | } | 1211 | } |
1044 | 1212 | ||
1045 | static void nfc_llcp_rx_work(struct work_struct *work) | 1213 | static void nfc_llcp_rx_work(struct work_struct *work) |
@@ -1072,6 +1240,11 @@ static void nfc_llcp_rx_work(struct work_struct *work) | |||
1072 | pr_debug("SYMM\n"); | 1240 | pr_debug("SYMM\n"); |
1073 | break; | 1241 | break; |
1074 | 1242 | ||
1243 | case LLCP_PDU_UI: | ||
1244 | pr_debug("UI\n"); | ||
1245 | nfc_llcp_recv_ui(local, skb); | ||
1246 | break; | ||
1247 | |||
1075 | case LLCP_PDU_CONNECT: | 1248 | case LLCP_PDU_CONNECT: |
1076 | pr_debug("CONNECT\n"); | 1249 | pr_debug("CONNECT\n"); |
1077 | nfc_llcp_recv_connect(local, skb); | 1250 | nfc_llcp_recv_connect(local, skb); |
@@ -1092,6 +1265,11 @@ static void nfc_llcp_rx_work(struct work_struct *work) | |||
1092 | nfc_llcp_recv_dm(local, skb); | 1265 | nfc_llcp_recv_dm(local, skb); |
1093 | break; | 1266 | break; |
1094 | 1267 | ||
1268 | case LLCP_PDU_SNL: | ||
1269 | pr_debug("SNL\n"); | ||
1270 | nfc_llcp_recv_snl(local, skb); | ||
1271 | break; | ||
1272 | |||
1095 | case LLCP_PDU_I: | 1273 | case LLCP_PDU_I: |
1096 | case LLCP_PDU_RR: | 1274 | case LLCP_PDU_RR: |
1097 | case LLCP_PDU_RNR: | 1275 | case LLCP_PDU_RNR: |
@@ -1104,8 +1282,6 @@ static void nfc_llcp_rx_work(struct work_struct *work) | |||
1104 | schedule_work(&local->tx_work); | 1282 | schedule_work(&local->tx_work); |
1105 | kfree_skb(local->rx_pending); | 1283 | kfree_skb(local->rx_pending); |
1106 | local->rx_pending = NULL; | 1284 | local->rx_pending = NULL; |
1107 | |||
1108 | return; | ||
1109 | } | 1285 | } |
1110 | 1286 | ||
1111 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) | 1287 | void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) |
@@ -1121,8 +1297,6 @@ void nfc_llcp_recv(void *data, struct sk_buff *skb, int err) | |||
1121 | local->rx_pending = skb_get(skb); | 1297 | local->rx_pending = skb_get(skb); |
1122 | del_timer(&local->link_timer); | 1298 | del_timer(&local->link_timer); |
1123 | schedule_work(&local->rx_work); | 1299 | schedule_work(&local->rx_work); |
1124 | |||
1125 | return; | ||
1126 | } | 1300 | } |
1127 | 1301 | ||
1128 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) | 1302 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb) |
@@ -1205,6 +1379,10 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) | |||
1205 | rwlock_init(&local->connecting_sockets.lock); | 1379 | rwlock_init(&local->connecting_sockets.lock); |
1206 | rwlock_init(&local->raw_sockets.lock); | 1380 | rwlock_init(&local->raw_sockets.lock); |
1207 | 1381 | ||
1382 | local->lto = 150; /* 1500 ms */ | ||
1383 | local->rw = LLCP_MAX_RW; | ||
1384 | local->miux = cpu_to_be16(LLCP_MAX_MIUX); | ||
1385 | |||
1208 | nfc_llcp_build_gb(local); | 1386 | nfc_llcp_build_gb(local); |
1209 | 1387 | ||
1210 | local->remote_miu = LLCP_DEFAULT_MIU; | 1388 | local->remote_miu = LLCP_DEFAULT_MIU; |
diff --git a/net/nfc/llcp/llcp.h b/net/nfc/llcp/llcp.h index fdb2d24e60bd..0d62366f8cc3 100644 --- a/net/nfc/llcp/llcp.h +++ b/net/nfc/llcp/llcp.h | |||
@@ -64,6 +64,9 @@ struct nfc_llcp_local { | |||
64 | u32 target_idx; | 64 | u32 target_idx; |
65 | u8 rf_mode; | 65 | u8 rf_mode; |
66 | u8 comm_mode; | 66 | u8 comm_mode; |
67 | u8 lto; | ||
68 | u8 rw; | ||
69 | __be16 miux; | ||
67 | unsigned long local_wks; /* Well known services */ | 70 | unsigned long local_wks; /* Well known services */ |
68 | unsigned long local_sdp; /* Local services */ | 71 | unsigned long local_sdp; /* Local services */ |
69 | unsigned long local_sap; /* Local SAPs, not available for discovery */ | 72 | unsigned long local_sap; /* Local SAPs, not available for discovery */ |
@@ -124,6 +127,13 @@ struct nfc_llcp_sock { | |||
124 | struct sock *parent; | 127 | struct sock *parent; |
125 | }; | 128 | }; |
126 | 129 | ||
130 | struct nfc_llcp_ui_cb { | ||
131 | __u8 dsap; | ||
132 | __u8 ssap; | ||
133 | }; | ||
134 | |||
135 | #define nfc_llcp_ui_skb_cb(__skb) ((struct nfc_llcp_ui_cb *)&((__skb)->cb[0])) | ||
136 | |||
127 | #define nfc_llcp_sock(sk) ((struct nfc_llcp_sock *) (sk)) | 137 | #define nfc_llcp_sock(sk) ((struct nfc_llcp_sock *) (sk)) |
128 | #define nfc_llcp_dev(sk) (nfc_llcp_sock((sk))->dev) | 138 | #define nfc_llcp_dev(sk) (nfc_llcp_sock((sk))->dev) |
129 | 139 | ||
@@ -209,10 +219,13 @@ int nfc_llcp_disconnect(struct nfc_llcp_sock *sock); | |||
209 | int nfc_llcp_send_symm(struct nfc_dev *dev); | 219 | int nfc_llcp_send_symm(struct nfc_dev *dev); |
210 | int nfc_llcp_send_connect(struct nfc_llcp_sock *sock); | 220 | int nfc_llcp_send_connect(struct nfc_llcp_sock *sock); |
211 | int nfc_llcp_send_cc(struct nfc_llcp_sock *sock); | 221 | int nfc_llcp_send_cc(struct nfc_llcp_sock *sock); |
222 | int nfc_llcp_send_snl(struct nfc_llcp_local *local, u8 tid, u8 sap); | ||
212 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason); | 223 | int nfc_llcp_send_dm(struct nfc_llcp_local *local, u8 ssap, u8 dsap, u8 reason); |
213 | int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock); | 224 | int nfc_llcp_send_disconnect(struct nfc_llcp_sock *sock); |
214 | int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, | 225 | int nfc_llcp_send_i_frame(struct nfc_llcp_sock *sock, |
215 | struct msghdr *msg, size_t len); | 226 | struct msghdr *msg, size_t len); |
227 | int nfc_llcp_send_ui_frame(struct nfc_llcp_sock *sock, u8 ssap, u8 dsap, | ||
228 | struct msghdr *msg, size_t len); | ||
216 | int nfc_llcp_send_rr(struct nfc_llcp_sock *sock); | 229 | int nfc_llcp_send_rr(struct nfc_llcp_sock *sock); |
217 | 230 | ||
218 | /* Socket API */ | 231 | /* Socket API */ |
diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index 63e4cdc92376..0fa1e92ceac8 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c | |||
@@ -205,8 +205,8 @@ static int llcp_sock_listen(struct socket *sock, int backlog) | |||
205 | 205 | ||
206 | lock_sock(sk); | 206 | lock_sock(sk); |
207 | 207 | ||
208 | if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM) | 208 | if ((sock->type != SOCK_SEQPACKET && sock->type != SOCK_STREAM) || |
209 | || sk->sk_state != LLCP_BOUND) { | 209 | sk->sk_state != LLCP_BOUND) { |
210 | ret = -EBADFD; | 210 | ret = -EBADFD; |
211 | goto error; | 211 | goto error; |
212 | } | 212 | } |
@@ -608,6 +608,25 @@ static int llcp_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
608 | 608 | ||
609 | lock_sock(sk); | 609 | lock_sock(sk); |
610 | 610 | ||
611 | if (sk->sk_type == SOCK_DGRAM) { | ||
612 | struct sockaddr_nfc_llcp *addr = | ||
613 | (struct sockaddr_nfc_llcp *)msg->msg_name; | ||
614 | |||
615 | if (msg->msg_namelen < sizeof(*addr)) { | ||
616 | release_sock(sk); | ||
617 | |||
618 | pr_err("Invalid socket address length %d\n", | ||
619 | msg->msg_namelen); | ||
620 | |||
621 | return -EINVAL; | ||
622 | } | ||
623 | |||
624 | release_sock(sk); | ||
625 | |||
626 | return nfc_llcp_send_ui_frame(llcp_sock, addr->dsap, addr->ssap, | ||
627 | msg, len); | ||
628 | } | ||
629 | |||
611 | if (sk->sk_state != LLCP_CONNECTED) { | 630 | if (sk->sk_state != LLCP_CONNECTED) { |
612 | release_sock(sk); | 631 | release_sock(sk); |
613 | return -ENOTCONN; | 632 | return -ENOTCONN; |
@@ -663,11 +682,28 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
663 | return -EFAULT; | 682 | return -EFAULT; |
664 | } | 683 | } |
665 | 684 | ||
685 | if (sk->sk_type == SOCK_DGRAM && msg->msg_name) { | ||
686 | struct nfc_llcp_ui_cb *ui_cb = nfc_llcp_ui_skb_cb(skb); | ||
687 | struct sockaddr_nfc_llcp sockaddr; | ||
688 | |||
689 | pr_debug("Datagram socket %d %d\n", ui_cb->dsap, ui_cb->ssap); | ||
690 | |||
691 | sockaddr.sa_family = AF_NFC; | ||
692 | sockaddr.nfc_protocol = NFC_PROTO_NFC_DEP; | ||
693 | sockaddr.dsap = ui_cb->dsap; | ||
694 | sockaddr.ssap = ui_cb->ssap; | ||
695 | |||
696 | memcpy(msg->msg_name, &sockaddr, sizeof(sockaddr)); | ||
697 | msg->msg_namelen = sizeof(sockaddr); | ||
698 | } | ||
699 | |||
666 | /* Mark read part of skb as used */ | 700 | /* Mark read part of skb as used */ |
667 | if (!(flags & MSG_PEEK)) { | 701 | if (!(flags & MSG_PEEK)) { |
668 | 702 | ||
669 | /* SOCK_STREAM: re-queue skb if it contains unreceived data */ | 703 | /* SOCK_STREAM: re-queue skb if it contains unreceived data */ |
670 | if (sk->sk_type == SOCK_STREAM || sk->sk_type == SOCK_RAW) { | 704 | if (sk->sk_type == SOCK_STREAM || |
705 | sk->sk_type == SOCK_DGRAM || | ||
706 | sk->sk_type == SOCK_RAW) { | ||
671 | skb_pull(skb, copied); | 707 | skb_pull(skb, copied); |
672 | if (skb->len) { | 708 | if (skb->len) { |
673 | skb_queue_head(&sk->sk_receive_queue, skb); | 709 | skb_queue_head(&sk->sk_receive_queue, skb); |
diff --git a/net/nfc/nci/Kconfig b/net/nfc/nci/Kconfig index decdc49b26d8..6d69b5f0f19b 100644 --- a/net/nfc/nci/Kconfig +++ b/net/nfc/nci/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config NFC_NCI | 1 | config NFC_NCI |
2 | depends on NFC && EXPERIMENTAL | 2 | depends on NFC |
3 | tristate "NCI protocol support (EXPERIMENTAL)" | 3 | tristate "NCI protocol support" |
4 | default n | 4 | default n |
5 | help | 5 | help |
6 | NCI (NFC Controller Interface) is a communication protocol between | 6 | NCI (NFC Controller Interface) is a communication protocol between |
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index acf9abb7d99b..5f98dc1bf039 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
@@ -205,10 +205,10 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) | |||
205 | cmd.num_disc_configs = 0; | 205 | cmd.num_disc_configs = 0; |
206 | 206 | ||
207 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && | 207 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && |
208 | (protocols & NFC_PROTO_JEWEL_MASK | 208 | (protocols & NFC_PROTO_JEWEL_MASK || |
209 | || protocols & NFC_PROTO_MIFARE_MASK | 209 | protocols & NFC_PROTO_MIFARE_MASK || |
210 | || protocols & NFC_PROTO_ISO14443_MASK | 210 | protocols & NFC_PROTO_ISO14443_MASK || |
211 | || protocols & NFC_PROTO_NFC_DEP_MASK)) { | 211 | protocols & NFC_PROTO_NFC_DEP_MASK)) { |
212 | cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = | 212 | cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = |
213 | NCI_NFC_A_PASSIVE_POLL_MODE; | 213 | NCI_NFC_A_PASSIVE_POLL_MODE; |
214 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; | 214 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; |
@@ -224,8 +224,8 @@ static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt) | |||
224 | } | 224 | } |
225 | 225 | ||
226 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && | 226 | if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) && |
227 | (protocols & NFC_PROTO_FELICA_MASK | 227 | (protocols & NFC_PROTO_FELICA_MASK || |
228 | || protocols & NFC_PROTO_NFC_DEP_MASK)) { | 228 | protocols & NFC_PROTO_NFC_DEP_MASK)) { |
229 | cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = | 229 | cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode = |
230 | NCI_NFC_F_PASSIVE_POLL_MODE; | 230 | NCI_NFC_F_PASSIVE_POLL_MODE; |
231 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; | 231 | cmd.disc_configs[cmd.num_disc_configs].frequency = 1; |
@@ -414,13 +414,13 @@ static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev) | |||
414 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); | 414 | struct nci_dev *ndev = nfc_get_drvdata(nfc_dev); |
415 | struct nci_set_config_param param; | 415 | struct nci_set_config_param param; |
416 | __u8 local_gb[NFC_MAX_GT_LEN]; | 416 | __u8 local_gb[NFC_MAX_GT_LEN]; |
417 | int i, rc = 0; | 417 | int i; |
418 | 418 | ||
419 | param.val = nfc_get_local_general_bytes(nfc_dev, ¶m.len); | 419 | param.val = nfc_get_local_general_bytes(nfc_dev, ¶m.len); |
420 | if ((param.val == NULL) || (param.len == 0)) | 420 | if ((param.val == NULL) || (param.len == 0)) |
421 | return rc; | 421 | return 0; |
422 | 422 | ||
423 | if (param.len > NCI_MAX_PARAM_LEN) | 423 | if (param.len > NFC_MAX_GT_LEN) |
424 | return -EINVAL; | 424 | return -EINVAL; |
425 | 425 | ||
426 | for (i = 0; i < param.len; i++) | 426 | for (i = 0; i < param.len; i++) |
@@ -429,10 +429,8 @@ static int nci_set_local_general_bytes(struct nfc_dev *nfc_dev) | |||
429 | param.id = NCI_PN_ATR_REQ_GEN_BYTES; | 429 | param.id = NCI_PN_ATR_REQ_GEN_BYTES; |
430 | param.val = local_gb; | 430 | param.val = local_gb; |
431 | 431 | ||
432 | rc = nci_request(ndev, nci_set_config_req, (unsigned long)¶m, | 432 | return nci_request(ndev, nci_set_config_req, (unsigned long)¶m, |
433 | msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT)); | 433 | msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT)); |
434 | |||
435 | return rc; | ||
436 | } | 434 | } |
437 | 435 | ||
438 | static int nci_start_poll(struct nfc_dev *nfc_dev, | 436 | static int nci_start_poll(struct nfc_dev *nfc_dev, |
@@ -579,7 +577,6 @@ static void nci_deactivate_target(struct nfc_dev *nfc_dev, | |||
579 | } | 577 | } |
580 | } | 578 | } |
581 | 579 | ||
582 | |||
583 | static int nci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | 580 | static int nci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, |
584 | __u8 comm_mode, __u8 *gb, size_t gb_len) | 581 | __u8 comm_mode, __u8 *gb, size_t gb_len) |
585 | { | 582 | { |
@@ -806,8 +803,8 @@ int nci_recv_frame(struct sk_buff *skb) | |||
806 | 803 | ||
807 | pr_debug("len %d\n", skb->len); | 804 | pr_debug("len %d\n", skb->len); |
808 | 805 | ||
809 | if (!ndev || (!test_bit(NCI_UP, &ndev->flags) | 806 | if (!ndev || (!test_bit(NCI_UP, &ndev->flags) && |
810 | && !test_bit(NCI_INIT, &ndev->flags))) { | 807 | !test_bit(NCI_INIT, &ndev->flags))) { |
811 | kfree_skb(skb); | 808 | kfree_skb(skb); |
812 | return -ENXIO; | 809 | return -ENXIO; |
813 | } | 810 | } |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index c1b5285cbde7..3568ae16786d 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
@@ -29,6 +29,8 @@ | |||
29 | 29 | ||
30 | #include "nfc.h" | 30 | #include "nfc.h" |
31 | 31 | ||
32 | #include "llcp/llcp.h" | ||
33 | |||
32 | static struct genl_multicast_group nfc_genl_event_mcgrp = { | 34 | static struct genl_multicast_group nfc_genl_event_mcgrp = { |
33 | .name = NFC_GENL_MCAST_EVENT_NAME, | 35 | .name = NFC_GENL_MCAST_EVENT_NAME, |
34 | }; | 36 | }; |
@@ -364,7 +366,8 @@ static int nfc_genl_send_device(struct sk_buff *msg, struct nfc_dev *dev, | |||
364 | if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) || | 366 | if (nla_put_string(msg, NFC_ATTR_DEVICE_NAME, nfc_device_name(dev)) || |
365 | nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) || | 367 | nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, dev->idx) || |
366 | nla_put_u32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols) || | 368 | nla_put_u32(msg, NFC_ATTR_PROTOCOLS, dev->supported_protocols) || |
367 | nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up)) | 369 | nla_put_u8(msg, NFC_ATTR_DEVICE_POWERED, dev->dev_up) || |
370 | nla_put_u8(msg, NFC_ATTR_RF_MODE, dev->rf_mode)) | ||
368 | goto nla_put_failure; | 371 | goto nla_put_failure; |
369 | 372 | ||
370 | return genlmsg_end(msg, hdr); | 373 | return genlmsg_end(msg, hdr); |
@@ -590,7 +593,7 @@ static int nfc_genl_start_poll(struct sk_buff *skb, struct genl_info *info) | |||
590 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || | 593 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || |
591 | ((!info->attrs[NFC_ATTR_IM_PROTOCOLS] && | 594 | ((!info->attrs[NFC_ATTR_IM_PROTOCOLS] && |
592 | !info->attrs[NFC_ATTR_PROTOCOLS]) && | 595 | !info->attrs[NFC_ATTR_PROTOCOLS]) && |
593 | !info->attrs[NFC_ATTR_TM_PROTOCOLS])) | 596 | !info->attrs[NFC_ATTR_TM_PROTOCOLS])) |
594 | return -EINVAL; | 597 | return -EINVAL; |
595 | 598 | ||
596 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | 599 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); |
@@ -715,6 +718,146 @@ static int nfc_genl_dep_link_down(struct sk_buff *skb, struct genl_info *info) | |||
715 | return rc; | 718 | return rc; |
716 | } | 719 | } |
717 | 720 | ||
721 | static int nfc_genl_send_params(struct sk_buff *msg, | ||
722 | struct nfc_llcp_local *local, | ||
723 | u32 portid, u32 seq) | ||
724 | { | ||
725 | void *hdr; | ||
726 | |||
727 | hdr = genlmsg_put(msg, portid, seq, &nfc_genl_family, 0, | ||
728 | NFC_CMD_LLC_GET_PARAMS); | ||
729 | if (!hdr) | ||
730 | return -EMSGSIZE; | ||
731 | |||
732 | if (nla_put_u32(msg, NFC_ATTR_DEVICE_INDEX, local->dev->idx) || | ||
733 | nla_put_u8(msg, NFC_ATTR_LLC_PARAM_LTO, local->lto) || | ||
734 | nla_put_u8(msg, NFC_ATTR_LLC_PARAM_RW, local->rw) || | ||
735 | nla_put_u16(msg, NFC_ATTR_LLC_PARAM_MIUX, be16_to_cpu(local->miux))) | ||
736 | goto nla_put_failure; | ||
737 | |||
738 | return genlmsg_end(msg, hdr); | ||
739 | |||
740 | nla_put_failure: | ||
741 | |||
742 | genlmsg_cancel(msg, hdr); | ||
743 | return -EMSGSIZE; | ||
744 | } | ||
745 | |||
746 | static int nfc_genl_llc_get_params(struct sk_buff *skb, struct genl_info *info) | ||
747 | { | ||
748 | struct nfc_dev *dev; | ||
749 | struct nfc_llcp_local *local; | ||
750 | int rc = 0; | ||
751 | struct sk_buff *msg = NULL; | ||
752 | u32 idx; | ||
753 | |||
754 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX]) | ||
755 | return -EINVAL; | ||
756 | |||
757 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | ||
758 | |||
759 | dev = nfc_get_device(idx); | ||
760 | if (!dev) | ||
761 | return -ENODEV; | ||
762 | |||
763 | device_lock(&dev->dev); | ||
764 | |||
765 | local = nfc_llcp_find_local(dev); | ||
766 | if (!local) { | ||
767 | rc = -ENODEV; | ||
768 | goto exit; | ||
769 | } | ||
770 | |||
771 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
772 | if (!msg) { | ||
773 | rc = -ENOMEM; | ||
774 | goto exit; | ||
775 | } | ||
776 | |||
777 | rc = nfc_genl_send_params(msg, local, info->snd_portid, info->snd_seq); | ||
778 | |||
779 | exit: | ||
780 | device_unlock(&dev->dev); | ||
781 | |||
782 | nfc_put_device(dev); | ||
783 | |||
784 | if (rc < 0) { | ||
785 | if (msg) | ||
786 | nlmsg_free(msg); | ||
787 | |||
788 | return rc; | ||
789 | } | ||
790 | |||
791 | return genlmsg_reply(msg, info); | ||
792 | } | ||
793 | |||
794 | static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info) | ||
795 | { | ||
796 | struct nfc_dev *dev; | ||
797 | struct nfc_llcp_local *local; | ||
798 | u8 rw = 0; | ||
799 | u16 miux = 0; | ||
800 | u32 idx; | ||
801 | int rc = 0; | ||
802 | |||
803 | if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || | ||
804 | (!info->attrs[NFC_ATTR_LLC_PARAM_LTO] && | ||
805 | !info->attrs[NFC_ATTR_LLC_PARAM_RW] && | ||
806 | !info->attrs[NFC_ATTR_LLC_PARAM_MIUX])) | ||
807 | return -EINVAL; | ||
808 | |||
809 | if (info->attrs[NFC_ATTR_LLC_PARAM_RW]) { | ||
810 | rw = nla_get_u8(info->attrs[NFC_ATTR_LLC_PARAM_RW]); | ||
811 | |||
812 | if (rw > LLCP_MAX_RW) | ||
813 | return -EINVAL; | ||
814 | } | ||
815 | |||
816 | if (info->attrs[NFC_ATTR_LLC_PARAM_MIUX]) { | ||
817 | miux = nla_get_u16(info->attrs[NFC_ATTR_LLC_PARAM_MIUX]); | ||
818 | |||
819 | if (miux > LLCP_MAX_MIUX) | ||
820 | return -EINVAL; | ||
821 | } | ||
822 | |||
823 | idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]); | ||
824 | |||
825 | dev = nfc_get_device(idx); | ||
826 | if (!dev) | ||
827 | return -ENODEV; | ||
828 | |||
829 | device_lock(&dev->dev); | ||
830 | |||
831 | local = nfc_llcp_find_local(dev); | ||
832 | if (!local) { | ||
833 | nfc_put_device(dev); | ||
834 | rc = -ENODEV; | ||
835 | goto exit; | ||
836 | } | ||
837 | |||
838 | if (info->attrs[NFC_ATTR_LLC_PARAM_LTO]) { | ||
839 | if (dev->dep_link_up) { | ||
840 | rc = -EINPROGRESS; | ||
841 | goto exit; | ||
842 | } | ||
843 | |||
844 | local->lto = nla_get_u8(info->attrs[NFC_ATTR_LLC_PARAM_LTO]); | ||
845 | } | ||
846 | |||
847 | if (info->attrs[NFC_ATTR_LLC_PARAM_RW]) | ||
848 | local->rw = rw; | ||
849 | |||
850 | if (info->attrs[NFC_ATTR_LLC_PARAM_MIUX]) | ||
851 | local->miux = cpu_to_be16(miux); | ||
852 | |||
853 | exit: | ||
854 | device_unlock(&dev->dev); | ||
855 | |||
856 | nfc_put_device(dev); | ||
857 | |||
858 | return rc; | ||
859 | } | ||
860 | |||
718 | static struct genl_ops nfc_genl_ops[] = { | 861 | static struct genl_ops nfc_genl_ops[] = { |
719 | { | 862 | { |
720 | .cmd = NFC_CMD_GET_DEVICE, | 863 | .cmd = NFC_CMD_GET_DEVICE, |
@@ -759,6 +902,16 @@ static struct genl_ops nfc_genl_ops[] = { | |||
759 | .done = nfc_genl_dump_targets_done, | 902 | .done = nfc_genl_dump_targets_done, |
760 | .policy = nfc_genl_policy, | 903 | .policy = nfc_genl_policy, |
761 | }, | 904 | }, |
905 | { | ||
906 | .cmd = NFC_CMD_LLC_GET_PARAMS, | ||
907 | .doit = nfc_genl_llc_get_params, | ||
908 | .policy = nfc_genl_policy, | ||
909 | }, | ||
910 | { | ||
911 | .cmd = NFC_CMD_LLC_SET_PARAMS, | ||
912 | .doit = nfc_genl_llc_set_params, | ||
913 | .policy = nfc_genl_policy, | ||
914 | }, | ||
762 | }; | 915 | }; |
763 | 916 | ||
764 | 917 | ||
diff --git a/net/nfc/nfc.h b/net/nfc/nfc.h index c5e42b79a418..87d914d2876a 100644 --- a/net/nfc/nfc.h +++ b/net/nfc/nfc.h | |||
@@ -56,6 +56,7 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev); | |||
56 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); | 56 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); |
57 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); | 57 | u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); |
58 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb); | 58 | int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb); |
59 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); | ||
59 | int __init nfc_llcp_init(void); | 60 | int __init nfc_llcp_init(void); |
60 | void nfc_llcp_exit(void); | 61 | void nfc_llcp_exit(void); |
61 | 62 | ||
@@ -97,6 +98,11 @@ static inline int nfc_llcp_data_received(struct nfc_dev *dev, | |||
97 | return 0; | 98 | return 0; |
98 | } | 99 | } |
99 | 100 | ||
101 | static inline struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) | ||
102 | { | ||
103 | return NULL; | ||
104 | } | ||
105 | |||
100 | static inline int nfc_llcp_init(void) | 106 | static inline int nfc_llcp_init(void) |
101 | { | 107 | { |
102 | return 0; | 108 | return 0; |
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index 8b8a6a2b2bad..313bf1bc848a 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c | |||
@@ -256,7 +256,6 @@ static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
256 | return rc ? : copied; | 256 | return rc ? : copied; |
257 | } | 257 | } |
258 | 258 | ||
259 | |||
260 | static const struct proto_ops rawsock_ops = { | 259 | static const struct proto_ops rawsock_ops = { |
261 | .family = PF_NFC, | 260 | .family = PF_NFC, |
262 | .owner = THIS_MODULE, | 261 | .owner = THIS_MODULE, |
diff --git a/net/wireless/core.c b/net/wireless/core.c index ce1ad776dfb5..26711f46a3be 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -529,8 +529,7 @@ int wiphy_register(struct wiphy *wiphy) | |||
529 | for (i = 0; i < sband->n_channels; i++) { | 529 | for (i = 0; i < sband->n_channels; i++) { |
530 | sband->channels[i].orig_flags = | 530 | sband->channels[i].orig_flags = |
531 | sband->channels[i].flags; | 531 | sband->channels[i].flags; |
532 | sband->channels[i].orig_mag = | 532 | sband->channels[i].orig_mag = INT_MAX; |
533 | sband->channels[i].max_antenna_gain; | ||
534 | sband->channels[i].orig_mpwr = | 533 | sband->channels[i].orig_mpwr = |
535 | sband->channels[i].max_power; | 534 | sband->channels[i].max_power; |
536 | sband->channels[i].band = band; | 535 | sband->channels[i].band = band; |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 46aeafce08d0..4bfd14f7c592 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -473,20 +473,14 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev, | |||
473 | .reason_code = reason, | 473 | .reason_code = reason, |
474 | .ie = ie, | 474 | .ie = ie, |
475 | .ie_len = ie_len, | 475 | .ie_len = ie_len, |
476 | .local_state_change = local_state_change, | ||
476 | }; | 477 | }; |
477 | 478 | ||
478 | ASSERT_WDEV_LOCK(wdev); | 479 | ASSERT_WDEV_LOCK(wdev); |
479 | 480 | ||
480 | if (local_state_change) { | 481 | if (local_state_change && (!wdev->current_bss || |
481 | if (wdev->current_bss && | 482 | !ether_addr_equal(wdev->current_bss->pub.bssid, bssid))) |
482 | ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) { | ||
483 | cfg80211_unhold_bss(wdev->current_bss); | ||
484 | cfg80211_put_bss(&wdev->current_bss->pub); | ||
485 | wdev->current_bss = NULL; | ||
486 | } | ||
487 | |||
488 | return 0; | 483 | return 0; |
489 | } | ||
490 | 484 | ||
491 | return rdev_deauth(rdev, dev, &req); | 485 | return rdev_deauth(rdev, dev, &req); |
492 | } | 486 | } |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 3b8cbbc214db..bcc7d7ee5a51 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -908,7 +908,7 @@ static void handle_channel(struct wiphy *wiphy, | |||
908 | map_regdom_flags(reg_rule->flags) | bw_flags; | 908 | map_regdom_flags(reg_rule->flags) | bw_flags; |
909 | chan->max_antenna_gain = chan->orig_mag = | 909 | chan->max_antenna_gain = chan->orig_mag = |
910 | (int) MBI_TO_DBI(power_rule->max_antenna_gain); | 910 | (int) MBI_TO_DBI(power_rule->max_antenna_gain); |
911 | chan->max_power = chan->orig_mpwr = | 911 | chan->max_reg_power = chan->max_power = chan->orig_mpwr = |
912 | (int) MBM_TO_DBM(power_rule->max_eirp); | 912 | (int) MBM_TO_DBM(power_rule->max_eirp); |
913 | return; | 913 | return; |
914 | } | 914 | } |
@@ -1331,7 +1331,8 @@ static void handle_channel_custom(struct wiphy *wiphy, | |||
1331 | 1331 | ||
1332 | chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; | 1332 | chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; |
1333 | chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); | 1333 | chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); |
1334 | chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); | 1334 | chan->max_reg_power = chan->max_power = |
1335 | (int) MBM_TO_DBM(power_rule->max_eirp); | ||
1335 | } | 1336 | } |
1336 | 1337 | ||
1337 | static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band, | 1338 | static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band, |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 343f13c1d31d..5b6c1df72f31 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -311,23 +311,21 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb) | |||
311 | } | 311 | } |
312 | EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); | 312 | EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); |
313 | 313 | ||
314 | static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) | 314 | unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) |
315 | { | 315 | { |
316 | int ae = meshhdr->flags & MESH_FLAGS_AE; | 316 | int ae = meshhdr->flags & MESH_FLAGS_AE; |
317 | /* 7.1.3.5a.2 */ | 317 | /* 802.11-2012, 8.2.4.7.3 */ |
318 | switch (ae) { | 318 | switch (ae) { |
319 | default: | ||
319 | case 0: | 320 | case 0: |
320 | return 6; | 321 | return 6; |
321 | case MESH_FLAGS_AE_A4: | 322 | case MESH_FLAGS_AE_A4: |
322 | return 12; | 323 | return 12; |
323 | case MESH_FLAGS_AE_A5_A6: | 324 | case MESH_FLAGS_AE_A5_A6: |
324 | return 18; | 325 | return 18; |
325 | case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6): | ||
326 | return 24; | ||
327 | default: | ||
328 | return 6; | ||
329 | } | 326 | } |
330 | } | 327 | } |
328 | EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen); | ||
331 | 329 | ||
332 | int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | 330 | int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, |
333 | enum nl80211_iftype iftype) | 331 | enum nl80211_iftype iftype) |
@@ -375,6 +373,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
375 | /* make sure meshdr->flags is on the linear part */ | 373 | /* make sure meshdr->flags is on the linear part */ |
376 | if (!pskb_may_pull(skb, hdrlen + 1)) | 374 | if (!pskb_may_pull(skb, hdrlen + 1)) |
377 | return -1; | 375 | return -1; |
376 | if (meshdr->flags & MESH_FLAGS_AE_A4) | ||
377 | return -1; | ||
378 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { | 378 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { |
379 | skb_copy_bits(skb, hdrlen + | 379 | skb_copy_bits(skb, hdrlen + |
380 | offsetof(struct ieee80211s_hdr, eaddr1), | 380 | offsetof(struct ieee80211s_hdr, eaddr1), |
@@ -399,6 +399,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
399 | /* make sure meshdr->flags is on the linear part */ | 399 | /* make sure meshdr->flags is on the linear part */ |
400 | if (!pskb_may_pull(skb, hdrlen + 1)) | 400 | if (!pskb_may_pull(skb, hdrlen + 1)) |
401 | return -1; | 401 | return -1; |
402 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) | ||
403 | return -1; | ||
402 | if (meshdr->flags & MESH_FLAGS_AE_A4) | 404 | if (meshdr->flags & MESH_FLAGS_AE_A4) |
403 | skb_copy_bits(skb, hdrlen + | 405 | skb_copy_bits(skb, hdrlen + |
404 | offsetof(struct ieee80211s_hdr, eaddr1), | 406 | offsetof(struct ieee80211s_hdr, eaddr1), |