diff options
213 files changed, 19165 insertions, 2154 deletions
diff --git a/Documentation/ABI/testing/sysfs-bus-bcma b/Documentation/ABI/testing/sysfs-bus-bcma new file mode 100644 index 000000000000..06b62badddd1 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-bcma | |||
@@ -0,0 +1,31 @@ | |||
1 | What: /sys/bus/bcma/devices/.../manuf | ||
2 | Date: May 2011 | ||
3 | KernelVersion: 2.6.40 | ||
4 | Contact: Rafał Miłecki <zajec5@gmail.com> | ||
5 | Description: | ||
6 | Each BCMA core has it's manufacturer id. See | ||
7 | include/linux/bcma/bcma.h for possible values. | ||
8 | |||
9 | What: /sys/bus/bcma/devices/.../id | ||
10 | Date: May 2011 | ||
11 | KernelVersion: 2.6.40 | ||
12 | Contact: Rafał Miłecki <zajec5@gmail.com> | ||
13 | Description: | ||
14 | There are a few types of BCMA cores, they can be identified by | ||
15 | id field. | ||
16 | |||
17 | What: /sys/bus/bcma/devices/.../rev | ||
18 | Date: May 2011 | ||
19 | KernelVersion: 2.6.40 | ||
20 | Contact: Rafał Miłecki <zajec5@gmail.com> | ||
21 | Description: | ||
22 | BCMA cores of the same type can still slightly differ depending | ||
23 | on their revision. Use it for detailed programming. | ||
24 | |||
25 | What: /sys/bus/bcma/devices/.../class | ||
26 | Date: May 2011 | ||
27 | KernelVersion: 2.6.40 | ||
28 | Contact: Rafał Miłecki <zajec5@gmail.com> | ||
29 | Description: | ||
30 | Each BCMA core is identified by few fields, including class it | ||
31 | belongs to. See include/linux/bcma/bcma.h for possible values. | ||
diff --git a/MAINTAINERS b/MAINTAINERS index e653a99ddc4c..e23cbd16f1bd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -5812,6 +5812,13 @@ S: Maintained | |||
5812 | F: drivers/ssb/ | 5812 | F: drivers/ssb/ |
5813 | F: include/linux/ssb/ | 5813 | F: include/linux/ssb/ |
5814 | 5814 | ||
5815 | BROADCOM SPECIFIC AMBA DRIVER (BCMA) | ||
5816 | M: Rafał Miłecki <zajec5@gmail.com> | ||
5817 | L: linux-wireless@vger.kernel.org | ||
5818 | S: Maintained | ||
5819 | F: drivers/bcma/ | ||
5820 | F: include/linux/bcma/ | ||
5821 | |||
5815 | SONY VAIO CONTROL DEVICE DRIVER | 5822 | SONY VAIO CONTROL DEVICE DRIVER |
5816 | M: Mattia Dongili <malattia@linux.it> | 5823 | M: Mattia Dongili <malattia@linux.it> |
5817 | L: platform-driver-x86@vger.kernel.org | 5824 | L: platform-driver-x86@vger.kernel.org |
diff --git a/drivers/Kconfig b/drivers/Kconfig index 177c7d156933..aca706751469 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig | |||
@@ -68,6 +68,8 @@ source "drivers/watchdog/Kconfig" | |||
68 | 68 | ||
69 | source "drivers/ssb/Kconfig" | 69 | source "drivers/ssb/Kconfig" |
70 | 70 | ||
71 | source "drivers/bcma/Kconfig" | ||
72 | |||
71 | source "drivers/mfd/Kconfig" | 73 | source "drivers/mfd/Kconfig" |
72 | 74 | ||
73 | source "drivers/regulator/Kconfig" | 75 | source "drivers/regulator/Kconfig" |
diff --git a/drivers/Makefile b/drivers/Makefile index 3f135b6fb014..a29527f4ded6 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
@@ -110,6 +110,7 @@ obj-$(CONFIG_HID) += hid/ | |||
110 | obj-$(CONFIG_PPC_PS3) += ps3/ | 110 | obj-$(CONFIG_PPC_PS3) += ps3/ |
111 | obj-$(CONFIG_OF) += of/ | 111 | obj-$(CONFIG_OF) += of/ |
112 | obj-$(CONFIG_SSB) += ssb/ | 112 | obj-$(CONFIG_SSB) += ssb/ |
113 | obj-$(CONFIG_BCMA) += bcma/ | ||
113 | obj-$(CONFIG_VHOST_NET) += vhost/ | 114 | obj-$(CONFIG_VHOST_NET) += vhost/ |
114 | obj-$(CONFIG_VLYNQ) += vlynq/ | 115 | obj-$(CONFIG_VLYNQ) += vlynq/ |
115 | obj-$(CONFIG_STAGING) += staging/ | 116 | obj-$(CONFIG_STAGING) += staging/ |
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig new file mode 100644 index 000000000000..353781b5b78b --- /dev/null +++ b/drivers/bcma/Kconfig | |||
@@ -0,0 +1,33 @@ | |||
1 | config BCMA_POSSIBLE | ||
2 | bool | ||
3 | depends on HAS_IOMEM && HAS_DMA | ||
4 | default y | ||
5 | |||
6 | menu "Broadcom specific AMBA" | ||
7 | depends on BCMA_POSSIBLE | ||
8 | |||
9 | config BCMA | ||
10 | tristate "BCMA support" | ||
11 | depends on BCMA_POSSIBLE | ||
12 | help | ||
13 | Bus driver for Broadcom specific Advanced Microcontroller Bus | ||
14 | Architecture. | ||
15 | |||
16 | config BCMA_HOST_PCI_POSSIBLE | ||
17 | bool | ||
18 | depends on BCMA && PCI = y | ||
19 | default y | ||
20 | |||
21 | config BCMA_HOST_PCI | ||
22 | bool "Support for BCMA on PCI-host bus" | ||
23 | depends on BCMA_HOST_PCI_POSSIBLE | ||
24 | |||
25 | config BCMA_DEBUG | ||
26 | bool "BCMA debugging" | ||
27 | depends on BCMA | ||
28 | help | ||
29 | This turns on additional debugging messages. | ||
30 | |||
31 | If unsure, say N | ||
32 | |||
33 | endmenu | ||
diff --git a/drivers/bcma/Makefile b/drivers/bcma/Makefile new file mode 100644 index 000000000000..0d56245bcb79 --- /dev/null +++ b/drivers/bcma/Makefile | |||
@@ -0,0 +1,7 @@ | |||
1 | bcma-y += main.o scan.o core.o | ||
2 | bcma-y += driver_chipcommon.o driver_chipcommon_pmu.o | ||
3 | bcma-y += driver_pci.o | ||
4 | bcma-$(CONFIG_BCMA_HOST_PCI) += host_pci.o | ||
5 | obj-$(CONFIG_BCMA) += bcma.o | ||
6 | |||
7 | ccflags-$(CONFIG_BCMA_DEBUG) := -DDEBUG | ||
diff --git a/drivers/bcma/README b/drivers/bcma/README new file mode 100644 index 000000000000..f7e7ce46c603 --- /dev/null +++ b/drivers/bcma/README | |||
@@ -0,0 +1,19 @@ | |||
1 | Broadcom introduced new bus as replacement for older SSB. It is based on AMBA, | ||
2 | however from programming point of view there is nothing AMBA specific we use. | ||
3 | |||
4 | Standard AMBA drivers are platform specific, have hardcoded addresses and use | ||
5 | AMBA standard fields like CID and PID. | ||
6 | |||
7 | In case of Broadcom's cards every device consists of: | ||
8 | 1) Broadcom specific AMBA device. It is put on AMBA bus, but can not be treated | ||
9 | as standard AMBA device. Reading it's CID or PID can cause machine lockup. | ||
10 | 2) AMBA standard devices called ports or wrappers. They have CIDs (AMBA_CID) | ||
11 | and PIDs (0x103BB369), but we do not use that info for anything. One of that | ||
12 | devices is used for managing Broadcom specific core. | ||
13 | |||
14 | Addresses of AMBA devices are not hardcoded in driver and have to be read from | ||
15 | EPROM. | ||
16 | |||
17 | In this situation we decided to introduce separated bus. It can contain up to | ||
18 | 16 devices identified by Broadcom specific fields: manufacturer, id, revision | ||
19 | and class. | ||
diff --git a/drivers/bcma/TODO b/drivers/bcma/TODO new file mode 100644 index 000000000000..da7aa99fe81c --- /dev/null +++ b/drivers/bcma/TODO | |||
@@ -0,0 +1,3 @@ | |||
1 | - Interrupts | ||
2 | - Defines for PCI core driver | ||
3 | - Create kernel Documentation (use info from README) | ||
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h new file mode 100644 index 000000000000..2f72e9c585fd --- /dev/null +++ b/drivers/bcma/bcma_private.h | |||
@@ -0,0 +1,28 @@ | |||
1 | #ifndef LINUX_BCMA_PRIVATE_H_ | ||
2 | #define LINUX_BCMA_PRIVATE_H_ | ||
3 | |||
4 | #ifndef pr_fmt | ||
5 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
6 | #endif | ||
7 | |||
8 | #include <linux/bcma/bcma.h> | ||
9 | #include <linux/delay.h> | ||
10 | |||
11 | #define BCMA_CORE_SIZE 0x1000 | ||
12 | |||
13 | struct bcma_bus; | ||
14 | |||
15 | /* main.c */ | ||
16 | extern int bcma_bus_register(struct bcma_bus *bus); | ||
17 | extern void bcma_bus_unregister(struct bcma_bus *bus); | ||
18 | |||
19 | /* scan.c */ | ||
20 | int bcma_bus_scan(struct bcma_bus *bus); | ||
21 | |||
22 | #ifdef CONFIG_BCMA_HOST_PCI | ||
23 | /* host_pci.c */ | ||
24 | extern int __init bcma_host_pci_init(void); | ||
25 | extern void __exit bcma_host_pci_exit(void); | ||
26 | #endif /* CONFIG_BCMA_HOST_PCI */ | ||
27 | |||
28 | #endif | ||
diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c new file mode 100644 index 000000000000..ced379f7b371 --- /dev/null +++ b/drivers/bcma/core.c | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * Broadcom specific AMBA | ||
3 | * Core ops | ||
4 | * | ||
5 | * Licensed under the GNU/GPL. See COPYING for details. | ||
6 | */ | ||
7 | |||
8 | #include "bcma_private.h" | ||
9 | #include <linux/bcma/bcma.h> | ||
10 | |||
11 | bool bcma_core_is_enabled(struct bcma_device *core) | ||
12 | { | ||
13 | if ((bcma_aread32(core, BCMA_IOCTL) & (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC)) | ||
14 | != BCMA_IOCTL_CLK) | ||
15 | return false; | ||
16 | if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET) | ||
17 | return false; | ||
18 | return true; | ||
19 | } | ||
20 | EXPORT_SYMBOL_GPL(bcma_core_is_enabled); | ||
21 | |||
22 | static void bcma_core_disable(struct bcma_device *core, u32 flags) | ||
23 | { | ||
24 | if (bcma_aread32(core, BCMA_RESET_CTL) & BCMA_RESET_CTL_RESET) | ||
25 | return; | ||
26 | |||
27 | bcma_awrite32(core, BCMA_IOCTL, flags); | ||
28 | bcma_aread32(core, BCMA_IOCTL); | ||
29 | udelay(10); | ||
30 | |||
31 | bcma_awrite32(core, BCMA_RESET_CTL, BCMA_RESET_CTL_RESET); | ||
32 | udelay(1); | ||
33 | } | ||
34 | |||
35 | int bcma_core_enable(struct bcma_device *core, u32 flags) | ||
36 | { | ||
37 | bcma_core_disable(core, flags); | ||
38 | |||
39 | bcma_awrite32(core, BCMA_IOCTL, (BCMA_IOCTL_CLK | BCMA_IOCTL_FGC | flags)); | ||
40 | bcma_aread32(core, BCMA_IOCTL); | ||
41 | |||
42 | bcma_awrite32(core, BCMA_RESET_CTL, 0); | ||
43 | udelay(1); | ||
44 | |||
45 | bcma_awrite32(core, BCMA_IOCTL, (BCMA_IOCTL_CLK | flags)); | ||
46 | bcma_aread32(core, BCMA_IOCTL); | ||
47 | udelay(1); | ||
48 | |||
49 | return 0; | ||
50 | } | ||
51 | EXPORT_SYMBOL_GPL(bcma_core_enable); | ||
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c new file mode 100644 index 000000000000..606102256b44 --- /dev/null +++ b/drivers/bcma/driver_chipcommon.c | |||
@@ -0,0 +1,89 @@ | |||
1 | /* | ||
2 | * Broadcom specific AMBA | ||
3 | * ChipCommon core driver | ||
4 | * | ||
5 | * Copyright 2005, Broadcom Corporation | ||
6 | * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de> | ||
7 | * | ||
8 | * Licensed under the GNU/GPL. See COPYING for details. | ||
9 | */ | ||
10 | |||
11 | #include "bcma_private.h" | ||
12 | #include <linux/bcma/bcma.h> | ||
13 | |||
14 | static inline u32 bcma_cc_write32_masked(struct bcma_drv_cc *cc, u16 offset, | ||
15 | u32 mask, u32 value) | ||
16 | { | ||
17 | value &= mask; | ||
18 | value |= bcma_cc_read32(cc, offset) & ~mask; | ||
19 | bcma_cc_write32(cc, offset, value); | ||
20 | |||
21 | return value; | ||
22 | } | ||
23 | |||
24 | void bcma_core_chipcommon_init(struct bcma_drv_cc *cc) | ||
25 | { | ||
26 | if (cc->core->id.rev >= 11) | ||
27 | cc->status = bcma_cc_read32(cc, BCMA_CC_CHIPSTAT); | ||
28 | cc->capabilities = bcma_cc_read32(cc, BCMA_CC_CAP); | ||
29 | if (cc->core->id.rev >= 35) | ||
30 | cc->capabilities_ext = bcma_cc_read32(cc, BCMA_CC_CAP_EXT); | ||
31 | |||
32 | if (cc->core->id.rev >= 20) { | ||
33 | bcma_cc_write32(cc, BCMA_CC_GPIOPULLUP, 0); | ||
34 | bcma_cc_write32(cc, BCMA_CC_GPIOPULLDOWN, 0); | ||
35 | } | ||
36 | |||
37 | if (cc->capabilities & BCMA_CC_CAP_PMU) | ||
38 | bcma_pmu_init(cc); | ||
39 | if (cc->capabilities & BCMA_CC_CAP_PCTL) | ||
40 | pr_err("Power control not implemented!\n"); | ||
41 | } | ||
42 | |||
43 | /* Set chip watchdog reset timer to fire in 'ticks' backplane cycles */ | ||
44 | void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, u32 ticks) | ||
45 | { | ||
46 | /* instant NMI */ | ||
47 | bcma_cc_write32(cc, BCMA_CC_WATCHDOG, ticks); | ||
48 | } | ||
49 | |||
50 | void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value) | ||
51 | { | ||
52 | bcma_cc_write32_masked(cc, BCMA_CC_IRQMASK, mask, value); | ||
53 | } | ||
54 | |||
55 | u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask) | ||
56 | { | ||
57 | return bcma_cc_read32(cc, BCMA_CC_IRQSTAT) & mask; | ||
58 | } | ||
59 | |||
60 | u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask) | ||
61 | { | ||
62 | return bcma_cc_read32(cc, BCMA_CC_GPIOIN) & mask; | ||
63 | } | ||
64 | |||
65 | u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value) | ||
66 | { | ||
67 | return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUT, mask, value); | ||
68 | } | ||
69 | |||
70 | u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value) | ||
71 | { | ||
72 | return bcma_cc_write32_masked(cc, BCMA_CC_GPIOOUTEN, mask, value); | ||
73 | } | ||
74 | |||
75 | u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value) | ||
76 | { | ||
77 | return bcma_cc_write32_masked(cc, BCMA_CC_GPIOCTL, mask, value); | ||
78 | } | ||
79 | EXPORT_SYMBOL_GPL(bcma_chipco_gpio_control); | ||
80 | |||
81 | u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value) | ||
82 | { | ||
83 | return bcma_cc_write32_masked(cc, BCMA_CC_GPIOIRQ, mask, value); | ||
84 | } | ||
85 | |||
86 | u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value) | ||
87 | { | ||
88 | return bcma_cc_write32_masked(cc, BCMA_CC_GPIOPOL, mask, value); | ||
89 | } | ||
diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c new file mode 100644 index 000000000000..f44177a644c7 --- /dev/null +++ b/drivers/bcma/driver_chipcommon_pmu.c | |||
@@ -0,0 +1,134 @@ | |||
1 | /* | ||
2 | * Broadcom specific AMBA | ||
3 | * ChipCommon Power Management Unit driver | ||
4 | * | ||
5 | * Copyright 2009, Michael Buesch <mb@bu3sch.de> | ||
6 | * Copyright 2007, Broadcom Corporation | ||
7 | * | ||
8 | * Licensed under the GNU/GPL. See COPYING for details. | ||
9 | */ | ||
10 | |||
11 | #include "bcma_private.h" | ||
12 | #include <linux/bcma/bcma.h> | ||
13 | |||
14 | static void bcma_chipco_chipctl_maskset(struct bcma_drv_cc *cc, | ||
15 | u32 offset, u32 mask, u32 set) | ||
16 | { | ||
17 | u32 value; | ||
18 | |||
19 | bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR); | ||
20 | bcma_cc_write32(cc, BCMA_CC_CHIPCTL_ADDR, offset); | ||
21 | bcma_cc_read32(cc, BCMA_CC_CHIPCTL_ADDR); | ||
22 | value = bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA); | ||
23 | value &= mask; | ||
24 | value |= set; | ||
25 | bcma_cc_write32(cc, BCMA_CC_CHIPCTL_DATA, value); | ||
26 | bcma_cc_read32(cc, BCMA_CC_CHIPCTL_DATA); | ||
27 | } | ||
28 | |||
29 | static void bcma_pmu_pll_init(struct bcma_drv_cc *cc) | ||
30 | { | ||
31 | struct bcma_bus *bus = cc->core->bus; | ||
32 | |||
33 | switch (bus->chipinfo.id) { | ||
34 | case 0x4313: | ||
35 | case 0x4331: | ||
36 | case 43224: | ||
37 | case 43225: | ||
38 | break; | ||
39 | default: | ||
40 | pr_err("PLL init unknown for device 0x%04X\n", | ||
41 | bus->chipinfo.id); | ||
42 | } | ||
43 | } | ||
44 | |||
45 | static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) | ||
46 | { | ||
47 | struct bcma_bus *bus = cc->core->bus; | ||
48 | u32 min_msk = 0, max_msk = 0; | ||
49 | |||
50 | switch (bus->chipinfo.id) { | ||
51 | case 0x4313: | ||
52 | min_msk = 0x200D; | ||
53 | max_msk = 0xFFFF; | ||
54 | break; | ||
55 | case 43224: | ||
56 | break; | ||
57 | default: | ||
58 | pr_err("PMU resource config unknown for device 0x%04X\n", | ||
59 | bus->chipinfo.id); | ||
60 | } | ||
61 | |||
62 | /* Set the resource masks. */ | ||
63 | if (min_msk) | ||
64 | bcma_cc_write32(cc, BCMA_CC_PMU_MINRES_MSK, min_msk); | ||
65 | if (max_msk) | ||
66 | bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); | ||
67 | } | ||
68 | |||
69 | void bcma_pmu_swreg_init(struct bcma_drv_cc *cc) | ||
70 | { | ||
71 | struct bcma_bus *bus = cc->core->bus; | ||
72 | |||
73 | switch (bus->chipinfo.id) { | ||
74 | case 0x4313: | ||
75 | case 0x4331: | ||
76 | case 43224: | ||
77 | break; | ||
78 | default: | ||
79 | pr_err("PMU switch/regulators init unknown for device " | ||
80 | "0x%04X\n", bus->chipinfo.id); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | void bcma_pmu_workarounds(struct bcma_drv_cc *cc) | ||
85 | { | ||
86 | struct bcma_bus *bus = cc->core->bus; | ||
87 | |||
88 | switch (bus->chipinfo.id) { | ||
89 | case 0x4313: | ||
90 | bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7); | ||
91 | break; | ||
92 | case 0x4331: | ||
93 | pr_err("Enabling Ext PA lines not implemented\n"); | ||
94 | break; | ||
95 | case 43224: | ||
96 | if (bus->chipinfo.rev == 0) { | ||
97 | pr_err("Workarounds for 43224 rev 0 not fully " | ||
98 | "implemented\n"); | ||
99 | bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0); | ||
100 | } else { | ||
101 | bcma_chipco_chipctl_maskset(cc, 0, ~0, 0xF0); | ||
102 | } | ||
103 | break; | ||
104 | default: | ||
105 | pr_err("Workarounds unknown for device 0x%04X\n", | ||
106 | bus->chipinfo.id); | ||
107 | } | ||
108 | } | ||
109 | |||
110 | void bcma_pmu_init(struct bcma_drv_cc *cc) | ||
111 | { | ||
112 | u32 pmucap; | ||
113 | |||
114 | pmucap = bcma_cc_read32(cc, BCMA_CC_PMU_CAP); | ||
115 | cc->pmu.rev = (pmucap & BCMA_CC_PMU_CAP_REVISION); | ||
116 | |||
117 | pr_debug("Found rev %u PMU (capabilities 0x%08X)\n", cc->pmu.rev, | ||
118 | pmucap); | ||
119 | |||
120 | if (cc->pmu.rev == 1) | ||
121 | bcma_cc_mask32(cc, BCMA_CC_PMU_CTL, | ||
122 | ~BCMA_CC_PMU_CTL_NOILPONW); | ||
123 | else | ||
124 | bcma_cc_set32(cc, BCMA_CC_PMU_CTL, | ||
125 | BCMA_CC_PMU_CTL_NOILPONW); | ||
126 | |||
127 | if (cc->core->id.id == 0x4329 && cc->core->id.rev == 2) | ||
128 | pr_err("Fix for 4329b0 bad LPOM state not implemented!\n"); | ||
129 | |||
130 | bcma_pmu_pll_init(cc); | ||
131 | bcma_pmu_resources_init(cc); | ||
132 | bcma_pmu_swreg_init(cc); | ||
133 | bcma_pmu_workarounds(cc); | ||
134 | } | ||
diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c new file mode 100644 index 000000000000..e757e4e3c7e2 --- /dev/null +++ b/drivers/bcma/driver_pci.c | |||
@@ -0,0 +1,163 @@ | |||
1 | /* | ||
2 | * Broadcom specific AMBA | ||
3 | * PCI Core | ||
4 | * | ||
5 | * Copyright 2005, Broadcom Corporation | ||
6 | * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de> | ||
7 | * | ||
8 | * Licensed under the GNU/GPL. See COPYING for details. | ||
9 | */ | ||
10 | |||
11 | #include "bcma_private.h" | ||
12 | #include <linux/bcma/bcma.h> | ||
13 | |||
14 | /************************************************** | ||
15 | * R/W ops. | ||
16 | **************************************************/ | ||
17 | |||
18 | static u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address) | ||
19 | { | ||
20 | pcicore_write32(pc, 0x130, address); | ||
21 | pcicore_read32(pc, 0x130); | ||
22 | return pcicore_read32(pc, 0x134); | ||
23 | } | ||
24 | |||
25 | #if 0 | ||
26 | static void bcma_pcie_write(struct bcma_drv_pci *pc, u32 address, u32 data) | ||
27 | { | ||
28 | pcicore_write32(pc, 0x130, address); | ||
29 | pcicore_read32(pc, 0x130); | ||
30 | pcicore_write32(pc, 0x134, data); | ||
31 | } | ||
32 | #endif | ||
33 | |||
34 | static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy) | ||
35 | { | ||
36 | const u16 mdio_control = 0x128; | ||
37 | const u16 mdio_data = 0x12C; | ||
38 | u32 v; | ||
39 | int i; | ||
40 | |||
41 | v = (1 << 30); /* Start of Transaction */ | ||
42 | v |= (1 << 28); /* Write Transaction */ | ||
43 | v |= (1 << 17); /* Turnaround */ | ||
44 | v |= (0x1F << 18); | ||
45 | v |= (phy << 4); | ||
46 | pcicore_write32(pc, mdio_data, v); | ||
47 | |||
48 | udelay(10); | ||
49 | for (i = 0; i < 200; i++) { | ||
50 | v = pcicore_read32(pc, mdio_control); | ||
51 | if (v & 0x100 /* Trans complete */) | ||
52 | break; | ||
53 | msleep(1); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address) | ||
58 | { | ||
59 | const u16 mdio_control = 0x128; | ||
60 | const u16 mdio_data = 0x12C; | ||
61 | int max_retries = 10; | ||
62 | u16 ret = 0; | ||
63 | u32 v; | ||
64 | int i; | ||
65 | |||
66 | v = 0x80; /* Enable Preamble Sequence */ | ||
67 | v |= 0x2; /* MDIO Clock Divisor */ | ||
68 | pcicore_write32(pc, mdio_control, v); | ||
69 | |||
70 | if (pc->core->id.rev >= 10) { | ||
71 | max_retries = 200; | ||
72 | bcma_pcie_mdio_set_phy(pc, device); | ||
73 | } | ||
74 | |||
75 | v = (1 << 30); /* Start of Transaction */ | ||
76 | v |= (1 << 29); /* Read Transaction */ | ||
77 | v |= (1 << 17); /* Turnaround */ | ||
78 | if (pc->core->id.rev < 10) | ||
79 | v |= (u32)device << 22; | ||
80 | v |= (u32)address << 18; | ||
81 | pcicore_write32(pc, mdio_data, v); | ||
82 | /* Wait for the device to complete the transaction */ | ||
83 | udelay(10); | ||
84 | for (i = 0; i < max_retries; i++) { | ||
85 | v = pcicore_read32(pc, mdio_control); | ||
86 | if (v & 0x100 /* Trans complete */) { | ||
87 | udelay(10); | ||
88 | ret = pcicore_read32(pc, mdio_data); | ||
89 | break; | ||
90 | } | ||
91 | msleep(1); | ||
92 | } | ||
93 | pcicore_write32(pc, mdio_control, 0); | ||
94 | return ret; | ||
95 | } | ||
96 | |||
97 | static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device, | ||
98 | u8 address, u16 data) | ||
99 | { | ||
100 | const u16 mdio_control = 0x128; | ||
101 | const u16 mdio_data = 0x12C; | ||
102 | int max_retries = 10; | ||
103 | u32 v; | ||
104 | int i; | ||
105 | |||
106 | v = 0x80; /* Enable Preamble Sequence */ | ||
107 | v |= 0x2; /* MDIO Clock Divisor */ | ||
108 | pcicore_write32(pc, mdio_control, v); | ||
109 | |||
110 | if (pc->core->id.rev >= 10) { | ||
111 | max_retries = 200; | ||
112 | bcma_pcie_mdio_set_phy(pc, device); | ||
113 | } | ||
114 | |||
115 | v = (1 << 30); /* Start of Transaction */ | ||
116 | v |= (1 << 28); /* Write Transaction */ | ||
117 | v |= (1 << 17); /* Turnaround */ | ||
118 | if (pc->core->id.rev < 10) | ||
119 | v |= (u32)device << 22; | ||
120 | v |= (u32)address << 18; | ||
121 | v |= data; | ||
122 | pcicore_write32(pc, mdio_data, v); | ||
123 | /* Wait for the device to complete the transaction */ | ||
124 | udelay(10); | ||
125 | for (i = 0; i < max_retries; i++) { | ||
126 | v = pcicore_read32(pc, mdio_control); | ||
127 | if (v & 0x100 /* Trans complete */) | ||
128 | break; | ||
129 | msleep(1); | ||
130 | } | ||
131 | pcicore_write32(pc, mdio_control, 0); | ||
132 | } | ||
133 | |||
134 | /************************************************** | ||
135 | * Workarounds. | ||
136 | **************************************************/ | ||
137 | |||
138 | static u8 bcma_pcicore_polarity_workaround(struct bcma_drv_pci *pc) | ||
139 | { | ||
140 | return (bcma_pcie_read(pc, 0x204) & 0x10) ? 0xC0 : 0x80; | ||
141 | } | ||
142 | |||
143 | static void bcma_pcicore_serdes_workaround(struct bcma_drv_pci *pc) | ||
144 | { | ||
145 | const u8 serdes_pll_device = 0x1D; | ||
146 | const u8 serdes_rx_device = 0x1F; | ||
147 | u16 tmp; | ||
148 | |||
149 | bcma_pcie_mdio_write(pc, serdes_rx_device, 1 /* Control */, | ||
150 | bcma_pcicore_polarity_workaround(pc)); | ||
151 | tmp = bcma_pcie_mdio_read(pc, serdes_pll_device, 1 /* Control */); | ||
152 | if (tmp & 0x4000) | ||
153 | bcma_pcie_mdio_write(pc, serdes_pll_device, 1, tmp & ~0x4000); | ||
154 | } | ||
155 | |||
156 | /************************************************** | ||
157 | * Init. | ||
158 | **************************************************/ | ||
159 | |||
160 | void bcma_core_pci_init(struct bcma_drv_pci *pc) | ||
161 | { | ||
162 | bcma_pcicore_serdes_workaround(pc); | ||
163 | } | ||
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c new file mode 100644 index 000000000000..99dd36e8500b --- /dev/null +++ b/drivers/bcma/host_pci.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /* | ||
2 | * Broadcom specific AMBA | ||
3 | * PCI Host | ||
4 | * | ||
5 | * Licensed under the GNU/GPL. See COPYING for details. | ||
6 | */ | ||
7 | |||
8 | #include "bcma_private.h" | ||
9 | #include <linux/bcma/bcma.h> | ||
10 | #include <linux/pci.h> | ||
11 | |||
12 | static void bcma_host_pci_switch_core(struct bcma_device *core) | ||
13 | { | ||
14 | pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN, | ||
15 | core->addr); | ||
16 | pci_write_config_dword(core->bus->host_pci, BCMA_PCI_BAR0_WIN2, | ||
17 | core->wrap); | ||
18 | core->bus->mapped_core = core; | ||
19 | pr_debug("Switched to core: 0x%X\n", core->id.id); | ||
20 | } | ||
21 | |||
22 | static u8 bcma_host_pci_read8(struct bcma_device *core, u16 offset) | ||
23 | { | ||
24 | if (core->bus->mapped_core != core) | ||
25 | bcma_host_pci_switch_core(core); | ||
26 | return ioread8(core->bus->mmio + offset); | ||
27 | } | ||
28 | |||
29 | static u16 bcma_host_pci_read16(struct bcma_device *core, u16 offset) | ||
30 | { | ||
31 | if (core->bus->mapped_core != core) | ||
32 | bcma_host_pci_switch_core(core); | ||
33 | return ioread16(core->bus->mmio + offset); | ||
34 | } | ||
35 | |||
36 | static u32 bcma_host_pci_read32(struct bcma_device *core, u16 offset) | ||
37 | { | ||
38 | if (core->bus->mapped_core != core) | ||
39 | bcma_host_pci_switch_core(core); | ||
40 | return ioread32(core->bus->mmio + offset); | ||
41 | } | ||
42 | |||
43 | static void bcma_host_pci_write8(struct bcma_device *core, u16 offset, | ||
44 | u8 value) | ||
45 | { | ||
46 | if (core->bus->mapped_core != core) | ||
47 | bcma_host_pci_switch_core(core); | ||
48 | iowrite8(value, core->bus->mmio + offset); | ||
49 | } | ||
50 | |||
51 | static void bcma_host_pci_write16(struct bcma_device *core, u16 offset, | ||
52 | u16 value) | ||
53 | { | ||
54 | if (core->bus->mapped_core != core) | ||
55 | bcma_host_pci_switch_core(core); | ||
56 | iowrite16(value, core->bus->mmio + offset); | ||
57 | } | ||
58 | |||
59 | static void bcma_host_pci_write32(struct bcma_device *core, u16 offset, | ||
60 | u32 value) | ||
61 | { | ||
62 | if (core->bus->mapped_core != core) | ||
63 | bcma_host_pci_switch_core(core); | ||
64 | iowrite32(value, core->bus->mmio + offset); | ||
65 | } | ||
66 | |||
67 | static u32 bcma_host_pci_aread32(struct bcma_device *core, u16 offset) | ||
68 | { | ||
69 | if (core->bus->mapped_core != core) | ||
70 | bcma_host_pci_switch_core(core); | ||
71 | return ioread32(core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset); | ||
72 | } | ||
73 | |||
74 | static void bcma_host_pci_awrite32(struct bcma_device *core, u16 offset, | ||
75 | u32 value) | ||
76 | { | ||
77 | if (core->bus->mapped_core != core) | ||
78 | bcma_host_pci_switch_core(core); | ||
79 | iowrite32(value, core->bus->mmio + (1 * BCMA_CORE_SIZE) + offset); | ||
80 | } | ||
81 | |||
82 | const struct bcma_host_ops bcma_host_pci_ops = { | ||
83 | .read8 = bcma_host_pci_read8, | ||
84 | .read16 = bcma_host_pci_read16, | ||
85 | .read32 = bcma_host_pci_read32, | ||
86 | .write8 = bcma_host_pci_write8, | ||
87 | .write16 = bcma_host_pci_write16, | ||
88 | .write32 = bcma_host_pci_write32, | ||
89 | .aread32 = bcma_host_pci_aread32, | ||
90 | .awrite32 = bcma_host_pci_awrite32, | ||
91 | }; | ||
92 | |||
93 | static int bcma_host_pci_probe(struct pci_dev *dev, | ||
94 | const struct pci_device_id *id) | ||
95 | { | ||
96 | struct bcma_bus *bus; | ||
97 | int err = -ENOMEM; | ||
98 | const char *name; | ||
99 | u32 val; | ||
100 | |||
101 | /* Alloc */ | ||
102 | bus = kzalloc(sizeof(*bus), GFP_KERNEL); | ||
103 | if (!bus) | ||
104 | goto out; | ||
105 | |||
106 | /* Basic PCI configuration */ | ||
107 | err = pci_enable_device(dev); | ||
108 | if (err) | ||
109 | goto err_kfree_bus; | ||
110 | |||
111 | name = dev_name(&dev->dev); | ||
112 | if (dev->driver && dev->driver->name) | ||
113 | name = dev->driver->name; | ||
114 | err = pci_request_regions(dev, name); | ||
115 | if (err) | ||
116 | goto err_pci_disable; | ||
117 | pci_set_master(dev); | ||
118 | |||
119 | /* Disable the RETRY_TIMEOUT register (0x41) to keep | ||
120 | * PCI Tx retries from interfering with C3 CPU state */ | ||
121 | pci_read_config_dword(dev, 0x40, &val); | ||
122 | if ((val & 0x0000ff00) != 0) | ||
123 | pci_write_config_dword(dev, 0x40, val & 0xffff00ff); | ||
124 | |||
125 | /* SSB needed additional powering up, do we have any AMBA PCI cards? */ | ||
126 | if (!pci_is_pcie(dev)) | ||
127 | pr_err("PCI card detected, report problems.\n"); | ||
128 | |||
129 | /* Map MMIO */ | ||
130 | err = -ENOMEM; | ||
131 | bus->mmio = pci_iomap(dev, 0, ~0UL); | ||
132 | if (!bus->mmio) | ||
133 | goto err_pci_release_regions; | ||
134 | |||
135 | /* Host specific */ | ||
136 | bus->host_pci = dev; | ||
137 | bus->hosttype = BCMA_HOSTTYPE_PCI; | ||
138 | bus->ops = &bcma_host_pci_ops; | ||
139 | |||
140 | /* Register */ | ||
141 | err = bcma_bus_register(bus); | ||
142 | if (err) | ||
143 | goto err_pci_unmap_mmio; | ||
144 | |||
145 | pci_set_drvdata(dev, bus); | ||
146 | |||
147 | out: | ||
148 | return err; | ||
149 | |||
150 | err_pci_unmap_mmio: | ||
151 | pci_iounmap(dev, bus->mmio); | ||
152 | err_pci_release_regions: | ||
153 | pci_release_regions(dev); | ||
154 | err_pci_disable: | ||
155 | pci_disable_device(dev); | ||
156 | err_kfree_bus: | ||
157 | kfree(bus); | ||
158 | return err; | ||
159 | } | ||
160 | |||
161 | static void bcma_host_pci_remove(struct pci_dev *dev) | ||
162 | { | ||
163 | struct bcma_bus *bus = pci_get_drvdata(dev); | ||
164 | |||
165 | bcma_bus_unregister(bus); | ||
166 | pci_iounmap(dev, bus->mmio); | ||
167 | pci_release_regions(dev); | ||
168 | pci_disable_device(dev); | ||
169 | kfree(bus); | ||
170 | pci_set_drvdata(dev, NULL); | ||
171 | } | ||
172 | |||
173 | static DEFINE_PCI_DEVICE_TABLE(bcma_pci_bridge_tbl) = { | ||
174 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) }, | ||
175 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) }, | ||
176 | { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) }, | ||
177 | { 0, }, | ||
178 | }; | ||
179 | MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl); | ||
180 | |||
181 | static struct pci_driver bcma_pci_bridge_driver = { | ||
182 | .name = "bcma-pci-bridge", | ||
183 | .id_table = bcma_pci_bridge_tbl, | ||
184 | .probe = bcma_host_pci_probe, | ||
185 | .remove = bcma_host_pci_remove, | ||
186 | }; | ||
187 | |||
188 | int __init bcma_host_pci_init(void) | ||
189 | { | ||
190 | return pci_register_driver(&bcma_pci_bridge_driver); | ||
191 | } | ||
192 | |||
193 | void __exit bcma_host_pci_exit(void) | ||
194 | { | ||
195 | pci_unregister_driver(&bcma_pci_bridge_driver); | ||
196 | } | ||
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c new file mode 100644 index 000000000000..be52344ed19d --- /dev/null +++ b/drivers/bcma/main.c | |||
@@ -0,0 +1,247 @@ | |||
1 | /* | ||
2 | * Broadcom specific AMBA | ||
3 | * Bus subsystem | ||
4 | * | ||
5 | * Licensed under the GNU/GPL. See COPYING for details. | ||
6 | */ | ||
7 | |||
8 | #include "bcma_private.h" | ||
9 | #include <linux/bcma/bcma.h> | ||
10 | |||
11 | MODULE_DESCRIPTION("Broadcom's specific AMBA driver"); | ||
12 | MODULE_LICENSE("GPL"); | ||
13 | |||
14 | static int bcma_bus_match(struct device *dev, struct device_driver *drv); | ||
15 | static int bcma_device_probe(struct device *dev); | ||
16 | static int bcma_device_remove(struct device *dev); | ||
17 | |||
18 | static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
19 | { | ||
20 | struct bcma_device *core = container_of(dev, struct bcma_device, dev); | ||
21 | return sprintf(buf, "0x%03X\n", core->id.manuf); | ||
22 | } | ||
23 | static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
24 | { | ||
25 | struct bcma_device *core = container_of(dev, struct bcma_device, dev); | ||
26 | return sprintf(buf, "0x%03X\n", core->id.id); | ||
27 | } | ||
28 | static ssize_t rev_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
29 | { | ||
30 | struct bcma_device *core = container_of(dev, struct bcma_device, dev); | ||
31 | return sprintf(buf, "0x%02X\n", core->id.rev); | ||
32 | } | ||
33 | static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf) | ||
34 | { | ||
35 | struct bcma_device *core = container_of(dev, struct bcma_device, dev); | ||
36 | return sprintf(buf, "0x%X\n", core->id.class); | ||
37 | } | ||
38 | static struct device_attribute bcma_device_attrs[] = { | ||
39 | __ATTR_RO(manuf), | ||
40 | __ATTR_RO(id), | ||
41 | __ATTR_RO(rev), | ||
42 | __ATTR_RO(class), | ||
43 | __ATTR_NULL, | ||
44 | }; | ||
45 | |||
46 | static struct bus_type bcma_bus_type = { | ||
47 | .name = "bcma", | ||
48 | .match = bcma_bus_match, | ||
49 | .probe = bcma_device_probe, | ||
50 | .remove = bcma_device_remove, | ||
51 | .dev_attrs = bcma_device_attrs, | ||
52 | }; | ||
53 | |||
54 | static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid) | ||
55 | { | ||
56 | struct bcma_device *core; | ||
57 | |||
58 | list_for_each_entry(core, &bus->cores, list) { | ||
59 | if (core->id.id == coreid) | ||
60 | return core; | ||
61 | } | ||
62 | return NULL; | ||
63 | } | ||
64 | |||
65 | static void bcma_release_core_dev(struct device *dev) | ||
66 | { | ||
67 | struct bcma_device *core = container_of(dev, struct bcma_device, dev); | ||
68 | kfree(core); | ||
69 | } | ||
70 | |||
71 | static int bcma_register_cores(struct bcma_bus *bus) | ||
72 | { | ||
73 | struct bcma_device *core; | ||
74 | int err, dev_id = 0; | ||
75 | |||
76 | list_for_each_entry(core, &bus->cores, list) { | ||
77 | /* We support that cores ourself */ | ||
78 | switch (core->id.id) { | ||
79 | case BCMA_CORE_CHIPCOMMON: | ||
80 | case BCMA_CORE_PCI: | ||
81 | case BCMA_CORE_PCIE: | ||
82 | continue; | ||
83 | } | ||
84 | |||
85 | core->dev.release = bcma_release_core_dev; | ||
86 | core->dev.bus = &bcma_bus_type; | ||
87 | dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id); | ||
88 | |||
89 | switch (bus->hosttype) { | ||
90 | case BCMA_HOSTTYPE_PCI: | ||
91 | core->dev.parent = &bus->host_pci->dev; | ||
92 | break; | ||
93 | case BCMA_HOSTTYPE_NONE: | ||
94 | case BCMA_HOSTTYPE_SDIO: | ||
95 | break; | ||
96 | } | ||
97 | |||
98 | err = device_register(&core->dev); | ||
99 | if (err) { | ||
100 | pr_err("Could not register dev for core 0x%03X\n", | ||
101 | core->id.id); | ||
102 | continue; | ||
103 | } | ||
104 | core->dev_registered = true; | ||
105 | dev_id++; | ||
106 | } | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static void bcma_unregister_cores(struct bcma_bus *bus) | ||
112 | { | ||
113 | struct bcma_device *core; | ||
114 | |||
115 | list_for_each_entry(core, &bus->cores, list) { | ||
116 | if (core->dev_registered) | ||
117 | device_unregister(&core->dev); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | int bcma_bus_register(struct bcma_bus *bus) | ||
122 | { | ||
123 | int err; | ||
124 | struct bcma_device *core; | ||
125 | |||
126 | /* Scan for devices (cores) */ | ||
127 | err = bcma_bus_scan(bus); | ||
128 | if (err) { | ||
129 | pr_err("Failed to scan: %d\n", err); | ||
130 | return -1; | ||
131 | } | ||
132 | |||
133 | /* Init CC core */ | ||
134 | core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON); | ||
135 | if (core) { | ||
136 | bus->drv_cc.core = core; | ||
137 | bcma_core_chipcommon_init(&bus->drv_cc); | ||
138 | } | ||
139 | |||
140 | /* Init PCIE core */ | ||
141 | core = bcma_find_core(bus, BCMA_CORE_PCIE); | ||
142 | if (core) { | ||
143 | bus->drv_pci.core = core; | ||
144 | bcma_core_pci_init(&bus->drv_pci); | ||
145 | } | ||
146 | |||
147 | /* Register found cores */ | ||
148 | bcma_register_cores(bus); | ||
149 | |||
150 | pr_info("Bus registered\n"); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | EXPORT_SYMBOL_GPL(bcma_bus_register); | ||
155 | |||
156 | void bcma_bus_unregister(struct bcma_bus *bus) | ||
157 | { | ||
158 | bcma_unregister_cores(bus); | ||
159 | } | ||
160 | EXPORT_SYMBOL_GPL(bcma_bus_unregister); | ||
161 | |||
162 | int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) | ||
163 | { | ||
164 | drv->drv.name = drv->name; | ||
165 | drv->drv.bus = &bcma_bus_type; | ||
166 | drv->drv.owner = owner; | ||
167 | |||
168 | return driver_register(&drv->drv); | ||
169 | } | ||
170 | EXPORT_SYMBOL_GPL(__bcma_driver_register); | ||
171 | |||
172 | void bcma_driver_unregister(struct bcma_driver *drv) | ||
173 | { | ||
174 | driver_unregister(&drv->drv); | ||
175 | } | ||
176 | EXPORT_SYMBOL_GPL(bcma_driver_unregister); | ||
177 | |||
178 | static int bcma_bus_match(struct device *dev, struct device_driver *drv) | ||
179 | { | ||
180 | struct bcma_device *core = container_of(dev, struct bcma_device, dev); | ||
181 | struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv); | ||
182 | const struct bcma_device_id *cid = &core->id; | ||
183 | const struct bcma_device_id *did; | ||
184 | |||
185 | for (did = adrv->id_table; did->manuf || did->id || did->rev; did++) { | ||
186 | if ((did->manuf == cid->manuf || did->manuf == BCMA_ANY_MANUF) && | ||
187 | (did->id == cid->id || did->id == BCMA_ANY_ID) && | ||
188 | (did->rev == cid->rev || did->rev == BCMA_ANY_REV) && | ||
189 | (did->class == cid->class || did->class == BCMA_ANY_CLASS)) | ||
190 | return 1; | ||
191 | } | ||
192 | return 0; | ||
193 | } | ||
194 | |||
195 | static int bcma_device_probe(struct device *dev) | ||
196 | { | ||
197 | struct bcma_device *core = container_of(dev, struct bcma_device, dev); | ||
198 | struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver, | ||
199 | drv); | ||
200 | int err = 0; | ||
201 | |||
202 | if (adrv->probe) | ||
203 | err = adrv->probe(core); | ||
204 | |||
205 | return err; | ||
206 | } | ||
207 | |||
208 | static int bcma_device_remove(struct device *dev) | ||
209 | { | ||
210 | struct bcma_device *core = container_of(dev, struct bcma_device, dev); | ||
211 | struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver, | ||
212 | drv); | ||
213 | |||
214 | if (adrv->remove) | ||
215 | adrv->remove(core); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static int __init bcma_modinit(void) | ||
221 | { | ||
222 | int err; | ||
223 | |||
224 | err = bus_register(&bcma_bus_type); | ||
225 | if (err) | ||
226 | return err; | ||
227 | |||
228 | #ifdef CONFIG_BCMA_HOST_PCI | ||
229 | err = bcma_host_pci_init(); | ||
230 | if (err) { | ||
231 | pr_err("PCI host initialization failed\n"); | ||
232 | err = 0; | ||
233 | } | ||
234 | #endif | ||
235 | |||
236 | return err; | ||
237 | } | ||
238 | fs_initcall(bcma_modinit); | ||
239 | |||
240 | static void __exit bcma_modexit(void) | ||
241 | { | ||
242 | #ifdef CONFIG_BCMA_HOST_PCI | ||
243 | bcma_host_pci_exit(); | ||
244 | #endif | ||
245 | bus_unregister(&bcma_bus_type); | ||
246 | } | ||
247 | module_exit(bcma_modexit) | ||
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c new file mode 100644 index 000000000000..40d7dcce8933 --- /dev/null +++ b/drivers/bcma/scan.c | |||
@@ -0,0 +1,360 @@ | |||
1 | /* | ||
2 | * Broadcom specific AMBA | ||
3 | * Bus scanning | ||
4 | * | ||
5 | * Licensed under the GNU/GPL. See COPYING for details. | ||
6 | */ | ||
7 | |||
8 | #include "scan.h" | ||
9 | #include "bcma_private.h" | ||
10 | |||
11 | #include <linux/bcma/bcma.h> | ||
12 | #include <linux/bcma/bcma_regs.h> | ||
13 | #include <linux/pci.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/dma-mapping.h> | ||
16 | #include <linux/slab.h> | ||
17 | |||
18 | struct bcma_device_id_name { | ||
19 | u16 id; | ||
20 | const char *name; | ||
21 | }; | ||
22 | struct bcma_device_id_name bcma_device_names[] = { | ||
23 | { BCMA_CORE_OOB_ROUTER, "OOB Router" }, | ||
24 | { BCMA_CORE_INVALID, "Invalid" }, | ||
25 | { BCMA_CORE_CHIPCOMMON, "ChipCommon" }, | ||
26 | { BCMA_CORE_ILINE20, "ILine 20" }, | ||
27 | { BCMA_CORE_SRAM, "SRAM" }, | ||
28 | { BCMA_CORE_SDRAM, "SDRAM" }, | ||
29 | { BCMA_CORE_PCI, "PCI" }, | ||
30 | { BCMA_CORE_MIPS, "MIPS" }, | ||
31 | { BCMA_CORE_ETHERNET, "Fast Ethernet" }, | ||
32 | { BCMA_CORE_V90, "V90" }, | ||
33 | { BCMA_CORE_USB11_HOSTDEV, "USB 1.1 Hostdev" }, | ||
34 | { BCMA_CORE_ADSL, "ADSL" }, | ||
35 | { BCMA_CORE_ILINE100, "ILine 100" }, | ||
36 | { BCMA_CORE_IPSEC, "IPSEC" }, | ||
37 | { BCMA_CORE_UTOPIA, "UTOPIA" }, | ||
38 | { BCMA_CORE_PCMCIA, "PCMCIA" }, | ||
39 | { BCMA_CORE_INTERNAL_MEM, "Internal Memory" }, | ||
40 | { BCMA_CORE_MEMC_SDRAM, "MEMC SDRAM" }, | ||
41 | { BCMA_CORE_OFDM, "OFDM" }, | ||
42 | { BCMA_CORE_EXTIF, "EXTIF" }, | ||
43 | { BCMA_CORE_80211, "IEEE 802.11" }, | ||
44 | { BCMA_CORE_PHY_A, "PHY A" }, | ||
45 | { BCMA_CORE_PHY_B, "PHY B" }, | ||
46 | { BCMA_CORE_PHY_G, "PHY G" }, | ||
47 | { BCMA_CORE_MIPS_3302, "MIPS 3302" }, | ||
48 | { BCMA_CORE_USB11_HOST, "USB 1.1 Host" }, | ||
49 | { BCMA_CORE_USB11_DEV, "USB 1.1 Device" }, | ||
50 | { BCMA_CORE_USB20_HOST, "USB 2.0 Host" }, | ||
51 | { BCMA_CORE_USB20_DEV, "USB 2.0 Device" }, | ||
52 | { BCMA_CORE_SDIO_HOST, "SDIO Host" }, | ||
53 | { BCMA_CORE_ROBOSWITCH, "Roboswitch" }, | ||
54 | { BCMA_CORE_PARA_ATA, "PATA" }, | ||
55 | { BCMA_CORE_SATA_XORDMA, "SATA XOR-DMA" }, | ||
56 | { BCMA_CORE_ETHERNET_GBIT, "GBit Ethernet" }, | ||
57 | { BCMA_CORE_PCIE, "PCIe" }, | ||
58 | { BCMA_CORE_PHY_N, "PHY N" }, | ||
59 | { BCMA_CORE_SRAM_CTL, "SRAM Controller" }, | ||
60 | { BCMA_CORE_MINI_MACPHY, "Mini MACPHY" }, | ||
61 | { BCMA_CORE_ARM_1176, "ARM 1176" }, | ||
62 | { BCMA_CORE_ARM_7TDMI, "ARM 7TDMI" }, | ||
63 | { BCMA_CORE_PHY_LP, "PHY LP" }, | ||
64 | { BCMA_CORE_PMU, "PMU" }, | ||
65 | { BCMA_CORE_PHY_SSN, "PHY SSN" }, | ||
66 | { BCMA_CORE_SDIO_DEV, "SDIO Device" }, | ||
67 | { BCMA_CORE_ARM_CM3, "ARM CM3" }, | ||
68 | { BCMA_CORE_PHY_HT, "PHY HT" }, | ||
69 | { BCMA_CORE_MIPS_74K, "MIPS 74K" }, | ||
70 | { BCMA_CORE_MAC_GBIT, "GBit MAC" }, | ||
71 | { BCMA_CORE_DDR12_MEM_CTL, "DDR1/DDR2 Memory Controller" }, | ||
72 | { BCMA_CORE_PCIE_RC, "PCIe Root Complex" }, | ||
73 | { BCMA_CORE_OCP_OCP_BRIDGE, "OCP to OCP Bridge" }, | ||
74 | { BCMA_CORE_SHARED_COMMON, "Common Shared" }, | ||
75 | { BCMA_CORE_OCP_AHB_BRIDGE, "OCP to AHB Bridge" }, | ||
76 | { BCMA_CORE_SPI_HOST, "SPI Host" }, | ||
77 | { BCMA_CORE_I2S, "I2S" }, | ||
78 | { BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" }, | ||
79 | { BCMA_CORE_SHIM, "SHIM" }, | ||
80 | { BCMA_CORE_DEFAULT, "Default" }, | ||
81 | }; | ||
82 | const char *bcma_device_name(struct bcma_device_id *id) | ||
83 | { | ||
84 | int i; | ||
85 | |||
86 | if (id->manuf == BCMA_MANUF_BCM) { | ||
87 | for (i = 0; i < ARRAY_SIZE(bcma_device_names); i++) { | ||
88 | if (bcma_device_names[i].id == id->id) | ||
89 | return bcma_device_names[i].name; | ||
90 | } | ||
91 | } | ||
92 | return "UNKNOWN"; | ||
93 | } | ||
94 | |||
95 | static u32 bcma_scan_read32(struct bcma_bus *bus, u8 current_coreidx, | ||
96 | u16 offset) | ||
97 | { | ||
98 | return readl(bus->mmio + offset); | ||
99 | } | ||
100 | |||
101 | static void bcma_scan_switch_core(struct bcma_bus *bus, u32 addr) | ||
102 | { | ||
103 | if (bus->hosttype == BCMA_HOSTTYPE_PCI) | ||
104 | pci_write_config_dword(bus->host_pci, BCMA_PCI_BAR0_WIN, | ||
105 | addr); | ||
106 | } | ||
107 | |||
108 | static u32 bcma_erom_get_ent(struct bcma_bus *bus, u32 **eromptr) | ||
109 | { | ||
110 | u32 ent = readl(*eromptr); | ||
111 | (*eromptr)++; | ||
112 | return ent; | ||
113 | } | ||
114 | |||
115 | static void bcma_erom_push_ent(u32 **eromptr) | ||
116 | { | ||
117 | (*eromptr)--; | ||
118 | } | ||
119 | |||
120 | static s32 bcma_erom_get_ci(struct bcma_bus *bus, u32 **eromptr) | ||
121 | { | ||
122 | u32 ent = bcma_erom_get_ent(bus, eromptr); | ||
123 | if (!(ent & SCAN_ER_VALID)) | ||
124 | return -ENOENT; | ||
125 | if ((ent & SCAN_ER_TAG) != SCAN_ER_TAG_CI) | ||
126 | return -ENOENT; | ||
127 | return ent; | ||
128 | } | ||
129 | |||
130 | static bool bcma_erom_is_end(struct bcma_bus *bus, u32 **eromptr) | ||
131 | { | ||
132 | u32 ent = bcma_erom_get_ent(bus, eromptr); | ||
133 | bcma_erom_push_ent(eromptr); | ||
134 | return (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID)); | ||
135 | } | ||
136 | |||
137 | static bool bcma_erom_is_bridge(struct bcma_bus *bus, u32 **eromptr) | ||
138 | { | ||
139 | u32 ent = bcma_erom_get_ent(bus, eromptr); | ||
140 | bcma_erom_push_ent(eromptr); | ||
141 | return (((ent & SCAN_ER_VALID)) && | ||
142 | ((ent & SCAN_ER_TAGX) == SCAN_ER_TAG_ADDR) && | ||
143 | ((ent & SCAN_ADDR_TYPE) == SCAN_ADDR_TYPE_BRIDGE)); | ||
144 | } | ||
145 | |||
146 | static void bcma_erom_skip_component(struct bcma_bus *bus, u32 **eromptr) | ||
147 | { | ||
148 | u32 ent; | ||
149 | while (1) { | ||
150 | ent = bcma_erom_get_ent(bus, eromptr); | ||
151 | if ((ent & SCAN_ER_VALID) && | ||
152 | ((ent & SCAN_ER_TAG) == SCAN_ER_TAG_CI)) | ||
153 | break; | ||
154 | if (ent == (SCAN_ER_TAG_END | SCAN_ER_VALID)) | ||
155 | break; | ||
156 | } | ||
157 | bcma_erom_push_ent(eromptr); | ||
158 | } | ||
159 | |||
160 | static s32 bcma_erom_get_mst_port(struct bcma_bus *bus, u32 **eromptr) | ||
161 | { | ||
162 | u32 ent = bcma_erom_get_ent(bus, eromptr); | ||
163 | if (!(ent & SCAN_ER_VALID)) | ||
164 | return -ENOENT; | ||
165 | if ((ent & SCAN_ER_TAG) != SCAN_ER_TAG_MP) | ||
166 | return -ENOENT; | ||
167 | return ent; | ||
168 | } | ||
169 | |||
170 | static s32 bcma_erom_get_addr_desc(struct bcma_bus *bus, u32 **eromptr, | ||
171 | u32 type, u8 port) | ||
172 | { | ||
173 | u32 addrl, addrh, sizel, sizeh = 0; | ||
174 | u32 size; | ||
175 | |||
176 | u32 ent = bcma_erom_get_ent(bus, eromptr); | ||
177 | if ((!(ent & SCAN_ER_VALID)) || | ||
178 | ((ent & SCAN_ER_TAGX) != SCAN_ER_TAG_ADDR) || | ||
179 | ((ent & SCAN_ADDR_TYPE) != type) || | ||
180 | (((ent & SCAN_ADDR_PORT) >> SCAN_ADDR_PORT_SHIFT) != port)) { | ||
181 | bcma_erom_push_ent(eromptr); | ||
182 | return -EINVAL; | ||
183 | } | ||
184 | |||
185 | addrl = ent & SCAN_ADDR_ADDR; | ||
186 | if (ent & SCAN_ADDR_AG32) | ||
187 | addrh = bcma_erom_get_ent(bus, eromptr); | ||
188 | else | ||
189 | addrh = 0; | ||
190 | |||
191 | if ((ent & SCAN_ADDR_SZ) == SCAN_ADDR_SZ_SZD) { | ||
192 | size = bcma_erom_get_ent(bus, eromptr); | ||
193 | sizel = size & SCAN_SIZE_SZ; | ||
194 | if (size & SCAN_SIZE_SG32) | ||
195 | sizeh = bcma_erom_get_ent(bus, eromptr); | ||
196 | } else | ||
197 | sizel = SCAN_ADDR_SZ_BASE << | ||
198 | ((ent & SCAN_ADDR_SZ) >> SCAN_ADDR_SZ_SHIFT); | ||
199 | |||
200 | return addrl; | ||
201 | } | ||
202 | |||
203 | int bcma_bus_scan(struct bcma_bus *bus) | ||
204 | { | ||
205 | u32 erombase; | ||
206 | u32 __iomem *eromptr, *eromend; | ||
207 | |||
208 | s32 cia, cib; | ||
209 | u8 ports[2], wrappers[2]; | ||
210 | |||
211 | s32 tmp; | ||
212 | u8 i, j; | ||
213 | |||
214 | int err; | ||
215 | |||
216 | INIT_LIST_HEAD(&bus->cores); | ||
217 | bus->nr_cores = 0; | ||
218 | |||
219 | bcma_scan_switch_core(bus, BCMA_ADDR_BASE); | ||
220 | |||
221 | tmp = bcma_scan_read32(bus, 0, BCMA_CC_ID); | ||
222 | bus->chipinfo.id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; | ||
223 | bus->chipinfo.rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; | ||
224 | bus->chipinfo.pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; | ||
225 | |||
226 | erombase = bcma_scan_read32(bus, 0, BCMA_CC_EROM); | ||
227 | eromptr = bus->mmio; | ||
228 | eromend = eromptr + BCMA_CORE_SIZE / sizeof(u32); | ||
229 | |||
230 | bcma_scan_switch_core(bus, erombase); | ||
231 | |||
232 | while (eromptr < eromend) { | ||
233 | struct bcma_device *core = kzalloc(sizeof(*core), GFP_KERNEL); | ||
234 | if (!core) | ||
235 | return -ENOMEM; | ||
236 | INIT_LIST_HEAD(&core->list); | ||
237 | core->bus = bus; | ||
238 | |||
239 | /* get CIs */ | ||
240 | cia = bcma_erom_get_ci(bus, &eromptr); | ||
241 | if (cia < 0) { | ||
242 | bcma_erom_push_ent(&eromptr); | ||
243 | if (bcma_erom_is_end(bus, &eromptr)) | ||
244 | break; | ||
245 | err= -EILSEQ; | ||
246 | goto out; | ||
247 | } | ||
248 | cib = bcma_erom_get_ci(bus, &eromptr); | ||
249 | if (cib < 0) { | ||
250 | err= -EILSEQ; | ||
251 | goto out; | ||
252 | } | ||
253 | |||
254 | /* parse CIs */ | ||
255 | core->id.class = (cia & SCAN_CIA_CLASS) >> SCAN_CIA_CLASS_SHIFT; | ||
256 | core->id.id = (cia & SCAN_CIA_ID) >> SCAN_CIA_ID_SHIFT; | ||
257 | core->id.manuf = (cia & SCAN_CIA_MANUF) >> SCAN_CIA_MANUF_SHIFT; | ||
258 | ports[0] = (cib & SCAN_CIB_NMP) >> SCAN_CIB_NMP_SHIFT; | ||
259 | ports[1] = (cib & SCAN_CIB_NSP) >> SCAN_CIB_NSP_SHIFT; | ||
260 | wrappers[0] = (cib & SCAN_CIB_NMW) >> SCAN_CIB_NMW_SHIFT; | ||
261 | wrappers[1] = (cib & SCAN_CIB_NSW) >> SCAN_CIB_NSW_SHIFT; | ||
262 | core->id.rev = (cib & SCAN_CIB_REV) >> SCAN_CIB_REV_SHIFT; | ||
263 | |||
264 | if (((core->id.manuf == BCMA_MANUF_ARM) && | ||
265 | (core->id.id == 0xFFF)) || | ||
266 | (ports[1] == 0)) { | ||
267 | bcma_erom_skip_component(bus, &eromptr); | ||
268 | continue; | ||
269 | } | ||
270 | |||
271 | /* check if component is a core at all */ | ||
272 | if (wrappers[0] + wrappers[1] == 0) { | ||
273 | /* we could save addrl of the router | ||
274 | if (cid == BCMA_CORE_OOB_ROUTER) | ||
275 | */ | ||
276 | bcma_erom_skip_component(bus, &eromptr); | ||
277 | continue; | ||
278 | } | ||
279 | |||
280 | if (bcma_erom_is_bridge(bus, &eromptr)) { | ||
281 | bcma_erom_skip_component(bus, &eromptr); | ||
282 | continue; | ||
283 | } | ||
284 | |||
285 | /* get & parse master ports */ | ||
286 | for (i = 0; i < ports[0]; i++) { | ||
287 | u32 mst_port_d = bcma_erom_get_mst_port(bus, &eromptr); | ||
288 | if (mst_port_d < 0) { | ||
289 | err= -EILSEQ; | ||
290 | goto out; | ||
291 | } | ||
292 | } | ||
293 | |||
294 | /* get & parse slave ports */ | ||
295 | for (i = 0; i < ports[1]; i++) { | ||
296 | for (j = 0; ; j++) { | ||
297 | tmp = bcma_erom_get_addr_desc(bus, &eromptr, | ||
298 | SCAN_ADDR_TYPE_SLAVE, i); | ||
299 | if (tmp < 0) { | ||
300 | /* no more entries for port _i_ */ | ||
301 | /* pr_debug("erom: slave port %d " | ||
302 | * "has %d descriptors\n", i, j); */ | ||
303 | break; | ||
304 | } else { | ||
305 | if (i == 0 && j == 0) | ||
306 | core->addr = tmp; | ||
307 | } | ||
308 | } | ||
309 | } | ||
310 | |||
311 | /* get & parse master wrappers */ | ||
312 | for (i = 0; i < wrappers[0]; i++) { | ||
313 | for (j = 0; ; j++) { | ||
314 | tmp = bcma_erom_get_addr_desc(bus, &eromptr, | ||
315 | SCAN_ADDR_TYPE_MWRAP, i); | ||
316 | if (tmp < 0) { | ||
317 | /* no more entries for port _i_ */ | ||
318 | /* pr_debug("erom: master wrapper %d " | ||
319 | * "has %d descriptors\n", i, j); */ | ||
320 | break; | ||
321 | } else { | ||
322 | if (i == 0 && j == 0) | ||
323 | core->wrap = tmp; | ||
324 | } | ||
325 | } | ||
326 | } | ||
327 | |||
328 | /* get & parse slave wrappers */ | ||
329 | for (i = 0; i < wrappers[1]; i++) { | ||
330 | u8 hack = (ports[1] == 1) ? 0 : 1; | ||
331 | for (j = 0; ; j++) { | ||
332 | tmp = bcma_erom_get_addr_desc(bus, &eromptr, | ||
333 | SCAN_ADDR_TYPE_SWRAP, i + hack); | ||
334 | if (tmp < 0) { | ||
335 | /* no more entries for port _i_ */ | ||
336 | /* pr_debug("erom: master wrapper %d " | ||
337 | * has %d descriptors\n", i, j); */ | ||
338 | break; | ||
339 | } else { | ||
340 | if (wrappers[0] == 0 && !i && !j) | ||
341 | core->wrap = tmp; | ||
342 | } | ||
343 | } | ||
344 | } | ||
345 | |||
346 | pr_info("Core %d found: %s " | ||
347 | "(manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n", | ||
348 | bus->nr_cores, bcma_device_name(&core->id), | ||
349 | core->id.manuf, core->id.id, core->id.rev, | ||
350 | core->id.class); | ||
351 | |||
352 | core->core_index = bus->nr_cores++; | ||
353 | list_add(&core->list, &bus->cores); | ||
354 | continue; | ||
355 | out: | ||
356 | return err; | ||
357 | } | ||
358 | |||
359 | return 0; | ||
360 | } | ||
diff --git a/drivers/bcma/scan.h b/drivers/bcma/scan.h new file mode 100644 index 000000000000..113e6a66884c --- /dev/null +++ b/drivers/bcma/scan.h | |||
@@ -0,0 +1,56 @@ | |||
1 | #ifndef BCMA_SCAN_H_ | ||
2 | #define BCMA_SCAN_H_ | ||
3 | |||
4 | #define BCMA_ADDR_BASE 0x18000000 | ||
5 | #define BCMA_WRAP_BASE 0x18100000 | ||
6 | |||
7 | #define SCAN_ER_VALID 0x00000001 | ||
8 | #define SCAN_ER_TAGX 0x00000006 /* we have to ignore 0x8 bit when checking tag for SCAN_ER_TAG_ADDR */ | ||
9 | #define SCAN_ER_TAG 0x0000000E | ||
10 | #define SCAN_ER_TAG_CI 0x00000000 | ||
11 | #define SCAN_ER_TAG_MP 0x00000002 | ||
12 | #define SCAN_ER_TAG_ADDR 0x00000004 | ||
13 | #define SCAN_ER_TAG_END 0x0000000E | ||
14 | #define SCAN_ER_BAD 0xFFFFFFFF | ||
15 | |||
16 | #define SCAN_CIA_CLASS 0x000000F0 | ||
17 | #define SCAN_CIA_CLASS_SHIFT 4 | ||
18 | #define SCAN_CIA_ID 0x000FFF00 | ||
19 | #define SCAN_CIA_ID_SHIFT 8 | ||
20 | #define SCAN_CIA_MANUF 0xFFF00000 | ||
21 | #define SCAN_CIA_MANUF_SHIFT 20 | ||
22 | |||
23 | #define SCAN_CIB_NMP 0x000001F0 | ||
24 | #define SCAN_CIB_NMP_SHIFT 4 | ||
25 | #define SCAN_CIB_NSP 0x00003E00 | ||
26 | #define SCAN_CIB_NSP_SHIFT 9 | ||
27 | #define SCAN_CIB_NMW 0x0007C000 | ||
28 | #define SCAN_CIB_NMW_SHIFT 14 | ||
29 | #define SCAN_CIB_NSW 0x00F80000 | ||
30 | #define SCAN_CIB_NSW_SHIFT 17 | ||
31 | #define SCAN_CIB_REV 0xFF000000 | ||
32 | #define SCAN_CIB_REV_SHIFT 24 | ||
33 | |||
34 | #define SCAN_ADDR_AG32 0x00000008 | ||
35 | #define SCAN_ADDR_SZ 0x00000030 | ||
36 | #define SCAN_ADDR_SZ_SHIFT 4 | ||
37 | #define SCAN_ADDR_SZ_4K 0x00000000 | ||
38 | #define SCAN_ADDR_SZ_8K 0x00000010 | ||
39 | #define SCAN_ADDR_SZ_16K 0x00000020 | ||
40 | #define SCAN_ADDR_SZ_SZD 0x00000030 | ||
41 | #define SCAN_ADDR_TYPE 0x000000C0 | ||
42 | #define SCAN_ADDR_TYPE_SLAVE 0x00000000 | ||
43 | #define SCAN_ADDR_TYPE_BRIDGE 0x00000040 | ||
44 | #define SCAN_ADDR_TYPE_SWRAP 0x00000080 | ||
45 | #define SCAN_ADDR_TYPE_MWRAP 0x000000C0 | ||
46 | #define SCAN_ADDR_PORT 0x00000F00 | ||
47 | #define SCAN_ADDR_PORT_SHIFT 8 | ||
48 | #define SCAN_ADDR_ADDR 0xFFFFF000 | ||
49 | |||
50 | #define SCAN_ADDR_SZ_BASE 0x00001000 /* 4KB */ | ||
51 | |||
52 | #define SCAN_SIZE_SZ_ALIGN 0x00000FFF | ||
53 | #define SCAN_SIZE_SZ 0xFFFFF000 | ||
54 | #define SCAN_SIZE_SG32 0x00000008 | ||
55 | |||
56 | #endif /* BCMA_SCAN_H_ */ | ||
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 695d4414bd4c..6bacef368fab 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c | |||
@@ -62,6 +62,7 @@ static struct usb_device_id ath3k_table[] = { | |||
62 | 62 | ||
63 | /* Atheros AR3011 with sflash firmware*/ | 63 | /* Atheros AR3011 with sflash firmware*/ |
64 | { USB_DEVICE(0x0CF3, 0x3002) }, | 64 | { USB_DEVICE(0x0CF3, 0x3002) }, |
65 | { USB_DEVICE(0x13d3, 0x3304) }, | ||
65 | 66 | ||
66 | /* Atheros AR9285 Malbec with sflash firmware */ | 67 | /* Atheros AR9285 Malbec with sflash firmware */ |
67 | { USB_DEVICE(0x03F0, 0x311D) }, | 68 | { USB_DEVICE(0x03F0, 0x311D) }, |
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 762a5109c68a..c2de8951e3fb 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -104,6 +104,7 @@ static struct usb_device_id blacklist_table[] = { | |||
104 | 104 | ||
105 | /* Atheros 3011 with sflash firmware */ | 105 | /* Atheros 3011 with sflash firmware */ |
106 | { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE }, | 106 | { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE }, |
107 | { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE }, | ||
107 | 108 | ||
108 | /* Atheros AR9285 Malbec with sflash firmware */ | 109 | /* Atheros AR9285 Malbec with sflash firmware */ |
109 | { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, | 110 | { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 203243bacc89..22047628ccfa 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
@@ -2394,7 +2394,7 @@ ath5k_init_softc(struct ath5k_softc *sc, const struct ath_bus_ops *bus_ops) | |||
2394 | spin_lock_init(&sc->rxbuflock); | 2394 | spin_lock_init(&sc->rxbuflock); |
2395 | spin_lock_init(&sc->txbuflock); | 2395 | spin_lock_init(&sc->txbuflock); |
2396 | spin_lock_init(&sc->block); | 2396 | spin_lock_init(&sc->block); |
2397 | 2397 | spin_lock_init(&sc->irqlock); | |
2398 | 2398 | ||
2399 | /* Setup interrupt handler */ | 2399 | /* Setup interrupt handler */ |
2400 | ret = request_irq(sc->irq, ath5k_intr, IRQF_SHARED, "ath", sc); | 2400 | ret = request_irq(sc->irq, ath5k_intr, IRQF_SHARED, "ath", sc); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index c338efbccf40..7a332f16b79a 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c | |||
@@ -415,15 +415,6 @@ static void ar9002_hw_clr11n_aggr(struct ath_hw *ah, void *ds) | |||
415 | ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); | 415 | ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); |
416 | } | 416 | } |
417 | 417 | ||
418 | static void ar9002_hw_set11n_burstduration(struct ath_hw *ah, void *ds, | ||
419 | u32 burstDuration) | ||
420 | { | ||
421 | struct ar5416_desc *ads = AR5416DESC(ds); | ||
422 | |||
423 | ads->ds_ctl2 &= ~AR_BurstDur; | ||
424 | ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); | ||
425 | } | ||
426 | |||
427 | void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, | 418 | void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, |
428 | u32 size, u32 flags) | 419 | u32 size, u32 flags) |
429 | { | 420 | { |
@@ -456,6 +447,5 @@ void ar9002_hw_attach_mac_ops(struct ath_hw *ah) | |||
456 | ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle; | 447 | ops->set11n_aggr_middle = ar9002_hw_set11n_aggr_middle; |
457 | ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; | 448 | ops->set11n_aggr_last = ar9002_hw_set11n_aggr_last; |
458 | ops->clr11n_aggr = ar9002_hw_clr11n_aggr; | 449 | ops->clr11n_aggr = ar9002_hw_clr11n_aggr; |
459 | ops->set11n_burstduration = ar9002_hw_set11n_burstduration; | ||
460 | ops->set_clrdmask = ar9002_hw_set_clrdmask; | 450 | ops->set_clrdmask = ar9002_hw_set_clrdmask; |
461 | } | 451 | } |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index 7d68d61e406b..a57e963cf0dc 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c | |||
@@ -517,23 +517,7 @@ static void ar9002_hw_set_nf_limits(struct ath_hw *ah) | |||
517 | } | 517 | } |
518 | } | 518 | } |
519 | 519 | ||
520 | void ar9002_hw_attach_phy_ops(struct ath_hw *ah) | 520 | static void ar9002_hw_antdiv_comb_conf_get(struct ath_hw *ah, |
521 | { | ||
522 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | ||
523 | |||
524 | priv_ops->set_rf_regs = NULL; | ||
525 | priv_ops->rf_alloc_ext_banks = NULL; | ||
526 | priv_ops->rf_free_ext_banks = NULL; | ||
527 | priv_ops->rf_set_freq = ar9002_hw_set_channel; | ||
528 | priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate; | ||
529 | priv_ops->olc_init = ar9002_olc_init; | ||
530 | priv_ops->compute_pll_control = ar9002_hw_compute_pll_control; | ||
531 | priv_ops->do_getnf = ar9002_hw_do_getnf; | ||
532 | |||
533 | ar9002_hw_set_nf_limits(ah); | ||
534 | } | ||
535 | |||
536 | void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, | ||
537 | struct ath_hw_antcomb_conf *antconf) | 521 | struct ath_hw_antcomb_conf *antconf) |
538 | { | 522 | { |
539 | u32 regval; | 523 | u32 regval; |
@@ -545,10 +529,11 @@ void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, | |||
545 | AR_PHY_9285_ANT_DIV_ALT_LNACONF_S; | 529 | AR_PHY_9285_ANT_DIV_ALT_LNACONF_S; |
546 | antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >> | 530 | antconf->fast_div_bias = (regval & AR_PHY_9285_FAST_DIV_BIAS) >> |
547 | AR_PHY_9285_FAST_DIV_BIAS_S; | 531 | AR_PHY_9285_FAST_DIV_BIAS_S; |
532 | antconf->lna1_lna2_delta = -3; | ||
533 | antconf->div_group = 0; | ||
548 | } | 534 | } |
549 | EXPORT_SYMBOL(ath9k_hw_antdiv_comb_conf_get); | ||
550 | 535 | ||
551 | void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, | 536 | static void ar9002_hw_antdiv_comb_conf_set(struct ath_hw *ah, |
552 | struct ath_hw_antcomb_conf *antconf) | 537 | struct ath_hw_antcomb_conf *antconf) |
553 | { | 538 | { |
554 | u32 regval; | 539 | u32 regval; |
@@ -566,4 +551,23 @@ void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, | |||
566 | 551 | ||
567 | REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval); | 552 | REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regval); |
568 | } | 553 | } |
569 | EXPORT_SYMBOL(ath9k_hw_antdiv_comb_conf_set); | 554 | |
555 | void ar9002_hw_attach_phy_ops(struct ath_hw *ah) | ||
556 | { | ||
557 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | ||
558 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | ||
559 | |||
560 | priv_ops->set_rf_regs = NULL; | ||
561 | priv_ops->rf_alloc_ext_banks = NULL; | ||
562 | priv_ops->rf_free_ext_banks = NULL; | ||
563 | priv_ops->rf_set_freq = ar9002_hw_set_channel; | ||
564 | priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate; | ||
565 | priv_ops->olc_init = ar9002_olc_init; | ||
566 | priv_ops->compute_pll_control = ar9002_hw_compute_pll_control; | ||
567 | priv_ops->do_getnf = ar9002_hw_do_getnf; | ||
568 | |||
569 | ops->antdiv_comb_conf_get = ar9002_hw_antdiv_comb_conf_get; | ||
570 | ops->antdiv_comb_conf_set = ar9002_hw_antdiv_comb_conf_set; | ||
571 | |||
572 | ar9002_hw_set_nf_limits(ah); | ||
573 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index fb892e5d141a..1e220354e4be 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -652,7 +652,7 @@ static const struct ar9300_eeprom ar9300_x113 = { | |||
652 | .regDmn = { LE16(0), LE16(0x1f) }, | 652 | .regDmn = { LE16(0), LE16(0x1f) }, |
653 | .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ | 653 | .txrxMask = 0x77, /* 4 bits tx and 4 bits rx */ |
654 | .opCapFlags = { | 654 | .opCapFlags = { |
655 | .opFlags = AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A, | 655 | .opFlags = AR5416_OPFLAGS_11A, |
656 | .eepMisc = 0, | 656 | .eepMisc = 0, |
657 | }, | 657 | }, |
658 | .rfSilent = 0, | 658 | .rfSilent = 0, |
@@ -922,7 +922,7 @@ static const struct ar9300_eeprom ar9300_x113 = { | |||
922 | .db_stage2 = {3, 3, 3}, /* 3 chain */ | 922 | .db_stage2 = {3, 3, 3}, /* 3 chain */ |
923 | .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */ | 923 | .db_stage3 = {3, 3, 3}, /* doesn't exist for 2G */ |
924 | .db_stage4 = {3, 3, 3}, /* don't exist for 2G */ | 924 | .db_stage4 = {3, 3, 3}, /* don't exist for 2G */ |
925 | .xpaBiasLvl = 0, | 925 | .xpaBiasLvl = 0xf, |
926 | .txFrameToDataStart = 0x0e, | 926 | .txFrameToDataStart = 0x0e, |
927 | .txFrameToPaOn = 0x0e, | 927 | .txFrameToPaOn = 0x0e, |
928 | .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ | 928 | .txClip = 3, /* 4 bits tx_clip, 4 bits dac_scale_cck */ |
@@ -3442,17 +3442,15 @@ static void ar9003_hw_xpa_bias_level_apply(struct ath_hw *ah, bool is2ghz) | |||
3442 | { | 3442 | { |
3443 | int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz); | 3443 | int bias = ar9003_hw_xpa_bias_level_get(ah, is2ghz); |
3444 | 3444 | ||
3445 | if (AR_SREV_9485(ah)) | 3445 | if (AR_SREV_9485(ah) || AR_SREV_9340(ah)) |
3446 | REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias); | 3446 | REG_RMW_FIELD(ah, AR_CH0_TOP2, AR_CH0_TOP2_XPABIASLVL, bias); |
3447 | else { | 3447 | else { |
3448 | REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); | 3448 | REG_RMW_FIELD(ah, AR_CH0_TOP, AR_CH0_TOP_XPABIASLVL, bias); |
3449 | if (!AR_SREV_9340(ah)) { | 3449 | REG_RMW_FIELD(ah, AR_CH0_THERM, |
3450 | REG_RMW_FIELD(ah, AR_CH0_THERM, | 3450 | AR_CH0_THERM_XPABIASLVL_MSB, |
3451 | AR_CH0_THERM_XPABIASLVL_MSB, | 3451 | bias >> 2); |
3452 | bias >> 2); | 3452 | REG_RMW_FIELD(ah, AR_CH0_THERM, |
3453 | REG_RMW_FIELD(ah, AR_CH0_THERM, | 3453 | AR_CH0_THERM_XPASHORT2GND, 1); |
3454 | AR_CH0_THERM_XPASHORT2GND, 1); | ||
3455 | } | ||
3456 | } | 3454 | } |
3457 | } | 3455 | } |
3458 | 3456 | ||
@@ -3500,6 +3498,8 @@ static u16 ar9003_hw_ant_ctrl_chain_get(struct ath_hw *ah, | |||
3500 | static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | 3498 | static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) |
3501 | { | 3499 | { |
3502 | int chain; | 3500 | int chain; |
3501 | u32 regval; | ||
3502 | u32 ant_div_ctl1; | ||
3503 | static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = { | 3503 | static const u32 switch_chain_reg[AR9300_MAX_CHAINS] = { |
3504 | AR_PHY_SWITCH_CHAIN_0, | 3504 | AR_PHY_SWITCH_CHAIN_0, |
3505 | AR_PHY_SWITCH_CHAIN_1, | 3505 | AR_PHY_SWITCH_CHAIN_1, |
@@ -3525,13 +3525,49 @@ static void ar9003_hw_ant_ctrl_apply(struct ath_hw *ah, bool is2ghz) | |||
3525 | 3525 | ||
3526 | if (AR_SREV_9485(ah)) { | 3526 | if (AR_SREV_9485(ah)) { |
3527 | value = ath9k_hw_ar9300_get_eeprom(ah, EEP_ANT_DIV_CTL1); | 3527 | value = ath9k_hw_ar9300_get_eeprom(ah, EEP_ANT_DIV_CTL1); |
3528 | REG_RMW_FIELD(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_CTRL_ALL, | 3528 | /* |
3529 | value); | 3529 | * main_lnaconf, alt_lnaconf, main_tb, alt_tb |
3530 | REG_RMW_FIELD(ah, AR_PHY_MC_GAIN_CTRL, AR_ANT_DIV_ENABLE, | 3530 | * are the fields present |
3531 | value >> 6); | 3531 | */ |
3532 | REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, AR_FAST_DIV_ENABLE, | 3532 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); |
3533 | value >> 7); | 3533 | regval &= (~AR_ANT_DIV_CTRL_ALL); |
3534 | regval |= (value & 0x3f) << AR_ANT_DIV_CTRL_ALL_S; | ||
3535 | /* enable_lnadiv */ | ||
3536 | regval &= (~AR_PHY_9485_ANT_DIV_LNADIV); | ||
3537 | regval |= ((value >> 6) & 0x1) << | ||
3538 | AR_PHY_9485_ANT_DIV_LNADIV_S; | ||
3539 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | ||
3540 | |||
3541 | /*enable fast_div */ | ||
3542 | regval = REG_READ(ah, AR_PHY_CCK_DETECT); | ||
3543 | regval &= (~AR_FAST_DIV_ENABLE); | ||
3544 | regval |= ((value >> 7) & 0x1) << | ||
3545 | AR_FAST_DIV_ENABLE_S; | ||
3546 | REG_WRITE(ah, AR_PHY_CCK_DETECT, regval); | ||
3547 | ant_div_ctl1 = | ||
3548 | ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); | ||
3549 | /* check whether antenna diversity is enabled */ | ||
3550 | if ((ant_div_ctl1 >> 0x6) == 0x3) { | ||
3551 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); | ||
3552 | /* | ||
3553 | * clear bits 25-30 main_lnaconf, alt_lnaconf, | ||
3554 | * main_tb, alt_tb | ||
3555 | */ | ||
3556 | regval &= (~(AR_PHY_9485_ANT_DIV_MAIN_LNACONF | | ||
3557 | AR_PHY_9485_ANT_DIV_ALT_LNACONF | | ||
3558 | AR_PHY_9485_ANT_DIV_ALT_GAINTB | | ||
3559 | AR_PHY_9485_ANT_DIV_MAIN_GAINTB)); | ||
3560 | /* by default use LNA1 for the main antenna */ | ||
3561 | regval |= (AR_PHY_9485_ANT_DIV_LNA1 << | ||
3562 | AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S); | ||
3563 | regval |= (AR_PHY_9485_ANT_DIV_LNA2 << | ||
3564 | AR_PHY_9485_ANT_DIV_ALT_LNACONF_S); | ||
3565 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | ||
3566 | } | ||
3567 | |||
3568 | |||
3534 | } | 3569 | } |
3570 | |||
3535 | } | 3571 | } |
3536 | 3572 | ||
3537 | static void ar9003_hw_drive_strength_apply(struct ath_hw *ah) | 3573 | static void ar9003_hw_drive_strength_apply(struct ath_hw *ah) |
@@ -4005,6 +4041,16 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray) | |||
4005 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0) | 4041 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0) |
4006 | ); | 4042 | ); |
4007 | 4043 | ||
4044 | /* Write the power for duplicated frames - HT40 */ | ||
4045 | |||
4046 | /* dup40_cck (LSB), dup40_ofdm, ext20_cck, ext20_ofdm (MSB) */ | ||
4047 | REG_WRITE(ah, 0xa3e0, | ||
4048 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) | | ||
4049 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) | | ||
4050 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) | | ||
4051 | POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0) | ||
4052 | ); | ||
4053 | |||
4008 | /* Write the HT20 power per rate set */ | 4054 | /* Write the HT20 power per rate set */ |
4009 | 4055 | ||
4010 | /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */ | 4056 | /* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */ |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index c1264d60c499..be6adec33ddb 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c | |||
@@ -484,16 +484,6 @@ static void ar9003_hw_clr11n_aggr(struct ath_hw *ah, void *ds) | |||
484 | ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr); | 484 | ads->ctl12 &= (~AR_IsAggr & ~AR_MoreAggr); |
485 | } | 485 | } |
486 | 486 | ||
487 | static void ar9003_hw_set11n_burstduration(struct ath_hw *ah, void *ds, | ||
488 | u32 burstDuration) | ||
489 | { | ||
490 | struct ar9003_txc *ads = (struct ar9003_txc *) ds; | ||
491 | |||
492 | ads->ctl13 &= ~AR_BurstDur; | ||
493 | ads->ctl13 |= SM(burstDuration, AR_BurstDur); | ||
494 | |||
495 | } | ||
496 | |||
497 | void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains) | 487 | void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains) |
498 | { | 488 | { |
499 | struct ar9003_txc *ads = ds; | 489 | struct ar9003_txc *ads = ds; |
@@ -518,7 +508,6 @@ void ar9003_hw_attach_mac_ops(struct ath_hw *hw) | |||
518 | ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle; | 508 | ops->set11n_aggr_middle = ar9003_hw_set11n_aggr_middle; |
519 | ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; | 509 | ops->set11n_aggr_last = ar9003_hw_set11n_aggr_last; |
520 | ops->clr11n_aggr = ar9003_hw_clr11n_aggr; | 510 | ops->clr11n_aggr = ar9003_hw_clr11n_aggr; |
521 | ops->set11n_burstduration = ar9003_hw_set11n_burstduration; | ||
522 | ops->set_clrdmask = ar9003_hw_set_clrdmask; | 511 | ops->set_clrdmask = ar9003_hw_set_clrdmask; |
523 | } | 512 | } |
524 | 513 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index c83be2dd5718..25f3c2fdf2bc 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -1184,9 +1184,52 @@ static void ar9003_hw_set_radar_conf(struct ath_hw *ah) | |||
1184 | conf->radar_inband = 8; | 1184 | conf->radar_inband = 8; |
1185 | } | 1185 | } |
1186 | 1186 | ||
1187 | static void ar9003_hw_antdiv_comb_conf_get(struct ath_hw *ah, | ||
1188 | struct ath_hw_antcomb_conf *antconf) | ||
1189 | { | ||
1190 | u32 regval; | ||
1191 | |||
1192 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); | ||
1193 | antconf->main_lna_conf = (regval & AR_PHY_9485_ANT_DIV_MAIN_LNACONF) >> | ||
1194 | AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S; | ||
1195 | antconf->alt_lna_conf = (regval & AR_PHY_9485_ANT_DIV_ALT_LNACONF) >> | ||
1196 | AR_PHY_9485_ANT_DIV_ALT_LNACONF_S; | ||
1197 | antconf->fast_div_bias = (regval & AR_PHY_9485_ANT_FAST_DIV_BIAS) >> | ||
1198 | AR_PHY_9485_ANT_FAST_DIV_BIAS_S; | ||
1199 | antconf->lna1_lna2_delta = -9; | ||
1200 | antconf->div_group = 2; | ||
1201 | } | ||
1202 | |||
1203 | static void ar9003_hw_antdiv_comb_conf_set(struct ath_hw *ah, | ||
1204 | struct ath_hw_antcomb_conf *antconf) | ||
1205 | { | ||
1206 | u32 regval; | ||
1207 | |||
1208 | regval = REG_READ(ah, AR_PHY_MC_GAIN_CTRL); | ||
1209 | regval &= ~(AR_PHY_9485_ANT_DIV_MAIN_LNACONF | | ||
1210 | AR_PHY_9485_ANT_DIV_ALT_LNACONF | | ||
1211 | AR_PHY_9485_ANT_FAST_DIV_BIAS | | ||
1212 | AR_PHY_9485_ANT_DIV_MAIN_GAINTB | | ||
1213 | AR_PHY_9485_ANT_DIV_ALT_GAINTB); | ||
1214 | regval |= ((antconf->main_lna_conf << | ||
1215 | AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S) | ||
1216 | & AR_PHY_9485_ANT_DIV_MAIN_LNACONF); | ||
1217 | regval |= ((antconf->alt_lna_conf << AR_PHY_9485_ANT_DIV_ALT_LNACONF_S) | ||
1218 | & AR_PHY_9485_ANT_DIV_ALT_LNACONF); | ||
1219 | regval |= ((antconf->fast_div_bias << AR_PHY_9485_ANT_FAST_DIV_BIAS_S) | ||
1220 | & AR_PHY_9485_ANT_FAST_DIV_BIAS); | ||
1221 | regval |= ((antconf->main_gaintb << AR_PHY_9485_ANT_DIV_MAIN_GAINTB_S) | ||
1222 | & AR_PHY_9485_ANT_DIV_MAIN_GAINTB); | ||
1223 | regval |= ((antconf->alt_gaintb << AR_PHY_9485_ANT_DIV_ALT_GAINTB_S) | ||
1224 | & AR_PHY_9485_ANT_DIV_ALT_GAINTB); | ||
1225 | |||
1226 | REG_WRITE(ah, AR_PHY_MC_GAIN_CTRL, regval); | ||
1227 | } | ||
1228 | |||
1187 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | 1229 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) |
1188 | { | 1230 | { |
1189 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); | 1231 | struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); |
1232 | struct ath_hw_ops *ops = ath9k_hw_ops(ah); | ||
1190 | static const u32 ar9300_cca_regs[6] = { | 1233 | static const u32 ar9300_cca_regs[6] = { |
1191 | AR_PHY_CCA_0, | 1234 | AR_PHY_CCA_0, |
1192 | AR_PHY_CCA_1, | 1235 | AR_PHY_CCA_1, |
@@ -1213,6 +1256,9 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | |||
1213 | priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs; | 1256 | priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs; |
1214 | priv_ops->set_radar_params = ar9003_hw_set_radar_params; | 1257 | priv_ops->set_radar_params = ar9003_hw_set_radar_params; |
1215 | 1258 | ||
1259 | ops->antdiv_comb_conf_get = ar9003_hw_antdiv_comb_conf_get; | ||
1260 | ops->antdiv_comb_conf_set = ar9003_hw_antdiv_comb_conf_set; | ||
1261 | |||
1216 | ar9003_hw_set_nf_limits(ah); | 1262 | ar9003_hw_set_nf_limits(ah); |
1217 | ar9003_hw_set_radar_conf(ah); | 1263 | ar9003_hw_set_radar_conf(ah); |
1218 | memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs)); | 1264 | memcpy(ah->nf_regs, ar9300_cca_regs, sizeof(ah->nf_regs)); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h index 2a0d5cbb7e76..c7505b48e5c0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h | |||
@@ -261,12 +261,34 @@ | |||
261 | #define AR_PHY_EXT_CCA0 (AR_AGC_BASE + 0x20) | 261 | #define AR_PHY_EXT_CCA0 (AR_AGC_BASE + 0x20) |
262 | #define AR_PHY_RESTART (AR_AGC_BASE + 0x24) | 262 | #define AR_PHY_RESTART (AR_AGC_BASE + 0x24) |
263 | 263 | ||
264 | /* | ||
265 | * Antenna Diversity settings | ||
266 | */ | ||
264 | #define AR_PHY_MC_GAIN_CTRL (AR_AGC_BASE + 0x28) | 267 | #define AR_PHY_MC_GAIN_CTRL (AR_AGC_BASE + 0x28) |
265 | #define AR_ANT_DIV_CTRL_ALL 0x7e000000 | 268 | #define AR_ANT_DIV_CTRL_ALL 0x7e000000 |
266 | #define AR_ANT_DIV_CTRL_ALL_S 25 | 269 | #define AR_ANT_DIV_CTRL_ALL_S 25 |
267 | #define AR_ANT_DIV_ENABLE 0x1000000 | 270 | #define AR_ANT_DIV_ENABLE 0x1000000 |
268 | #define AR_ANT_DIV_ENABLE_S 24 | 271 | #define AR_ANT_DIV_ENABLE_S 24 |
269 | 272 | ||
273 | |||
274 | #define AR_PHY_9485_ANT_FAST_DIV_BIAS 0x00007e00 | ||
275 | #define AR_PHY_9485_ANT_FAST_DIV_BIAS_S 9 | ||
276 | #define AR_PHY_9485_ANT_DIV_LNADIV 0x01000000 | ||
277 | #define AR_PHY_9485_ANT_DIV_LNADIV_S 24 | ||
278 | #define AR_PHY_9485_ANT_DIV_ALT_LNACONF 0x06000000 | ||
279 | #define AR_PHY_9485_ANT_DIV_ALT_LNACONF_S 25 | ||
280 | #define AR_PHY_9485_ANT_DIV_MAIN_LNACONF 0x18000000 | ||
281 | #define AR_PHY_9485_ANT_DIV_MAIN_LNACONF_S 27 | ||
282 | #define AR_PHY_9485_ANT_DIV_ALT_GAINTB 0x20000000 | ||
283 | #define AR_PHY_9485_ANT_DIV_ALT_GAINTB_S 29 | ||
284 | #define AR_PHY_9485_ANT_DIV_MAIN_GAINTB 0x40000000 | ||
285 | #define AR_PHY_9485_ANT_DIV_MAIN_GAINTB_S 30 | ||
286 | |||
287 | #define AR_PHY_9485_ANT_DIV_LNA1_MINUS_LNA2 0x0 | ||
288 | #define AR_PHY_9485_ANT_DIV_LNA2 0x1 | ||
289 | #define AR_PHY_9485_ANT_DIV_LNA1 0x2 | ||
290 | #define AR_PHY_9485_ANT_DIV_LNA1_PLUS_LNA2 0x3 | ||
291 | |||
270 | #define AR_PHY_EXTCHN_PWRTHR1 (AR_AGC_BASE + 0x2c) | 292 | #define AR_PHY_EXTCHN_PWRTHR1 (AR_AGC_BASE + 0x2c) |
271 | #define AR_PHY_EXT_CHN_WIN (AR_AGC_BASE + 0x30) | 293 | #define AR_PHY_EXT_CHN_WIN (AR_AGC_BASE + 0x30) |
272 | #define AR_PHY_20_40_DET_THR (AR_AGC_BASE + 0x34) | 294 | #define AR_PHY_20_40_DET_THR (AR_AGC_BASE + 0x34) |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 0312aa091807..03b37d7be1c3 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -62,7 +62,6 @@ struct ath_node; | |||
62 | #define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i)) | 62 | #define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<<i)) |
63 | 63 | ||
64 | struct ath_config { | 64 | struct ath_config { |
65 | u32 ath_aggr_prot; | ||
66 | u16 txpowlimit; | 65 | u16 txpowlimit; |
67 | u8 cabqReadytime; | 66 | u8 cabqReadytime; |
68 | }; | 67 | }; |
@@ -484,7 +483,6 @@ static inline void ath_deinit_leds(struct ath_softc *sc) | |||
484 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO 30 | 483 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO 30 |
485 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20 | 484 | #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20 |
486 | 485 | ||
487 | #define ATH_ANT_DIV_COMB_LNA1_LNA2_DELTA -3 | ||
488 | #define ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA -1 | 486 | #define ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA -1 |
489 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4 | 487 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4 |
490 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_MID -2 | 488 | #define ATH_ANT_DIV_COMB_LNA1_DELTA_MID -2 |
@@ -565,6 +563,7 @@ struct ath_ant_comb { | |||
565 | #define PS_WAIT_FOR_PSPOLL_DATA BIT(2) | 563 | #define PS_WAIT_FOR_PSPOLL_DATA BIT(2) |
566 | #define PS_WAIT_FOR_TX_ACK BIT(3) | 564 | #define PS_WAIT_FOR_TX_ACK BIT(3) |
567 | #define PS_BEACON_SYNC BIT(4) | 565 | #define PS_BEACON_SYNC BIT(4) |
566 | #define PS_TSFOOR_SYNC BIT(5) | ||
568 | 567 | ||
569 | struct ath_rate_table; | 568 | struct ath_rate_table; |
570 | 569 | ||
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 22cd241a098b..637dbc5f7b67 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -620,7 +620,13 @@ static void ath_beacon_config_sta(struct ath_softc *sc, | |||
620 | ath9k_hw_disable_interrupts(ah); | 620 | ath9k_hw_disable_interrupts(ah); |
621 | ath9k_hw_set_sta_beacon_timers(ah, &bs); | 621 | ath9k_hw_set_sta_beacon_timers(ah, &bs); |
622 | ah->imask |= ATH9K_INT_BMISS; | 622 | ah->imask |= ATH9K_INT_BMISS; |
623 | ath9k_hw_set_interrupts(ah, ah->imask); | 623 | |
624 | /* | ||
625 | * If the beacon config is called beacause of TSFOOR, | ||
626 | * Interrupts will be enabled back at the end of ath9k_tasklet | ||
627 | */ | ||
628 | if (!(sc->ps_flags & PS_TSFOOR_SYNC)) | ||
629 | ath9k_hw_set_interrupts(ah, ah->imask); | ||
624 | } | 630 | } |
625 | 631 | ||
626 | static void ath_beacon_config_adhoc(struct ath_softc *sc, | 632 | static void ath_beacon_config_adhoc(struct ath_softc *sc, |
@@ -661,7 +667,12 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc, | |||
661 | ath9k_hw_disable_interrupts(ah); | 667 | ath9k_hw_disable_interrupts(ah); |
662 | ath9k_beacon_init(sc, nexttbtt, intval); | 668 | ath9k_beacon_init(sc, nexttbtt, intval); |
663 | sc->beacon.bmisscnt = 0; | 669 | sc->beacon.bmisscnt = 0; |
664 | ath9k_hw_set_interrupts(ah, ah->imask); | 670 | /* |
671 | * If the beacon config is called beacause of TSFOOR, | ||
672 | * Interrupts will be enabled back at the end of ath9k_tasklet | ||
673 | */ | ||
674 | if (!(sc->ps_flags & PS_TSFOOR_SYNC)) | ||
675 | ath9k_hw_set_interrupts(ah, ah->imask); | ||
665 | } | 676 | } |
666 | 677 | ||
667 | static bool ath9k_allow_beacon_config(struct ath_softc *sc, | 678 | static bool ath9k_allow_beacon_config(struct ath_softc *sc, |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 8649581fa4dd..558b228a717f 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -69,15 +69,21 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, | |||
69 | int16_t *nfarray) | 69 | int16_t *nfarray) |
70 | { | 70 | { |
71 | struct ath_common *common = ath9k_hw_common(ah); | 71 | struct ath_common *common = ath9k_hw_common(ah); |
72 | struct ieee80211_conf *conf = &common->hw->conf; | ||
72 | struct ath_nf_limits *limit; | 73 | struct ath_nf_limits *limit; |
73 | struct ath9k_nfcal_hist *h; | 74 | struct ath9k_nfcal_hist *h; |
74 | bool high_nf_mid = false; | 75 | bool high_nf_mid = false; |
76 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; | ||
75 | int i; | 77 | int i; |
76 | 78 | ||
77 | h = cal->nfCalHist; | 79 | h = cal->nfCalHist; |
78 | limit = ath9k_hw_get_nf_limits(ah, ah->curchan); | 80 | limit = ath9k_hw_get_nf_limits(ah, ah->curchan); |
79 | 81 | ||
80 | for (i = 0; i < NUM_NF_READINGS; i++) { | 82 | for (i = 0; i < NUM_NF_READINGS; i++) { |
83 | if (!(chainmask & (1 << i)) || | ||
84 | ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))) | ||
85 | continue; | ||
86 | |||
81 | h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; | 87 | h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; |
82 | 88 | ||
83 | if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX) | 89 | if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX) |
@@ -225,6 +231,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
225 | int32_t val; | 231 | int32_t val; |
226 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; | 232 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; |
227 | struct ath_common *common = ath9k_hw_common(ah); | 233 | struct ath_common *common = ath9k_hw_common(ah); |
234 | struct ieee80211_conf *conf = &common->hw->conf; | ||
228 | s16 default_nf = ath9k_hw_get_default_nf(ah, chan); | 235 | s16 default_nf = ath9k_hw_get_default_nf(ah, chan); |
229 | 236 | ||
230 | if (ah->caldata) | 237 | if (ah->caldata) |
@@ -234,6 +241,9 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
234 | if (chainmask & (1 << i)) { | 241 | if (chainmask & (1 << i)) { |
235 | s16 nfval; | 242 | s16 nfval; |
236 | 243 | ||
244 | if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)) | ||
245 | continue; | ||
246 | |||
237 | if (h) | 247 | if (h) |
238 | nfval = h[i].privNF; | 248 | nfval = h[i].privNF; |
239 | else | 249 | else |
@@ -293,6 +303,9 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
293 | ENABLE_REGWRITE_BUFFER(ah); | 303 | ENABLE_REGWRITE_BUFFER(ah); |
294 | for (i = 0; i < NUM_NF_READINGS; i++) { | 304 | for (i = 0; i < NUM_NF_READINGS; i++) { |
295 | if (chainmask & (1 << i)) { | 305 | if (chainmask & (1 << i)) { |
306 | if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)) | ||
307 | continue; | ||
308 | |||
296 | val = REG_READ(ah, ah->nf_regs[i]); | 309 | val = REG_READ(ah, ah->nf_regs[i]); |
297 | val &= 0xFFFFFE00; | 310 | val &= 0xFFFFFE00; |
298 | val |= (((u32) (-50) << 1) & 0x1ff); | 311 | val |= (((u32) (-50) << 1) & 0x1ff); |
@@ -396,14 +409,6 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | |||
396 | } | 409 | } |
397 | } | 410 | } |
398 | 411 | ||
399 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) | ||
400 | { | ||
401 | if (!ah->curchan || !ah->curchan->noisefloor) | ||
402 | return ath9k_hw_get_default_nf(ah, chan); | ||
403 | |||
404 | return ah->curchan->noisefloor; | ||
405 | } | ||
406 | EXPORT_SYMBOL(ath9k_hw_getchan_noise); | ||
407 | 412 | ||
408 | void ath9k_hw_bstuck_nfcal(struct ath_hw *ah) | 413 | void ath9k_hw_bstuck_nfcal(struct ath_hw *ah) |
409 | { | 414 | { |
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index b8973eb8d858..4420780fa3b8 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h | |||
@@ -106,7 +106,6 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); | |||
106 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | 106 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, |
107 | struct ath9k_channel *chan); | 107 | struct ath9k_channel *chan); |
108 | void ath9k_hw_bstuck_nfcal(struct ath_hw *ah); | 108 | void ath9k_hw_bstuck_nfcal(struct ath_hw *ah); |
109 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); | ||
110 | void ath9k_hw_reset_calibration(struct ath_hw *ah, | 109 | void ath9k_hw_reset_calibration(struct ath_hw *ah, |
111 | struct ath9k_cal_list *currCal); | 110 | struct ath9k_cal_list *currCal); |
112 | 111 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 9dd90a85ad63..8b8f0445aef8 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -116,15 +116,21 @@ static inline void ath9k_hw_clr11n_aggr(struct ath_hw *ah, void *ds) | |||
116 | ath9k_hw_ops(ah)->clr11n_aggr(ah, ds); | 116 | ath9k_hw_ops(ah)->clr11n_aggr(ah, ds); |
117 | } | 117 | } |
118 | 118 | ||
119 | static inline void ath9k_hw_set11n_burstduration(struct ath_hw *ah, void *ds, | 119 | static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) |
120 | u32 burstDuration) | ||
121 | { | 120 | { |
122 | ath9k_hw_ops(ah)->set11n_burstduration(ah, ds, burstDuration); | 121 | ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val); |
123 | } | 122 | } |
124 | 123 | ||
125 | static inline void ath9k_hw_set_clrdmask(struct ath_hw *ah, void *ds, bool val) | 124 | static inline void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, |
125 | struct ath_hw_antcomb_conf *antconf) | ||
126 | { | 126 | { |
127 | ath9k_hw_ops(ah)->set_clrdmask(ah, ds, val); | 127 | ath9k_hw_ops(ah)->antdiv_comb_conf_get(ah, antconf); |
128 | } | ||
129 | |||
130 | static inline void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, | ||
131 | struct ath_hw_antcomb_conf *antconf) | ||
132 | { | ||
133 | ath9k_hw_ops(ah)->antdiv_comb_conf_set(ah, antconf); | ||
128 | } | 134 | } |
129 | 135 | ||
130 | /* Private hardware call ops */ | 136 | /* Private hardware call ops */ |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 58f3d4210338..b75b5dca4e29 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -2022,6 +2022,22 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2022 | } | 2022 | } |
2023 | 2023 | ||
2024 | 2024 | ||
2025 | if (AR_SREV_9485(ah)) { | ||
2026 | ant_div_ctl1 = ah->eep_ops->get_eeprom(ah, EEP_ANT_DIV_CTL1); | ||
2027 | /* | ||
2028 | * enable the diversity-combining algorithm only when | ||
2029 | * both enable_lna_div and enable_fast_div are set | ||
2030 | * Table for Diversity | ||
2031 | * ant_div_alt_lnaconf bit 0-1 | ||
2032 | * ant_div_main_lnaconf bit 2-3 | ||
2033 | * ant_div_alt_gaintb bit 4 | ||
2034 | * ant_div_main_gaintb bit 5 | ||
2035 | * enable_ant_div_lnadiv bit 6 | ||
2036 | * enable_ant_fast_div bit 7 | ||
2037 | */ | ||
2038 | if ((ant_div_ctl1 >> 0x6) == 0x3) | ||
2039 | pCap->hw_caps |= ATH9K_HW_CAP_ANT_DIV_COMB; | ||
2040 | } | ||
2025 | 2041 | ||
2026 | if (AR_SREV_9485_10(ah)) { | 2042 | if (AR_SREV_9485_10(ah)) { |
2027 | pCap->pcie_lcr_extsync_en = true; | 2043 | pCap->pcie_lcr_extsync_en = true; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 34ed1bd0e855..7af2773d2bfc 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -479,6 +479,10 @@ struct ath_hw_antcomb_conf { | |||
479 | u8 main_lna_conf; | 479 | u8 main_lna_conf; |
480 | u8 alt_lna_conf; | 480 | u8 alt_lna_conf; |
481 | u8 fast_div_bias; | 481 | u8 fast_div_bias; |
482 | u8 main_gaintb; | ||
483 | u8 alt_gaintb; | ||
484 | int lna1_lna2_delta; | ||
485 | u8 div_group; | ||
482 | }; | 486 | }; |
483 | 487 | ||
484 | /** | 488 | /** |
@@ -628,9 +632,12 @@ struct ath_hw_ops { | |||
628 | u32 numDelims); | 632 | u32 numDelims); |
629 | void (*set11n_aggr_last)(struct ath_hw *ah, void *ds); | 633 | void (*set11n_aggr_last)(struct ath_hw *ah, void *ds); |
630 | void (*clr11n_aggr)(struct ath_hw *ah, void *ds); | 634 | void (*clr11n_aggr)(struct ath_hw *ah, void *ds); |
631 | void (*set11n_burstduration)(struct ath_hw *ah, void *ds, | ||
632 | u32 burstDuration); | ||
633 | void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val); | 635 | void (*set_clrdmask)(struct ath_hw *ah, void *ds, bool val); |
636 | void (*antdiv_comb_conf_get)(struct ath_hw *ah, | ||
637 | struct ath_hw_antcomb_conf *antconf); | ||
638 | void (*antdiv_comb_conf_set)(struct ath_hw *ah, | ||
639 | struct ath_hw_antcomb_conf *antconf); | ||
640 | |||
634 | }; | 641 | }; |
635 | 642 | ||
636 | struct ath_nf_limits { | 643 | struct ath_nf_limits { |
@@ -906,10 +913,6 @@ void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, | |||
906 | void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val); | 913 | void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val); |
907 | u32 ath9k_hw_getdefantenna(struct ath_hw *ah); | 914 | u32 ath9k_hw_getdefantenna(struct ath_hw *ah); |
908 | void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna); | 915 | void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna); |
909 | void ath9k_hw_antdiv_comb_conf_get(struct ath_hw *ah, | ||
910 | struct ath_hw_antcomb_conf *antconf); | ||
911 | void ath9k_hw_antdiv_comb_conf_set(struct ath_hw *ah, | ||
912 | struct ath_hw_antcomb_conf *antconf); | ||
913 | 916 | ||
914 | /* General Operation */ | 917 | /* General Operation */ |
915 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); | 918 | bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); |
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 9cf7a7d0e118..bd6d2b9d736f 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c | |||
@@ -430,8 +430,13 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) | |||
430 | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)); | 430 | SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)); |
431 | 431 | ||
432 | REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ); | 432 | REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ); |
433 | REG_WRITE(ah, AR_DMISC(q), | 433 | |
434 | AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2); | 434 | if (AR_SREV_9340(ah)) |
435 | REG_WRITE(ah, AR_DMISC(q), | ||
436 | AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1); | ||
437 | else | ||
438 | REG_WRITE(ah, AR_DMISC(q), | ||
439 | AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2); | ||
435 | 440 | ||
436 | if (qi->tqi_cbrPeriod) { | 441 | if (qi->tqi_cbrPeriod) { |
437 | REG_WRITE(ah, AR_QCBRCFG(q), | 442 | REG_WRITE(ah, AR_QCBRCFG(q), |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index c3dbf2661a3f..45303bdbc465 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -689,6 +689,17 @@ void ath9k_tasklet(unsigned long data) | |||
689 | !ath9k_hw_check_alive(ah)) | 689 | !ath9k_hw_check_alive(ah)) |
690 | ieee80211_queue_work(sc->hw, &sc->hw_check_work); | 690 | ieee80211_queue_work(sc->hw, &sc->hw_check_work); |
691 | 691 | ||
692 | if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { | ||
693 | /* | ||
694 | * TSF sync does not look correct; remain awake to sync with | ||
695 | * the next Beacon. | ||
696 | */ | ||
697 | ath_dbg(common, ATH_DBG_PS, | ||
698 | "TSFOOR - Sync with next Beacon\n"); | ||
699 | sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC | | ||
700 | PS_TSFOOR_SYNC; | ||
701 | } | ||
702 | |||
692 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | 703 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) |
693 | rxmask = (ATH9K_INT_RXHP | ATH9K_INT_RXLP | ATH9K_INT_RXEOL | | 704 | rxmask = (ATH9K_INT_RXHP | ATH9K_INT_RXLP | ATH9K_INT_RXEOL | |
694 | ATH9K_INT_RXORN); | 705 | ATH9K_INT_RXORN); |
@@ -711,16 +722,6 @@ void ath9k_tasklet(unsigned long data) | |||
711 | ath_tx_tasklet(sc); | 722 | ath_tx_tasklet(sc); |
712 | } | 723 | } |
713 | 724 | ||
714 | if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { | ||
715 | /* | ||
716 | * TSF sync does not look correct; remain awake to sync with | ||
717 | * the next Beacon. | ||
718 | */ | ||
719 | ath_dbg(common, ATH_DBG_PS, | ||
720 | "TSFOOR - Sync with next Beacon\n"); | ||
721 | sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC; | ||
722 | } | ||
723 | |||
724 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) | 725 | if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) |
725 | if (status & ATH9K_INT_GENTIMER) | 726 | if (status & ATH9K_INT_GENTIMER) |
726 | ath_gen_timer_isr(sc->sc_ah); | 727 | ath_gen_timer_isr(sc->sc_ah); |
@@ -1384,7 +1385,9 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, | |||
1384 | ath9k_hw_set_tsfadjust(ah, 0); | 1385 | ath9k_hw_set_tsfadjust(ah, 0); |
1385 | sc->sc_flags &= ~SC_OP_TSF_RESET; | 1386 | sc->sc_flags &= ~SC_OP_TSF_RESET; |
1386 | 1387 | ||
1387 | if (iter_data.nwds + iter_data.nmeshes) | 1388 | if (iter_data.nmeshes) |
1389 | ah->opmode = NL80211_IFTYPE_MESH_POINT; | ||
1390 | else if (iter_data.nwds) | ||
1388 | ah->opmode = NL80211_IFTYPE_AP; | 1391 | ah->opmode = NL80211_IFTYPE_AP; |
1389 | else if (iter_data.nadhocs) | 1392 | else if (iter_data.nadhocs) |
1390 | ah->opmode = NL80211_IFTYPE_ADHOC; | 1393 | ah->opmode = NL80211_IFTYPE_ADHOC; |
@@ -1408,6 +1411,7 @@ static void ath9k_calculate_summary_state(struct ieee80211_hw *hw, | |||
1408 | 1411 | ||
1409 | /* Set up ANI */ | 1412 | /* Set up ANI */ |
1410 | if ((iter_data.naps + iter_data.nadhocs) > 0) { | 1413 | if ((iter_data.naps + iter_data.nadhocs) > 0) { |
1414 | sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; | ||
1411 | sc->sc_flags |= SC_OP_ANI_RUN; | 1415 | sc->sc_flags |= SC_OP_ANI_RUN; |
1412 | ath_start_ani(common); | 1416 | ath_start_ani(common); |
1413 | } else { | 1417 | } else { |
@@ -1778,6 +1782,11 @@ static int ath9k_sta_add(struct ieee80211_hw *hw, | |||
1778 | struct ieee80211_key_conf ps_key = { }; | 1782 | struct ieee80211_key_conf ps_key = { }; |
1779 | 1783 | ||
1780 | ath_node_attach(sc, sta); | 1784 | ath_node_attach(sc, sta); |
1785 | |||
1786 | if (vif->type != NL80211_IFTYPE_AP && | ||
1787 | vif->type != NL80211_IFTYPE_AP_VLAN) | ||
1788 | return 0; | ||
1789 | |||
1781 | an->ps_key = ath_key_config(common, vif, sta, &ps_key); | 1790 | an->ps_key = ath_key_config(common, vif, sta, &ps_key); |
1782 | 1791 | ||
1783 | return 0; | 1792 | return 0; |
@@ -2039,9 +2048,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2039 | if (changed & BSS_CHANGED_BSSID) { | 2048 | if (changed & BSS_CHANGED_BSSID) { |
2040 | ath9k_config_bss(sc, vif); | 2049 | ath9k_config_bss(sc, vif); |
2041 | 2050 | ||
2042 | /* Set aggregation protection mode parameters */ | ||
2043 | sc->config.ath_aggr_prot = 0; | ||
2044 | |||
2045 | ath_dbg(common, ATH_DBG_CONFIG, "BSSID: %pM aid: 0x%x\n", | 2051 | ath_dbg(common, ATH_DBG_CONFIG, "BSSID: %pM aid: 0x%x\n", |
2046 | common->curbssid, common->curaid); | 2052 | common->curbssid, common->curaid); |
2047 | } | 2053 | } |
@@ -2261,6 +2267,7 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) | |||
2261 | struct ath_softc *sc = hw->priv; | 2267 | struct ath_softc *sc = hw->priv; |
2262 | int timeout = 200; /* ms */ | 2268 | int timeout = 200; /* ms */ |
2263 | int i, j; | 2269 | int i, j; |
2270 | bool drain_txq; | ||
2264 | 2271 | ||
2265 | mutex_lock(&sc->mutex); | 2272 | mutex_lock(&sc->mutex); |
2266 | cancel_delayed_work_sync(&sc->tx_complete_work); | 2273 | cancel_delayed_work_sync(&sc->tx_complete_work); |
@@ -2269,7 +2276,7 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) | |||
2269 | timeout = 1; | 2276 | timeout = 1; |
2270 | 2277 | ||
2271 | for (j = 0; j < timeout; j++) { | 2278 | for (j = 0; j < timeout; j++) { |
2272 | int npend = 0; | 2279 | bool npend = false; |
2273 | 2280 | ||
2274 | if (j) | 2281 | if (j) |
2275 | usleep_range(1000, 2000); | 2282 | usleep_range(1000, 2000); |
@@ -2278,7 +2285,10 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) | |||
2278 | if (!ATH_TXQ_SETUP(sc, i)) | 2285 | if (!ATH_TXQ_SETUP(sc, i)) |
2279 | continue; | 2286 | continue; |
2280 | 2287 | ||
2281 | npend += ath9k_has_pending_frames(sc, &sc->tx.txq[i]); | 2288 | npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]); |
2289 | |||
2290 | if (npend) | ||
2291 | break; | ||
2282 | } | 2292 | } |
2283 | 2293 | ||
2284 | if (!npend) | 2294 | if (!npend) |
@@ -2286,7 +2296,10 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) | |||
2286 | } | 2296 | } |
2287 | 2297 | ||
2288 | ath9k_ps_wakeup(sc); | 2298 | ath9k_ps_wakeup(sc); |
2289 | if (!ath_drain_all_txq(sc, false)) | 2299 | spin_lock_bh(&sc->sc_pcu_lock); |
2300 | drain_txq = ath_drain_all_txq(sc, false); | ||
2301 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
2302 | if (!drain_txq) | ||
2290 | ath_reset(sc, false); | 2303 | ath_reset(sc, false); |
2291 | ath9k_ps_restore(sc); | 2304 | ath9k_ps_restore(sc); |
2292 | ieee80211_wake_queues(hw); | 2305 | ieee80211_wake_queues(hw); |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index c5b7cbe59bfa..4f52e0429f99 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -28,6 +28,33 @@ static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta, | |||
28 | (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); | 28 | (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50); |
29 | } | 29 | } |
30 | 30 | ||
31 | static inline bool ath_ant_div_comb_alt_check(u8 div_group, int alt_ratio, | ||
32 | int curr_main_set, int curr_alt_set, | ||
33 | int alt_rssi_avg, int main_rssi_avg) | ||
34 | { | ||
35 | bool result = false; | ||
36 | switch (div_group) { | ||
37 | case 0: | ||
38 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) | ||
39 | result = true; | ||
40 | break; | ||
41 | case 1: | ||
42 | if ((((curr_main_set == ATH_ANT_DIV_COMB_LNA2) && | ||
43 | (curr_alt_set == ATH_ANT_DIV_COMB_LNA1) && | ||
44 | (alt_rssi_avg >= (main_rssi_avg - 5))) || | ||
45 | ((curr_main_set == ATH_ANT_DIV_COMB_LNA1) && | ||
46 | (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) && | ||
47 | (alt_rssi_avg >= (main_rssi_avg - 2)))) && | ||
48 | (alt_rssi_avg >= 4)) | ||
49 | result = true; | ||
50 | else | ||
51 | result = false; | ||
52 | break; | ||
53 | } | ||
54 | |||
55 | return result; | ||
56 | } | ||
57 | |||
31 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) | 58 | static inline bool ath9k_check_auto_sleep(struct ath_softc *sc) |
32 | { | 59 | { |
33 | return sc->ps_enabled && | 60 | return sc->ps_enabled && |
@@ -572,6 +599,7 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) | |||
572 | ath_dbg(common, ATH_DBG_PS, | 599 | ath_dbg(common, ATH_DBG_PS, |
573 | "Reconfigure Beacon timers based on timestamp from the AP\n"); | 600 | "Reconfigure Beacon timers based on timestamp from the AP\n"); |
574 | ath_set_beacon(sc); | 601 | ath_set_beacon(sc); |
602 | sc->ps_flags &= ~PS_TSFOOR_SYNC; | ||
575 | } | 603 | } |
576 | 604 | ||
577 | if (ath_beacon_dtim_pending_cab(skb)) { | 605 | if (ath_beacon_dtim_pending_cab(skb)) { |
@@ -916,7 +944,8 @@ static void ath9k_process_rssi(struct ath_common *common, | |||
916 | int last_rssi; | 944 | int last_rssi; |
917 | __le16 fc; | 945 | __le16 fc; |
918 | 946 | ||
919 | if (ah->opmode != NL80211_IFTYPE_STATION) | 947 | if ((ah->opmode != NL80211_IFTYPE_STATION) && |
948 | (ah->opmode != NL80211_IFTYPE_ADHOC)) | ||
920 | return; | 949 | return; |
921 | 950 | ||
922 | fc = hdr->frame_control; | 951 | fc = hdr->frame_control; |
@@ -1288,49 +1317,138 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb, | |||
1288 | } | 1317 | } |
1289 | } | 1318 | } |
1290 | 1319 | ||
1291 | static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf) | 1320 | static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf, |
1321 | struct ath_ant_comb *antcomb, int alt_ratio) | ||
1292 | { | 1322 | { |
1293 | /* Adjust the fast_div_bias based on main and alt lna conf */ | 1323 | if (ant_conf->div_group == 0) { |
1294 | switch ((ant_conf->main_lna_conf << 4) | ant_conf->alt_lna_conf) { | 1324 | /* Adjust the fast_div_bias based on main and alt lna conf */ |
1295 | case (0x01): /* A-B LNA2 */ | 1325 | switch ((ant_conf->main_lna_conf << 4) | |
1296 | ant_conf->fast_div_bias = 0x3b; | 1326 | ant_conf->alt_lna_conf) { |
1297 | break; | 1327 | case (0x01): /* A-B LNA2 */ |
1298 | case (0x02): /* A-B LNA1 */ | 1328 | ant_conf->fast_div_bias = 0x3b; |
1299 | ant_conf->fast_div_bias = 0x3d; | 1329 | break; |
1300 | break; | 1330 | case (0x02): /* A-B LNA1 */ |
1301 | case (0x03): /* A-B A+B */ | 1331 | ant_conf->fast_div_bias = 0x3d; |
1302 | ant_conf->fast_div_bias = 0x1; | 1332 | break; |
1303 | break; | 1333 | case (0x03): /* A-B A+B */ |
1304 | case (0x10): /* LNA2 A-B */ | 1334 | ant_conf->fast_div_bias = 0x1; |
1305 | ant_conf->fast_div_bias = 0x7; | 1335 | break; |
1306 | break; | 1336 | case (0x10): /* LNA2 A-B */ |
1307 | case (0x12): /* LNA2 LNA1 */ | 1337 | ant_conf->fast_div_bias = 0x7; |
1308 | ant_conf->fast_div_bias = 0x2; | 1338 | break; |
1309 | break; | 1339 | case (0x12): /* LNA2 LNA1 */ |
1310 | case (0x13): /* LNA2 A+B */ | 1340 | ant_conf->fast_div_bias = 0x2; |
1311 | ant_conf->fast_div_bias = 0x7; | 1341 | break; |
1312 | break; | 1342 | case (0x13): /* LNA2 A+B */ |
1313 | case (0x20): /* LNA1 A-B */ | 1343 | ant_conf->fast_div_bias = 0x7; |
1314 | ant_conf->fast_div_bias = 0x6; | 1344 | break; |
1315 | break; | 1345 | case (0x20): /* LNA1 A-B */ |
1316 | case (0x21): /* LNA1 LNA2 */ | 1346 | ant_conf->fast_div_bias = 0x6; |
1317 | ant_conf->fast_div_bias = 0x0; | 1347 | break; |
1318 | break; | 1348 | case (0x21): /* LNA1 LNA2 */ |
1319 | case (0x23): /* LNA1 A+B */ | 1349 | ant_conf->fast_div_bias = 0x0; |
1320 | ant_conf->fast_div_bias = 0x6; | 1350 | break; |
1321 | break; | 1351 | case (0x23): /* LNA1 A+B */ |
1322 | case (0x30): /* A+B A-B */ | 1352 | ant_conf->fast_div_bias = 0x6; |
1323 | ant_conf->fast_div_bias = 0x1; | 1353 | break; |
1324 | break; | 1354 | case (0x30): /* A+B A-B */ |
1325 | case (0x31): /* A+B LNA2 */ | 1355 | ant_conf->fast_div_bias = 0x1; |
1326 | ant_conf->fast_div_bias = 0x3b; | 1356 | break; |
1327 | break; | 1357 | case (0x31): /* A+B LNA2 */ |
1328 | case (0x32): /* A+B LNA1 */ | 1358 | ant_conf->fast_div_bias = 0x3b; |
1329 | ant_conf->fast_div_bias = 0x3d; | 1359 | break; |
1330 | break; | 1360 | case (0x32): /* A+B LNA1 */ |
1331 | default: | 1361 | ant_conf->fast_div_bias = 0x3d; |
1332 | break; | 1362 | break; |
1363 | default: | ||
1364 | break; | ||
1365 | } | ||
1366 | } else if (ant_conf->div_group == 2) { | ||
1367 | /* Adjust the fast_div_bias based on main and alt_lna_conf */ | ||
1368 | switch ((ant_conf->main_lna_conf << 4) | | ||
1369 | ant_conf->alt_lna_conf) { | ||
1370 | case (0x01): /* A-B LNA2 */ | ||
1371 | ant_conf->fast_div_bias = 0x1; | ||
1372 | ant_conf->main_gaintb = 0; | ||
1373 | ant_conf->alt_gaintb = 0; | ||
1374 | break; | ||
1375 | case (0x02): /* A-B LNA1 */ | ||
1376 | ant_conf->fast_div_bias = 0x1; | ||
1377 | ant_conf->main_gaintb = 0; | ||
1378 | ant_conf->alt_gaintb = 0; | ||
1379 | break; | ||
1380 | case (0x03): /* A-B A+B */ | ||
1381 | ant_conf->fast_div_bias = 0x1; | ||
1382 | ant_conf->main_gaintb = 0; | ||
1383 | ant_conf->alt_gaintb = 0; | ||
1384 | break; | ||
1385 | case (0x10): /* LNA2 A-B */ | ||
1386 | if (!(antcomb->scan) && | ||
1387 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1388 | ant_conf->fast_div_bias = 0x1; | ||
1389 | else | ||
1390 | ant_conf->fast_div_bias = 0x2; | ||
1391 | ant_conf->main_gaintb = 0; | ||
1392 | ant_conf->alt_gaintb = 0; | ||
1393 | break; | ||
1394 | case (0x12): /* LNA2 LNA1 */ | ||
1395 | ant_conf->fast_div_bias = 0x1; | ||
1396 | ant_conf->main_gaintb = 0; | ||
1397 | ant_conf->alt_gaintb = 0; | ||
1398 | break; | ||
1399 | case (0x13): /* LNA2 A+B */ | ||
1400 | if (!(antcomb->scan) && | ||
1401 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1402 | ant_conf->fast_div_bias = 0x1; | ||
1403 | else | ||
1404 | ant_conf->fast_div_bias = 0x2; | ||
1405 | ant_conf->main_gaintb = 0; | ||
1406 | ant_conf->alt_gaintb = 0; | ||
1407 | break; | ||
1408 | case (0x20): /* LNA1 A-B */ | ||
1409 | if (!(antcomb->scan) && | ||
1410 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1411 | ant_conf->fast_div_bias = 0x1; | ||
1412 | else | ||
1413 | ant_conf->fast_div_bias = 0x2; | ||
1414 | ant_conf->main_gaintb = 0; | ||
1415 | ant_conf->alt_gaintb = 0; | ||
1416 | break; | ||
1417 | case (0x21): /* LNA1 LNA2 */ | ||
1418 | ant_conf->fast_div_bias = 0x1; | ||
1419 | ant_conf->main_gaintb = 0; | ||
1420 | ant_conf->alt_gaintb = 0; | ||
1421 | break; | ||
1422 | case (0x23): /* LNA1 A+B */ | ||
1423 | if (!(antcomb->scan) && | ||
1424 | (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO)) | ||
1425 | ant_conf->fast_div_bias = 0x1; | ||
1426 | else | ||
1427 | ant_conf->fast_div_bias = 0x2; | ||
1428 | ant_conf->main_gaintb = 0; | ||
1429 | ant_conf->alt_gaintb = 0; | ||
1430 | break; | ||
1431 | case (0x30): /* A+B A-B */ | ||
1432 | ant_conf->fast_div_bias = 0x1; | ||
1433 | ant_conf->main_gaintb = 0; | ||
1434 | ant_conf->alt_gaintb = 0; | ||
1435 | break; | ||
1436 | case (0x31): /* A+B LNA2 */ | ||
1437 | ant_conf->fast_div_bias = 0x1; | ||
1438 | ant_conf->main_gaintb = 0; | ||
1439 | ant_conf->alt_gaintb = 0; | ||
1440 | break; | ||
1441 | case (0x32): /* A+B LNA1 */ | ||
1442 | ant_conf->fast_div_bias = 0x1; | ||
1443 | ant_conf->main_gaintb = 0; | ||
1444 | ant_conf->alt_gaintb = 0; | ||
1445 | break; | ||
1446 | default: | ||
1447 | break; | ||
1448 | } | ||
1449 | |||
1333 | } | 1450 | } |
1451 | |||
1334 | } | 1452 | } |
1335 | 1453 | ||
1336 | /* Antenna diversity and combining */ | 1454 | /* Antenna diversity and combining */ |
@@ -1350,8 +1468,8 @@ static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | |||
1350 | main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & | 1468 | main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) & |
1351 | ATH_ANT_RX_MASK; | 1469 | ATH_ANT_RX_MASK; |
1352 | 1470 | ||
1353 | /* Record packet only when alt_rssi is positive */ | 1471 | /* Record packet only when both main_rssi and alt_rssi is positive */ |
1354 | if (alt_rssi > 0) { | 1472 | if (main_rssi > 0 && alt_rssi > 0) { |
1355 | antcomb->total_pkt_count++; | 1473 | antcomb->total_pkt_count++; |
1356 | antcomb->main_total_rssi += main_rssi; | 1474 | antcomb->main_total_rssi += main_rssi; |
1357 | antcomb->alt_total_rssi += alt_rssi; | 1475 | antcomb->alt_total_rssi += alt_rssi; |
@@ -1411,7 +1529,9 @@ static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | |||
1411 | } | 1529 | } |
1412 | 1530 | ||
1413 | if (!antcomb->scan) { | 1531 | if (!antcomb->scan) { |
1414 | if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) { | 1532 | if (ath_ant_div_comb_alt_check(div_ant_conf.div_group, |
1533 | alt_ratio, curr_main_set, curr_alt_set, | ||
1534 | alt_rssi_avg, main_rssi_avg)) { | ||
1415 | if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { | 1535 | if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) { |
1416 | /* Switch main and alt LNA */ | 1536 | /* Switch main and alt LNA */ |
1417 | div_ant_conf.main_lna_conf = | 1537 | div_ant_conf.main_lna_conf = |
@@ -1440,7 +1560,7 @@ static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | |||
1440 | } | 1560 | } |
1441 | 1561 | ||
1442 | if ((alt_rssi_avg < (main_rssi_avg + | 1562 | if ((alt_rssi_avg < (main_rssi_avg + |
1443 | ATH_ANT_DIV_COMB_LNA1_LNA2_DELTA))) | 1563 | div_ant_conf.lna1_lna2_delta))) |
1444 | goto div_comb_done; | 1564 | goto div_comb_done; |
1445 | } | 1565 | } |
1446 | 1566 | ||
@@ -1554,8 +1674,7 @@ static void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs) | |||
1554 | antcomb->quick_scan_cnt++; | 1674 | antcomb->quick_scan_cnt++; |
1555 | 1675 | ||
1556 | div_comb_done: | 1676 | div_comb_done: |
1557 | ath_ant_div_conf_fast_divbias(&div_ant_conf); | 1677 | ath_ant_div_conf_fast_divbias(&div_ant_conf, antcomb, alt_ratio); |
1558 | |||
1559 | ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf); | 1678 | ath9k_hw_antdiv_comb_conf_set(sc->sc_ah, &div_ant_conf); |
1560 | 1679 | ||
1561 | antcomb->scan_start_time = jiffies; | 1680 | antcomb->scan_start_time = jiffies; |
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 7b91b2aa6240..97dd1fac98b6 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -1663,8 +1663,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) | |||
1663 | rix = rates[i].idx; | 1663 | rix = rates[i].idx; |
1664 | series[i].Tries = rates[i].count; | 1664 | series[i].Tries = rates[i].count; |
1665 | 1665 | ||
1666 | if ((sc->config.ath_aggr_prot && bf_isaggr(bf)) || | 1666 | if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) { |
1667 | (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)) { | ||
1668 | series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; | 1667 | series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; |
1669 | flags |= ATH9K_TXDESC_RTSENA; | 1668 | flags |= ATH9K_TXDESC_RTSENA; |
1670 | } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { | 1669 | } else if (rates[i].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { |
@@ -1733,8 +1732,6 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, int len) | |||
1733 | !is_pspoll, ctsrate, | 1732 | !is_pspoll, ctsrate, |
1734 | 0, series, 4, flags); | 1733 | 0, series, 4, flags); |
1735 | 1734 | ||
1736 | if (sc->config.ath_aggr_prot && flags) | ||
1737 | ath9k_hw_set11n_burstduration(sc->sc_ah, bf->bf_desc, 8192); | ||
1738 | } | 1735 | } |
1739 | 1736 | ||
1740 | static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw, | 1737 | static struct ath_buf *ath_tx_setup_buffer(struct ieee80211_hw *hw, |
@@ -1848,6 +1845,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1848 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 1845 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1849 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1846 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1850 | struct ieee80211_sta *sta = info->control.sta; | 1847 | struct ieee80211_sta *sta = info->control.sta; |
1848 | struct ieee80211_vif *vif = info->control.vif; | ||
1851 | struct ath_softc *sc = hw->priv; | 1849 | struct ath_softc *sc = hw->priv; |
1852 | struct ath_txq *txq = txctl->txq; | 1850 | struct ath_txq *txq = txctl->txq; |
1853 | struct ath_buf *bf; | 1851 | struct ath_buf *bf; |
@@ -1885,6 +1883,11 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
1885 | memmove(skb->data, skb->data + padsize, padpos); | 1883 | memmove(skb->data, skb->data + padsize, padpos); |
1886 | } | 1884 | } |
1887 | 1885 | ||
1886 | if ((vif && vif->type != NL80211_IFTYPE_AP && | ||
1887 | vif->type != NL80211_IFTYPE_AP_VLAN) || | ||
1888 | !ieee80211_is_data(hdr->frame_control)) | ||
1889 | info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT; | ||
1890 | |||
1888 | setup_frame_info(hw, skb, frmlen); | 1891 | setup_frame_info(hw, skb, frmlen); |
1889 | 1892 | ||
1890 | /* | 1893 | /* |
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index 1638468be5a3..7d5c65ea94e6 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c | |||
@@ -883,7 +883,7 @@ static void carl9170_op_configure_filter(struct ieee80211_hw *hw, | |||
883 | * then checking the error flags, later. | 883 | * then checking the error flags, later. |
884 | */ | 884 | */ |
885 | 885 | ||
886 | if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI) | 886 | if (*new_flags & FIF_ALLMULTI) |
887 | multicast = ~0ULL; | 887 | multicast = ~0ULL; |
888 | 888 | ||
889 | if (multicast != ar->cur_mc_hash) | 889 | if (multicast != ar->cur_mc_hash) |
diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index bf2eff9dd582..e94084fcf6f5 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c | |||
@@ -156,10 +156,8 @@ out_rcu: | |||
156 | 156 | ||
157 | static void carl9170_tx_accounting_free(struct ar9170 *ar, struct sk_buff *skb) | 157 | static void carl9170_tx_accounting_free(struct ar9170 *ar, struct sk_buff *skb) |
158 | { | 158 | { |
159 | struct ieee80211_tx_info *txinfo; | ||
160 | int queue; | 159 | int queue; |
161 | 160 | ||
162 | txinfo = IEEE80211_SKB_CB(skb); | ||
163 | queue = skb_get_queue_mapping(skb); | 161 | queue = skb_get_queue_mapping(skb); |
164 | 162 | ||
165 | spin_lock_bh(&ar->tx_stats_lock); | 163 | spin_lock_bh(&ar->tx_stats_lock); |
@@ -380,7 +378,6 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, | |||
380 | { | 378 | { |
381 | struct _carl9170_tx_superframe *super = (void *) skb->data; | 379 | struct _carl9170_tx_superframe *super = (void *) skb->data; |
382 | struct ieee80211_hdr *hdr = (void *) super->frame_data; | 380 | struct ieee80211_hdr *hdr = (void *) super->frame_data; |
383 | struct carl9170_tx_info *ar_info; | ||
384 | struct ieee80211_sta *sta; | 381 | struct ieee80211_sta *sta; |
385 | struct carl9170_sta_info *sta_info; | 382 | struct carl9170_sta_info *sta_info; |
386 | struct carl9170_sta_tid *tid_info; | 383 | struct carl9170_sta_tid *tid_info; |
@@ -391,8 +388,6 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, | |||
391 | (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR)))) | 388 | (!(super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_AGGR)))) |
392 | return; | 389 | return; |
393 | 390 | ||
394 | ar_info = (void *) txinfo->rate_driver_data; | ||
395 | |||
396 | rcu_read_lock(); | 391 | rcu_read_lock(); |
397 | sta = __carl9170_get_tx_sta(ar, skb); | 392 | sta = __carl9170_get_tx_sta(ar, skb); |
398 | if (unlikely(!sta)) | 393 | if (unlikely(!sta)) |
@@ -623,7 +618,6 @@ static void __carl9170_tx_process_status(struct ar9170 *ar, | |||
623 | { | 618 | { |
624 | struct sk_buff *skb; | 619 | struct sk_buff *skb; |
625 | struct ieee80211_tx_info *txinfo; | 620 | struct ieee80211_tx_info *txinfo; |
626 | struct carl9170_tx_info *arinfo; | ||
627 | unsigned int r, t, q; | 621 | unsigned int r, t, q; |
628 | bool success = true; | 622 | bool success = true; |
629 | 623 | ||
@@ -639,7 +633,6 @@ static void __carl9170_tx_process_status(struct ar9170 *ar, | |||
639 | } | 633 | } |
640 | 634 | ||
641 | txinfo = IEEE80211_SKB_CB(skb); | 635 | txinfo = IEEE80211_SKB_CB(skb); |
642 | arinfo = (void *) txinfo->rate_driver_data; | ||
643 | 636 | ||
644 | if (!(info & CARL9170_TX_STATUS_SUCCESS)) | 637 | if (!(info & CARL9170_TX_STATUS_SUCCESS)) |
645 | success = false; | 638 | success = false; |
@@ -1321,7 +1314,6 @@ static bool carl9170_tx_ampdu_queue(struct ar9170 *ar, | |||
1321 | struct carl9170_sta_info *sta_info; | 1314 | struct carl9170_sta_info *sta_info; |
1322 | struct carl9170_sta_tid *agg; | 1315 | struct carl9170_sta_tid *agg; |
1323 | struct sk_buff *iter; | 1316 | struct sk_buff *iter; |
1324 | unsigned int max; | ||
1325 | u16 tid, seq, qseq, off; | 1317 | u16 tid, seq, qseq, off; |
1326 | bool run = false; | 1318 | bool run = false; |
1327 | 1319 | ||
@@ -1331,7 +1323,6 @@ static bool carl9170_tx_ampdu_queue(struct ar9170 *ar, | |||
1331 | 1323 | ||
1332 | rcu_read_lock(); | 1324 | rcu_read_lock(); |
1333 | agg = rcu_dereference(sta_info->agg[tid]); | 1325 | agg = rcu_dereference(sta_info->agg[tid]); |
1334 | max = sta_info->ampdu_max_len; | ||
1335 | 1326 | ||
1336 | if (!agg) | 1327 | if (!agg) |
1337 | goto err_unlock_rcu; | 1328 | goto err_unlock_rcu; |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 5af40d9170a0..5a43984bdcea 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -2686,6 +2686,17 @@ out: | |||
2686 | dev->mac_suspended++; | 2686 | dev->mac_suspended++; |
2687 | } | 2687 | } |
2688 | 2688 | ||
2689 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */ | ||
2690 | void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on) | ||
2691 | { | ||
2692 | u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW); | ||
2693 | if (on) | ||
2694 | tmslow |= B43_TMSLOW_MACPHYCLKEN; | ||
2695 | else | ||
2696 | tmslow &= ~B43_TMSLOW_MACPHYCLKEN; | ||
2697 | ssb_write32(dev->dev, SSB_TMSLOW, tmslow); | ||
2698 | } | ||
2699 | |||
2689 | static void b43_adjust_opmode(struct b43_wldev *dev) | 2700 | static void b43_adjust_opmode(struct b43_wldev *dev) |
2690 | { | 2701 | { |
2691 | struct b43_wl *wl = dev->wl; | 2702 | struct b43_wl *wl = dev->wl; |
@@ -2842,7 +2853,7 @@ static int b43_chip_init(struct b43_wldev *dev) | |||
2842 | { | 2853 | { |
2843 | struct b43_phy *phy = &dev->phy; | 2854 | struct b43_phy *phy = &dev->phy; |
2844 | int err; | 2855 | int err; |
2845 | u32 value32, macctl; | 2856 | u32 macctl; |
2846 | u16 value16; | 2857 | u16 value16; |
2847 | 2858 | ||
2848 | /* Initialize the MAC control */ | 2859 | /* Initialize the MAC control */ |
@@ -2920,9 +2931,7 @@ static int b43_chip_init(struct b43_wldev *dev) | |||
2920 | b43_write32(dev, B43_MMIO_DMA4_IRQ_MASK, 0x0000DC00); | 2931 | b43_write32(dev, B43_MMIO_DMA4_IRQ_MASK, 0x0000DC00); |
2921 | b43_write32(dev, B43_MMIO_DMA5_IRQ_MASK, 0x0000DC00); | 2932 | b43_write32(dev, B43_MMIO_DMA5_IRQ_MASK, 0x0000DC00); |
2922 | 2933 | ||
2923 | value32 = ssb_read32(dev->dev, SSB_TMSLOW); | 2934 | b43_mac_phy_clock_set(dev, true); |
2924 | value32 |= 0x00100000; | ||
2925 | ssb_write32(dev->dev, SSB_TMSLOW, value32); | ||
2926 | 2935 | ||
2927 | b43_write16(dev, B43_MMIO_POWERUP_DELAY, | 2936 | b43_write16(dev, B43_MMIO_POWERUP_DELAY, |
2928 | dev->dev->bus->chipco.fast_pwrup_delay); | 2937 | dev->dev->bus->chipco.fast_pwrup_delay); |
@@ -4213,33 +4222,18 @@ static void b43_bluetooth_coext_disable(struct b43_wldev *dev) | |||
4213 | 4222 | ||
4214 | static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev) | 4223 | static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev) |
4215 | { | 4224 | { |
4216 | #ifdef CONFIG_SSB_DRIVER_PCICORE | ||
4217 | struct ssb_bus *bus = dev->dev->bus; | 4225 | struct ssb_bus *bus = dev->dev->bus; |
4218 | u32 tmp; | 4226 | u32 tmp; |
4219 | 4227 | ||
4220 | if (bus->pcicore.dev && | 4228 | if ((bus->chip_id == 0x4311 && bus->chip_rev == 2) || |
4221 | bus->pcicore.dev->id.coreid == SSB_DEV_PCI && | 4229 | (bus->chip_id == 0x4312)) { |
4222 | bus->pcicore.dev->id.revision <= 5) { | ||
4223 | /* IMCFGLO timeouts workaround. */ | ||
4224 | tmp = ssb_read32(dev->dev, SSB_IMCFGLO); | 4230 | tmp = ssb_read32(dev->dev, SSB_IMCFGLO); |
4225 | switch (bus->bustype) { | 4231 | tmp &= ~SSB_IMCFGLO_REQTO; |
4226 | case SSB_BUSTYPE_PCI: | 4232 | tmp &= ~SSB_IMCFGLO_SERTO; |
4227 | case SSB_BUSTYPE_PCMCIA: | 4233 | tmp |= 0x3; |
4228 | tmp &= ~SSB_IMCFGLO_REQTO; | ||
4229 | tmp &= ~SSB_IMCFGLO_SERTO; | ||
4230 | tmp |= 0x32; | ||
4231 | break; | ||
4232 | case SSB_BUSTYPE_SSB: | ||
4233 | tmp &= ~SSB_IMCFGLO_REQTO; | ||
4234 | tmp &= ~SSB_IMCFGLO_SERTO; | ||
4235 | tmp |= 0x53; | ||
4236 | break; | ||
4237 | default: | ||
4238 | break; | ||
4239 | } | ||
4240 | ssb_write32(dev->dev, SSB_IMCFGLO, tmp); | 4234 | ssb_write32(dev->dev, SSB_IMCFGLO, tmp); |
4235 | ssb_commit_settings(bus); | ||
4241 | } | 4236 | } |
4242 | #endif /* CONFIG_SSB_DRIVER_PCICORE */ | ||
4243 | } | 4237 | } |
4244 | 4238 | ||
4245 | static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle) | 4239 | static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle) |
@@ -4863,25 +4857,8 @@ static void b43_one_core_detach(struct ssb_device *dev) | |||
4863 | static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl) | 4857 | static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl) |
4864 | { | 4858 | { |
4865 | struct b43_wldev *wldev; | 4859 | struct b43_wldev *wldev; |
4866 | struct pci_dev *pdev; | ||
4867 | int err = -ENOMEM; | 4860 | int err = -ENOMEM; |
4868 | 4861 | ||
4869 | if (!list_empty(&wl->devlist)) { | ||
4870 | /* We are not the first core on this chip. */ | ||
4871 | pdev = (dev->bus->bustype == SSB_BUSTYPE_PCI) ? dev->bus->host_pci : NULL; | ||
4872 | /* Only special chips support more than one wireless | ||
4873 | * core, although some of the other chips have more than | ||
4874 | * one wireless core as well. Check for this and | ||
4875 | * bail out early. | ||
4876 | */ | ||
4877 | if (!pdev || | ||
4878 | ((pdev->device != 0x4321) && | ||
4879 | (pdev->device != 0x4313) && (pdev->device != 0x431A))) { | ||
4880 | b43dbg(wl, "Ignoring unconnected 802.11 core\n"); | ||
4881 | return -ENODEV; | ||
4882 | } | ||
4883 | } | ||
4884 | |||
4885 | wldev = kzalloc(sizeof(*wldev), GFP_KERNEL); | 4862 | wldev = kzalloc(sizeof(*wldev), GFP_KERNEL); |
4886 | if (!wldev) | 4863 | if (!wldev) |
4887 | goto out; | 4864 | goto out; |
@@ -5002,7 +4979,7 @@ out: | |||
5002 | return err; | 4979 | return err; |
5003 | } | 4980 | } |
5004 | 4981 | ||
5005 | static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id) | 4982 | static int b43_ssb_probe(struct ssb_device *dev, const struct ssb_device_id *id) |
5006 | { | 4983 | { |
5007 | struct b43_wl *wl; | 4984 | struct b43_wl *wl; |
5008 | int err; | 4985 | int err; |
@@ -5040,7 +5017,7 @@ static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id) | |||
5040 | return err; | 5017 | return err; |
5041 | } | 5018 | } |
5042 | 5019 | ||
5043 | static void b43_remove(struct ssb_device *dev) | 5020 | static void b43_ssb_remove(struct ssb_device *dev) |
5044 | { | 5021 | { |
5045 | struct b43_wl *wl = ssb_get_devtypedata(dev); | 5022 | struct b43_wl *wl = ssb_get_devtypedata(dev); |
5046 | struct b43_wldev *wldev = ssb_get_drvdata(dev); | 5023 | struct b43_wldev *wldev = ssb_get_drvdata(dev); |
@@ -5083,8 +5060,8 @@ void b43_controller_restart(struct b43_wldev *dev, const char *reason) | |||
5083 | static struct ssb_driver b43_ssb_driver = { | 5060 | static struct ssb_driver b43_ssb_driver = { |
5084 | .name = KBUILD_MODNAME, | 5061 | .name = KBUILD_MODNAME, |
5085 | .id_table = b43_ssb_tbl, | 5062 | .id_table = b43_ssb_tbl, |
5086 | .probe = b43_probe, | 5063 | .probe = b43_ssb_probe, |
5087 | .remove = b43_remove, | 5064 | .remove = b43_ssb_remove, |
5088 | }; | 5065 | }; |
5089 | 5066 | ||
5090 | static void b43_print_driverinfo(void) | 5067 | static void b43_print_driverinfo(void) |
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 40db03678d9f..a0d327f13183 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h | |||
@@ -133,6 +133,7 @@ void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags); | |||
133 | 133 | ||
134 | void b43_mac_suspend(struct b43_wldev *dev); | 134 | void b43_mac_suspend(struct b43_wldev *dev); |
135 | void b43_mac_enable(struct b43_wldev *dev); | 135 | void b43_mac_enable(struct b43_wldev *dev); |
136 | void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on); | ||
136 | 137 | ||
137 | 138 | ||
138 | struct b43_request_fw_context; | 139 | struct b43_request_fw_context; |
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 6755063f955a..b075a3f82a43 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c | |||
@@ -3540,17 +3540,6 @@ static int b43_nphy_cal_rx_iq(struct b43_wldev *dev, | |||
3540 | return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug); | 3540 | return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug); |
3541 | } | 3541 | } |
3542 | 3542 | ||
3543 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MacPhyClkSet */ | ||
3544 | static void b43_nphy_mac_phy_clock_set(struct b43_wldev *dev, bool on) | ||
3545 | { | ||
3546 | u32 tmslow = ssb_read32(dev->dev, SSB_TMSLOW); | ||
3547 | if (on) | ||
3548 | tmslow |= B43_TMSLOW_MACPHYCLKEN; | ||
3549 | else | ||
3550 | tmslow &= ~B43_TMSLOW_MACPHYCLKEN; | ||
3551 | ssb_write32(dev->dev, SSB_TMSLOW, tmslow); | ||
3552 | } | ||
3553 | |||
3554 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */ | 3543 | /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */ |
3555 | static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask) | 3544 | static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask) |
3556 | { | 3545 | { |
@@ -3691,7 +3680,7 @@ int b43_phy_initn(struct b43_wldev *dev) | |||
3691 | b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); | 3680 | b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA); |
3692 | b43_nphy_bmac_clock_fgc(dev, 0); | 3681 | b43_nphy_bmac_clock_fgc(dev, 0); |
3693 | 3682 | ||
3694 | b43_nphy_mac_phy_clock_set(dev, true); | 3683 | b43_mac_phy_clock_set(dev, true); |
3695 | 3684 | ||
3696 | b43_nphy_pa_override(dev, false); | 3685 | b43_nphy_pa_override(dev, false); |
3697 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); | 3686 | b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); |
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index c7fd73e3ad76..1ab8861dd43a 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c | |||
@@ -2234,7 +2234,7 @@ static int b43legacy_chip_init(struct b43legacy_wldev *dev) | |||
2234 | b43legacy_write32(dev, B43legacy_MMIO_DMA5_IRQ_MASK, 0x0000DC00); | 2234 | b43legacy_write32(dev, B43legacy_MMIO_DMA5_IRQ_MASK, 0x0000DC00); |
2235 | 2235 | ||
2236 | value32 = ssb_read32(dev->dev, SSB_TMSLOW); | 2236 | value32 = ssb_read32(dev->dev, SSB_TMSLOW); |
2237 | value32 |= 0x00100000; | 2237 | value32 |= B43legacy_TMSLOW_MACPHYCLKEN; |
2238 | ssb_write32(dev->dev, SSB_TMSLOW, value32); | 2238 | ssb_write32(dev->dev, SSB_TMSLOW, value32); |
2239 | 2239 | ||
2240 | b43legacy_write16(dev, B43legacy_MMIO_POWERUP_DELAY, | 2240 | b43legacy_write16(dev, B43legacy_MMIO_POWERUP_DELAY, |
@@ -3104,37 +3104,6 @@ static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev) | |||
3104 | memset(&dev->noisecalc, 0, sizeof(dev->noisecalc)); | 3104 | memset(&dev->noisecalc, 0, sizeof(dev->noisecalc)); |
3105 | } | 3105 | } |
3106 | 3106 | ||
3107 | static void b43legacy_imcfglo_timeouts_workaround(struct b43legacy_wldev *dev) | ||
3108 | { | ||
3109 | #ifdef CONFIG_SSB_DRIVER_PCICORE | ||
3110 | struct ssb_bus *bus = dev->dev->bus; | ||
3111 | u32 tmp; | ||
3112 | |||
3113 | if (bus->pcicore.dev && | ||
3114 | bus->pcicore.dev->id.coreid == SSB_DEV_PCI && | ||
3115 | bus->pcicore.dev->id.revision <= 5) { | ||
3116 | /* IMCFGLO timeouts workaround. */ | ||
3117 | tmp = ssb_read32(dev->dev, SSB_IMCFGLO); | ||
3118 | switch (bus->bustype) { | ||
3119 | case SSB_BUSTYPE_PCI: | ||
3120 | case SSB_BUSTYPE_PCMCIA: | ||
3121 | tmp &= ~SSB_IMCFGLO_REQTO; | ||
3122 | tmp &= ~SSB_IMCFGLO_SERTO; | ||
3123 | tmp |= 0x32; | ||
3124 | break; | ||
3125 | case SSB_BUSTYPE_SSB: | ||
3126 | tmp &= ~SSB_IMCFGLO_REQTO; | ||
3127 | tmp &= ~SSB_IMCFGLO_SERTO; | ||
3128 | tmp |= 0x53; | ||
3129 | break; | ||
3130 | default: | ||
3131 | break; | ||
3132 | } | ||
3133 | ssb_write32(dev->dev, SSB_IMCFGLO, tmp); | ||
3134 | } | ||
3135 | #endif /* CONFIG_SSB_DRIVER_PCICORE */ | ||
3136 | } | ||
3137 | |||
3138 | static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev, | 3107 | static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev, |
3139 | bool idle) { | 3108 | bool idle) { |
3140 | u16 pu_delay = 1050; | 3109 | u16 pu_delay = 1050; |
@@ -3278,7 +3247,6 @@ static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev) | |||
3278 | /* Enable IRQ routing to this device. */ | 3247 | /* Enable IRQ routing to this device. */ |
3279 | ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev); | 3248 | ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev); |
3280 | 3249 | ||
3281 | b43legacy_imcfglo_timeouts_workaround(dev); | ||
3282 | prepare_phy_data_for_init(dev); | 3250 | prepare_phy_data_for_init(dev); |
3283 | b43legacy_phy_calibrate(dev); | 3251 | b43legacy_phy_calibrate(dev); |
3284 | err = b43legacy_chip_init(dev); | 3252 | err = b43legacy_chip_init(dev); |
@@ -3728,26 +3696,8 @@ static int b43legacy_one_core_attach(struct ssb_device *dev, | |||
3728 | struct b43legacy_wl *wl) | 3696 | struct b43legacy_wl *wl) |
3729 | { | 3697 | { |
3730 | struct b43legacy_wldev *wldev; | 3698 | struct b43legacy_wldev *wldev; |
3731 | struct pci_dev *pdev; | ||
3732 | int err = -ENOMEM; | 3699 | int err = -ENOMEM; |
3733 | 3700 | ||
3734 | if (!list_empty(&wl->devlist)) { | ||
3735 | /* We are not the first core on this chip. */ | ||
3736 | pdev = (dev->bus->bustype == SSB_BUSTYPE_PCI) ? dev->bus->host_pci : NULL; | ||
3737 | /* Only special chips support more than one wireless | ||
3738 | * core, although some of the other chips have more than | ||
3739 | * one wireless core as well. Check for this and | ||
3740 | * bail out early. | ||
3741 | */ | ||
3742 | if (!pdev || | ||
3743 | ((pdev->device != 0x4321) && | ||
3744 | (pdev->device != 0x4313) && | ||
3745 | (pdev->device != 0x431A))) { | ||
3746 | b43legacydbg(wl, "Ignoring unconnected 802.11 core\n"); | ||
3747 | return -ENODEV; | ||
3748 | } | ||
3749 | } | ||
3750 | |||
3751 | wldev = kzalloc(sizeof(*wldev), GFP_KERNEL); | 3701 | wldev = kzalloc(sizeof(*wldev), GFP_KERNEL); |
3752 | if (!wldev) | 3702 | if (!wldev) |
3753 | goto out; | 3703 | goto out; |
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c index 89509392ef5d..24d149909ba3 100644 --- a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c | |||
@@ -2604,7 +2604,7 @@ static ssize_t iwl4965_rs_sta_dbgfs_scale_table_write(struct file *file, | |||
2604 | struct iwl_lq_sta *lq_sta = file->private_data; | 2604 | struct iwl_lq_sta *lq_sta = file->private_data; |
2605 | struct iwl_priv *priv; | 2605 | struct iwl_priv *priv; |
2606 | char buf[64]; | 2606 | char buf[64]; |
2607 | int buf_size; | 2607 | size_t buf_size; |
2608 | u32 parsed_rate; | 2608 | u32 parsed_rate; |
2609 | struct iwl_station_priv *sta_priv = | 2609 | struct iwl_station_priv *sta_priv = |
2610 | container_of(lq_sta, struct iwl_station_priv, lq_sta); | 2610 | container_of(lq_sta, struct iwl_station_priv, lq_sta); |
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 17d555f2215a..ad3bdba6beed 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -102,6 +102,16 @@ config IWLWIFI_DEVICE_TRACING | |||
102 | occur. | 102 | occur. |
103 | endmenu | 103 | endmenu |
104 | 104 | ||
105 | config IWLWIFI_DEVICE_SVTOOL | ||
106 | bool "iwlwifi device svtool support" | ||
107 | depends on IWLAGN | ||
108 | select NL80211_TESTMODE | ||
109 | help | ||
110 | This option enables the svtool support for iwlwifi device through | ||
111 | NL80211_TESTMODE. svtool is a software validation tool that runs in | ||
112 | the user space and interacts with the device in the kernel space | ||
113 | through the generic netlink message via NL80211_TESTMODE channel. | ||
114 | |||
105 | config IWL_P2P | 115 | config IWL_P2P |
106 | bool "iwlwifi experimental P2P support" | 116 | bool "iwlwifi experimental P2P support" |
107 | depends on IWLAGN | 117 | depends on IWLAGN |
diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile index 89a41d320c36..822660483f9f 100644 --- a/drivers/net/wireless/iwlwifi/Makefile +++ b/drivers/net/wireless/iwlwifi/Makefile | |||
@@ -16,6 +16,7 @@ iwlagn-objs += iwl-2000.o | |||
16 | 16 | ||
17 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o | 17 | iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o |
18 | iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o | 18 | iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o |
19 | iwlagn-$(CONFIG_IWLWIFI_DEVICE_SVTOOL) += iwl-sv-open.o | ||
19 | 20 | ||
20 | CFLAGS_iwl-devtrace.o := -I$(src) | 21 | CFLAGS_iwl-devtrace.o := -I$(src) |
21 | 22 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c index 3da8cf27dcb9..b4c81931e136 100644 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ b/drivers/net/wireless/iwlwifi/iwl-1000.c | |||
@@ -171,8 +171,6 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |||
171 | 171 | ||
172 | static struct iwl_lib_ops iwl1000_lib = { | 172 | static struct iwl_lib_ops iwl1000_lib = { |
173 | .set_hw_params = iwl1000_hw_set_hw_params, | 173 | .set_hw_params = iwl1000_hw_set_hw_params, |
174 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, | ||
175 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, | ||
176 | .txq_set_sched = iwlagn_txq_set_sched, | 174 | .txq_set_sched = iwlagn_txq_set_sched, |
177 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 175 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
178 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 176 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index bca462c47e37..89b8da7a6c8b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c | |||
@@ -252,8 +252,6 @@ static int iwl2030_hw_channel_switch(struct iwl_priv *priv, | |||
252 | 252 | ||
253 | static struct iwl_lib_ops iwl2000_lib = { | 253 | static struct iwl_lib_ops iwl2000_lib = { |
254 | .set_hw_params = iwl2000_hw_set_hw_params, | 254 | .set_hw_params = iwl2000_hw_set_hw_params, |
255 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, | ||
256 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, | ||
257 | .txq_set_sched = iwlagn_txq_set_sched, | 255 | .txq_set_sched = iwlagn_txq_set_sched, |
258 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 256 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
259 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 257 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 561f2cd65dd4..98f81df166e3 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -339,8 +339,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv, | |||
339 | 339 | ||
340 | static struct iwl_lib_ops iwl5000_lib = { | 340 | static struct iwl_lib_ops iwl5000_lib = { |
341 | .set_hw_params = iwl5000_hw_set_hw_params, | 341 | .set_hw_params = iwl5000_hw_set_hw_params, |
342 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, | ||
343 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, | ||
344 | .txq_set_sched = iwlagn_txq_set_sched, | 342 | .txq_set_sched = iwlagn_txq_set_sched, |
345 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 343 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
346 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 344 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
@@ -376,8 +374,6 @@ static struct iwl_lib_ops iwl5000_lib = { | |||
376 | 374 | ||
377 | static struct iwl_lib_ops iwl5150_lib = { | 375 | static struct iwl_lib_ops iwl5150_lib = { |
378 | .set_hw_params = iwl5150_hw_set_hw_params, | 376 | .set_hw_params = iwl5150_hw_set_hw_params, |
379 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, | ||
380 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, | ||
381 | .txq_set_sched = iwlagn_txq_set_sched, | 377 | .txq_set_sched = iwlagn_txq_set_sched, |
382 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 378 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
383 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 379 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 6045457cc722..a7921f9a03c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c | |||
@@ -278,8 +278,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | |||
278 | 278 | ||
279 | static struct iwl_lib_ops iwl6000_lib = { | 279 | static struct iwl_lib_ops iwl6000_lib = { |
280 | .set_hw_params = iwl6000_hw_set_hw_params, | 280 | .set_hw_params = iwl6000_hw_set_hw_params, |
281 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, | ||
282 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, | ||
283 | .txq_set_sched = iwlagn_txq_set_sched, | 281 | .txq_set_sched = iwlagn_txq_set_sched, |
284 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 282 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
285 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 283 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
@@ -316,8 +314,6 @@ static struct iwl_lib_ops iwl6000_lib = { | |||
316 | 314 | ||
317 | static struct iwl_lib_ops iwl6030_lib = { | 315 | static struct iwl_lib_ops iwl6030_lib = { |
318 | .set_hw_params = iwl6000_hw_set_hw_params, | 316 | .set_hw_params = iwl6000_hw_set_hw_params, |
319 | .txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl, | ||
320 | .txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl, | ||
321 | .txq_set_sched = iwlagn_txq_set_sched, | 317 | .txq_set_sched = iwlagn_txq_set_sched, |
322 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, | 318 | .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, |
323 | .txq_free_tfd = iwl_hw_txq_free_tfd, | 319 | .txq_free_tfd = iwl_hw_txq_free_tfd, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c index 49dd03f9feda..b12c72d63ccb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c | |||
@@ -54,12 +54,6 @@ int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant) | |||
54 | } | 54 | } |
55 | } | 55 | } |
56 | 56 | ||
57 | /* Currently this is the superset of everything */ | ||
58 | static u16 iwlagn_get_hcmd_size(u8 cmd_id, u16 len) | ||
59 | { | ||
60 | return len; | ||
61 | } | ||
62 | |||
63 | static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) | 57 | static u16 iwlagn_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) |
64 | { | 58 | { |
65 | u16 size = (u16)sizeof(struct iwl_addsta_cmd); | 59 | u16 size = (u16)sizeof(struct iwl_addsta_cmd); |
@@ -332,7 +326,6 @@ struct iwl_hcmd_ops iwlagn_bt_hcmd = { | |||
332 | }; | 326 | }; |
333 | 327 | ||
334 | struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { | 328 | struct iwl_hcmd_utils_ops iwlagn_hcmd_utils = { |
335 | .get_hcmd_size = iwlagn_get_hcmd_size, | ||
336 | .build_addsta_hcmd = iwlagn_build_addsta_hcmd, | 329 | .build_addsta_hcmd = iwlagn_build_addsta_hcmd, |
337 | .gain_computation = iwlagn_gain_computation, | 330 | .gain_computation = iwlagn_gain_computation, |
338 | .chain_noise_reset = iwlagn_chain_noise_reset, | 331 | .chain_noise_reset = iwlagn_chain_noise_reset, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index dbe6295bbf23..91f26556ac23 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -3086,7 +3086,7 @@ static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, | |||
3086 | struct iwl_lq_sta *lq_sta = file->private_data; | 3086 | struct iwl_lq_sta *lq_sta = file->private_data; |
3087 | struct iwl_priv *priv; | 3087 | struct iwl_priv *priv; |
3088 | char buf[64]; | 3088 | char buf[64]; |
3089 | int buf_size; | 3089 | size_t buf_size; |
3090 | u32 parsed_rate; | 3090 | u32 parsed_rate; |
3091 | struct iwl_station_priv *sta_priv = | 3091 | struct iwl_station_priv *sta_priv = |
3092 | container_of(lq_sta, struct iwl_station_priv, lq_sta); | 3092 | container_of(lq_sta, struct iwl_station_priv, lq_sta); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 4afae1446582..342de780a366 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -98,9 +98,9 @@ static inline int get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid) | |||
98 | /** | 98 | /** |
99 | * iwlagn_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array | 99 | * iwlagn_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array |
100 | */ | 100 | */ |
101 | void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | 101 | static void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, |
102 | struct iwl_tx_queue *txq, | 102 | struct iwl_tx_queue *txq, |
103 | u16 byte_cnt) | 103 | u16 byte_cnt) |
104 | { | 104 | { |
105 | struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; | 105 | struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; |
106 | int write_ptr = txq->q.write_ptr; | 106 | int write_ptr = txq->q.write_ptr; |
@@ -112,21 +112,19 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | |||
112 | 112 | ||
113 | WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); | 113 | WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); |
114 | 114 | ||
115 | if (txq_id != priv->cmd_queue) { | 115 | sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; |
116 | sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; | 116 | sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; |
117 | sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; | 117 | |
118 | 118 | switch (sec_ctl & TX_CMD_SEC_MSK) { | |
119 | switch (sec_ctl & TX_CMD_SEC_MSK) { | 119 | case TX_CMD_SEC_CCM: |
120 | case TX_CMD_SEC_CCM: | 120 | len += CCMP_MIC_LEN; |
121 | len += CCMP_MIC_LEN; | 121 | break; |
122 | break; | 122 | case TX_CMD_SEC_TKIP: |
123 | case TX_CMD_SEC_TKIP: | 123 | len += TKIP_ICV_LEN; |
124 | len += TKIP_ICV_LEN; | 124 | break; |
125 | break; | 125 | case TX_CMD_SEC_WEP: |
126 | case TX_CMD_SEC_WEP: | 126 | len += WEP_IV_LEN + WEP_ICV_LEN; |
127 | len += WEP_IV_LEN + WEP_ICV_LEN; | 127 | break; |
128 | break; | ||
129 | } | ||
130 | } | 128 | } |
131 | 129 | ||
132 | bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); | 130 | bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); |
@@ -138,8 +136,8 @@ void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | |||
138 | tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; | 136 | tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; |
139 | } | 137 | } |
140 | 138 | ||
141 | void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | 139 | static void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, |
142 | struct iwl_tx_queue *txq) | 140 | struct iwl_tx_queue *txq) |
143 | { | 141 | { |
144 | struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; | 142 | struct iwlagn_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; |
145 | int txq_id = txq->q.id; | 143 | int txq_id = txq->q.id; |
@@ -539,7 +537,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
539 | struct iwl_tx_cmd *tx_cmd; | 537 | struct iwl_tx_cmd *tx_cmd; |
540 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 538 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
541 | int txq_id; | 539 | int txq_id; |
542 | dma_addr_t phys_addr; | 540 | dma_addr_t phys_addr = 0; |
543 | dma_addr_t txcmd_phys; | 541 | dma_addr_t txcmd_phys; |
544 | dma_addr_t scratch_phys; | 542 | dma_addr_t scratch_phys; |
545 | u16 len, firstlen, secondlen; | 543 | u16 len, firstlen, secondlen; |
@@ -566,7 +564,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
566 | spin_lock_irqsave(&priv->lock, flags); | 564 | spin_lock_irqsave(&priv->lock, flags); |
567 | if (iwl_is_rfkill(priv)) { | 565 | if (iwl_is_rfkill(priv)) { |
568 | IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); | 566 | IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); |
569 | goto drop_unlock; | 567 | goto drop_unlock_priv; |
570 | } | 568 | } |
571 | 569 | ||
572 | fc = hdr->frame_control; | 570 | fc = hdr->frame_control; |
@@ -591,7 +589,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
591 | if (sta_id == IWL_INVALID_STATION) { | 589 | if (sta_id == IWL_INVALID_STATION) { |
592 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", | 590 | IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", |
593 | hdr->addr1); | 591 | hdr->addr1); |
594 | goto drop_unlock; | 592 | goto drop_unlock_priv; |
595 | } | 593 | } |
596 | } | 594 | } |
597 | 595 | ||
@@ -635,10 +633,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
635 | if (ieee80211_is_data_qos(fc)) { | 633 | if (ieee80211_is_data_qos(fc)) { |
636 | qc = ieee80211_get_qos_ctl(hdr); | 634 | qc = ieee80211_get_qos_ctl(hdr); |
637 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; | 635 | tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; |
638 | if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) { | 636 | |
639 | spin_unlock(&priv->sta_lock); | 637 | if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) |
640 | goto drop_unlock; | 638 | goto drop_unlock_sta; |
641 | } | 639 | |
642 | seq_number = priv->stations[sta_id].tid[tid].seq_number; | 640 | seq_number = priv->stations[sta_id].tid[tid].seq_number; |
643 | seq_number &= IEEE80211_SCTL_SEQ; | 641 | seq_number &= IEEE80211_SCTL_SEQ; |
644 | hdr->seq_ctrl = hdr->seq_ctrl & | 642 | hdr->seq_ctrl = hdr->seq_ctrl & |
@@ -656,18 +654,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
656 | txq = &priv->txq[txq_id]; | 654 | txq = &priv->txq[txq_id]; |
657 | q = &txq->q; | 655 | q = &txq->q; |
658 | 656 | ||
659 | if (unlikely(iwl_queue_space(q) < q->high_mark)) { | 657 | if (unlikely(iwl_queue_space(q) < q->high_mark)) |
660 | spin_unlock(&priv->sta_lock); | 658 | goto drop_unlock_sta; |
661 | goto drop_unlock; | ||
662 | } | ||
663 | |||
664 | if (ieee80211_is_data_qos(fc)) { | ||
665 | priv->stations[sta_id].tid[tid].tfds_in_queue++; | ||
666 | if (!ieee80211_has_morefrags(fc)) | ||
667 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | ||
668 | } | ||
669 | |||
670 | spin_unlock(&priv->sta_lock); | ||
671 | 659 | ||
672 | /* Set up driver data for this TFD */ | 660 | /* Set up driver data for this TFD */ |
673 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); | 661 | memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); |
@@ -731,12 +719,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
731 | txcmd_phys = pci_map_single(priv->pci_dev, | 719 | txcmd_phys = pci_map_single(priv->pci_dev, |
732 | &out_cmd->hdr, firstlen, | 720 | &out_cmd->hdr, firstlen, |
733 | PCI_DMA_BIDIRECTIONAL); | 721 | PCI_DMA_BIDIRECTIONAL); |
722 | if (unlikely(pci_dma_mapping_error(priv->pci_dev, txcmd_phys))) | ||
723 | goto drop_unlock_sta; | ||
734 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); | 724 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); |
735 | dma_unmap_len_set(out_meta, len, firstlen); | 725 | dma_unmap_len_set(out_meta, len, firstlen); |
736 | /* Add buffer containing Tx command and MAC(!) header to TFD's | ||
737 | * first entry */ | ||
738 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
739 | txcmd_phys, firstlen, 1, 0); | ||
740 | 726 | ||
741 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | 727 | if (!ieee80211_has_morefrags(hdr->frame_control)) { |
742 | txq->need_update = 1; | 728 | txq->need_update = 1; |
@@ -751,10 +737,30 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
751 | if (secondlen > 0) { | 737 | if (secondlen > 0) { |
752 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, | 738 | phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, |
753 | secondlen, PCI_DMA_TODEVICE); | 739 | secondlen, PCI_DMA_TODEVICE); |
740 | if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) { | ||
741 | pci_unmap_single(priv->pci_dev, | ||
742 | dma_unmap_addr(out_meta, mapping), | ||
743 | dma_unmap_len(out_meta, len), | ||
744 | PCI_DMA_BIDIRECTIONAL); | ||
745 | goto drop_unlock_sta; | ||
746 | } | ||
747 | } | ||
748 | |||
749 | if (ieee80211_is_data_qos(fc)) { | ||
750 | priv->stations[sta_id].tid[tid].tfds_in_queue++; | ||
751 | if (!ieee80211_has_morefrags(fc)) | ||
752 | priv->stations[sta_id].tid[tid].seq_number = seq_number; | ||
753 | } | ||
754 | |||
755 | spin_unlock(&priv->sta_lock); | ||
756 | |||
757 | /* Attach buffers to TFD */ | ||
758 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | ||
759 | txcmd_phys, firstlen, 1, 0); | ||
760 | if (secondlen > 0) | ||
754 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | 761 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, |
755 | phys_addr, secondlen, | 762 | phys_addr, secondlen, |
756 | 0, 0); | 763 | 0, 0); |
757 | } | ||
758 | 764 | ||
759 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + | 765 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + |
760 | offsetof(struct iwl_tx_cmd, scratch); | 766 | offsetof(struct iwl_tx_cmd, scratch); |
@@ -773,8 +779,8 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
773 | 779 | ||
774 | /* Set up entry for this TFD in Tx byte-count array */ | 780 | /* Set up entry for this TFD in Tx byte-count array */ |
775 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | 781 | if (info->flags & IEEE80211_TX_CTL_AMPDU) |
776 | priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, | 782 | iwlagn_txq_update_byte_cnt_tbl(priv, txq, |
777 | le16_to_cpu(tx_cmd->len)); | 783 | le16_to_cpu(tx_cmd->len)); |
778 | 784 | ||
779 | pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, | 785 | pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, |
780 | firstlen, PCI_DMA_BIDIRECTIONAL); | 786 | firstlen, PCI_DMA_BIDIRECTIONAL); |
@@ -820,7 +826,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
820 | 826 | ||
821 | return 0; | 827 | return 0; |
822 | 828 | ||
823 | drop_unlock: | 829 | drop_unlock_sta: |
830 | spin_unlock(&priv->sta_lock); | ||
831 | drop_unlock_priv: | ||
824 | spin_unlock_irqrestore(&priv->lock, flags); | 832 | spin_unlock_irqrestore(&priv->lock, flags); |
825 | return -1; | 833 | return -1; |
826 | } | 834 | } |
@@ -1253,8 +1261,7 @@ int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) | |||
1253 | txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); | 1261 | txq_id >= IWLAGN_FIRST_AMPDU_QUEUE); |
1254 | tx_info->skb = NULL; | 1262 | tx_info->skb = NULL; |
1255 | 1263 | ||
1256 | if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) | 1264 | iwlagn_txq_inval_byte_cnt_tbl(priv, txq); |
1257 | priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); | ||
1258 | 1265 | ||
1259 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | 1266 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); |
1260 | } | 1267 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c index c3ae2e44fcc9..8bda0e8d6661 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c | |||
@@ -269,7 +269,7 @@ void iwlagn_rx_calib_result(struct iwl_priv *priv, | |||
269 | iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); | 269 | iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); |
270 | } | 270 | } |
271 | 271 | ||
272 | static int iwlagn_init_alive_start(struct iwl_priv *priv) | 272 | int iwlagn_init_alive_start(struct iwl_priv *priv) |
273 | { | 273 | { |
274 | int ret; | 274 | int ret; |
275 | 275 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 003d5243542b..3ecc3198d9bf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -102,70 +102,6 @@ void iwl_update_chain_flags(struct iwl_priv *priv) | |||
102 | } | 102 | } |
103 | } | 103 | } |
104 | 104 | ||
105 | static void iwl_clear_free_frames(struct iwl_priv *priv) | ||
106 | { | ||
107 | struct list_head *element; | ||
108 | |||
109 | IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n", | ||
110 | priv->frames_count); | ||
111 | |||
112 | while (!list_empty(&priv->free_frames)) { | ||
113 | element = priv->free_frames.next; | ||
114 | list_del(element); | ||
115 | kfree(list_entry(element, struct iwl_frame, list)); | ||
116 | priv->frames_count--; | ||
117 | } | ||
118 | |||
119 | if (priv->frames_count) { | ||
120 | IWL_WARN(priv, "%d frames still in use. Did we lose one?\n", | ||
121 | priv->frames_count); | ||
122 | priv->frames_count = 0; | ||
123 | } | ||
124 | } | ||
125 | |||
126 | static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv) | ||
127 | { | ||
128 | struct iwl_frame *frame; | ||
129 | struct list_head *element; | ||
130 | if (list_empty(&priv->free_frames)) { | ||
131 | frame = kzalloc(sizeof(*frame), GFP_KERNEL); | ||
132 | if (!frame) { | ||
133 | IWL_ERR(priv, "Could not allocate frame!\n"); | ||
134 | return NULL; | ||
135 | } | ||
136 | |||
137 | priv->frames_count++; | ||
138 | return frame; | ||
139 | } | ||
140 | |||
141 | element = priv->free_frames.next; | ||
142 | list_del(element); | ||
143 | return list_entry(element, struct iwl_frame, list); | ||
144 | } | ||
145 | |||
146 | static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame) | ||
147 | { | ||
148 | memset(frame, 0, sizeof(*frame)); | ||
149 | list_add(&frame->list, &priv->free_frames); | ||
150 | } | ||
151 | |||
152 | static u32 iwl_fill_beacon_frame(struct iwl_priv *priv, | ||
153 | struct ieee80211_hdr *hdr, | ||
154 | int left) | ||
155 | { | ||
156 | lockdep_assert_held(&priv->mutex); | ||
157 | |||
158 | if (!priv->beacon_skb) | ||
159 | return 0; | ||
160 | |||
161 | if (priv->beacon_skb->len > left) | ||
162 | return 0; | ||
163 | |||
164 | memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len); | ||
165 | |||
166 | return priv->beacon_skb->len; | ||
167 | } | ||
168 | |||
169 | /* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */ | 105 | /* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */ |
170 | static void iwl_set_beacon_tim(struct iwl_priv *priv, | 106 | static void iwl_set_beacon_tim(struct iwl_priv *priv, |
171 | struct iwl_tx_beacon_cmd *tx_beacon_cmd, | 107 | struct iwl_tx_beacon_cmd *tx_beacon_cmd, |
@@ -193,13 +129,18 @@ static void iwl_set_beacon_tim(struct iwl_priv *priv, | |||
193 | IWL_WARN(priv, "Unable to find TIM Element in beacon\n"); | 129 | IWL_WARN(priv, "Unable to find TIM Element in beacon\n"); |
194 | } | 130 | } |
195 | 131 | ||
196 | static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, | 132 | int iwlagn_send_beacon_cmd(struct iwl_priv *priv) |
197 | struct iwl_frame *frame) | ||
198 | { | 133 | { |
199 | struct iwl_tx_beacon_cmd *tx_beacon_cmd; | 134 | struct iwl_tx_beacon_cmd *tx_beacon_cmd; |
135 | struct iwl_host_cmd cmd = { | ||
136 | .id = REPLY_TX_BEACON, | ||
137 | .flags = CMD_SIZE_HUGE, | ||
138 | }; | ||
200 | u32 frame_size; | 139 | u32 frame_size; |
201 | u32 rate_flags; | 140 | u32 rate_flags; |
202 | u32 rate; | 141 | u32 rate; |
142 | int err; | ||
143 | |||
203 | /* | 144 | /* |
204 | * We have to set up the TX command, the TX Beacon command, and the | 145 | * We have to set up the TX command, the TX Beacon command, and the |
205 | * beacon contents. | 146 | * beacon contents. |
@@ -212,17 +153,19 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, | |||
212 | return 0; | 153 | return 0; |
213 | } | 154 | } |
214 | 155 | ||
215 | /* Initialize memory */ | 156 | if (WARN_ON(!priv->beacon_skb)) |
216 | tx_beacon_cmd = &frame->u.beacon; | 157 | return -EINVAL; |
217 | memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); | 158 | |
159 | /* Allocate beacon memory */ | ||
160 | tx_beacon_cmd = kzalloc(sizeof(*tx_beacon_cmd) + priv->beacon_skb->len, | ||
161 | GFP_KERNEL); | ||
162 | if (!tx_beacon_cmd) | ||
163 | return -ENOMEM; | ||
164 | |||
165 | frame_size = priv->beacon_skb->len; | ||
218 | 166 | ||
219 | /* Set up TX beacon contents */ | 167 | /* Set up TX beacon contents */ |
220 | frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame, | 168 | memcpy(tx_beacon_cmd->frame, priv->beacon_skb->data, frame_size); |
221 | sizeof(frame->u) - sizeof(*tx_beacon_cmd)); | ||
222 | if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE)) | ||
223 | return 0; | ||
224 | if (!frame_size) | ||
225 | return 0; | ||
226 | 169 | ||
227 | /* Set up TX command fields */ | 170 | /* Set up TX command fields */ |
228 | tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); | 171 | tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); |
@@ -245,41 +188,16 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, | |||
245 | tx_beacon_cmd->tx.rate_n_flags = iwl_hw_set_rate_n_flags(rate, | 188 | tx_beacon_cmd->tx.rate_n_flags = iwl_hw_set_rate_n_flags(rate, |
246 | rate_flags); | 189 | rate_flags); |
247 | 190 | ||
248 | return sizeof(*tx_beacon_cmd) + frame_size; | 191 | /* Submit command */ |
249 | } | 192 | cmd.len = sizeof(*tx_beacon_cmd) + frame_size; |
193 | cmd.data = tx_beacon_cmd; | ||
250 | 194 | ||
251 | int iwlagn_send_beacon_cmd(struct iwl_priv *priv) | 195 | err = iwl_send_cmd_sync(priv, &cmd); |
252 | { | ||
253 | struct iwl_frame *frame; | ||
254 | unsigned int frame_size; | ||
255 | int rc; | ||
256 | struct iwl_host_cmd cmd = { | ||
257 | .id = REPLY_TX_BEACON, | ||
258 | .flags = CMD_SIZE_HUGE, | ||
259 | }; | ||
260 | |||
261 | frame = iwl_get_free_frame(priv); | ||
262 | if (!frame) { | ||
263 | IWL_ERR(priv, "Could not obtain free frame buffer for beacon " | ||
264 | "command.\n"); | ||
265 | return -ENOMEM; | ||
266 | } | ||
267 | |||
268 | frame_size = iwl_hw_get_beacon_cmd(priv, frame); | ||
269 | if (!frame_size) { | ||
270 | IWL_ERR(priv, "Error configuring the beacon command\n"); | ||
271 | iwl_free_frame(priv, frame); | ||
272 | return -EINVAL; | ||
273 | } | ||
274 | |||
275 | cmd.len = frame_size; | ||
276 | cmd.data = &frame->u.cmd[0]; | ||
277 | |||
278 | rc = iwl_send_cmd_sync(priv, &cmd); | ||
279 | 196 | ||
280 | iwl_free_frame(priv, frame); | 197 | /* Free temporary storage */ |
198 | kfree(tx_beacon_cmd); | ||
281 | 199 | ||
282 | return rc; | 200 | return err; |
283 | } | 201 | } |
284 | 202 | ||
285 | static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) | 203 | static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) |
@@ -776,6 +694,8 @@ static void iwl_rx_handle(struct iwl_priv *priv) | |||
776 | 694 | ||
777 | wake_up_all(&priv->_agn.notif_waitq); | 695 | wake_up_all(&priv->_agn.notif_waitq); |
778 | } | 696 | } |
697 | if (priv->pre_rx_handler) | ||
698 | priv->pre_rx_handler(priv, rxb); | ||
779 | 699 | ||
780 | /* Based on type of command response or notification, | 700 | /* Based on type of command response or notification, |
781 | * handle those that need handling via function in | 701 | * handle those that need handling via function in |
@@ -2211,7 +2131,7 @@ static int iwlagn_send_calib_cfg_rt(struct iwl_priv *priv, u32 cfg) | |||
2211 | * from protocol/runtime uCode (initialization uCode's | 2131 | * from protocol/runtime uCode (initialization uCode's |
2212 | * Alive gets handled by iwl_init_alive_start()). | 2132 | * Alive gets handled by iwl_init_alive_start()). |
2213 | */ | 2133 | */ |
2214 | static int iwl_alive_start(struct iwl_priv *priv) | 2134 | int iwl_alive_start(struct iwl_priv *priv) |
2215 | { | 2135 | { |
2216 | int ret = 0; | 2136 | int ret = 0; |
2217 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | 2137 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; |
@@ -2354,9 +2274,6 @@ static void __iwl_down(struct iwl_priv *priv) | |||
2354 | 2274 | ||
2355 | dev_kfree_skb(priv->beacon_skb); | 2275 | dev_kfree_skb(priv->beacon_skb); |
2356 | priv->beacon_skb = NULL; | 2276 | priv->beacon_skb = NULL; |
2357 | |||
2358 | /* clear out any free frames */ | ||
2359 | iwl_clear_free_frames(priv); | ||
2360 | } | 2277 | } |
2361 | 2278 | ||
2362 | static void iwl_down(struct iwl_priv *priv) | 2279 | static void iwl_down(struct iwl_priv *priv) |
@@ -3414,8 +3331,6 @@ static int iwl_init_drv(struct iwl_priv *priv) | |||
3414 | spin_lock_init(&priv->sta_lock); | 3331 | spin_lock_init(&priv->sta_lock); |
3415 | spin_lock_init(&priv->hcmd_lock); | 3332 | spin_lock_init(&priv->hcmd_lock); |
3416 | 3333 | ||
3417 | INIT_LIST_HEAD(&priv->free_frames); | ||
3418 | |||
3419 | mutex_init(&priv->mutex); | 3334 | mutex_init(&priv->mutex); |
3420 | 3335 | ||
3421 | priv->ieee_channels = NULL; | 3336 | priv->ieee_channels = NULL; |
@@ -3507,6 +3422,7 @@ struct ieee80211_ops iwlagn_hw_ops = { | |||
3507 | .cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel, | 3422 | .cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel, |
3508 | .offchannel_tx = iwl_mac_offchannel_tx, | 3423 | .offchannel_tx = iwl_mac_offchannel_tx, |
3509 | .offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait, | 3424 | .offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait, |
3425 | CFG80211_TESTMODE_CMD(iwl_testmode_cmd) | ||
3510 | }; | 3426 | }; |
3511 | 3427 | ||
3512 | static u32 iwl_hw_detect(struct iwl_priv *priv) | 3428 | static u32 iwl_hw_detect(struct iwl_priv *priv) |
@@ -3816,6 +3732,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
3816 | 3732 | ||
3817 | iwl_setup_deferred_work(priv); | 3733 | iwl_setup_deferred_work(priv); |
3818 | iwl_setup_rx_handlers(priv); | 3734 | iwl_setup_rx_handlers(priv); |
3735 | iwl_testmode_init(priv); | ||
3819 | 3736 | ||
3820 | /********************************************* | 3737 | /********************************************* |
3821 | * 8. Enable interrupts and read RFKILL state | 3738 | * 8. Enable interrupts and read RFKILL state |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index b477336ff53a..fe33fe8aa418 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -139,11 +139,6 @@ void iwlagn_set_wr_ptrs(struct iwl_priv *priv, | |||
139 | void iwlagn_tx_queue_set_status(struct iwl_priv *priv, | 139 | void iwlagn_tx_queue_set_status(struct iwl_priv *priv, |
140 | struct iwl_tx_queue *txq, | 140 | struct iwl_tx_queue *txq, |
141 | int tx_fifo_id, int scd_retry); | 141 | int tx_fifo_id, int scd_retry); |
142 | void iwlagn_txq_update_byte_cnt_tbl(struct iwl_priv *priv, | ||
143 | struct iwl_tx_queue *txq, | ||
144 | u16 byte_cnt); | ||
145 | void iwlagn_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, | ||
146 | struct iwl_tx_queue *txq); | ||
147 | void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); | 142 | void iwlagn_txq_set_sched(struct iwl_priv *priv, u32 mask); |
148 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, | 143 | void iwl_free_tfds_in_queue(struct iwl_priv *priv, |
149 | int sta_id, int tid, int freed); | 144 | int sta_id, int tid, int freed); |
@@ -344,5 +339,22 @@ iwlagn_wait_notification(struct iwl_priv *priv, | |||
344 | void __releases(wait_entry) | 339 | void __releases(wait_entry) |
345 | iwlagn_remove_notification(struct iwl_priv *priv, | 340 | iwlagn_remove_notification(struct iwl_priv *priv, |
346 | struct iwl_notification_wait *wait_entry); | 341 | struct iwl_notification_wait *wait_entry); |
342 | extern int iwlagn_init_alive_start(struct iwl_priv *priv); | ||
343 | extern int iwl_alive_start(struct iwl_priv *priv); | ||
344 | /* svtool */ | ||
345 | #ifdef CONFIG_IWLWIFI_DEVICE_SVTOOL | ||
346 | extern int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len); | ||
347 | extern void iwl_testmode_init(struct iwl_priv *priv); | ||
348 | #else | ||
349 | static inline | ||
350 | int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) | ||
351 | { | ||
352 | return -ENOSYS; | ||
353 | } | ||
354 | static inline | ||
355 | void iwl_testmode_init(struct iwl_priv *priv) | ||
356 | { | ||
357 | } | ||
358 | #endif | ||
347 | 359 | ||
348 | #endif /* __iwl_agn_h__ */ | 360 | #endif /* __iwl_agn_h__ */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index dec9820753f8..5b5b0cce4a54 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -99,7 +99,6 @@ struct iwl_hcmd_ops { | |||
99 | }; | 99 | }; |
100 | 100 | ||
101 | struct iwl_hcmd_utils_ops { | 101 | struct iwl_hcmd_utils_ops { |
102 | u16 (*get_hcmd_size)(u8 cmd_id, u16 len); | ||
103 | u16 (*build_addsta_hcmd)(const struct iwl_addsta_cmd *cmd, u8 *data); | 102 | u16 (*build_addsta_hcmd)(const struct iwl_addsta_cmd *cmd, u8 *data); |
104 | void (*gain_computation)(struct iwl_priv *priv, | 103 | void (*gain_computation)(struct iwl_priv *priv, |
105 | u32 *average_noise, | 104 | u32 *average_noise, |
@@ -129,11 +128,6 @@ struct iwl_lib_ops { | |||
129 | /* set hw dependent parameters */ | 128 | /* set hw dependent parameters */ |
130 | int (*set_hw_params)(struct iwl_priv *priv); | 129 | int (*set_hw_params)(struct iwl_priv *priv); |
131 | /* Handling TX */ | 130 | /* Handling TX */ |
132 | void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv, | ||
133 | struct iwl_tx_queue *txq, | ||
134 | u16 byte_cnt); | ||
135 | void (*txq_inval_byte_cnt_tbl)(struct iwl_priv *priv, | ||
136 | struct iwl_tx_queue *txq); | ||
137 | void (*txq_set_sched)(struct iwl_priv *priv, u32 mask); | 131 | void (*txq_set_sched)(struct iwl_priv *priv, u32 mask); |
138 | int (*txq_attach_buf_to_tfd)(struct iwl_priv *priv, | 132 | int (*txq_attach_buf_to_tfd)(struct iwl_priv *priv, |
139 | struct iwl_tx_queue *txq, | 133 | struct iwl_tx_queue *txq, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index f098eff263f8..214e4658c495 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -238,15 +238,6 @@ struct iwl_channel_info { | |||
238 | #define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) | 238 | #define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) |
239 | #define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) | 239 | #define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) |
240 | 240 | ||
241 | struct iwl_frame { | ||
242 | union { | ||
243 | struct ieee80211_hdr frame; | ||
244 | struct iwl_tx_beacon_cmd beacon; | ||
245 | u8 raw[IEEE80211_FRAME_LEN]; | ||
246 | u8 cmd[360]; | ||
247 | } u; | ||
248 | struct list_head list; | ||
249 | }; | ||
250 | 241 | ||
251 | #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) | 242 | #define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) |
252 | #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) | 243 | #define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) |
@@ -1188,12 +1179,10 @@ struct iwl_priv { | |||
1188 | struct ieee80211_rate *ieee_rates; | 1179 | struct ieee80211_rate *ieee_rates; |
1189 | struct iwl_cfg *cfg; | 1180 | struct iwl_cfg *cfg; |
1190 | 1181 | ||
1191 | /* temporary frame storage list */ | ||
1192 | struct list_head free_frames; | ||
1193 | int frames_count; | ||
1194 | |||
1195 | enum ieee80211_band band; | 1182 | enum ieee80211_band band; |
1196 | 1183 | ||
1184 | void (*pre_rx_handler)(struct iwl_priv *priv, | ||
1185 | struct iwl_rx_mem_buffer *rxb); | ||
1197 | void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, | 1186 | void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, |
1198 | struct iwl_rx_mem_buffer *rxb); | 1187 | struct iwl_rx_mem_buffer *rxb); |
1199 | 1188 | ||
@@ -1569,21 +1558,24 @@ iwl_rxon_ctx_from_vif(struct ieee80211_vif *vif) | |||
1569 | ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++) \ | 1558 | ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++) \ |
1570 | if (priv->valid_contexts & BIT(ctx->ctxid)) | 1559 | if (priv->valid_contexts & BIT(ctx->ctxid)) |
1571 | 1560 | ||
1572 | static inline int iwl_is_associated(struct iwl_priv *priv, | 1561 | static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx) |
1573 | enum iwl_rxon_context_id ctxid) | ||
1574 | { | 1562 | { |
1575 | return (priv->contexts[ctxid].active.filter_flags & | 1563 | return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; |
1576 | RXON_FILTER_ASSOC_MSK) ? 1 : 0; | ||
1577 | } | 1564 | } |
1578 | 1565 | ||
1579 | static inline int iwl_is_any_associated(struct iwl_priv *priv) | 1566 | static inline int iwl_is_associated(struct iwl_priv *priv, |
1567 | enum iwl_rxon_context_id ctxid) | ||
1580 | { | 1568 | { |
1581 | return iwl_is_associated(priv, IWL_RXON_CTX_BSS); | 1569 | return iwl_is_associated_ctx(&priv->contexts[ctxid]); |
1582 | } | 1570 | } |
1583 | 1571 | ||
1584 | static inline int iwl_is_associated_ctx(struct iwl_rxon_context *ctx) | 1572 | static inline int iwl_is_any_associated(struct iwl_priv *priv) |
1585 | { | 1573 | { |
1586 | return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; | 1574 | struct iwl_rxon_context *ctx; |
1575 | for_each_context(priv, ctx) | ||
1576 | if (iwl_is_associated_ctx(ctx)) | ||
1577 | return true; | ||
1578 | return false; | ||
1587 | } | 1579 | } |
1588 | 1580 | ||
1589 | static inline int is_channel_valid(const struct iwl_channel_info *ch_info) | 1581 | static inline int is_channel_valid(const struct iwl_channel_info *ch_info) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index d798c2a152d3..439187f903c9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c | |||
@@ -48,8 +48,21 @@ module_param(led_mode, int, S_IRUGO); | |||
48 | MODULE_PARM_DESC(led_mode, "0=system default, " | 48 | MODULE_PARM_DESC(led_mode, "0=system default, " |
49 | "1=On(RF On)/Off(RF Off), 2=blinking"); | 49 | "1=On(RF On)/Off(RF Off), 2=blinking"); |
50 | 50 | ||
51 | /* Throughput OFF time(ms) ON time (ms) | ||
52 | * >300 25 25 | ||
53 | * >200 to 300 40 40 | ||
54 | * >100 to 200 55 55 | ||
55 | * >70 to 100 65 65 | ||
56 | * >50 to 70 75 75 | ||
57 | * >20 to 50 85 85 | ||
58 | * >10 to 20 95 95 | ||
59 | * >5 to 10 110 110 | ||
60 | * >1 to 5 130 130 | ||
61 | * >0 to 1 167 167 | ||
62 | * <=0 SOLID ON | ||
63 | */ | ||
51 | static const struct ieee80211_tpt_blink iwl_blink[] = { | 64 | static const struct ieee80211_tpt_blink iwl_blink[] = { |
52 | { .throughput = 0 * 1024 - 1, .blink_time = 334 }, | 65 | { .throughput = 0, .blink_time = 334 }, |
53 | { .throughput = 1 * 1024 - 1, .blink_time = 260 }, | 66 | { .throughput = 1 * 1024 - 1, .blink_time = 260 }, |
54 | { .throughput = 5 * 1024 - 1, .blink_time = 220 }, | 67 | { .throughput = 5 * 1024 - 1, .blink_time = 220 }, |
55 | { .throughput = 10 * 1024 - 1, .blink_time = 190 }, | 68 | { .throughput = 10 * 1024 - 1, .blink_time = 190 }, |
@@ -125,6 +138,11 @@ static int iwl_led_cmd(struct iwl_priv *priv, | |||
125 | if (priv->blink_on == on && priv->blink_off == off) | 138 | if (priv->blink_on == on && priv->blink_off == off) |
126 | return 0; | 139 | return 0; |
127 | 140 | ||
141 | if (off == 0) { | ||
142 | /* led is SOLID_ON */ | ||
143 | on = IWL_LED_SOLID; | ||
144 | } | ||
145 | |||
128 | IWL_DEBUG_LED(priv, "Led blink time compensation=%u\n", | 146 | IWL_DEBUG_LED(priv, "Led blink time compensation=%u\n", |
129 | priv->cfg->base_params->led_compensation); | 147 | priv->cfg->base_params->led_compensation); |
130 | led_cmd.on = iwl_blink_compensation(priv, on, | 148 | led_cmd.on = iwl_blink_compensation(priv, on, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-sv-open.c b/drivers/net/wireless/iwlwifi/iwl-sv-open.c new file mode 100644 index 000000000000..89b6696622c1 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-sv-open.c | |||
@@ -0,0 +1,469 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | #include <linux/init.h> | ||
64 | #include <linux/kernel.h> | ||
65 | #include <linux/module.h> | ||
66 | #include <net/net_namespace.h> | ||
67 | #include <linux/netdevice.h> | ||
68 | #include <net/cfg80211.h> | ||
69 | #include <net/mac80211.h> | ||
70 | #include <net/netlink.h> | ||
71 | |||
72 | |||
73 | #include "iwl-dev.h" | ||
74 | #include "iwl-core.h" | ||
75 | #include "iwl-debug.h" | ||
76 | #include "iwl-fh.h" | ||
77 | #include "iwl-io.h" | ||
78 | #include "iwl-agn.h" | ||
79 | #include "iwl-testmode.h" | ||
80 | |||
81 | |||
82 | /* The TLVs used in the gnl message policy between the kernel module and | ||
83 | * user space application. iwl_testmode_gnl_msg_policy is to be carried | ||
84 | * through the NL80211_CMD_TESTMODE channel regulated by nl80211. | ||
85 | * See iwl-testmode.h | ||
86 | */ | ||
87 | static | ||
88 | struct nla_policy iwl_testmode_gnl_msg_policy[IWL_TM_ATTR_MAX] = { | ||
89 | [IWL_TM_ATTR_COMMAND] = { .type = NLA_U32, }, | ||
90 | |||
91 | [IWL_TM_ATTR_UCODE_CMD_ID] = { .type = NLA_U8, }, | ||
92 | [IWL_TM_ATTR_UCODE_CMD_DATA] = { .type = NLA_UNSPEC, }, | ||
93 | |||
94 | [IWL_TM_ATTR_REG_OFFSET] = { .type = NLA_U32, }, | ||
95 | [IWL_TM_ATTR_REG_VALUE8] = { .type = NLA_U8, }, | ||
96 | [IWL_TM_ATTR_REG_VALUE32] = { .type = NLA_U32, }, | ||
97 | |||
98 | [IWL_TM_ATTR_SYNC_RSP] = { .type = NLA_UNSPEC, }, | ||
99 | [IWL_TM_ATTR_UCODE_RX_PKT] = { .type = NLA_UNSPEC, }, | ||
100 | }; | ||
101 | |||
102 | /* | ||
103 | * See the struct iwl_rx_packet in iwl-commands.h for the format of the | ||
104 | * received events from the device | ||
105 | */ | ||
106 | static inline int get_event_length(struct iwl_rx_mem_buffer *rxb) | ||
107 | { | ||
108 | struct iwl_rx_packet *pkt = rxb_addr(rxb); | ||
109 | if (pkt) | ||
110 | return le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; | ||
111 | else | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | |||
116 | /* | ||
117 | * This function multicasts the spontaneous messages from the device to the | ||
118 | * user space. It is invoked whenever there is a received messages | ||
119 | * from the device. This function is called within the ISR of the rx handlers | ||
120 | * in iwlagn driver. | ||
121 | * | ||
122 | * The parsing of the message content is left to the user space application, | ||
123 | * The message content is treated as unattacked raw data and is encapsulated | ||
124 | * with IWL_TM_ATTR_UCODE_RX_PKT multicasting to the user space. | ||
125 | * | ||
126 | * @priv: the instance of iwlwifi device | ||
127 | * @rxb: pointer to rx data content received by the ISR | ||
128 | * | ||
129 | * See the message policies and TLVs in iwl_testmode_gnl_msg_policy[]. | ||
130 | * For the messages multicasting to the user application, the mandatory | ||
131 | * TLV fields are : | ||
132 | * IWL_TM_ATTR_COMMAND must be IWL_TM_CMD_DEV2APP_UCODE_RX_PKT | ||
133 | * IWL_TM_ATTR_UCODE_RX_PKT for carrying the message content | ||
134 | */ | ||
135 | |||
136 | static void iwl_testmode_ucode_rx_pkt(struct iwl_priv *priv, | ||
137 | struct iwl_rx_mem_buffer *rxb) | ||
138 | { | ||
139 | struct ieee80211_hw *hw = priv->hw; | ||
140 | struct sk_buff *skb; | ||
141 | void *data; | ||
142 | int length; | ||
143 | |||
144 | data = (void *)rxb_addr(rxb); | ||
145 | length = get_event_length(rxb); | ||
146 | |||
147 | if (!data || length == 0) | ||
148 | return; | ||
149 | |||
150 | skb = cfg80211_testmode_alloc_event_skb(hw->wiphy, 20 + length, | ||
151 | GFP_ATOMIC); | ||
152 | if (skb == NULL) { | ||
153 | IWL_DEBUG_INFO(priv, | ||
154 | "Run out of memory for messages to user space ?\n"); | ||
155 | return; | ||
156 | } | ||
157 | NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, IWL_TM_CMD_DEV2APP_UCODE_RX_PKT); | ||
158 | NLA_PUT(skb, IWL_TM_ATTR_UCODE_RX_PKT, length, data); | ||
159 | cfg80211_testmode_event(skb, GFP_ATOMIC); | ||
160 | return; | ||
161 | |||
162 | nla_put_failure: | ||
163 | kfree_skb(skb); | ||
164 | IWL_DEBUG_INFO(priv, "Ouch, overran buffer, check allocation!\n"); | ||
165 | } | ||
166 | |||
167 | void iwl_testmode_init(struct iwl_priv *priv) | ||
168 | { | ||
169 | priv->pre_rx_handler = iwl_testmode_ucode_rx_pkt; | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * This function handles the user application commands to the ucode. | ||
174 | * | ||
175 | * It retrieves the mandatory fields IWL_TM_ATTR_UCODE_CMD_ID and | ||
176 | * IWL_TM_ATTR_UCODE_CMD_DATA and calls to the handler to send the | ||
177 | * host command to the ucode. | ||
178 | * | ||
179 | * If any mandatory field is missing, -ENOMSG is replied to the user space | ||
180 | * application; otherwise, the actual execution result of the host command to | ||
181 | * ucode is replied. | ||
182 | * | ||
183 | * @hw: ieee80211_hw object that represents the device | ||
184 | * @tb: gnl message fields from the user space | ||
185 | */ | ||
186 | static int iwl_testmode_ucode(struct ieee80211_hw *hw, struct nlattr **tb) | ||
187 | { | ||
188 | struct iwl_priv *priv = hw->priv; | ||
189 | struct iwl_host_cmd cmd; | ||
190 | |||
191 | memset(&cmd, 0, sizeof(struct iwl_host_cmd)); | ||
192 | |||
193 | if (!tb[IWL_TM_ATTR_UCODE_CMD_ID] || | ||
194 | !tb[IWL_TM_ATTR_UCODE_CMD_DATA]) { | ||
195 | IWL_DEBUG_INFO(priv, | ||
196 | "Error finding ucode command mandatory fields\n"); | ||
197 | return -ENOMSG; | ||
198 | } | ||
199 | |||
200 | cmd.id = nla_get_u8(tb[IWL_TM_ATTR_UCODE_CMD_ID]); | ||
201 | cmd.data = nla_data(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); | ||
202 | cmd.len = nla_len(tb[IWL_TM_ATTR_UCODE_CMD_DATA]); | ||
203 | IWL_INFO(priv, "testmode ucode command ID 0x%x, flags 0x%x," | ||
204 | " len %d\n", cmd.id, cmd.flags, cmd.len); | ||
205 | /* ok, let's submit the command to ucode */ | ||
206 | return iwl_send_cmd(priv, &cmd); | ||
207 | } | ||
208 | |||
209 | |||
210 | /* | ||
211 | * This function handles the user application commands for register access. | ||
212 | * | ||
213 | * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the | ||
214 | * handlers respectively. | ||
215 | * | ||
216 | * If it's an unknown commdn ID, -ENOSYS is returned; or -ENOMSG if the | ||
217 | * mandatory fields(IWL_TM_ATTR_REG_OFFSET,IWL_TM_ATTR_REG_VALUE32, | ||
218 | * IWL_TM_ATTR_REG_VALUE8) are missing; Otherwise 0 is replied indicating | ||
219 | * the success of the command execution. | ||
220 | * | ||
221 | * If IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_READ32, the register read | ||
222 | * value is returned with IWL_TM_ATTR_REG_VALUE32. | ||
223 | * | ||
224 | * @hw: ieee80211_hw object that represents the device | ||
225 | * @tb: gnl message fields from the user space | ||
226 | */ | ||
227 | static int iwl_testmode_reg(struct ieee80211_hw *hw, struct nlattr **tb) | ||
228 | { | ||
229 | struct iwl_priv *priv = hw->priv; | ||
230 | u32 ofs, val32; | ||
231 | u8 val8; | ||
232 | struct sk_buff *skb; | ||
233 | int status = 0; | ||
234 | |||
235 | if (!tb[IWL_TM_ATTR_REG_OFFSET]) { | ||
236 | IWL_DEBUG_INFO(priv, "Error finding register offset\n"); | ||
237 | return -ENOMSG; | ||
238 | } | ||
239 | ofs = nla_get_u32(tb[IWL_TM_ATTR_REG_OFFSET]); | ||
240 | IWL_INFO(priv, "testmode register access command offset 0x%x\n", ofs); | ||
241 | |||
242 | switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { | ||
243 | case IWL_TM_CMD_APP2DEV_REG_READ32: | ||
244 | val32 = iwl_read32(priv, ofs); | ||
245 | IWL_INFO(priv, "32bit value to read 0x%x\n", val32); | ||
246 | |||
247 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, 20); | ||
248 | if (!skb) { | ||
249 | IWL_DEBUG_INFO(priv, "Error allocating memory\n"); | ||
250 | return -ENOMEM; | ||
251 | } | ||
252 | NLA_PUT_U32(skb, IWL_TM_ATTR_REG_VALUE32, val32); | ||
253 | status = cfg80211_testmode_reply(skb); | ||
254 | if (status < 0) | ||
255 | IWL_DEBUG_INFO(priv, | ||
256 | "Error sending msg : %d\n", status); | ||
257 | break; | ||
258 | case IWL_TM_CMD_APP2DEV_REG_WRITE32: | ||
259 | if (!tb[IWL_TM_ATTR_REG_VALUE32]) { | ||
260 | IWL_DEBUG_INFO(priv, | ||
261 | "Error finding value to write\n"); | ||
262 | return -ENOMSG; | ||
263 | } else { | ||
264 | val32 = nla_get_u32(tb[IWL_TM_ATTR_REG_VALUE32]); | ||
265 | IWL_INFO(priv, "32bit value to write 0x%x\n", val32); | ||
266 | iwl_write32(priv, ofs, val32); | ||
267 | } | ||
268 | break; | ||
269 | case IWL_TM_CMD_APP2DEV_REG_WRITE8: | ||
270 | if (!tb[IWL_TM_ATTR_REG_VALUE8]) { | ||
271 | IWL_DEBUG_INFO(priv, "Error finding value to write\n"); | ||
272 | return -ENOMSG; | ||
273 | } else { | ||
274 | val8 = nla_get_u8(tb[IWL_TM_ATTR_REG_VALUE8]); | ||
275 | IWL_INFO(priv, "8bit value to write 0x%x\n", val8); | ||
276 | iwl_write8(priv, ofs, val8); | ||
277 | } | ||
278 | break; | ||
279 | default: | ||
280 | IWL_DEBUG_INFO(priv, "Unknown testmode register command ID\n"); | ||
281 | return -ENOSYS; | ||
282 | } | ||
283 | |||
284 | return status; | ||
285 | |||
286 | nla_put_failure: | ||
287 | kfree_skb(skb); | ||
288 | return -EMSGSIZE; | ||
289 | } | ||
290 | |||
291 | |||
292 | static int iwl_testmode_cfg_init_calib(struct iwl_priv *priv) | ||
293 | { | ||
294 | struct iwl_notification_wait calib_wait; | ||
295 | int ret; | ||
296 | |||
297 | iwlagn_init_notification_wait(priv, &calib_wait, | ||
298 | CALIBRATION_COMPLETE_NOTIFICATION, | ||
299 | NULL, NULL); | ||
300 | ret = iwlagn_init_alive_start(priv); | ||
301 | if (ret) { | ||
302 | IWL_DEBUG_INFO(priv, | ||
303 | "Error configuring init calibration: %d\n", ret); | ||
304 | goto cfg_init_calib_error; | ||
305 | } | ||
306 | |||
307 | ret = iwlagn_wait_notification(priv, &calib_wait, 2 * HZ); | ||
308 | if (ret) | ||
309 | IWL_DEBUG_INFO(priv, "Error detecting" | ||
310 | " CALIBRATION_COMPLETE_NOTIFICATION: %d\n", ret); | ||
311 | return ret; | ||
312 | |||
313 | cfg_init_calib_error: | ||
314 | iwlagn_remove_notification(priv, &calib_wait); | ||
315 | return ret; | ||
316 | } | ||
317 | |||
318 | /* | ||
319 | * This function handles the user application commands for driver. | ||
320 | * | ||
321 | * It retrieves command ID carried with IWL_TM_ATTR_COMMAND and calls to the | ||
322 | * handlers respectively. | ||
323 | * | ||
324 | * If it's an unknown commdn ID, -ENOSYS is replied; otherwise, the returned | ||
325 | * value of the actual command execution is replied to the user application. | ||
326 | * | ||
327 | * If there's any message responding to the user space, IWL_TM_ATTR_SYNC_RSP | ||
328 | * is used for carry the message while IWL_TM_ATTR_COMMAND must set to | ||
329 | * IWL_TM_CMD_DEV2APP_SYNC_RSP. | ||
330 | * | ||
331 | * @hw: ieee80211_hw object that represents the device | ||
332 | * @tb: gnl message fields from the user space | ||
333 | */ | ||
334 | static int iwl_testmode_driver(struct ieee80211_hw *hw, struct nlattr **tb) | ||
335 | { | ||
336 | struct iwl_priv *priv = hw->priv; | ||
337 | struct sk_buff *skb; | ||
338 | unsigned char *rsp_data_ptr = NULL; | ||
339 | int status = 0, rsp_data_len = 0; | ||
340 | |||
341 | switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { | ||
342 | case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: | ||
343 | rsp_data_ptr = (unsigned char *)priv->cfg->name; | ||
344 | rsp_data_len = strlen(priv->cfg->name); | ||
345 | skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, | ||
346 | rsp_data_len + 20); | ||
347 | if (!skb) { | ||
348 | IWL_DEBUG_INFO(priv, | ||
349 | "Error allocating memory\n"); | ||
350 | return -ENOMEM; | ||
351 | } | ||
352 | NLA_PUT_U32(skb, IWL_TM_ATTR_COMMAND, | ||
353 | IWL_TM_CMD_DEV2APP_SYNC_RSP); | ||
354 | NLA_PUT(skb, IWL_TM_ATTR_SYNC_RSP, | ||
355 | rsp_data_len, rsp_data_ptr); | ||
356 | status = cfg80211_testmode_reply(skb); | ||
357 | if (status < 0) | ||
358 | IWL_DEBUG_INFO(priv, "Error sending msg : %d\n", | ||
359 | status); | ||
360 | break; | ||
361 | |||
362 | case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: | ||
363 | status = iwlagn_load_ucode_wait_alive(priv, &priv->ucode_init, | ||
364 | UCODE_SUBTYPE_INIT, -1); | ||
365 | if (status) | ||
366 | IWL_DEBUG_INFO(priv, | ||
367 | "Error loading init ucode: %d\n", status); | ||
368 | break; | ||
369 | |||
370 | case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: | ||
371 | iwl_testmode_cfg_init_calib(priv); | ||
372 | iwlagn_stop_device(priv); | ||
373 | break; | ||
374 | |||
375 | case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: | ||
376 | status = iwlagn_load_ucode_wait_alive(priv, | ||
377 | &priv->ucode_rt, | ||
378 | UCODE_SUBTYPE_REGULAR, | ||
379 | UCODE_SUBTYPE_REGULAR_NEW); | ||
380 | if (status) { | ||
381 | IWL_DEBUG_INFO(priv, | ||
382 | "Error loading runtime ucode: %d\n", status); | ||
383 | break; | ||
384 | } | ||
385 | status = iwl_alive_start(priv); | ||
386 | if (status) | ||
387 | IWL_DEBUG_INFO(priv, | ||
388 | "Error starting the device: %d\n", status); | ||
389 | break; | ||
390 | |||
391 | default: | ||
392 | IWL_DEBUG_INFO(priv, "Unknown testmode driver command ID\n"); | ||
393 | return -ENOSYS; | ||
394 | } | ||
395 | return status; | ||
396 | |||
397 | nla_put_failure: | ||
398 | kfree_skb(skb); | ||
399 | return -EMSGSIZE; | ||
400 | } | ||
401 | |||
402 | /* The testmode gnl message handler that takes the gnl message from the | ||
403 | * user space and parses it per the policy iwl_testmode_gnl_msg_policy, then | ||
404 | * invoke the corresponding handlers. | ||
405 | * | ||
406 | * This function is invoked when there is user space application sending | ||
407 | * gnl message through the testmode tunnel NL80211_CMD_TESTMODE regulated | ||
408 | * by nl80211. | ||
409 | * | ||
410 | * It retrieves the mandatory field, IWL_TM_ATTR_COMMAND, before | ||
411 | * dispatching it to the corresponding handler. | ||
412 | * | ||
413 | * If IWL_TM_ATTR_COMMAND is missing, -ENOMSG is replied to user application; | ||
414 | * -ENOSYS is replied to the user application if the command is unknown; | ||
415 | * Otherwise, the command is dispatched to the respective handler. | ||
416 | * | ||
417 | * @hw: ieee80211_hw object that represents the device | ||
418 | * @data: pointer to user space message | ||
419 | * @len: length in byte of @data | ||
420 | */ | ||
421 | int iwl_testmode_cmd(struct ieee80211_hw *hw, void *data, int len) | ||
422 | { | ||
423 | struct nlattr *tb[IWL_TM_ATTR_MAX - 1]; | ||
424 | struct iwl_priv *priv = hw->priv; | ||
425 | int result; | ||
426 | |||
427 | result = nla_parse(tb, IWL_TM_ATTR_MAX - 1, data, len, | ||
428 | iwl_testmode_gnl_msg_policy); | ||
429 | if (result != 0) { | ||
430 | IWL_DEBUG_INFO(priv, | ||
431 | "Error parsing the gnl message : %d\n", result); | ||
432 | return result; | ||
433 | } | ||
434 | |||
435 | /* IWL_TM_ATTR_COMMAND is absolutely mandatory */ | ||
436 | if (!tb[IWL_TM_ATTR_COMMAND]) { | ||
437 | IWL_DEBUG_INFO(priv, "Error finding testmode command type\n"); | ||
438 | return -ENOMSG; | ||
439 | } | ||
440 | /* in case multiple accesses to the device happens */ | ||
441 | mutex_lock(&priv->mutex); | ||
442 | |||
443 | switch (nla_get_u32(tb[IWL_TM_ATTR_COMMAND])) { | ||
444 | case IWL_TM_CMD_APP2DEV_UCODE: | ||
445 | IWL_DEBUG_INFO(priv, "testmode cmd to uCode\n"); | ||
446 | result = iwl_testmode_ucode(hw, tb); | ||
447 | break; | ||
448 | case IWL_TM_CMD_APP2DEV_REG_READ32: | ||
449 | case IWL_TM_CMD_APP2DEV_REG_WRITE32: | ||
450 | case IWL_TM_CMD_APP2DEV_REG_WRITE8: | ||
451 | IWL_DEBUG_INFO(priv, "testmode cmd to register\n"); | ||
452 | result = iwl_testmode_reg(hw, tb); | ||
453 | break; | ||
454 | case IWL_TM_CMD_APP2DEV_GET_DEVICENAME: | ||
455 | case IWL_TM_CMD_APP2DEV_LOAD_INIT_FW: | ||
456 | case IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB: | ||
457 | case IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW: | ||
458 | IWL_DEBUG_INFO(priv, "testmode cmd to driver\n"); | ||
459 | result = iwl_testmode_driver(hw, tb); | ||
460 | break; | ||
461 | default: | ||
462 | IWL_DEBUG_INFO(priv, "Unknown testmode command\n"); | ||
463 | result = -ENOSYS; | ||
464 | break; | ||
465 | } | ||
466 | |||
467 | mutex_unlock(&priv->mutex); | ||
468 | return result; | ||
469 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-testmode.h b/drivers/net/wireless/iwlwifi/iwl-testmode.h new file mode 100644 index 000000000000..31f8949f2801 --- /dev/null +++ b/drivers/net/wireless/iwlwifi/iwl-testmode.h | |||
@@ -0,0 +1,151 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * This file is provided under a dual BSD/GPLv2 license. When using or | ||
4 | * redistributing this file, you may do so under either license. | ||
5 | * | ||
6 | * GPL LICENSE SUMMARY | ||
7 | * | ||
8 | * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of version 2 of the GNU General Public License as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, | ||
22 | * USA | ||
23 | * | ||
24 | * The full GNU General Public License is included in this distribution | ||
25 | * in the file called LICENSE.GPL. | ||
26 | * | ||
27 | * Contact Information: | ||
28 | * Intel Linux Wireless <ilw@linux.intel.com> | ||
29 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | ||
30 | * | ||
31 | * BSD LICENSE | ||
32 | * | ||
33 | * Copyright(c) 2010 - 2011 Intel Corporation. All rights reserved. | ||
34 | * All rights reserved. | ||
35 | * | ||
36 | * Redistribution and use in source and binary forms, with or without | ||
37 | * modification, are permitted provided that the following conditions | ||
38 | * are met: | ||
39 | * | ||
40 | * * Redistributions of source code must retain the above copyright | ||
41 | * notice, this list of conditions and the following disclaimer. | ||
42 | * * Redistributions in binary form must reproduce the above copyright | ||
43 | * notice, this list of conditions and the following disclaimer in | ||
44 | * the documentation and/or other materials provided with the | ||
45 | * distribution. | ||
46 | * * Neither the name Intel Corporation nor the names of its | ||
47 | * contributors may be used to endorse or promote products derived | ||
48 | * from this software without specific prior written permission. | ||
49 | * | ||
50 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
51 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
52 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
53 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
54 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
55 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
56 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
57 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
58 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
59 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
60 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
61 | * | ||
62 | *****************************************************************************/ | ||
63 | #ifndef __IWL_TESTMODE_H__ | ||
64 | #define __IWL_TESTMODE_H__ | ||
65 | |||
66 | #include <linux/types.h> | ||
67 | |||
68 | |||
69 | /* Commands from user space to kernel space(IWL_TM_CMD_ID_APP2DEV_XX) and | ||
70 | * from and kernel space to user space(IWL_TM_CMD_ID_DEV2APP_XX). | ||
71 | * The command ID is carried with IWL_TM_ATTR_COMMAND. There are three types of | ||
72 | * of command from user space and two types of command from kernel space. | ||
73 | * See below. | ||
74 | */ | ||
75 | enum iwl_tm_cmd_t { | ||
76 | /* commands from user application to the uCode, | ||
77 | * the actual uCode host command ID is carried with | ||
78 | * IWL_TM_ATTR_UCODE_CMD_ID */ | ||
79 | IWL_TM_CMD_APP2DEV_UCODE = 1, | ||
80 | |||
81 | /* commands from user applicaiton to access register */ | ||
82 | IWL_TM_CMD_APP2DEV_REG_READ32, | ||
83 | IWL_TM_CMD_APP2DEV_REG_WRITE32, | ||
84 | IWL_TM_CMD_APP2DEV_REG_WRITE8, | ||
85 | |||
86 | /* commands fom user space for pure driver level operations */ | ||
87 | IWL_TM_CMD_APP2DEV_GET_DEVICENAME, | ||
88 | IWL_TM_CMD_APP2DEV_LOAD_INIT_FW, | ||
89 | IWL_TM_CMD_APP2DEV_CFG_INIT_CALIB, | ||
90 | IWL_TM_CMD_APP2DEV_LOAD_RUNTIME_FW, | ||
91 | /* if there is other new command for the driver layer operation, | ||
92 | * append them here */ | ||
93 | |||
94 | |||
95 | /* commands from kernel space to carry the synchronous response | ||
96 | * to user application */ | ||
97 | IWL_TM_CMD_DEV2APP_SYNC_RSP, | ||
98 | |||
99 | /* commands from kernel space to multicast the spontaneous messages | ||
100 | * to user application */ | ||
101 | IWL_TM_CMD_DEV2APP_UCODE_RX_PKT, | ||
102 | IWL_TM_CMD_MAX, | ||
103 | }; | ||
104 | |||
105 | enum iwl_tm_attr_t { | ||
106 | IWL_TM_ATTR_NOT_APPLICABLE = 0, | ||
107 | |||
108 | /* From user space to kernel space: | ||
109 | * the command either destines to ucode, driver, or register; | ||
110 | * See enum iwl_tm_cmd_t. | ||
111 | * | ||
112 | * From kernel space to user space: | ||
113 | * the command either carries synchronous response, | ||
114 | * or the spontaneous message multicast from the device; | ||
115 | * See enum iwl_tm_cmd_t. */ | ||
116 | IWL_TM_ATTR_COMMAND, | ||
117 | |||
118 | /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_UCODE, | ||
119 | * The mandatory fields are : | ||
120 | * IWL_TM_ATTR_UCODE_CMD_ID for recognizable command ID; | ||
121 | * IWL_TM_ATTR_COMMAND_FLAG for the flags of the commands; | ||
122 | * The optional fields are: | ||
123 | * IWL_TM_ATTR_UCODE_CMD_DATA for the actual command payload | ||
124 | * to the ucode */ | ||
125 | IWL_TM_ATTR_UCODE_CMD_ID, | ||
126 | IWL_TM_ATTR_UCODE_CMD_DATA, | ||
127 | |||
128 | /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_APP2DEV_REG_XXX, | ||
129 | * The mandatory fields are: | ||
130 | * IWL_TM_ATTR_REG_OFFSET for the offset of the target register; | ||
131 | * IWL_TM_ATTR_REG_VALUE8 or IWL_TM_ATTR_REG_VALUE32 for value */ | ||
132 | IWL_TM_ATTR_REG_OFFSET, | ||
133 | IWL_TM_ATTR_REG_VALUE8, | ||
134 | IWL_TM_ATTR_REG_VALUE32, | ||
135 | |||
136 | /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_SYNC_RSP, | ||
137 | * The mandatory fields are: | ||
138 | * IWL_TM_ATTR_SYNC_RSP for the data content responding to the user | ||
139 | * application command */ | ||
140 | IWL_TM_ATTR_SYNC_RSP, | ||
141 | /* When IWL_TM_ATTR_COMMAND is IWL_TM_CMD_DEV2APP_UCODE_RX_PKT, | ||
142 | * The mandatory fields are: | ||
143 | * IWL_TM_ATTR_UCODE_RX_PKT for the data content multicast to the user | ||
144 | * application */ | ||
145 | IWL_TM_ATTR_UCODE_RX_PKT, | ||
146 | |||
147 | IWL_TM_ATTR_MAX, | ||
148 | }; | ||
149 | |||
150 | |||
151 | #endif | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 52b1b66f32d0..e69597ea43e2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -442,12 +442,10 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
442 | struct iwl_cmd_meta *out_meta; | 442 | struct iwl_cmd_meta *out_meta; |
443 | dma_addr_t phys_addr; | 443 | dma_addr_t phys_addr; |
444 | unsigned long flags; | 444 | unsigned long flags; |
445 | int len; | ||
446 | u32 idx; | 445 | u32 idx; |
447 | u16 fix_size; | 446 | u16 fix_size; |
448 | bool is_ct_kill = false; | 447 | bool is_ct_kill = false; |
449 | 448 | ||
450 | cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); | ||
451 | fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); | 449 | fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); |
452 | 450 | ||
453 | /* | 451 | /* |
@@ -502,7 +500,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
502 | } | 500 | } |
503 | 501 | ||
504 | memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */ | 502 | memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */ |
505 | out_meta->flags = cmd->flags | CMD_MAPPED; | ||
506 | if (cmd->flags & CMD_WANT_SKB) | 503 | if (cmd->flags & CMD_WANT_SKB) |
507 | out_meta->source = cmd; | 504 | out_meta->source = cmd; |
508 | if (cmd->flags & CMD_ASYNC) | 505 | if (cmd->flags & CMD_ASYNC) |
@@ -519,9 +516,6 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
519 | INDEX_TO_SEQ(q->write_ptr)); | 516 | INDEX_TO_SEQ(q->write_ptr)); |
520 | if (cmd->flags & CMD_SIZE_HUGE) | 517 | if (cmd->flags & CMD_SIZE_HUGE) |
521 | out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; | 518 | out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; |
522 | len = sizeof(struct iwl_device_cmd); | ||
523 | if (idx == TFD_CMD_SLOTS) | ||
524 | len = IWL_MAX_CMD_SIZE; | ||
525 | 519 | ||
526 | #ifdef CONFIG_IWLWIFI_DEBUG | 520 | #ifdef CONFIG_IWLWIFI_DEBUG |
527 | switch (out_cmd->hdr.cmd) { | 521 | switch (out_cmd->hdr.cmd) { |
@@ -543,17 +537,20 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
543 | q->write_ptr, idx, priv->cmd_queue); | 537 | q->write_ptr, idx, priv->cmd_queue); |
544 | } | 538 | } |
545 | #endif | 539 | #endif |
546 | txq->need_update = 1; | ||
547 | |||
548 | if (priv->cfg->ops->lib->txq_update_byte_cnt_tbl) | ||
549 | /* Set up entry in queue's byte count circular buffer */ | ||
550 | priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0); | ||
551 | |||
552 | phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, | 540 | phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, |
553 | fix_size, PCI_DMA_BIDIRECTIONAL); | 541 | fix_size, PCI_DMA_BIDIRECTIONAL); |
542 | if (unlikely(pci_dma_mapping_error(priv->pci_dev, phys_addr))) { | ||
543 | idx = -ENOMEM; | ||
544 | goto out; | ||
545 | } | ||
546 | |||
554 | dma_unmap_addr_set(out_meta, mapping, phys_addr); | 547 | dma_unmap_addr_set(out_meta, mapping, phys_addr); |
555 | dma_unmap_len_set(out_meta, len, fix_size); | 548 | dma_unmap_len_set(out_meta, len, fix_size); |
556 | 549 | ||
550 | out_meta->flags = cmd->flags | CMD_MAPPED; | ||
551 | |||
552 | txq->need_update = 1; | ||
553 | |||
557 | trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); | 554 | trace_iwlwifi_dev_hcmd(priv, &out_cmd->hdr, fix_size, cmd->flags); |
558 | 555 | ||
559 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, | 556 | priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, |
@@ -564,6 +561,7 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) | |||
564 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); | 561 | q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); |
565 | iwl_txq_update_write_ptr(priv, txq); | 562 | iwl_txq_update_write_ptr(priv, txq); |
566 | 563 | ||
564 | out: | ||
567 | spin_unlock_irqrestore(&priv->hcmd_lock, flags); | 565 | spin_unlock_irqrestore(&priv->hcmd_lock, flags); |
568 | return idx; | 566 | return idx; |
569 | } | 567 | } |
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c index 9a57cf6a488f..5665a1a9b99e 100644 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ b/drivers/net/wireless/iwmc3200wifi/rx.c | |||
@@ -1576,7 +1576,8 @@ static void iwm_rx_process_amsdu(struct iwm_priv *iwm, struct sk_buff *skb) | |||
1576 | IWM_HEXDUMP(iwm, DBG, RX, "A-MSDU: ", skb->data, skb->len); | 1576 | IWM_HEXDUMP(iwm, DBG, RX, "A-MSDU: ", skb->data, skb->len); |
1577 | 1577 | ||
1578 | __skb_queue_head_init(&list); | 1578 | __skb_queue_head_init(&list); |
1579 | ieee80211_amsdu_to_8023s(skb, &list, ndev->dev_addr, wdev->iftype, 0); | 1579 | ieee80211_amsdu_to_8023s(skb, &list, ndev->dev_addr, wdev->iftype, 0, |
1580 | true); | ||
1580 | 1581 | ||
1581 | while ((frame = __skb_dequeue(&list))) { | 1582 | while ((frame = __skb_dequeue(&list))) { |
1582 | ndev->stats.rx_packets++; | 1583 | ndev->stats.rx_packets++; |
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 486544e01a56..5d637af2d7c3 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -6,6 +6,8 @@ | |||
6 | * | 6 | * |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
10 | |||
9 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
10 | #include <linux/wait.h> | 12 | #include <linux/wait.h> |
11 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
@@ -1322,8 +1324,8 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, | |||
1322 | sme->ssid, sme->ssid_len, | 1324 | sme->ssid, sme->ssid_len, |
1323 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | 1325 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); |
1324 | if (!bss) { | 1326 | if (!bss) { |
1325 | lbs_pr_err("assoc: bss %pM not in scan results\n", | 1327 | wiphy_err(wiphy, "assoc: bss %pM not in scan results\n", |
1326 | sme->bssid); | 1328 | sme->bssid); |
1327 | ret = -ENOENT; | 1329 | ret = -ENOENT; |
1328 | goto done; | 1330 | goto done; |
1329 | } | 1331 | } |
@@ -1380,8 +1382,8 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev, | |||
1380 | lbs_enable_rsn(priv, sme->crypto.cipher_group != 0); | 1382 | lbs_enable_rsn(priv, sme->crypto.cipher_group != 0); |
1381 | break; | 1383 | break; |
1382 | default: | 1384 | default: |
1383 | lbs_pr_err("unsupported cipher group 0x%x\n", | 1385 | wiphy_err(wiphy, "unsupported cipher group 0x%x\n", |
1384 | sme->crypto.cipher_group); | 1386 | sme->crypto.cipher_group); |
1385 | ret = -ENOTSUPP; | 1387 | ret = -ENOTSUPP; |
1386 | goto done; | 1388 | goto done; |
1387 | } | 1389 | } |
@@ -1499,7 +1501,7 @@ static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev, | |||
1499 | params->key, params->key_len); | 1501 | params->key, params->key_len); |
1500 | break; | 1502 | break; |
1501 | default: | 1503 | default: |
1502 | lbs_pr_err("unhandled cipher 0x%x\n", params->cipher); | 1504 | wiphy_err(wiphy, "unhandled cipher 0x%x\n", params->cipher); |
1503 | ret = -ENOTSUPP; | 1505 | ret = -ENOTSUPP; |
1504 | break; | 1506 | break; |
1505 | } | 1507 | } |
@@ -2127,13 +2129,13 @@ int lbs_cfg_register(struct lbs_private *priv) | |||
2127 | 2129 | ||
2128 | ret = wiphy_register(wdev->wiphy); | 2130 | ret = wiphy_register(wdev->wiphy); |
2129 | if (ret < 0) | 2131 | if (ret < 0) |
2130 | lbs_pr_err("cannot register wiphy device\n"); | 2132 | pr_err("cannot register wiphy device\n"); |
2131 | 2133 | ||
2132 | priv->wiphy_registered = true; | 2134 | priv->wiphy_registered = true; |
2133 | 2135 | ||
2134 | ret = register_netdev(priv->dev); | 2136 | ret = register_netdev(priv->dev); |
2135 | if (ret) | 2137 | if (ret) |
2136 | lbs_pr_err("cannot register network device\n"); | 2138 | pr_err("cannot register network device\n"); |
2137 | 2139 | ||
2138 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); | 2140 | INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); |
2139 | 2141 | ||
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c index 6a96fc9c1cea..6d59b4cf8fce 100644 --- a/drivers/net/wireless/libertas/cmd.c +++ b/drivers/net/wireless/libertas/cmd.c | |||
@@ -110,7 +110,7 @@ int lbs_update_hw_spec(struct lbs_private *priv) | |||
110 | * CF card firmware 5.0.16p0: cap 0x00000303 | 110 | * CF card firmware 5.0.16p0: cap 0x00000303 |
111 | * USB dongle firmware 5.110.17p2: cap 0x00000303 | 111 | * USB dongle firmware 5.110.17p2: cap 0x00000303 |
112 | */ | 112 | */ |
113 | lbs_pr_info("%pM, fw %u.%u.%up%u, cap 0x%08x\n", | 113 | netdev_info(priv->dev, "%pM, fw %u.%u.%up%u, cap 0x%08x\n", |
114 | cmd.permanentaddr, | 114 | cmd.permanentaddr, |
115 | priv->fwrelease >> 24 & 0xff, | 115 | priv->fwrelease >> 24 & 0xff, |
116 | priv->fwrelease >> 16 & 0xff, | 116 | priv->fwrelease >> 16 & 0xff, |
@@ -141,7 +141,8 @@ int lbs_update_hw_spec(struct lbs_private *priv) | |||
141 | /* if it's unidentified region code, use the default (USA) */ | 141 | /* if it's unidentified region code, use the default (USA) */ |
142 | if (i >= MRVDRV_MAX_REGION_CODE) { | 142 | if (i >= MRVDRV_MAX_REGION_CODE) { |
143 | priv->regioncode = 0x10; | 143 | priv->regioncode = 0x10; |
144 | lbs_pr_info("unidentified region code; using the default (USA)\n"); | 144 | netdev_info(priv->dev, |
145 | "unidentified region code; using the default (USA)\n"); | ||
145 | } | 146 | } |
146 | 147 | ||
147 | if (priv->current_addr[0] == 0xff) | 148 | if (priv->current_addr[0] == 0xff) |
@@ -211,7 +212,7 @@ int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, | |||
211 | (uint8_t *)&cmd_config.wol_conf, | 212 | (uint8_t *)&cmd_config.wol_conf, |
212 | sizeof(struct wol_config)); | 213 | sizeof(struct wol_config)); |
213 | } else { | 214 | } else { |
214 | lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret); | 215 | netdev_info(priv->dev, "HOST_SLEEP_CFG failed %d\n", ret); |
215 | } | 216 | } |
216 | 217 | ||
217 | return ret; | 218 | return ret; |
@@ -314,7 +315,7 @@ static int lbs_wait_for_ds_awake(struct lbs_private *priv) | |||
314 | if (priv->is_deep_sleep) { | 315 | if (priv->is_deep_sleep) { |
315 | if (!wait_event_interruptible_timeout(priv->ds_awake_q, | 316 | if (!wait_event_interruptible_timeout(priv->ds_awake_q, |
316 | !priv->is_deep_sleep, (10 * HZ))) { | 317 | !priv->is_deep_sleep, (10 * HZ))) { |
317 | lbs_pr_err("ds_awake_q: timer expired\n"); | 318 | netdev_err(priv->dev, "ds_awake_q: timer expired\n"); |
318 | ret = -1; | 319 | ret = -1; |
319 | } | 320 | } |
320 | } | 321 | } |
@@ -339,7 +340,7 @@ int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep) | |||
339 | netif_carrier_off(priv->dev); | 340 | netif_carrier_off(priv->dev); |
340 | } | 341 | } |
341 | } else { | 342 | } else { |
342 | lbs_pr_err("deep sleep: already enabled\n"); | 343 | netdev_err(priv->dev, "deep sleep: already enabled\n"); |
343 | } | 344 | } |
344 | } else { | 345 | } else { |
345 | if (priv->is_deep_sleep) { | 346 | if (priv->is_deep_sleep) { |
@@ -349,8 +350,8 @@ int lbs_set_deep_sleep(struct lbs_private *priv, int deep_sleep) | |||
349 | if (!ret) { | 350 | if (!ret) { |
350 | ret = lbs_wait_for_ds_awake(priv); | 351 | ret = lbs_wait_for_ds_awake(priv); |
351 | if (ret) | 352 | if (ret) |
352 | lbs_pr_err("deep sleep: wakeup" | 353 | netdev_err(priv->dev, |
353 | "failed\n"); | 354 | "deep sleep: wakeup failed\n"); |
354 | } | 355 | } |
355 | } | 356 | } |
356 | } | 357 | } |
@@ -384,8 +385,9 @@ int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep) | |||
384 | ret = lbs_host_sleep_cfg(priv, priv->wol_criteria, | 385 | ret = lbs_host_sleep_cfg(priv, priv->wol_criteria, |
385 | (struct wol_config *)NULL); | 386 | (struct wol_config *)NULL); |
386 | if (ret) { | 387 | if (ret) { |
387 | lbs_pr_info("Host sleep configuration failed: " | 388 | netdev_info(priv->dev, |
388 | "%d\n", ret); | 389 | "Host sleep configuration failed: %d\n", |
390 | ret); | ||
389 | return ret; | 391 | return ret; |
390 | } | 392 | } |
391 | if (priv->psstate == PS_STATE_FULL_POWER) { | 393 | if (priv->psstate == PS_STATE_FULL_POWER) { |
@@ -395,19 +397,21 @@ int lbs_set_host_sleep(struct lbs_private *priv, int host_sleep) | |||
395 | sizeof(cmd), | 397 | sizeof(cmd), |
396 | lbs_ret_host_sleep_activate, 0); | 398 | lbs_ret_host_sleep_activate, 0); |
397 | if (ret) | 399 | if (ret) |
398 | lbs_pr_info("HOST_SLEEP_ACTIVATE " | 400 | netdev_info(priv->dev, |
399 | "failed: %d\n", ret); | 401 | "HOST_SLEEP_ACTIVATE failed: %d\n", |
402 | ret); | ||
400 | } | 403 | } |
401 | 404 | ||
402 | if (!wait_event_interruptible_timeout( | 405 | if (!wait_event_interruptible_timeout( |
403 | priv->host_sleep_q, | 406 | priv->host_sleep_q, |
404 | priv->is_host_sleep_activated, | 407 | priv->is_host_sleep_activated, |
405 | (10 * HZ))) { | 408 | (10 * HZ))) { |
406 | lbs_pr_err("host_sleep_q: timer expired\n"); | 409 | netdev_err(priv->dev, |
410 | "host_sleep_q: timer expired\n"); | ||
407 | ret = -1; | 411 | ret = -1; |
408 | } | 412 | } |
409 | } else { | 413 | } else { |
410 | lbs_pr_err("host sleep: already enabled\n"); | 414 | netdev_err(priv->dev, "host sleep: already enabled\n"); |
411 | } | 415 | } |
412 | } else { | 416 | } else { |
413 | if (priv->is_host_sleep_activated) | 417 | if (priv->is_host_sleep_activated) |
@@ -1007,7 +1011,8 @@ static void lbs_submit_command(struct lbs_private *priv, | |||
1007 | ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize); | 1011 | ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize); |
1008 | 1012 | ||
1009 | if (ret) { | 1013 | if (ret) { |
1010 | lbs_pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret); | 1014 | netdev_info(priv->dev, "DNLD_CMD: hw_host_to_card failed: %d\n", |
1015 | ret); | ||
1011 | /* Let the timer kick in and retry, and potentially reset | 1016 | /* Let the timer kick in and retry, and potentially reset |
1012 | the whole thing if the condition persists */ | 1017 | the whole thing if the condition persists */ |
1013 | timeo = HZ/4; | 1018 | timeo = HZ/4; |
@@ -1276,7 +1281,8 @@ int lbs_execute_next_command(struct lbs_private *priv) | |||
1276 | spin_lock_irqsave(&priv->driver_lock, flags); | 1281 | spin_lock_irqsave(&priv->driver_lock, flags); |
1277 | 1282 | ||
1278 | if (priv->cur_cmd) { | 1283 | if (priv->cur_cmd) { |
1279 | lbs_pr_alert( "EXEC_NEXT_CMD: already processing command!\n"); | 1284 | netdev_alert(priv->dev, |
1285 | "EXEC_NEXT_CMD: already processing command!\n"); | ||
1280 | spin_unlock_irqrestore(&priv->driver_lock, flags); | 1286 | spin_unlock_irqrestore(&priv->driver_lock, flags); |
1281 | ret = -1; | 1287 | ret = -1; |
1282 | goto done; | 1288 | goto done; |
@@ -1438,7 +1444,7 @@ static void lbs_send_confirmsleep(struct lbs_private *priv) | |||
1438 | ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep, | 1444 | ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep, |
1439 | sizeof(confirm_sleep)); | 1445 | sizeof(confirm_sleep)); |
1440 | if (ret) { | 1446 | if (ret) { |
1441 | lbs_pr_alert("confirm_sleep failed\n"); | 1447 | netdev_alert(priv->dev, "confirm_sleep failed\n"); |
1442 | goto out; | 1448 | goto out; |
1443 | } | 1449 | } |
1444 | 1450 | ||
@@ -1664,7 +1670,7 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command, | |||
1664 | spin_lock_irqsave(&priv->driver_lock, flags); | 1670 | spin_lock_irqsave(&priv->driver_lock, flags); |
1665 | ret = cmdnode->result; | 1671 | ret = cmdnode->result; |
1666 | if (ret) | 1672 | if (ret) |
1667 | lbs_pr_info("PREP_CMD: command 0x%04x failed: %d\n", | 1673 | netdev_info(priv->dev, "PREP_CMD: command 0x%04x failed: %d\n", |
1668 | command, ret); | 1674 | command, ret); |
1669 | 1675 | ||
1670 | __lbs_cleanup_and_insert_cmd(priv, cmdnode); | 1676 | __lbs_cleanup_and_insert_cmd(priv, cmdnode); |
diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c index 03e528994a9e..207fc361db84 100644 --- a/drivers/net/wireless/libertas/cmdresp.c +++ b/drivers/net/wireless/libertas/cmdresp.c | |||
@@ -2,6 +2,7 @@ | |||
2 | * This file contains the handling of command | 2 | * This file contains the handling of command |
3 | * responses as well as events generated by firmware. | 3 | * responses as well as events generated by firmware. |
4 | */ | 4 | */ |
5 | |||
5 | #include <linux/slab.h> | 6 | #include <linux/slab.h> |
6 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
7 | #include <linux/sched.h> | 8 | #include <linux/sched.h> |
@@ -85,15 +86,18 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) | |||
85 | lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len); | 86 | lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len); |
86 | 87 | ||
87 | if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) { | 88 | if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) { |
88 | lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n", | 89 | netdev_info(priv->dev, |
89 | le16_to_cpu(resp->seqnum), le16_to_cpu(priv->cur_cmd->cmdbuf->seqnum)); | 90 | "Received CMD_RESP with invalid sequence %d (expected %d)\n", |
91 | le16_to_cpu(resp->seqnum), | ||
92 | le16_to_cpu(priv->cur_cmd->cmdbuf->seqnum)); | ||
90 | spin_unlock_irqrestore(&priv->driver_lock, flags); | 93 | spin_unlock_irqrestore(&priv->driver_lock, flags); |
91 | ret = -1; | 94 | ret = -1; |
92 | goto done; | 95 | goto done; |
93 | } | 96 | } |
94 | if (respcmd != CMD_RET(curcmd) && | 97 | if (respcmd != CMD_RET(curcmd) && |
95 | respcmd != CMD_RET_802_11_ASSOCIATE && curcmd != CMD_802_11_ASSOCIATE) { | 98 | respcmd != CMD_RET_802_11_ASSOCIATE && curcmd != CMD_802_11_ASSOCIATE) { |
96 | lbs_pr_info("Invalid CMD_RESP %x to command %x!\n", respcmd, curcmd); | 99 | netdev_info(priv->dev, "Invalid CMD_RESP %x to command %x!\n", |
100 | respcmd, curcmd); | ||
97 | spin_unlock_irqrestore(&priv->driver_lock, flags); | 101 | spin_unlock_irqrestore(&priv->driver_lock, flags); |
98 | ret = -1; | 102 | ret = -1; |
99 | goto done; | 103 | goto done; |
@@ -102,7 +106,8 @@ int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) | |||
102 | if (resp->result == cpu_to_le16(0x0004)) { | 106 | if (resp->result == cpu_to_le16(0x0004)) { |
103 | /* 0x0004 means -EAGAIN. Drop the response, let it time out | 107 | /* 0x0004 means -EAGAIN. Drop the response, let it time out |
104 | and be resubmitted */ | 108 | and be resubmitted */ |
105 | lbs_pr_info("Firmware returns DEFER to command %x. Will let it time out...\n", | 109 | netdev_info(priv->dev, |
110 | "Firmware returns DEFER to command %x. Will let it time out...\n", | ||
106 | le16_to_cpu(resp->command)); | 111 | le16_to_cpu(resp->command)); |
107 | spin_unlock_irqrestore(&priv->driver_lock, flags); | 112 | spin_unlock_irqrestore(&priv->driver_lock, flags); |
108 | ret = -1; | 113 | ret = -1; |
@@ -314,28 +319,28 @@ int lbs_process_event(struct lbs_private *priv, u32 event) | |||
314 | lbs_deb_cmd("EVENT: ADHOC beacon lost\n"); | 319 | lbs_deb_cmd("EVENT: ADHOC beacon lost\n"); |
315 | break; | 320 | break; |
316 | case MACREG_INT_CODE_RSSI_LOW: | 321 | case MACREG_INT_CODE_RSSI_LOW: |
317 | lbs_pr_alert("EVENT: rssi low\n"); | 322 | netdev_alert(priv->dev, "EVENT: rssi low\n"); |
318 | break; | 323 | break; |
319 | case MACREG_INT_CODE_SNR_LOW: | 324 | case MACREG_INT_CODE_SNR_LOW: |
320 | lbs_pr_alert("EVENT: snr low\n"); | 325 | netdev_alert(priv->dev, "EVENT: snr low\n"); |
321 | break; | 326 | break; |
322 | case MACREG_INT_CODE_MAX_FAIL: | 327 | case MACREG_INT_CODE_MAX_FAIL: |
323 | lbs_pr_alert("EVENT: max fail\n"); | 328 | netdev_alert(priv->dev, "EVENT: max fail\n"); |
324 | break; | 329 | break; |
325 | case MACREG_INT_CODE_RSSI_HIGH: | 330 | case MACREG_INT_CODE_RSSI_HIGH: |
326 | lbs_pr_alert("EVENT: rssi high\n"); | 331 | netdev_alert(priv->dev, "EVENT: rssi high\n"); |
327 | break; | 332 | break; |
328 | case MACREG_INT_CODE_SNR_HIGH: | 333 | case MACREG_INT_CODE_SNR_HIGH: |
329 | lbs_pr_alert("EVENT: snr high\n"); | 334 | netdev_alert(priv->dev, "EVENT: snr high\n"); |
330 | break; | 335 | break; |
331 | 336 | ||
332 | case MACREG_INT_CODE_MESH_AUTO_STARTED: | 337 | case MACREG_INT_CODE_MESH_AUTO_STARTED: |
333 | /* Ignore spurious autostart events */ | 338 | /* Ignore spurious autostart events */ |
334 | lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n"); | 339 | netdev_info(priv->dev, "EVENT: MESH_AUTO_STARTED (ignoring)\n"); |
335 | break; | 340 | break; |
336 | 341 | ||
337 | default: | 342 | default: |
338 | lbs_pr_alert("EVENT: unknown event id %d\n", event); | 343 | netdev_alert(priv->dev, "EVENT: unknown event id %d\n", event); |
339 | break; | 344 | break; |
340 | } | 345 | } |
341 | 346 | ||
diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index 851fe7bd4ba4..23250f621761 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c | |||
@@ -151,13 +151,14 @@ static ssize_t lbs_host_sleep_write(struct file *file, | |||
151 | ret = lbs_set_host_sleep(priv, 0); | 151 | ret = lbs_set_host_sleep(priv, 0); |
152 | else if (host_sleep == 1) { | 152 | else if (host_sleep == 1) { |
153 | if (priv->wol_criteria == EHS_REMOVE_WAKEUP) { | 153 | if (priv->wol_criteria == EHS_REMOVE_WAKEUP) { |
154 | lbs_pr_info("wake parameters not configured"); | 154 | netdev_info(priv->dev, |
155 | "wake parameters not configured\n"); | ||
155 | ret = -EINVAL; | 156 | ret = -EINVAL; |
156 | goto out_unlock; | 157 | goto out_unlock; |
157 | } | 158 | } |
158 | ret = lbs_set_host_sleep(priv, 1); | 159 | ret = lbs_set_host_sleep(priv, 1); |
159 | } else { | 160 | } else { |
160 | lbs_pr_err("invalid option\n"); | 161 | netdev_err(priv->dev, "invalid option\n"); |
161 | ret = -EINVAL; | 162 | ret = -EINVAL; |
162 | } | 163 | } |
163 | 164 | ||
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h index 92b5b1f8fd75..ab966f08024a 100644 --- a/drivers/net/wireless/libertas/defs.h +++ b/drivers/net/wireless/libertas/defs.h | |||
@@ -89,13 +89,6 @@ do { if ((lbs_debug & (grp)) == (grp)) \ | |||
89 | #define lbs_deb_spi(fmt, args...) LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args) | 89 | #define lbs_deb_spi(fmt, args...) LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args) |
90 | #define lbs_deb_cfg80211(fmt, args...) LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args) | 90 | #define lbs_deb_cfg80211(fmt, args...) LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args) |
91 | 91 | ||
92 | #define lbs_pr_info(format, args...) \ | ||
93 | printk(KERN_INFO DRV_NAME": " format, ## args) | ||
94 | #define lbs_pr_err(format, args...) \ | ||
95 | printk(KERN_ERR DRV_NAME": " format, ## args) | ||
96 | #define lbs_pr_alert(format, args...) \ | ||
97 | printk(KERN_ALERT DRV_NAME": " format, ## args) | ||
98 | |||
99 | #ifdef DEBUG | 92 | #ifdef DEBUG |
100 | static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len) | 93 | static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len) |
101 | { | 94 | { |
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c index 4dfd48fe8b6e..63ed5798365c 100644 --- a/drivers/net/wireless/libertas/if_cs.c +++ b/drivers/net/wireless/libertas/if_cs.c | |||
@@ -21,6 +21,8 @@ | |||
21 | 21 | ||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
25 | |||
24 | #include <linux/module.h> | 26 | #include <linux/module.h> |
25 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
26 | #include <linux/delay.h> | 28 | #include <linux/delay.h> |
@@ -362,7 +364,7 @@ static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb) | |||
362 | if (status & IF_CS_BIT_COMMAND) | 364 | if (status & IF_CS_BIT_COMMAND) |
363 | break; | 365 | break; |
364 | if (++loops > 100) { | 366 | if (++loops > 100) { |
365 | lbs_pr_err("card not ready for commands\n"); | 367 | netdev_err(priv->dev, "card not ready for commands\n"); |
366 | goto done; | 368 | goto done; |
367 | } | 369 | } |
368 | mdelay(1); | 370 | mdelay(1); |
@@ -432,14 +434,16 @@ static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) | |||
432 | /* is hardware ready? */ | 434 | /* is hardware ready? */ |
433 | status = if_cs_read16(priv->card, IF_CS_CARD_STATUS); | 435 | status = if_cs_read16(priv->card, IF_CS_CARD_STATUS); |
434 | if ((status & IF_CS_BIT_RESP) == 0) { | 436 | if ((status & IF_CS_BIT_RESP) == 0) { |
435 | lbs_pr_err("no cmd response in card\n"); | 437 | netdev_err(priv->dev, "no cmd response in card\n"); |
436 | *len = 0; | 438 | *len = 0; |
437 | goto out; | 439 | goto out; |
438 | } | 440 | } |
439 | 441 | ||
440 | *len = if_cs_read16(priv->card, IF_CS_RESP_LEN); | 442 | *len = if_cs_read16(priv->card, IF_CS_RESP_LEN); |
441 | if ((*len == 0) || (*len > LBS_CMD_BUFFER_SIZE)) { | 443 | if ((*len == 0) || (*len > LBS_CMD_BUFFER_SIZE)) { |
442 | lbs_pr_err("card cmd buffer has invalid # of bytes (%d)\n", *len); | 444 | netdev_err(priv->dev, |
445 | "card cmd buffer has invalid # of bytes (%d)\n", | ||
446 | *len); | ||
443 | goto out; | 447 | goto out; |
444 | } | 448 | } |
445 | 449 | ||
@@ -473,7 +477,9 @@ static struct sk_buff *if_cs_receive_data(struct lbs_private *priv) | |||
473 | 477 | ||
474 | len = if_cs_read16(priv->card, IF_CS_READ_LEN); | 478 | len = if_cs_read16(priv->card, IF_CS_READ_LEN); |
475 | if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { | 479 | if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { |
476 | lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len); | 480 | netdev_err(priv->dev, |
481 | "card data buffer has invalid # of bytes (%d)\n", | ||
482 | len); | ||
477 | priv->dev->stats.rx_dropped++; | 483 | priv->dev->stats.rx_dropped++; |
478 | goto dat_err; | 484 | goto dat_err; |
479 | } | 485 | } |
@@ -653,8 +659,8 @@ static int if_cs_prog_helper(struct if_cs_card *card, const struct firmware *fw) | |||
653 | ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS, | 659 | ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS, |
654 | IF_CS_BIT_COMMAND); | 660 | IF_CS_BIT_COMMAND); |
655 | if (ret < 0) { | 661 | if (ret < 0) { |
656 | lbs_pr_err("can't download helper at 0x%x, ret %d\n", | 662 | pr_err("can't download helper at 0x%x, ret %d\n", |
657 | sent, ret); | 663 | sent, ret); |
658 | goto done; | 664 | goto done; |
659 | } | 665 | } |
660 | 666 | ||
@@ -684,7 +690,7 @@ static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw) | |||
684 | ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW, | 690 | ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW, |
685 | IF_CS_SQ_HELPER_OK); | 691 | IF_CS_SQ_HELPER_OK); |
686 | if (ret < 0) { | 692 | if (ret < 0) { |
687 | lbs_pr_err("helper firmware doesn't answer\n"); | 693 | pr_err("helper firmware doesn't answer\n"); |
688 | goto done; | 694 | goto done; |
689 | } | 695 | } |
690 | 696 | ||
@@ -692,13 +698,13 @@ static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw) | |||
692 | len = if_cs_read16(card, IF_CS_SQ_READ_LOW); | 698 | len = if_cs_read16(card, IF_CS_SQ_READ_LOW); |
693 | if (len & 1) { | 699 | if (len & 1) { |
694 | retry++; | 700 | retry++; |
695 | lbs_pr_info("odd, need to retry this firmware block\n"); | 701 | pr_info("odd, need to retry this firmware block\n"); |
696 | } else { | 702 | } else { |
697 | retry = 0; | 703 | retry = 0; |
698 | } | 704 | } |
699 | 705 | ||
700 | if (retry > 20) { | 706 | if (retry > 20) { |
701 | lbs_pr_err("could not download firmware\n"); | 707 | pr_err("could not download firmware\n"); |
702 | ret = -ENODEV; | 708 | ret = -ENODEV; |
703 | goto done; | 709 | goto done; |
704 | } | 710 | } |
@@ -718,14 +724,14 @@ static int if_cs_prog_real(struct if_cs_card *card, const struct firmware *fw) | |||
718 | ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS, | 724 | ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS, |
719 | IF_CS_BIT_COMMAND); | 725 | IF_CS_BIT_COMMAND); |
720 | if (ret < 0) { | 726 | if (ret < 0) { |
721 | lbs_pr_err("can't download firmware at 0x%x\n", sent); | 727 | pr_err("can't download firmware at 0x%x\n", sent); |
722 | goto done; | 728 | goto done; |
723 | } | 729 | } |
724 | } | 730 | } |
725 | 731 | ||
726 | ret = if_cs_poll_while_fw_download(card, IF_CS_SCRATCH, 0x5a); | 732 | ret = if_cs_poll_while_fw_download(card, IF_CS_SCRATCH, 0x5a); |
727 | if (ret < 0) | 733 | if (ret < 0) |
728 | lbs_pr_err("firmware download failed\n"); | 734 | pr_err("firmware download failed\n"); |
729 | 735 | ||
730 | done: | 736 | done: |
731 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | 737 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); |
@@ -759,7 +765,8 @@ static int if_cs_host_to_card(struct lbs_private *priv, | |||
759 | ret = if_cs_send_cmd(priv, buf, nb); | 765 | ret = if_cs_send_cmd(priv, buf, nb); |
760 | break; | 766 | break; |
761 | default: | 767 | default: |
762 | lbs_pr_err("%s: unsupported type %d\n", __func__, type); | 768 | netdev_err(priv->dev, "%s: unsupported type %d\n", |
769 | __func__, type); | ||
763 | } | 770 | } |
764 | 771 | ||
765 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); | 772 | lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); |
@@ -788,7 +795,7 @@ static int if_cs_ioprobe(struct pcmcia_device *p_dev, void *priv_data) | |||
788 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; | 795 | p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; |
789 | 796 | ||
790 | if (p_dev->resource[1]->end) { | 797 | if (p_dev->resource[1]->end) { |
791 | lbs_pr_err("wrong CIS (check number of IO windows)\n"); | 798 | pr_err("wrong CIS (check number of IO windows)\n"); |
792 | return -ENODEV; | 799 | return -ENODEV; |
793 | } | 800 | } |
794 | 801 | ||
@@ -809,7 +816,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
809 | 816 | ||
810 | card = kzalloc(sizeof(struct if_cs_card), GFP_KERNEL); | 817 | card = kzalloc(sizeof(struct if_cs_card), GFP_KERNEL); |
811 | if (!card) { | 818 | if (!card) { |
812 | lbs_pr_err("error in kzalloc\n"); | 819 | pr_err("error in kzalloc\n"); |
813 | goto out; | 820 | goto out; |
814 | } | 821 | } |
815 | card->p_dev = p_dev; | 822 | card->p_dev = p_dev; |
@@ -818,7 +825,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
818 | p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; | 825 | p_dev->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO; |
819 | 826 | ||
820 | if (pcmcia_loop_config(p_dev, if_cs_ioprobe, NULL)) { | 827 | if (pcmcia_loop_config(p_dev, if_cs_ioprobe, NULL)) { |
821 | lbs_pr_err("error in pcmcia_loop_config\n"); | 828 | pr_err("error in pcmcia_loop_config\n"); |
822 | goto out1; | 829 | goto out1; |
823 | } | 830 | } |
824 | 831 | ||
@@ -834,14 +841,14 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
834 | card->iobase = ioport_map(p_dev->resource[0]->start, | 841 | card->iobase = ioport_map(p_dev->resource[0]->start, |
835 | resource_size(p_dev->resource[0])); | 842 | resource_size(p_dev->resource[0])); |
836 | if (!card->iobase) { | 843 | if (!card->iobase) { |
837 | lbs_pr_err("error in ioport_map\n"); | 844 | pr_err("error in ioport_map\n"); |
838 | ret = -EIO; | 845 | ret = -EIO; |
839 | goto out1; | 846 | goto out1; |
840 | } | 847 | } |
841 | 848 | ||
842 | ret = pcmcia_enable_device(p_dev); | 849 | ret = pcmcia_enable_device(p_dev); |
843 | if (ret) { | 850 | if (ret) { |
844 | lbs_pr_err("error in pcmcia_enable_device\n"); | 851 | pr_err("error in pcmcia_enable_device\n"); |
845 | goto out2; | 852 | goto out2; |
846 | } | 853 | } |
847 | 854 | ||
@@ -856,8 +863,8 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
856 | 863 | ||
857 | card->model = get_model(p_dev->manf_id, p_dev->card_id); | 864 | card->model = get_model(p_dev->manf_id, p_dev->card_id); |
858 | if (card->model == MODEL_UNKNOWN) { | 865 | if (card->model == MODEL_UNKNOWN) { |
859 | lbs_pr_err("unsupported manf_id 0x%04x / card_id 0x%04x\n", | 866 | pr_err("unsupported manf_id 0x%04x / card_id 0x%04x\n", |
860 | p_dev->manf_id, p_dev->card_id); | 867 | p_dev->manf_id, p_dev->card_id); |
861 | goto out2; | 868 | goto out2; |
862 | } | 869 | } |
863 | 870 | ||
@@ -866,20 +873,20 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
866 | if (card->model == MODEL_8305) { | 873 | if (card->model == MODEL_8305) { |
867 | card->align_regs = 1; | 874 | card->align_regs = 1; |
868 | if (prod_id < IF_CS_CF8305_B1_REV) { | 875 | if (prod_id < IF_CS_CF8305_B1_REV) { |
869 | lbs_pr_err("8305 rev B0 and older are not supported\n"); | 876 | pr_err("8305 rev B0 and older are not supported\n"); |
870 | ret = -ENODEV; | 877 | ret = -ENODEV; |
871 | goto out2; | 878 | goto out2; |
872 | } | 879 | } |
873 | } | 880 | } |
874 | 881 | ||
875 | if ((card->model == MODEL_8381) && prod_id < IF_CS_CF8381_B3_REV) { | 882 | if ((card->model == MODEL_8381) && prod_id < IF_CS_CF8381_B3_REV) { |
876 | lbs_pr_err("8381 rev B2 and older are not supported\n"); | 883 | pr_err("8381 rev B2 and older are not supported\n"); |
877 | ret = -ENODEV; | 884 | ret = -ENODEV; |
878 | goto out2; | 885 | goto out2; |
879 | } | 886 | } |
880 | 887 | ||
881 | if ((card->model == MODEL_8385) && prod_id < IF_CS_CF8385_B1_REV) { | 888 | if ((card->model == MODEL_8385) && prod_id < IF_CS_CF8385_B1_REV) { |
882 | lbs_pr_err("8385 rev B0 and older are not supported\n"); | 889 | pr_err("8385 rev B0 and older are not supported\n"); |
883 | ret = -ENODEV; | 890 | ret = -ENODEV; |
884 | goto out2; | 891 | goto out2; |
885 | } | 892 | } |
@@ -887,7 +894,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
887 | ret = lbs_get_firmware(&p_dev->dev, NULL, NULL, card->model, | 894 | ret = lbs_get_firmware(&p_dev->dev, NULL, NULL, card->model, |
888 | &fw_table[0], &helper, &mainfw); | 895 | &fw_table[0], &helper, &mainfw); |
889 | if (ret) { | 896 | if (ret) { |
890 | lbs_pr_err("failed to find firmware (%d)\n", ret); | 897 | pr_err("failed to find firmware (%d)\n", ret); |
891 | goto out2; | 898 | goto out2; |
892 | } | 899 | } |
893 | 900 | ||
@@ -918,7 +925,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
918 | ret = request_irq(p_dev->irq, if_cs_interrupt, | 925 | ret = request_irq(p_dev->irq, if_cs_interrupt, |
919 | IRQF_SHARED, DRV_NAME, card); | 926 | IRQF_SHARED, DRV_NAME, card); |
920 | if (ret) { | 927 | if (ret) { |
921 | lbs_pr_err("error in request_irq\n"); | 928 | pr_err("error in request_irq\n"); |
922 | goto out3; | 929 | goto out3; |
923 | } | 930 | } |
924 | 931 | ||
@@ -931,7 +938,7 @@ static int if_cs_probe(struct pcmcia_device *p_dev) | |||
931 | 938 | ||
932 | /* And finally bring the card up */ | 939 | /* And finally bring the card up */ |
933 | if (lbs_start_card(priv) != 0) { | 940 | if (lbs_start_card(priv) != 0) { |
934 | lbs_pr_err("could not activate card\n"); | 941 | pr_err("could not activate card\n"); |
935 | goto out3; | 942 | goto out3; |
936 | } | 943 | } |
937 | 944 | ||
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index b4de0ca10feb..a7b5cb0c2753 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -26,6 +26,8 @@ | |||
26 | * if_sdio_card_to_host() to pad the data. | 26 | * if_sdio_card_to_host() to pad the data. |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
30 | |||
29 | #include <linux/kernel.h> | 31 | #include <linux/kernel.h> |
30 | #include <linux/moduleparam.h> | 32 | #include <linux/moduleparam.h> |
31 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
@@ -409,7 +411,7 @@ static int if_sdio_card_to_host(struct if_sdio_card *card) | |||
409 | 411 | ||
410 | out: | 412 | out: |
411 | if (ret) | 413 | if (ret) |
412 | lbs_pr_err("problem fetching packet from firmware\n"); | 414 | pr_err("problem fetching packet from firmware\n"); |
413 | 415 | ||
414 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 416 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); |
415 | 417 | ||
@@ -446,7 +448,7 @@ static void if_sdio_host_to_card_worker(struct work_struct *work) | |||
446 | } | 448 | } |
447 | 449 | ||
448 | if (ret) | 450 | if (ret) |
449 | lbs_pr_err("error %d sending packet to firmware\n", ret); | 451 | pr_err("error %d sending packet to firmware\n", ret); |
450 | 452 | ||
451 | sdio_release_host(card->func); | 453 | sdio_release_host(card->func); |
452 | 454 | ||
@@ -555,7 +557,7 @@ release: | |||
555 | 557 | ||
556 | out: | 558 | out: |
557 | if (ret) | 559 | if (ret) |
558 | lbs_pr_err("failed to load helper firmware\n"); | 560 | pr_err("failed to load helper firmware\n"); |
559 | 561 | ||
560 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 562 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); |
561 | return ret; | 563 | return ret; |
@@ -669,7 +671,7 @@ release: | |||
669 | 671 | ||
670 | out: | 672 | out: |
671 | if (ret) | 673 | if (ret) |
672 | lbs_pr_err("failed to load firmware\n"); | 674 | pr_err("failed to load firmware\n"); |
673 | 675 | ||
674 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 676 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); |
675 | return ret; | 677 | return ret; |
@@ -723,7 +725,7 @@ static int if_sdio_prog_firmware(struct if_sdio_card *card) | |||
723 | ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name, | 725 | ret = lbs_get_firmware(&card->func->dev, lbs_helper_name, lbs_fw_name, |
724 | card->model, &fw_table[0], &helper, &mainfw); | 726 | card->model, &fw_table[0], &helper, &mainfw); |
725 | if (ret) { | 727 | if (ret) { |
726 | lbs_pr_err("failed to find firmware (%d)\n", ret); | 728 | pr_err("failed to find firmware (%d)\n", ret); |
727 | goto out; | 729 | goto out; |
728 | } | 730 | } |
729 | 731 | ||
@@ -849,7 +851,7 @@ static int if_sdio_enter_deep_sleep(struct lbs_private *priv) | |||
849 | ret = __lbs_cmd(priv, CMD_802_11_DEEP_SLEEP, &cmd, sizeof(cmd), | 851 | ret = __lbs_cmd(priv, CMD_802_11_DEEP_SLEEP, &cmd, sizeof(cmd), |
850 | lbs_cmd_copyback, (unsigned long) &cmd); | 852 | lbs_cmd_copyback, (unsigned long) &cmd); |
851 | if (ret) | 853 | if (ret) |
852 | lbs_pr_err("DEEP_SLEEP cmd failed\n"); | 854 | netdev_err(priv->dev, "DEEP_SLEEP cmd failed\n"); |
853 | 855 | ||
854 | mdelay(200); | 856 | mdelay(200); |
855 | return ret; | 857 | return ret; |
@@ -865,7 +867,7 @@ static int if_sdio_exit_deep_sleep(struct lbs_private *priv) | |||
865 | 867 | ||
866 | sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret); | 868 | sdio_writeb(card->func, HOST_POWER_UP, CONFIGURATION_REG, &ret); |
867 | if (ret) | 869 | if (ret) |
868 | lbs_pr_err("sdio_writeb failed!\n"); | 870 | netdev_err(priv->dev, "sdio_writeb failed!\n"); |
869 | 871 | ||
870 | sdio_release_host(card->func); | 872 | sdio_release_host(card->func); |
871 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 873 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); |
@@ -882,7 +884,7 @@ static int if_sdio_reset_deep_sleep_wakeup(struct lbs_private *priv) | |||
882 | 884 | ||
883 | sdio_writeb(card->func, 0, CONFIGURATION_REG, &ret); | 885 | sdio_writeb(card->func, 0, CONFIGURATION_REG, &ret); |
884 | if (ret) | 886 | if (ret) |
885 | lbs_pr_err("sdio_writeb failed!\n"); | 887 | netdev_err(priv->dev, "sdio_writeb failed!\n"); |
886 | 888 | ||
887 | sdio_release_host(card->func); | 889 | sdio_release_host(card->func); |
888 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); | 890 | lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); |
@@ -961,7 +963,7 @@ static int if_sdio_probe(struct sdio_func *func, | |||
961 | } | 963 | } |
962 | 964 | ||
963 | if (i == func->card->num_info) { | 965 | if (i == func->card->num_info) { |
964 | lbs_pr_err("unable to identify card model\n"); | 966 | pr_err("unable to identify card model\n"); |
965 | return -ENODEV; | 967 | return -ENODEV; |
966 | } | 968 | } |
967 | 969 | ||
@@ -995,7 +997,7 @@ static int if_sdio_probe(struct sdio_func *func, | |||
995 | break; | 997 | break; |
996 | } | 998 | } |
997 | if (i == ARRAY_SIZE(fw_table)) { | 999 | if (i == ARRAY_SIZE(fw_table)) { |
998 | lbs_pr_err("unknown card model 0x%x\n", card->model); | 1000 | pr_err("unknown card model 0x%x\n", card->model); |
999 | ret = -ENODEV; | 1001 | ret = -ENODEV; |
1000 | goto free; | 1002 | goto free; |
1001 | } | 1003 | } |
@@ -1101,7 +1103,7 @@ static int if_sdio_probe(struct sdio_func *func, | |||
1101 | lbs_deb_sdio("send function INIT command\n"); | 1103 | lbs_deb_sdio("send function INIT command\n"); |
1102 | if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd), | 1104 | if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd), |
1103 | lbs_cmd_copyback, (unsigned long) &cmd)) | 1105 | lbs_cmd_copyback, (unsigned long) &cmd)) |
1104 | lbs_pr_alert("CMD_FUNC_INIT cmd failed\n"); | 1106 | netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n"); |
1105 | } | 1107 | } |
1106 | 1108 | ||
1107 | ret = lbs_start_card(priv); | 1109 | ret = lbs_start_card(priv); |
@@ -1163,7 +1165,7 @@ static void if_sdio_remove(struct sdio_func *func) | |||
1163 | if (__lbs_cmd(card->priv, CMD_FUNC_SHUTDOWN, | 1165 | if (__lbs_cmd(card->priv, CMD_FUNC_SHUTDOWN, |
1164 | &cmd, sizeof(cmd), lbs_cmd_copyback, | 1166 | &cmd, sizeof(cmd), lbs_cmd_copyback, |
1165 | (unsigned long) &cmd)) | 1167 | (unsigned long) &cmd)) |
1166 | lbs_pr_alert("CMD_FUNC_SHUTDOWN cmd failed\n"); | 1168 | pr_alert("CMD_FUNC_SHUTDOWN cmd failed\n"); |
1167 | } | 1169 | } |
1168 | 1170 | ||
1169 | 1171 | ||
@@ -1202,20 +1204,19 @@ static int if_sdio_suspend(struct device *dev) | |||
1202 | 1204 | ||
1203 | mmc_pm_flag_t flags = sdio_get_host_pm_caps(func); | 1205 | mmc_pm_flag_t flags = sdio_get_host_pm_caps(func); |
1204 | 1206 | ||
1205 | lbs_pr_info("%s: suspend: PM flags = 0x%x\n", | 1207 | dev_info(dev, "%s: suspend: PM flags = 0x%x\n", |
1206 | sdio_func_id(func), flags); | 1208 | sdio_func_id(func), flags); |
1207 | 1209 | ||
1208 | /* If we aren't being asked to wake on anything, we should bail out | 1210 | /* If we aren't being asked to wake on anything, we should bail out |
1209 | * and let the SD stack power down the card. | 1211 | * and let the SD stack power down the card. |
1210 | */ | 1212 | */ |
1211 | if (card->priv->wol_criteria == EHS_REMOVE_WAKEUP) { | 1213 | if (card->priv->wol_criteria == EHS_REMOVE_WAKEUP) { |
1212 | lbs_pr_info("Suspend without wake params -- " | 1214 | dev_info(dev, "Suspend without wake params -- powering down card\n"); |
1213 | "powering down card."); | ||
1214 | return -ENOSYS; | 1215 | return -ENOSYS; |
1215 | } | 1216 | } |
1216 | 1217 | ||
1217 | if (!(flags & MMC_PM_KEEP_POWER)) { | 1218 | if (!(flags & MMC_PM_KEEP_POWER)) { |
1218 | lbs_pr_err("%s: cannot remain alive while host is suspended\n", | 1219 | dev_err(dev, "%s: cannot remain alive while host is suspended\n", |
1219 | sdio_func_id(func)); | 1220 | sdio_func_id(func)); |
1220 | return -ENOSYS; | 1221 | return -ENOSYS; |
1221 | } | 1222 | } |
@@ -1237,7 +1238,7 @@ static int if_sdio_resume(struct device *dev) | |||
1237 | struct if_sdio_card *card = sdio_get_drvdata(func); | 1238 | struct if_sdio_card *card = sdio_get_drvdata(func); |
1238 | int ret; | 1239 | int ret; |
1239 | 1240 | ||
1240 | lbs_pr_info("%s: resume: we're back\n", sdio_func_id(func)); | 1241 | dev_info(dev, "%s: resume: we're back\n", sdio_func_id(func)); |
1241 | 1242 | ||
1242 | ret = lbs_resume(card->priv); | 1243 | ret = lbs_resume(card->priv); |
1243 | 1244 | ||
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c index 67de5b3c68b2..463352c890d7 100644 --- a/drivers/net/wireless/libertas/if_spi.c +++ b/drivers/net/wireless/libertas/if_spi.c | |||
@@ -17,6 +17,8 @@ | |||
17 | * (at your option) any later version. | 17 | * (at your option) any later version. |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
21 | |||
20 | #include <linux/moduleparam.h> | 22 | #include <linux/moduleparam.h> |
21 | #include <linux/firmware.h> | 23 | #include <linux/firmware.h> |
22 | #include <linux/jiffies.h> | 24 | #include <linux/jiffies.h> |
@@ -305,8 +307,7 @@ static int spu_wait_for_u16(struct if_spi_card *card, u16 reg, | |||
305 | } | 307 | } |
306 | udelay(100); | 308 | udelay(100); |
307 | if (time_after(jiffies, timeout)) { | 309 | if (time_after(jiffies, timeout)) { |
308 | lbs_pr_err("%s: timeout with val=%02x, " | 310 | pr_err("%s: timeout with val=%02x, target_mask=%02x, target=%02x\n", |
309 | "target_mask=%02x, target=%02x\n", | ||
310 | __func__, val, target_mask, target); | 311 | __func__, val, target_mask, target); |
311 | return -ETIMEDOUT; | 312 | return -ETIMEDOUT; |
312 | } | 313 | } |
@@ -405,7 +406,7 @@ static int spu_set_bus_mode(struct if_spi_card *card, u16 mode) | |||
405 | if (err) | 406 | if (err) |
406 | return err; | 407 | return err; |
407 | if ((rval & 0xF) != mode) { | 408 | if ((rval & 0xF) != mode) { |
408 | lbs_pr_err("Can't read bus mode register.\n"); | 409 | pr_err("Can't read bus mode register\n"); |
409 | return -EIO; | 410 | return -EIO; |
410 | } | 411 | } |
411 | return 0; | 412 | return 0; |
@@ -534,7 +535,7 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card, | |||
534 | 535 | ||
535 | out: | 536 | out: |
536 | if (err) | 537 | if (err) |
537 | lbs_pr_err("failed to load helper firmware (err=%d)\n", err); | 538 | pr_err("failed to load helper firmware (err=%d)\n", err); |
538 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err); | 539 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err); |
539 | return err; | 540 | return err; |
540 | } | 541 | } |
@@ -557,7 +558,7 @@ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card, | |||
557 | IF_SPI_HIST_CMD_DOWNLOAD_RDY, | 558 | IF_SPI_HIST_CMD_DOWNLOAD_RDY, |
558 | IF_SPI_HIST_CMD_DOWNLOAD_RDY); | 559 | IF_SPI_HIST_CMD_DOWNLOAD_RDY); |
559 | if (err) { | 560 | if (err) { |
560 | lbs_pr_err("timed out waiting for host_int_status\n"); | 561 | pr_err("timed out waiting for host_int_status\n"); |
561 | return err; | 562 | return err; |
562 | } | 563 | } |
563 | 564 | ||
@@ -567,9 +568,8 @@ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card, | |||
567 | return err; | 568 | return err; |
568 | 569 | ||
569 | if (len > IF_SPI_CMD_BUF_SIZE) { | 570 | if (len > IF_SPI_CMD_BUF_SIZE) { |
570 | lbs_pr_err("firmware load device requested a larger " | 571 | pr_err("firmware load device requested a larger transfer than we are prepared to handle (len = %d)\n", |
571 | "tranfer than we are prepared to " | 572 | len); |
572 | "handle. (len = %d)\n", len); | ||
573 | return -EIO; | 573 | return -EIO; |
574 | } | 574 | } |
575 | if (len & 0x1) { | 575 | if (len & 0x1) { |
@@ -585,6 +585,7 @@ static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card, | |||
585 | static int if_spi_prog_main_firmware(struct if_spi_card *card, | 585 | static int if_spi_prog_main_firmware(struct if_spi_card *card, |
586 | const struct firmware *firmware) | 586 | const struct firmware *firmware) |
587 | { | 587 | { |
588 | struct lbs_private *priv = card->priv; | ||
588 | int len, prev_len; | 589 | int len, prev_len; |
589 | int bytes, crc_err = 0, err = 0; | 590 | int bytes, crc_err = 0, err = 0; |
590 | const u8 *fw; | 591 | const u8 *fw; |
@@ -598,8 +599,9 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card, | |||
598 | 599 | ||
599 | err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0); | 600 | err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0); |
600 | if (err) { | 601 | if (err) { |
601 | lbs_pr_err("%s: timed out waiting for initial " | 602 | netdev_err(priv->dev, |
602 | "scratch reg = 0\n", __func__); | 603 | "%s: timed out waiting for initial scratch reg = 0\n", |
604 | __func__); | ||
603 | goto out; | 605 | goto out; |
604 | } | 606 | } |
605 | 607 | ||
@@ -617,15 +619,14 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card, | |||
617 | * If there are no more bytes left, we would normally | 619 | * If there are no more bytes left, we would normally |
618 | * expect to have terminated with len = 0 | 620 | * expect to have terminated with len = 0 |
619 | */ | 621 | */ |
620 | lbs_pr_err("Firmware load wants more bytes " | 622 | netdev_err(priv->dev, |
621 | "than we have to offer.\n"); | 623 | "Firmware load wants more bytes than we have to offer.\n"); |
622 | break; | 624 | break; |
623 | } | 625 | } |
624 | if (crc_err) { | 626 | if (crc_err) { |
625 | /* Previous transfer failed. */ | 627 | /* Previous transfer failed. */ |
626 | if (++num_crc_errs > MAX_MAIN_FW_LOAD_CRC_ERR) { | 628 | if (++num_crc_errs > MAX_MAIN_FW_LOAD_CRC_ERR) { |
627 | lbs_pr_err("Too many CRC errors encountered " | 629 | pr_err("Too many CRC errors encountered in firmware load.\n"); |
628 | "in firmware load.\n"); | ||
629 | err = -EIO; | 630 | err = -EIO; |
630 | goto out; | 631 | goto out; |
631 | } | 632 | } |
@@ -654,21 +655,20 @@ static int if_spi_prog_main_firmware(struct if_spi_card *card, | |||
654 | prev_len = len; | 655 | prev_len = len; |
655 | } | 656 | } |
656 | if (bytes > prev_len) { | 657 | if (bytes > prev_len) { |
657 | lbs_pr_err("firmware load wants fewer bytes than " | 658 | pr_err("firmware load wants fewer bytes than we have to offer\n"); |
658 | "we have to offer.\n"); | ||
659 | } | 659 | } |
660 | 660 | ||
661 | /* Confirm firmware download */ | 661 | /* Confirm firmware download */ |
662 | err = spu_wait_for_u32(card, IF_SPI_SCRATCH_4_REG, | 662 | err = spu_wait_for_u32(card, IF_SPI_SCRATCH_4_REG, |
663 | SUCCESSFUL_FW_DOWNLOAD_MAGIC); | 663 | SUCCESSFUL_FW_DOWNLOAD_MAGIC); |
664 | if (err) { | 664 | if (err) { |
665 | lbs_pr_err("failed to confirm the firmware download\n"); | 665 | pr_err("failed to confirm the firmware download\n"); |
666 | goto out; | 666 | goto out; |
667 | } | 667 | } |
668 | 668 | ||
669 | out: | 669 | out: |
670 | if (err) | 670 | if (err) |
671 | lbs_pr_err("failed to load firmware (err=%d)\n", err); | 671 | pr_err("failed to load firmware (err=%d)\n", err); |
672 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err); | 672 | lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err); |
673 | return err; | 673 | return err; |
674 | } | 674 | } |
@@ -709,13 +709,13 @@ static int if_spi_c2h_cmd(struct if_spi_card *card) | |||
709 | if (err) | 709 | if (err) |
710 | goto out; | 710 | goto out; |
711 | if (!len) { | 711 | if (!len) { |
712 | lbs_pr_err("%s: error: card has no data for host\n", | 712 | netdev_err(priv->dev, "%s: error: card has no data for host\n", |
713 | __func__); | 713 | __func__); |
714 | err = -EINVAL; | 714 | err = -EINVAL; |
715 | goto out; | 715 | goto out; |
716 | } else if (len > IF_SPI_CMD_BUF_SIZE) { | 716 | } else if (len > IF_SPI_CMD_BUF_SIZE) { |
717 | lbs_pr_err("%s: error: response packet too large: " | 717 | netdev_err(priv->dev, |
718 | "%d bytes, but maximum is %d\n", | 718 | "%s: error: response packet too large: %d bytes, but maximum is %d\n", |
719 | __func__, len, IF_SPI_CMD_BUF_SIZE); | 719 | __func__, len, IF_SPI_CMD_BUF_SIZE); |
720 | err = -EINVAL; | 720 | err = -EINVAL; |
721 | goto out; | 721 | goto out; |
@@ -737,7 +737,7 @@ static int if_spi_c2h_cmd(struct if_spi_card *card) | |||
737 | 737 | ||
738 | out: | 738 | out: |
739 | if (err) | 739 | if (err) |
740 | lbs_pr_err("%s: err=%d\n", __func__, err); | 740 | netdev_err(priv->dev, "%s: err=%d\n", __func__, err); |
741 | lbs_deb_leave(LBS_DEB_SPI); | 741 | lbs_deb_leave(LBS_DEB_SPI); |
742 | return err; | 742 | return err; |
743 | } | 743 | } |
@@ -745,6 +745,7 @@ out: | |||
745 | /* Move data from the card to the host */ | 745 | /* Move data from the card to the host */ |
746 | static int if_spi_c2h_data(struct if_spi_card *card) | 746 | static int if_spi_c2h_data(struct if_spi_card *card) |
747 | { | 747 | { |
748 | struct lbs_private *priv = card->priv; | ||
748 | struct sk_buff *skb; | 749 | struct sk_buff *skb; |
749 | char *data; | 750 | char *data; |
750 | u16 len; | 751 | u16 len; |
@@ -757,13 +758,13 @@ static int if_spi_c2h_data(struct if_spi_card *card) | |||
757 | if (err) | 758 | if (err) |
758 | goto out; | 759 | goto out; |
759 | if (!len) { | 760 | if (!len) { |
760 | lbs_pr_err("%s: error: card has no data for host\n", | 761 | netdev_err(priv->dev, "%s: error: card has no data for host\n", |
761 | __func__); | 762 | __func__); |
762 | err = -EINVAL; | 763 | err = -EINVAL; |
763 | goto out; | 764 | goto out; |
764 | } else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { | 765 | } else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { |
765 | lbs_pr_err("%s: error: card has %d bytes of data, but " | 766 | netdev_err(priv->dev, |
766 | "our maximum skb size is %zu\n", | 767 | "%s: error: card has %d bytes of data, but our maximum skb size is %zu\n", |
767 | __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); | 768 | __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); |
768 | err = -EINVAL; | 769 | err = -EINVAL; |
769 | goto out; | 770 | goto out; |
@@ -795,7 +796,7 @@ free_skb: | |||
795 | dev_kfree_skb(skb); | 796 | dev_kfree_skb(skb); |
796 | out: | 797 | out: |
797 | if (err) | 798 | if (err) |
798 | lbs_pr_err("%s: err=%d\n", __func__, err); | 799 | netdev_err(priv->dev, "%s: err=%d\n", __func__, err); |
799 | lbs_deb_leave(LBS_DEB_SPI); | 800 | lbs_deb_leave(LBS_DEB_SPI); |
800 | return err; | 801 | return err; |
801 | } | 802 | } |
@@ -804,6 +805,7 @@ out: | |||
804 | static void if_spi_h2c(struct if_spi_card *card, | 805 | static void if_spi_h2c(struct if_spi_card *card, |
805 | struct if_spi_packet *packet, int type) | 806 | struct if_spi_packet *packet, int type) |
806 | { | 807 | { |
808 | struct lbs_private *priv = card->priv; | ||
807 | int err = 0; | 809 | int err = 0; |
808 | u16 int_type, port_reg; | 810 | u16 int_type, port_reg; |
809 | 811 | ||
@@ -817,7 +819,8 @@ static void if_spi_h2c(struct if_spi_card *card, | |||
817 | port_reg = IF_SPI_CMD_RDWRPORT_REG; | 819 | port_reg = IF_SPI_CMD_RDWRPORT_REG; |
818 | break; | 820 | break; |
819 | default: | 821 | default: |
820 | lbs_pr_err("can't transfer buffer of type %d\n", type); | 822 | netdev_err(priv->dev, "can't transfer buffer of type %d\n", |
823 | type); | ||
821 | err = -EINVAL; | 824 | err = -EINVAL; |
822 | goto out; | 825 | goto out; |
823 | } | 826 | } |
@@ -831,7 +834,7 @@ out: | |||
831 | kfree(packet); | 834 | kfree(packet); |
832 | 835 | ||
833 | if (err) | 836 | if (err) |
834 | lbs_pr_err("%s: error %d\n", __func__, err); | 837 | netdev_err(priv->dev, "%s: error %d\n", __func__, err); |
835 | } | 838 | } |
836 | 839 | ||
837 | /* Inform the host about a card event */ | 840 | /* Inform the host about a card event */ |
@@ -855,7 +858,7 @@ static void if_spi_e2h(struct if_spi_card *card) | |||
855 | lbs_queue_event(priv, cause & 0xff); | 858 | lbs_queue_event(priv, cause & 0xff); |
856 | out: | 859 | out: |
857 | if (err) | 860 | if (err) |
858 | lbs_pr_err("%s: error %d\n", __func__, err); | 861 | netdev_err(priv->dev, "%s: error %d\n", __func__, err); |
859 | } | 862 | } |
860 | 863 | ||
861 | static void if_spi_host_to_card_worker(struct work_struct *work) | 864 | static void if_spi_host_to_card_worker(struct work_struct *work) |
@@ -865,8 +868,10 @@ static void if_spi_host_to_card_worker(struct work_struct *work) | |||
865 | u16 hiStatus; | 868 | u16 hiStatus; |
866 | unsigned long flags; | 869 | unsigned long flags; |
867 | struct if_spi_packet *packet; | 870 | struct if_spi_packet *packet; |
871 | struct lbs_private *priv; | ||
868 | 872 | ||
869 | card = container_of(work, struct if_spi_card, packet_work); | 873 | card = container_of(work, struct if_spi_card, packet_work); |
874 | priv = card->priv; | ||
870 | 875 | ||
871 | lbs_deb_enter(LBS_DEB_SPI); | 876 | lbs_deb_enter(LBS_DEB_SPI); |
872 | 877 | ||
@@ -877,7 +882,7 @@ static void if_spi_host_to_card_worker(struct work_struct *work) | |||
877 | err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG, | 882 | err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG, |
878 | &hiStatus); | 883 | &hiStatus); |
879 | if (err) { | 884 | if (err) { |
880 | lbs_pr_err("I/O error\n"); | 885 | netdev_err(priv->dev, "I/O error\n"); |
881 | goto err; | 886 | goto err; |
882 | } | 887 | } |
883 | 888 | ||
@@ -940,7 +945,7 @@ static void if_spi_host_to_card_worker(struct work_struct *work) | |||
940 | 945 | ||
941 | err: | 946 | err: |
942 | if (err) | 947 | if (err) |
943 | lbs_pr_err("%s: got error %d\n", __func__, err); | 948 | netdev_err(priv->dev, "%s: got error %d\n", __func__, err); |
944 | 949 | ||
945 | lbs_deb_leave(LBS_DEB_SPI); | 950 | lbs_deb_leave(LBS_DEB_SPI); |
946 | } | 951 | } |
@@ -963,7 +968,8 @@ static int if_spi_host_to_card(struct lbs_private *priv, | |||
963 | lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb); | 968 | lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb); |
964 | 969 | ||
965 | if (nb == 0) { | 970 | if (nb == 0) { |
966 | lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb); | 971 | netdev_err(priv->dev, "%s: invalid size requested: %d\n", |
972 | __func__, nb); | ||
967 | err = -EINVAL; | 973 | err = -EINVAL; |
968 | goto out; | 974 | goto out; |
969 | } | 975 | } |
@@ -991,7 +997,8 @@ static int if_spi_host_to_card(struct lbs_private *priv, | |||
991 | spin_unlock_irqrestore(&card->buffer_lock, flags); | 997 | spin_unlock_irqrestore(&card->buffer_lock, flags); |
992 | break; | 998 | break; |
993 | default: | 999 | default: |
994 | lbs_pr_err("can't transfer buffer of type %d", type); | 1000 | netdev_err(priv->dev, "can't transfer buffer of type %d\n", |
1001 | type); | ||
995 | err = -EINVAL; | 1002 | err = -EINVAL; |
996 | break; | 1003 | break; |
997 | } | 1004 | } |
@@ -1024,6 +1031,7 @@ static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id) | |||
1024 | 1031 | ||
1025 | static int if_spi_init_card(struct if_spi_card *card) | 1032 | static int if_spi_init_card(struct if_spi_card *card) |
1026 | { | 1033 | { |
1034 | struct lbs_private *priv = card->priv; | ||
1027 | struct spi_device *spi = card->spi; | 1035 | struct spi_device *spi = card->spi; |
1028 | int err, i; | 1036 | int err, i; |
1029 | u32 scratch; | 1037 | u32 scratch; |
@@ -1052,8 +1060,8 @@ static int if_spi_init_card(struct if_spi_card *card) | |||
1052 | break; | 1060 | break; |
1053 | } | 1061 | } |
1054 | if (i == ARRAY_SIZE(fw_table)) { | 1062 | if (i == ARRAY_SIZE(fw_table)) { |
1055 | lbs_pr_err("Unsupported chip_id: 0x%02x\n", | 1063 | netdev_err(priv->dev, "Unsupported chip_id: 0x%02x\n", |
1056 | card->card_id); | 1064 | card->card_id); |
1057 | err = -ENODEV; | 1065 | err = -ENODEV; |
1058 | goto out; | 1066 | goto out; |
1059 | } | 1067 | } |
@@ -1062,7 +1070,8 @@ static int if_spi_init_card(struct if_spi_card *card) | |||
1062 | card->card_id, &fw_table[0], &helper, | 1070 | card->card_id, &fw_table[0], &helper, |
1063 | &mainfw); | 1071 | &mainfw); |
1064 | if (err) { | 1072 | if (err) { |
1065 | lbs_pr_err("failed to find firmware (%d)\n", err); | 1073 | netdev_err(priv->dev, "failed to find firmware (%d)\n", |
1074 | err); | ||
1066 | goto out; | 1075 | goto out; |
1067 | } | 1076 | } |
1068 | 1077 | ||
@@ -1187,7 +1196,7 @@ static int __devinit if_spi_probe(struct spi_device *spi) | |||
1187 | err = request_irq(spi->irq, if_spi_host_interrupt, | 1196 | err = request_irq(spi->irq, if_spi_host_interrupt, |
1188 | IRQF_TRIGGER_FALLING, "libertas_spi", card); | 1197 | IRQF_TRIGGER_FALLING, "libertas_spi", card); |
1189 | if (err) { | 1198 | if (err) { |
1190 | lbs_pr_err("can't get host irq line-- request_irq failed\n"); | 1199 | pr_err("can't get host irq line-- request_irq failed\n"); |
1191 | goto terminate_workqueue; | 1200 | goto terminate_workqueue; |
1192 | } | 1201 | } |
1193 | 1202 | ||
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c index e1e2128f4113..b5acc393a65a 100644 --- a/drivers/net/wireless/libertas/if_usb.c +++ b/drivers/net/wireless/libertas/if_usb.c | |||
@@ -1,6 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * This file contains functions used in USB interface module. | 2 | * This file contains functions used in USB interface module. |
3 | */ | 3 | */ |
4 | |||
5 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
6 | |||
4 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
5 | #include <linux/moduleparam.h> | 8 | #include <linux/moduleparam.h> |
6 | #include <linux/firmware.h> | 9 | #include <linux/firmware.h> |
@@ -153,7 +156,7 @@ static void if_usb_write_bulk_callback(struct urb *urb) | |||
153 | lbs_host_to_card_done(priv); | 156 | lbs_host_to_card_done(priv); |
154 | } else { | 157 | } else { |
155 | /* print the failure status number for debug */ | 158 | /* print the failure status number for debug */ |
156 | lbs_pr_info("URB in failure status: %d\n", urb->status); | 159 | pr_info("URB in failure status: %d\n", urb->status); |
157 | } | 160 | } |
158 | } | 161 | } |
159 | 162 | ||
@@ -203,7 +206,7 @@ static void if_usb_setup_firmware(struct lbs_private *priv) | |||
203 | wake_method.hdr.size = cpu_to_le16(sizeof(wake_method)); | 206 | wake_method.hdr.size = cpu_to_le16(sizeof(wake_method)); |
204 | wake_method.action = cpu_to_le16(CMD_ACT_GET); | 207 | wake_method.action = cpu_to_le16(CMD_ACT_GET); |
205 | if (lbs_cmd_with_response(priv, CMD_802_11_FW_WAKE_METHOD, &wake_method)) { | 208 | if (lbs_cmd_with_response(priv, CMD_802_11_FW_WAKE_METHOD, &wake_method)) { |
206 | lbs_pr_info("Firmware does not seem to support PS mode\n"); | 209 | netdev_info(priv->dev, "Firmware does not seem to support PS mode\n"); |
207 | priv->fwcapinfo &= ~FW_CAPINFO_PS; | 210 | priv->fwcapinfo &= ~FW_CAPINFO_PS; |
208 | } else { | 211 | } else { |
209 | if (le16_to_cpu(wake_method.method) == CMD_WAKE_METHOD_COMMAND_INT) { | 212 | if (le16_to_cpu(wake_method.method) == CMD_WAKE_METHOD_COMMAND_INT) { |
@@ -212,7 +215,8 @@ static void if_usb_setup_firmware(struct lbs_private *priv) | |||
212 | /* The versions which boot up this way don't seem to | 215 | /* The versions which boot up this way don't seem to |
213 | work even if we set it to the command interrupt */ | 216 | work even if we set it to the command interrupt */ |
214 | priv->fwcapinfo &= ~FW_CAPINFO_PS; | 217 | priv->fwcapinfo &= ~FW_CAPINFO_PS; |
215 | lbs_pr_info("Firmware doesn't wake via command interrupt; disabling PS mode\n"); | 218 | netdev_info(priv->dev, |
219 | "Firmware doesn't wake via command interrupt; disabling PS mode\n"); | ||
216 | } | 220 | } |
217 | } | 221 | } |
218 | } | 222 | } |
@@ -224,7 +228,7 @@ static void if_usb_fw_timeo(unsigned long priv) | |||
224 | if (cardp->fwdnldover) { | 228 | if (cardp->fwdnldover) { |
225 | lbs_deb_usb("Download complete, no event. Assuming success\n"); | 229 | lbs_deb_usb("Download complete, no event. Assuming success\n"); |
226 | } else { | 230 | } else { |
227 | lbs_pr_err("Download timed out\n"); | 231 | pr_err("Download timed out\n"); |
228 | cardp->surprise_removed = 1; | 232 | cardp->surprise_removed = 1; |
229 | } | 233 | } |
230 | wake_up(&cardp->fw_wq); | 234 | wake_up(&cardp->fw_wq); |
@@ -258,7 +262,7 @@ static int if_usb_probe(struct usb_interface *intf, | |||
258 | 262 | ||
259 | cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL); | 263 | cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL); |
260 | if (!cardp) { | 264 | if (!cardp) { |
261 | lbs_pr_err("Out of memory allocating private data.\n"); | 265 | pr_err("Out of memory allocating private data\n"); |
262 | goto error; | 266 | goto error; |
263 | } | 267 | } |
264 | 268 | ||
@@ -348,10 +352,12 @@ static int if_usb_probe(struct usb_interface *intf, | |||
348 | usb_set_intfdata(intf, cardp); | 352 | usb_set_intfdata(intf, cardp); |
349 | 353 | ||
350 | if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_fw)) | 354 | if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_fw)) |
351 | lbs_pr_err("cannot register lbs_flash_fw attribute\n"); | 355 | netdev_err(priv->dev, |
356 | "cannot register lbs_flash_fw attribute\n"); | ||
352 | 357 | ||
353 | if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2)) | 358 | if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2)) |
354 | lbs_pr_err("cannot register lbs_flash_boot2 attribute\n"); | 359 | netdev_err(priv->dev, |
360 | "cannot register lbs_flash_boot2 attribute\n"); | ||
355 | 361 | ||
356 | /* | 362 | /* |
357 | * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware. | 363 | * EHS_REMOVE_WAKEUP is not supported on all versions of the firmware. |
@@ -536,7 +542,7 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, | |||
536 | int ret = -1; | 542 | int ret = -1; |
537 | 543 | ||
538 | if (!(skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))) { | 544 | if (!(skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))) { |
539 | lbs_pr_err("No free skb\n"); | 545 | pr_err("No free skb\n"); |
540 | goto rx_ret; | 546 | goto rx_ret; |
541 | } | 547 | } |
542 | 548 | ||
@@ -595,7 +601,7 @@ static void if_usb_receive_fwload(struct urb *urb) | |||
595 | 601 | ||
596 | if (tmp[0] == cpu_to_le32(CMD_TYPE_INDICATION) && | 602 | if (tmp[0] == cpu_to_le32(CMD_TYPE_INDICATION) && |
597 | tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY)) { | 603 | tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY)) { |
598 | lbs_pr_info("Firmware ready event received\n"); | 604 | pr_info("Firmware ready event received\n"); |
599 | wake_up(&cardp->fw_wq); | 605 | wake_up(&cardp->fw_wq); |
600 | } else { | 606 | } else { |
601 | lbs_deb_usb("Waiting for confirmation; got %x %x\n", | 607 | lbs_deb_usb("Waiting for confirmation; got %x %x\n", |
@@ -622,20 +628,20 @@ static void if_usb_receive_fwload(struct urb *urb) | |||
622 | bootcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) || | 628 | bootcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) || |
623 | bootcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) { | 629 | bootcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) { |
624 | if (!cardp->bootcmdresp) | 630 | if (!cardp->bootcmdresp) |
625 | lbs_pr_info("Firmware already seems alive; resetting\n"); | 631 | pr_info("Firmware already seems alive; resetting\n"); |
626 | cardp->bootcmdresp = -1; | 632 | cardp->bootcmdresp = -1; |
627 | } else { | 633 | } else { |
628 | lbs_pr_info("boot cmd response wrong magic number (0x%x)\n", | 634 | pr_info("boot cmd response wrong magic number (0x%x)\n", |
629 | le32_to_cpu(bootcmdresp.magic)); | 635 | le32_to_cpu(bootcmdresp.magic)); |
630 | } | 636 | } |
631 | } else if ((bootcmdresp.cmd != BOOT_CMD_FW_BY_USB) && | 637 | } else if ((bootcmdresp.cmd != BOOT_CMD_FW_BY_USB) && |
632 | (bootcmdresp.cmd != BOOT_CMD_UPDATE_FW) && | 638 | (bootcmdresp.cmd != BOOT_CMD_UPDATE_FW) && |
633 | (bootcmdresp.cmd != BOOT_CMD_UPDATE_BOOT2)) { | 639 | (bootcmdresp.cmd != BOOT_CMD_UPDATE_BOOT2)) { |
634 | lbs_pr_info("boot cmd response cmd_tag error (%d)\n", | 640 | pr_info("boot cmd response cmd_tag error (%d)\n", |
635 | bootcmdresp.cmd); | 641 | bootcmdresp.cmd); |
636 | } else if (bootcmdresp.result != BOOT_CMD_RESP_OK) { | 642 | } else if (bootcmdresp.result != BOOT_CMD_RESP_OK) { |
637 | lbs_pr_info("boot cmd response result error (%d)\n", | 643 | pr_info("boot cmd response result error (%d)\n", |
638 | bootcmdresp.result); | 644 | bootcmdresp.result); |
639 | } else { | 645 | } else { |
640 | cardp->bootcmdresp = 1; | 646 | cardp->bootcmdresp = 1; |
641 | lbs_deb_usbd(&cardp->udev->dev, | 647 | lbs_deb_usbd(&cardp->udev->dev, |
@@ -901,7 +907,7 @@ static int check_fwfile_format(const uint8_t *data, uint32_t totlen) | |||
901 | } while (!exit); | 907 | } while (!exit); |
902 | 908 | ||
903 | if (ret) | 909 | if (ret) |
904 | lbs_pr_err("firmware file format check FAIL\n"); | 910 | pr_err("firmware file format check FAIL\n"); |
905 | else | 911 | else |
906 | lbs_deb_fw("firmware file format check PASS\n"); | 912 | lbs_deb_fw("firmware file format check PASS\n"); |
907 | 913 | ||
@@ -998,7 +1004,7 @@ static int __if_usb_prog_firmware(struct if_usb_card *cardp, | |||
998 | 1004 | ||
999 | ret = get_fw(cardp, fwname); | 1005 | ret = get_fw(cardp, fwname); |
1000 | if (ret) { | 1006 | if (ret) { |
1001 | lbs_pr_err("failed to find firmware (%d)\n", ret); | 1007 | pr_err("failed to find firmware (%d)\n", ret); |
1002 | goto done; | 1008 | goto done; |
1003 | } | 1009 | } |
1004 | 1010 | ||
@@ -1073,13 +1079,13 @@ restart: | |||
1073 | usb_kill_urb(cardp->rx_urb); | 1079 | usb_kill_urb(cardp->rx_urb); |
1074 | 1080 | ||
1075 | if (!cardp->fwdnldover) { | 1081 | if (!cardp->fwdnldover) { |
1076 | lbs_pr_info("failed to load fw, resetting device!\n"); | 1082 | pr_info("failed to load fw, resetting device!\n"); |
1077 | if (--reset_count >= 0) { | 1083 | if (--reset_count >= 0) { |
1078 | if_usb_reset_device(cardp); | 1084 | if_usb_reset_device(cardp); |
1079 | goto restart; | 1085 | goto restart; |
1080 | } | 1086 | } |
1081 | 1087 | ||
1082 | lbs_pr_info("FW download failure, time = %d ms\n", i * 100); | 1088 | pr_info("FW download failure, time = %d ms\n", i * 100); |
1083 | ret = -EIO; | 1089 | ret = -EIO; |
1084 | goto release_fw; | 1090 | goto release_fw; |
1085 | } | 1091 | } |
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c index ed57cf863b69..8c40949cb076 100644 --- a/drivers/net/wireless/libertas/main.c +++ b/drivers/net/wireless/libertas/main.c | |||
@@ -4,6 +4,8 @@ | |||
4 | * thread etc.. | 4 | * thread etc.. |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
8 | |||
7 | #include <linux/moduleparam.h> | 9 | #include <linux/moduleparam.h> |
8 | #include <linux/delay.h> | 10 | #include <linux/delay.h> |
9 | #include <linux/etherdevice.h> | 11 | #include <linux/etherdevice.h> |
@@ -34,6 +36,10 @@ unsigned int lbs_debug; | |||
34 | EXPORT_SYMBOL_GPL(lbs_debug); | 36 | EXPORT_SYMBOL_GPL(lbs_debug); |
35 | module_param_named(libertas_debug, lbs_debug, int, 0644); | 37 | module_param_named(libertas_debug, lbs_debug, int, 0644); |
36 | 38 | ||
39 | unsigned int lbs_disablemesh; | ||
40 | EXPORT_SYMBOL_GPL(lbs_disablemesh); | ||
41 | module_param_named(libertas_disablemesh, lbs_disablemesh, int, 0644); | ||
42 | |||
37 | 43 | ||
38 | /* | 44 | /* |
39 | * This global structure is used to send the confirm_sleep command as | 45 | * This global structure is used to send the confirm_sleep command as |
@@ -149,28 +155,6 @@ static int lbs_eth_stop(struct net_device *dev) | |||
149 | return 0; | 155 | return 0; |
150 | } | 156 | } |
151 | 157 | ||
152 | static void lbs_tx_timeout(struct net_device *dev) | ||
153 | { | ||
154 | struct lbs_private *priv = dev->ml_priv; | ||
155 | |||
156 | lbs_deb_enter(LBS_DEB_TX); | ||
157 | |||
158 | lbs_pr_err("tx watch dog timeout\n"); | ||
159 | |||
160 | dev->trans_start = jiffies; /* prevent tx timeout */ | ||
161 | |||
162 | if (priv->currenttxskb) | ||
163 | lbs_send_tx_feedback(priv, 0); | ||
164 | |||
165 | /* XX: Shouldn't we also call into the hw-specific driver | ||
166 | to kick it somehow? */ | ||
167 | lbs_host_to_card_done(priv); | ||
168 | |||
169 | /* FIXME: reset the card */ | ||
170 | |||
171 | lbs_deb_leave(LBS_DEB_TX); | ||
172 | } | ||
173 | |||
174 | void lbs_host_to_card_done(struct lbs_private *priv) | 158 | void lbs_host_to_card_done(struct lbs_private *priv) |
175 | { | 159 | { |
176 | unsigned long flags; | 160 | unsigned long flags; |
@@ -464,8 +448,8 @@ static int lbs_thread(void *data) | |||
464 | if (priv->cmd_timed_out && priv->cur_cmd) { | 448 | if (priv->cmd_timed_out && priv->cur_cmd) { |
465 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; | 449 | struct cmd_ctrl_node *cmdnode = priv->cur_cmd; |
466 | 450 | ||
467 | lbs_pr_info("Timeout submitting command 0x%04x\n", | 451 | netdev_info(dev, "Timeout submitting command 0x%04x\n", |
468 | le16_to_cpu(cmdnode->cmdbuf->command)); | 452 | le16_to_cpu(cmdnode->cmdbuf->command)); |
469 | lbs_complete_command(priv, cmdnode, -ETIMEDOUT); | 453 | lbs_complete_command(priv, cmdnode, -ETIMEDOUT); |
470 | if (priv->reset_card) | 454 | if (priv->reset_card) |
471 | priv->reset_card(priv); | 455 | priv->reset_card(priv); |
@@ -492,8 +476,8 @@ static int lbs_thread(void *data) | |||
492 | * after firmware fixes it | 476 | * after firmware fixes it |
493 | */ | 477 | */ |
494 | priv->psstate = PS_STATE_AWAKE; | 478 | priv->psstate = PS_STATE_AWAKE; |
495 | lbs_pr_alert("ignore PS_SleepConfirm in " | 479 | netdev_alert(dev, |
496 | "non-connected state\n"); | 480 | "ignore PS_SleepConfirm in non-connected state\n"); |
497 | } | 481 | } |
498 | } | 482 | } |
499 | 483 | ||
@@ -587,7 +571,8 @@ int lbs_suspend(struct lbs_private *priv) | |||
587 | if (priv->is_deep_sleep) { | 571 | if (priv->is_deep_sleep) { |
588 | ret = lbs_set_deep_sleep(priv, 0); | 572 | ret = lbs_set_deep_sleep(priv, 0); |
589 | if (ret) { | 573 | if (ret) { |
590 | lbs_pr_err("deep sleep cancellation failed: %d\n", ret); | 574 | netdev_err(priv->dev, |
575 | "deep sleep cancellation failed: %d\n", ret); | ||
591 | return ret; | 576 | return ret; |
592 | } | 577 | } |
593 | priv->deep_sleep_required = 1; | 578 | priv->deep_sleep_required = 1; |
@@ -620,7 +605,8 @@ int lbs_resume(struct lbs_private *priv) | |||
620 | priv->deep_sleep_required = 0; | 605 | priv->deep_sleep_required = 0; |
621 | ret = lbs_set_deep_sleep(priv, 1); | 606 | ret = lbs_set_deep_sleep(priv, 1); |
622 | if (ret) | 607 | if (ret) |
623 | lbs_pr_err("deep sleep activation failed: %d\n", ret); | 608 | netdev_err(priv->dev, |
609 | "deep sleep activation failed: %d\n", ret); | ||
624 | } | 610 | } |
625 | 611 | ||
626 | if (priv->setup_fw_on_resume) | 612 | if (priv->setup_fw_on_resume) |
@@ -648,8 +634,8 @@ static void lbs_cmd_timeout_handler(unsigned long data) | |||
648 | if (!priv->cur_cmd) | 634 | if (!priv->cur_cmd) |
649 | goto out; | 635 | goto out; |
650 | 636 | ||
651 | lbs_pr_info("command 0x%04x timed out\n", | 637 | netdev_info(priv->dev, "command 0x%04x timed out\n", |
652 | le16_to_cpu(priv->cur_cmd->cmdbuf->command)); | 638 | le16_to_cpu(priv->cur_cmd->cmdbuf->command)); |
653 | 639 | ||
654 | priv->cmd_timed_out = 1; | 640 | priv->cmd_timed_out = 1; |
655 | wake_up_interruptible(&priv->waitq); | 641 | wake_up_interruptible(&priv->waitq); |
@@ -754,7 +740,7 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
754 | 740 | ||
755 | /* Allocate the command buffers */ | 741 | /* Allocate the command buffers */ |
756 | if (lbs_allocate_cmd_buffer(priv)) { | 742 | if (lbs_allocate_cmd_buffer(priv)) { |
757 | lbs_pr_err("Out of memory allocating command buffers\n"); | 743 | pr_err("Out of memory allocating command buffers\n"); |
758 | ret = -ENOMEM; | 744 | ret = -ENOMEM; |
759 | goto out; | 745 | goto out; |
760 | } | 746 | } |
@@ -764,7 +750,7 @@ static int lbs_init_adapter(struct lbs_private *priv) | |||
764 | /* Create the event FIFO */ | 750 | /* Create the event FIFO */ |
765 | ret = kfifo_alloc(&priv->event_fifo, sizeof(u32) * 16, GFP_KERNEL); | 751 | ret = kfifo_alloc(&priv->event_fifo, sizeof(u32) * 16, GFP_KERNEL); |
766 | if (ret) { | 752 | if (ret) { |
767 | lbs_pr_err("Out of memory allocating event FIFO buffer\n"); | 753 | pr_err("Out of memory allocating event FIFO buffer\n"); |
768 | goto out; | 754 | goto out; |
769 | } | 755 | } |
770 | 756 | ||
@@ -791,7 +777,6 @@ static const struct net_device_ops lbs_netdev_ops = { | |||
791 | .ndo_stop = lbs_eth_stop, | 777 | .ndo_stop = lbs_eth_stop, |
792 | .ndo_start_xmit = lbs_hard_start_xmit, | 778 | .ndo_start_xmit = lbs_hard_start_xmit, |
793 | .ndo_set_mac_address = lbs_set_mac_address, | 779 | .ndo_set_mac_address = lbs_set_mac_address, |
794 | .ndo_tx_timeout = lbs_tx_timeout, | ||
795 | .ndo_set_multicast_list = lbs_set_multicast_list, | 780 | .ndo_set_multicast_list = lbs_set_multicast_list, |
796 | .ndo_change_mtu = eth_change_mtu, | 781 | .ndo_change_mtu = eth_change_mtu, |
797 | .ndo_validate_addr = eth_validate_addr, | 782 | .ndo_validate_addr = eth_validate_addr, |
@@ -816,7 +801,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
816 | /* Allocate an Ethernet device and register it */ | 801 | /* Allocate an Ethernet device and register it */ |
817 | wdev = lbs_cfg_alloc(dmdev); | 802 | wdev = lbs_cfg_alloc(dmdev); |
818 | if (IS_ERR(wdev)) { | 803 | if (IS_ERR(wdev)) { |
819 | lbs_pr_err("cfg80211 init failed\n"); | 804 | pr_err("cfg80211 init failed\n"); |
820 | goto done; | 805 | goto done; |
821 | } | 806 | } |
822 | 807 | ||
@@ -825,7 +810,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev) | |||
825 | priv->wdev = wdev; | 810 | priv->wdev = wdev; |
826 | 811 | ||
827 | if (lbs_init_adapter(priv)) { | 812 | if (lbs_init_adapter(priv)) { |
828 | lbs_pr_err("failed to initialize adapter structure.\n"); | 813 | pr_err("failed to initialize adapter structure\n"); |
829 | goto err_wdev; | 814 | goto err_wdev; |
830 | } | 815 | } |
831 | 816 | ||
@@ -957,17 +942,20 @@ int lbs_start_card(struct lbs_private *priv) | |||
957 | goto done; | 942 | goto done; |
958 | 943 | ||
959 | if (lbs_cfg_register(priv)) { | 944 | if (lbs_cfg_register(priv)) { |
960 | lbs_pr_err("cannot register device\n"); | 945 | pr_err("cannot register device\n"); |
961 | goto done; | 946 | goto done; |
962 | } | 947 | } |
963 | 948 | ||
964 | lbs_update_channel(priv); | 949 | lbs_update_channel(priv); |
965 | 950 | ||
966 | lbs_init_mesh(priv); | 951 | if (!lbs_disablemesh) |
952 | lbs_init_mesh(priv); | ||
953 | else | ||
954 | pr_info("%s: mesh disabled\n", dev->name); | ||
967 | 955 | ||
968 | lbs_debugfs_init_one(priv, dev); | 956 | lbs_debugfs_init_one(priv, dev); |
969 | 957 | ||
970 | lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name); | 958 | netdev_info(dev, "Marvell WLAN 802.11 adapter\n"); |
971 | 959 | ||
972 | ret = 0; | 960 | ret = 0; |
973 | 961 | ||
@@ -1094,16 +1082,16 @@ int lbs_get_firmware(struct device *dev, const char *user_helper, | |||
1094 | if (user_helper) { | 1082 | if (user_helper) { |
1095 | ret = request_firmware(helper, user_helper, dev); | 1083 | ret = request_firmware(helper, user_helper, dev); |
1096 | if (ret) { | 1084 | if (ret) { |
1097 | lbs_pr_err("couldn't find helper firmware %s", | 1085 | dev_err(dev, "couldn't find helper firmware %s\n", |
1098 | user_helper); | 1086 | user_helper); |
1099 | goto fail; | 1087 | goto fail; |
1100 | } | 1088 | } |
1101 | } | 1089 | } |
1102 | if (user_mainfw) { | 1090 | if (user_mainfw) { |
1103 | ret = request_firmware(mainfw, user_mainfw, dev); | 1091 | ret = request_firmware(mainfw, user_mainfw, dev); |
1104 | if (ret) { | 1092 | if (ret) { |
1105 | lbs_pr_err("couldn't find main firmware %s", | 1093 | dev_err(dev, "couldn't find main firmware %s\n", |
1106 | user_mainfw); | 1094 | user_mainfw); |
1107 | goto fail; | 1095 | goto fail; |
1108 | } | 1096 | } |
1109 | } | 1097 | } |
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index a0804d12bf20..24cf06680c6b 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c | |||
@@ -1,3 +1,5 @@ | |||
1 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
2 | |||
1 | #include <linux/delay.h> | 3 | #include <linux/delay.h> |
2 | #include <linux/etherdevice.h> | 4 | #include <linux/etherdevice.h> |
3 | #include <linux/netdevice.h> | 5 | #include <linux/netdevice.h> |
@@ -267,7 +269,7 @@ int lbs_init_mesh(struct lbs_private *priv) | |||
267 | lbs_add_mesh(priv); | 269 | lbs_add_mesh(priv); |
268 | 270 | ||
269 | if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) | 271 | if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) |
270 | lbs_pr_err("cannot register lbs_mesh attribute\n"); | 272 | netdev_err(dev, "cannot register lbs_mesh attribute\n"); |
271 | 273 | ||
272 | ret = 1; | 274 | ret = 1; |
273 | } | 275 | } |
@@ -395,7 +397,7 @@ int lbs_add_mesh(struct lbs_private *priv) | |||
395 | /* Register virtual mesh interface */ | 397 | /* Register virtual mesh interface */ |
396 | ret = register_netdev(mesh_dev); | 398 | ret = register_netdev(mesh_dev); |
397 | if (ret) { | 399 | if (ret) { |
398 | lbs_pr_err("cannot register mshX virtual interface\n"); | 400 | pr_err("cannot register mshX virtual interface\n"); |
399 | goto err_free; | 401 | goto err_free; |
400 | } | 402 | } |
401 | 403 | ||
@@ -973,7 +975,7 @@ static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr, | |||
973 | return ret; | 975 | return ret; |
974 | 976 | ||
975 | if (defs.meshie.val.mesh_id_len > IEEE80211_MAX_SSID_LEN) { | 977 | if (defs.meshie.val.mesh_id_len > IEEE80211_MAX_SSID_LEN) { |
976 | lbs_pr_err("inconsistent mesh ID length"); | 978 | dev_err(dev, "inconsistent mesh ID length\n"); |
977 | defs.meshie.val.mesh_id_len = IEEE80211_MAX_SSID_LEN; | 979 | defs.meshie.val.mesh_id_len = IEEE80211_MAX_SSID_LEN; |
978 | } | 980 | } |
979 | 981 | ||
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c index a3f4b55aa41f..fdb0448301a0 100644 --- a/drivers/net/wireless/libertas/rx.c +++ b/drivers/net/wireless/libertas/rx.c | |||
@@ -1,6 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * This file contains the handling of RX in wlan driver. | 2 | * This file contains the handling of RX in wlan driver. |
3 | */ | 3 | */ |
4 | |||
5 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
6 | |||
4 | #include <linux/etherdevice.h> | 7 | #include <linux/etherdevice.h> |
5 | #include <linux/slab.h> | 8 | #include <linux/slab.h> |
6 | #include <linux/types.h> | 9 | #include <linux/types.h> |
@@ -191,7 +194,7 @@ static u8 convert_mv_rate_to_radiotap(u8 rate) | |||
191 | case 12: /* 54 Mbps */ | 194 | case 12: /* 54 Mbps */ |
192 | return 108; | 195 | return 108; |
193 | } | 196 | } |
194 | lbs_pr_alert("Invalid Marvell WLAN rate %i\n", rate); | 197 | pr_alert("Invalid Marvell WLAN rate %i\n", rate); |
195 | return 0; | 198 | return 0; |
196 | } | 199 | } |
197 | 200 | ||
@@ -248,7 +251,7 @@ static int process_rxed_802_11_packet(struct lbs_private *priv, | |||
248 | /* add space for the new radio header */ | 251 | /* add space for the new radio header */ |
249 | if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) && | 252 | if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) && |
250 | pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0, GFP_ATOMIC)) { | 253 | pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0, GFP_ATOMIC)) { |
251 | lbs_pr_alert("%s: couldn't pskb_expand_head\n", __func__); | 254 | netdev_alert(dev, "%s: couldn't pskb_expand_head\n", __func__); |
252 | ret = -ENOMEM; | 255 | ret = -ENOMEM; |
253 | kfree_skb(skb); | 256 | kfree_skb(skb); |
254 | goto done; | 257 | goto done; |
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c index 1d294cfa6c9b..916183d39009 100644 --- a/drivers/net/wireless/mwifiex/11n.c +++ b/drivers/net/wireless/mwifiex/11n.c | |||
@@ -187,7 +187,7 @@ int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, | |||
187 | */ | 187 | */ |
188 | int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf) | 188 | int mwifiex_ret_11n_cfg(struct host_cmd_ds_command *resp, void *data_buf) |
189 | { | 189 | { |
190 | struct mwifiex_ds_11n_tx_cfg *tx_cfg = NULL; | 190 | struct mwifiex_ds_11n_tx_cfg *tx_cfg; |
191 | struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg; | 191 | struct host_cmd_ds_11n_cfg *htcfg = &resp->params.htcfg; |
192 | 192 | ||
193 | if (data_buf) { | 193 | if (data_buf) { |
@@ -274,7 +274,7 @@ int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, | |||
274 | int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp, | 274 | int mwifiex_ret_amsdu_aggr_ctrl(struct host_cmd_ds_command *resp, |
275 | void *data_buf) | 275 | void *data_buf) |
276 | { | 276 | { |
277 | struct mwifiex_ds_11n_amsdu_aggr_ctrl *amsdu_aggr_ctrl = NULL; | 277 | struct mwifiex_ds_11n_amsdu_aggr_ctrl *amsdu_aggr_ctrl; |
278 | struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl = | 278 | struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl = |
279 | &resp->params.amsdu_aggr_ctrl; | 279 | &resp->params.amsdu_aggr_ctrl; |
280 | 280 | ||
@@ -461,8 +461,7 @@ mwifiex_cfg_tx_buf(struct mwifiex_private *priv, | |||
461 | struct mwifiex_bssdescriptor *bss_desc) | 461 | struct mwifiex_bssdescriptor *bss_desc) |
462 | { | 462 | { |
463 | u16 max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_2K; | 463 | u16 max_amsdu = MWIFIEX_TX_DATA_BUF_SIZE_2K; |
464 | u16 tx_buf = 0; | 464 | u16 tx_buf, curr_tx_buf_size = 0; |
465 | u16 curr_tx_buf_size = 0; | ||
466 | 465 | ||
467 | if (bss_desc->bcn_ht_cap) { | 466 | if (bss_desc->bcn_ht_cap) { |
468 | if (le16_to_cpu(bss_desc->bcn_ht_cap->cap_info) & | 467 | if (le16_to_cpu(bss_desc->bcn_ht_cap->cap_info) & |
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c index c9fb0627de43..d3d5e0853c45 100644 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ b/drivers/net/wireless/mwifiex/11n_aggr.c | |||
@@ -60,7 +60,7 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr, | |||
60 | * later with ethertype | 60 | * later with ethertype |
61 | */ | 61 | */ |
62 | }; | 62 | }; |
63 | struct tx_packet_hdr *tx_header = NULL; | 63 | struct tx_packet_hdr *tx_header; |
64 | 64 | ||
65 | skb_put(skb_aggr, sizeof(*tx_header)); | 65 | skb_put(skb_aggr, sizeof(*tx_header)); |
66 | 66 | ||
@@ -136,131 +136,6 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv, | |||
136 | } | 136 | } |
137 | 137 | ||
138 | /* | 138 | /* |
139 | * Counts the number of subframes in an aggregate packet. | ||
140 | * | ||
141 | * This function parses an aggregate packet buffer, looking for | ||
142 | * subframes and counting the number of such subframe found. The | ||
143 | * function automatically skips the DA/SA fields at the beginning | ||
144 | * of each subframe and padding at the end. | ||
145 | */ | ||
146 | static int | ||
147 | mwifiex_11n_get_num_aggr_pkts(u8 *data, int total_pkt_len) | ||
148 | { | ||
149 | int pkt_count = 0, pkt_len, pad; | ||
150 | |||
151 | while (total_pkt_len > 0) { | ||
152 | /* Length will be in network format, change it to host */ | ||
153 | pkt_len = ntohs((*(__be16 *)(data + 2 * ETH_ALEN))); | ||
154 | pad = (((pkt_len + sizeof(struct ethhdr)) & 3)) ? | ||
155 | (4 - ((pkt_len + sizeof(struct ethhdr)) & 3)) : 0; | ||
156 | data += pkt_len + pad + sizeof(struct ethhdr); | ||
157 | total_pkt_len -= pkt_len + pad + sizeof(struct ethhdr); | ||
158 | ++pkt_count; | ||
159 | } | ||
160 | |||
161 | return pkt_count; | ||
162 | } | ||
163 | |||
164 | /* | ||
165 | * De-aggregate received packets. | ||
166 | * | ||
167 | * This function parses the received aggregate buffer, extracts each subframe, | ||
168 | * strips off the SNAP header from them and sends the data portion for further | ||
169 | * processing. | ||
170 | * | ||
171 | * Each subframe body is copied onto a separate buffer, which are freed by | ||
172 | * upper layer after processing. The function also performs sanity tests on | ||
173 | * the received buffer. | ||
174 | */ | ||
175 | int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv, | ||
176 | struct sk_buff *skb) | ||
177 | { | ||
178 | u16 pkt_len; | ||
179 | int total_pkt_len; | ||
180 | u8 *data; | ||
181 | int pad; | ||
182 | struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); | ||
183 | struct rxpd *local_rx_pd = (struct rxpd *) skb->data; | ||
184 | struct sk_buff *skb_daggr; | ||
185 | struct mwifiex_rxinfo *rx_info_daggr = NULL; | ||
186 | int ret = -1; | ||
187 | struct rx_packet_hdr *rx_pkt_hdr; | ||
188 | struct mwifiex_adapter *adapter = priv->adapter; | ||
189 | u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; | ||
190 | |||
191 | data = (u8 *) (local_rx_pd + local_rx_pd->rx_pkt_offset); | ||
192 | total_pkt_len = local_rx_pd->rx_pkt_length; | ||
193 | |||
194 | /* Sanity test */ | ||
195 | if (total_pkt_len > MWIFIEX_RX_DATA_BUF_SIZE) { | ||
196 | dev_err(adapter->dev, "total pkt len greater than buffer" | ||
197 | " size %d\n", total_pkt_len); | ||
198 | return -1; | ||
199 | } | ||
200 | |||
201 | rx_info->use_count = mwifiex_11n_get_num_aggr_pkts(data, total_pkt_len); | ||
202 | |||
203 | while (total_pkt_len > 0) { | ||
204 | rx_pkt_hdr = (struct rx_packet_hdr *) data; | ||
205 | /* Length will be in network format, change it to host */ | ||
206 | pkt_len = ntohs((*(__be16 *) (data + 2 * ETH_ALEN))); | ||
207 | if (pkt_len > total_pkt_len) { | ||
208 | dev_err(adapter->dev, "pkt_len %d > total_pkt_len %d\n", | ||
209 | total_pkt_len, pkt_len); | ||
210 | break; | ||
211 | } | ||
212 | |||
213 | pad = (((pkt_len + sizeof(struct ethhdr)) & 3)) ? | ||
214 | (4 - ((pkt_len + sizeof(struct ethhdr)) & 3)) : 0; | ||
215 | |||
216 | total_pkt_len -= pkt_len + pad + sizeof(struct ethhdr); | ||
217 | |||
218 | if (memcmp(&rx_pkt_hdr->rfc1042_hdr, | ||
219 | rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) { | ||
220 | memmove(data + LLC_SNAP_LEN, data, 2 * ETH_ALEN); | ||
221 | data += LLC_SNAP_LEN; | ||
222 | pkt_len += sizeof(struct ethhdr) - LLC_SNAP_LEN; | ||
223 | } else { | ||
224 | *(u16 *) (data + 2 * ETH_ALEN) = (u16) 0; | ||
225 | pkt_len += sizeof(struct ethhdr); | ||
226 | } | ||
227 | |||
228 | skb_daggr = dev_alloc_skb(pkt_len); | ||
229 | if (!skb_daggr) { | ||
230 | dev_err(adapter->dev, "%s: failed to alloc skb_daggr\n", | ||
231 | __func__); | ||
232 | return -1; | ||
233 | } | ||
234 | rx_info_daggr = MWIFIEX_SKB_RXCB(skb_daggr); | ||
235 | |||
236 | rx_info_daggr->bss_index = rx_info->bss_index; | ||
237 | skb_daggr->tstamp = skb->tstamp; | ||
238 | rx_info_daggr->parent = skb; | ||
239 | skb_daggr->priority = skb->priority; | ||
240 | skb_put(skb_daggr, pkt_len); | ||
241 | memcpy(skb_daggr->data, data, pkt_len); | ||
242 | |||
243 | ret = mwifiex_recv_packet(adapter, skb_daggr); | ||
244 | |||
245 | switch (ret) { | ||
246 | case -EINPROGRESS: | ||
247 | break; | ||
248 | case -1: | ||
249 | dev_err(adapter->dev, "deaggr: host_to_card failed\n"); | ||
250 | case 0: | ||
251 | mwifiex_recv_packet_complete(adapter, skb_daggr, ret); | ||
252 | break; | ||
253 | default: | ||
254 | break; | ||
255 | } | ||
256 | |||
257 | data += pkt_len + pad; | ||
258 | } | ||
259 | |||
260 | return ret; | ||
261 | } | ||
262 | |||
263 | /* | ||
264 | * Create aggregated packet. | 139 | * Create aggregated packet. |
265 | * | 140 | * |
266 | * This function creates an aggregated MSDU packet, by combining buffers | 141 | * This function creates an aggregated MSDU packet, by combining buffers |
@@ -285,8 +160,7 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
285 | struct mwifiex_adapter *adapter = priv->adapter; | 160 | struct mwifiex_adapter *adapter = priv->adapter; |
286 | struct sk_buff *skb_aggr, *skb_src; | 161 | struct sk_buff *skb_aggr, *skb_src; |
287 | struct mwifiex_txinfo *tx_info_aggr, *tx_info_src; | 162 | struct mwifiex_txinfo *tx_info_aggr, *tx_info_src; |
288 | int pad = 0; | 163 | int pad = 0, ret; |
289 | int ret = 0; | ||
290 | struct mwifiex_tx_param tx_param; | 164 | struct mwifiex_tx_param tx_param; |
291 | struct txpd *ptx_pd = NULL; | 165 | struct txpd *ptx_pd = NULL; |
292 | 166 | ||
@@ -319,7 +193,8 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
319 | else | 193 | else |
320 | skb_src = NULL; | 194 | skb_src = NULL; |
321 | 195 | ||
322 | pra_list->total_pkts_size -= skb_src->len; | 196 | if (skb_src) |
197 | pra_list->total_pkts_size -= skb_src->len; | ||
323 | 198 | ||
324 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, | 199 | spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, |
325 | ra_list_flags); | 200 | ra_list_flags); |
@@ -374,7 +249,8 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, | |||
374 | (adapter->pps_uapsd_mode) && | 249 | (adapter->pps_uapsd_mode) && |
375 | (adapter->tx_lock_flag)) { | 250 | (adapter->tx_lock_flag)) { |
376 | priv->adapter->tx_lock_flag = false; | 251 | priv->adapter->tx_lock_flag = false; |
377 | ptx_pd->flags = 0; | 252 | if (ptx_pd) |
253 | ptx_pd->flags = 0; | ||
378 | } | 254 | } |
379 | 255 | ||
380 | skb_queue_tail(&pra_list->skb_head, skb_aggr); | 256 | skb_queue_tail(&pra_list->skb_head, skb_aggr); |
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index a93c03fdea82..e5dfdc39a921 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c | |||
@@ -39,7 +39,7 @@ mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv, | |||
39 | *rx_reor_tbl_ptr, int start_win) | 39 | *rx_reor_tbl_ptr, int start_win) |
40 | { | 40 | { |
41 | int no_pkt_to_send, i; | 41 | int no_pkt_to_send, i; |
42 | void *rx_tmp_ptr = NULL; | 42 | void *rx_tmp_ptr; |
43 | unsigned long flags; | 43 | unsigned long flags; |
44 | 44 | ||
45 | no_pkt_to_send = (start_win > rx_reor_tbl_ptr->start_win) ? | 45 | no_pkt_to_send = (start_win > rx_reor_tbl_ptr->start_win) ? |
@@ -88,7 +88,7 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv, | |||
88 | struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr) | 88 | struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr) |
89 | { | 89 | { |
90 | int i, j, xchg; | 90 | int i, j, xchg; |
91 | void *rx_tmp_ptr = NULL; | 91 | void *rx_tmp_ptr; |
92 | unsigned long flags; | 92 | unsigned long flags; |
93 | 93 | ||
94 | for (i = 0; i < rx_reor_tbl_ptr->win_size; ++i) { | 94 | for (i = 0; i < rx_reor_tbl_ptr->win_size; ++i) { |
@@ -335,8 +335,8 @@ int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, | |||
335 | &cmd->params.add_ba_rsp; | 335 | &cmd->params.add_ba_rsp; |
336 | struct host_cmd_ds_11n_addba_req *cmd_addba_req = | 336 | struct host_cmd_ds_11n_addba_req *cmd_addba_req = |
337 | (struct host_cmd_ds_11n_addba_req *) data_buf; | 337 | (struct host_cmd_ds_11n_addba_req *) data_buf; |
338 | u8 tid = 0; | 338 | u8 tid; |
339 | int win_size = 0; | 339 | int win_size; |
340 | uint16_t block_ack_param_set; | 340 | uint16_t block_ack_param_set; |
341 | 341 | ||
342 | cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP); | 342 | cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP); |
@@ -406,9 +406,8 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, | |||
406 | u8 *ta, u8 pkt_type, void *payload) | 406 | u8 *ta, u8 pkt_type, void *payload) |
407 | { | 407 | { |
408 | struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr; | 408 | struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr; |
409 | int start_win, end_win, win_size; | 409 | int start_win, end_win, win_size, ret; |
410 | int ret = 0; | 410 | u16 pkt_index; |
411 | u16 pkt_index = 0; | ||
412 | 411 | ||
413 | rx_reor_tbl_ptr = | 412 | rx_reor_tbl_ptr = |
414 | mwifiex_11n_get_rx_reorder_tbl((struct mwifiex_private *) priv, | 413 | mwifiex_11n_get_rx_reorder_tbl((struct mwifiex_private *) priv, |
@@ -540,7 +539,7 @@ int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, | |||
540 | (struct host_cmd_ds_11n_addba_rsp *) | 539 | (struct host_cmd_ds_11n_addba_rsp *) |
541 | &resp->params.add_ba_rsp; | 540 | &resp->params.add_ba_rsp; |
542 | int tid, win_size; | 541 | int tid, win_size; |
543 | struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr = NULL; | 542 | struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr; |
544 | uint16_t block_ack_param_set; | 543 | uint16_t block_ack_param_set; |
545 | 544 | ||
546 | block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set); | 545 | block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set); |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 98009e2194c5..660831ce293c 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -77,18 +77,15 @@ mwifiex_channels_to_cfg80211_channel_type(int channel_type) | |||
77 | static int | 77 | static int |
78 | mwifiex_is_alg_wep(u32 cipher) | 78 | mwifiex_is_alg_wep(u32 cipher) |
79 | { | 79 | { |
80 | int alg = 0; | ||
81 | |||
82 | switch (cipher) { | 80 | switch (cipher) { |
83 | case WLAN_CIPHER_SUITE_WEP40: | 81 | case WLAN_CIPHER_SUITE_WEP40: |
84 | case WLAN_CIPHER_SUITE_WEP104: | 82 | case WLAN_CIPHER_SUITE_WEP104: |
85 | alg = 1; | 83 | return 1; |
86 | break; | ||
87 | default: | 84 | default: |
88 | alg = 0; | ||
89 | break; | 85 | break; |
90 | } | 86 | } |
91 | return alg; | 87 | |
88 | return 0; | ||
92 | } | 89 | } |
93 | 90 | ||
94 | /* | 91 | /* |
@@ -408,7 +405,7 @@ mwifiex_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, | |||
408 | static int | 405 | static int |
409 | mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr) | 406 | mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr) |
410 | { | 407 | { |
411 | int ret = 0; | 408 | int ret; |
412 | 409 | ||
413 | if (frag_thr < MWIFIEX_FRAG_MIN_VALUE | 410 | if (frag_thr < MWIFIEX_FRAG_MIN_VALUE |
414 | || frag_thr > MWIFIEX_FRAG_MAX_VALUE) | 411 | || frag_thr > MWIFIEX_FRAG_MAX_VALUE) |
@@ -449,7 +446,6 @@ static int | |||
449 | mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | 446 | mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) |
450 | { | 447 | { |
451 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); | 448 | struct mwifiex_private *priv = mwifiex_cfg80211_get_priv(wiphy); |
452 | |||
453 | int ret = 0; | 449 | int ret = 0; |
454 | 450 | ||
455 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) { | 451 | if (changed & WIPHY_PARAM_RTS_THRESHOLD) { |
@@ -473,7 +469,7 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, | |||
473 | enum nl80211_iftype type, u32 *flags, | 469 | enum nl80211_iftype type, u32 *flags, |
474 | struct vif_params *params) | 470 | struct vif_params *params) |
475 | { | 471 | { |
476 | int ret = 0; | 472 | int ret; |
477 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 473 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
478 | 474 | ||
479 | if (priv->bss_mode == type) { | 475 | if (priv->bss_mode == type) { |
@@ -717,7 +713,7 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) | |||
717 | { | 713 | { |
718 | struct ieee80211_channel *chan; | 714 | struct ieee80211_channel *chan; |
719 | struct mwifiex_bss_info bss_info; | 715 | struct mwifiex_bss_info bss_info; |
720 | int ie_len = 0; | 716 | int ie_len; |
721 | u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)]; | 717 | u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)]; |
722 | 718 | ||
723 | if (mwifiex_get_bss_info(priv, &bss_info)) | 719 | if (mwifiex_get_bss_info(priv, &bss_info)) |
@@ -765,7 +761,6 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) | |||
765 | static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv, | 761 | static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv, |
766 | struct mwifiex_802_11_ssid *ssid) | 762 | struct mwifiex_802_11_ssid *ssid) |
767 | { | 763 | { |
768 | struct mwifiex_scan_resp scan_resp; | ||
769 | struct mwifiex_bssdescriptor *scan_table; | 764 | struct mwifiex_bssdescriptor *scan_table; |
770 | int i, j; | 765 | int i, j; |
771 | struct ieee80211_channel *chan; | 766 | struct ieee80211_channel *chan; |
@@ -775,10 +770,6 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv, | |||
775 | int beacon_size; | 770 | int beacon_size; |
776 | u8 element_id, element_len; | 771 | u8 element_id, element_len; |
777 | 772 | ||
778 | memset(&scan_resp, 0, sizeof(scan_resp)); | ||
779 | scan_resp.scan_table = (u8 *) priv->adapter->scan_table; | ||
780 | scan_resp.num_in_scan_table = priv->adapter->num_in_scan_table; | ||
781 | |||
782 | #define MAX_IE_BUF 2048 | 773 | #define MAX_IE_BUF 2048 |
783 | ie_buf = kzalloc(MAX_IE_BUF, GFP_KERNEL); | 774 | ie_buf = kzalloc(MAX_IE_BUF, GFP_KERNEL); |
784 | if (!ie_buf) { | 775 | if (!ie_buf) { |
@@ -787,8 +778,8 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv, | |||
787 | return -ENOMEM; | 778 | return -ENOMEM; |
788 | } | 779 | } |
789 | 780 | ||
790 | scan_table = (struct mwifiex_bssdescriptor *) scan_resp.scan_table; | 781 | scan_table = priv->adapter->scan_table; |
791 | for (i = 0; i < scan_resp.num_in_scan_table; i++) { | 782 | for (i = 0; i < priv->adapter->num_in_scan_table; i++) { |
792 | if (ssid) { | 783 | if (ssid) { |
793 | /* Inform specific BSS only */ | 784 | /* Inform specific BSS only */ |
794 | if (memcmp(ssid->ssid, scan_table[i].ssid.ssid, | 785 | if (memcmp(ssid->ssid, scan_table[i].ssid.ssid, |
@@ -903,8 +894,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, | |||
903 | { | 894 | { |
904 | struct mwifiex_802_11_ssid req_ssid; | 895 | struct mwifiex_802_11_ssid req_ssid; |
905 | struct mwifiex_ssid_bssid ssid_bssid; | 896 | struct mwifiex_ssid_bssid ssid_bssid; |
906 | int ret = 0; | 897 | int ret, auth_type = 0; |
907 | int auth_type = 0; | ||
908 | 898 | ||
909 | memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid)); | 899 | memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid)); |
910 | memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); | 900 | memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid)); |
@@ -1044,7 +1034,7 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
1044 | goto done; | 1034 | goto done; |
1045 | } | 1035 | } |
1046 | 1036 | ||
1047 | priv->assoc_request = 1; | 1037 | priv->assoc_request = -EINPROGRESS; |
1048 | 1038 | ||
1049 | wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", | 1039 | wiphy_dbg(wiphy, "info: Trying to associate to %s and bssid %pM\n", |
1050 | (char *) sme->ssid, sme->bssid); | 1040 | (char *) sme->ssid, sme->bssid); |
@@ -1052,6 +1042,7 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
1052 | ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, | 1042 | ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, |
1053 | priv->bss_mode, sme->channel, sme, 0); | 1043 | priv->bss_mode, sme->channel, sme, 0); |
1054 | 1044 | ||
1045 | priv->assoc_request = 1; | ||
1055 | done: | 1046 | done: |
1056 | priv->assoc_result = ret; | 1047 | priv->assoc_result = ret; |
1057 | queue_work(priv->workqueue, &priv->cfg_workqueue); | 1048 | queue_work(priv->workqueue, &priv->cfg_workqueue); |
@@ -1080,7 +1071,7 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, | |||
1080 | goto done; | 1071 | goto done; |
1081 | } | 1072 | } |
1082 | 1073 | ||
1083 | priv->ibss_join_request = 1; | 1074 | priv->ibss_join_request = -EINPROGRESS; |
1084 | 1075 | ||
1085 | wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n", | 1076 | wiphy_dbg(wiphy, "info: trying to join to %s and bssid %pM\n", |
1086 | (char *) params->ssid, params->bssid); | 1077 | (char *) params->ssid, params->bssid); |
@@ -1088,6 +1079,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, | |||
1088 | ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid, | 1079 | ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid, |
1089 | params->bssid, priv->bss_mode, | 1080 | params->bssid, priv->bss_mode, |
1090 | params->channel, NULL, params->privacy); | 1081 | params->channel, NULL, params->privacy); |
1082 | |||
1083 | priv->ibss_join_request = 1; | ||
1091 | done: | 1084 | done: |
1092 | priv->ibss_join_result = ret; | 1085 | priv->ibss_join_result = ret; |
1093 | queue_work(priv->workqueue, &priv->cfg_workqueue); | 1086 | queue_work(priv->workqueue, &priv->cfg_workqueue); |
@@ -1244,8 +1237,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
1244 | int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, | 1237 | int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, |
1245 | struct mwifiex_private *priv) | 1238 | struct mwifiex_private *priv) |
1246 | { | 1239 | { |
1247 | int ret = 0; | 1240 | int ret; |
1248 | void *wdev_priv = NULL; | 1241 | void *wdev_priv; |
1249 | struct wireless_dev *wdev; | 1242 | struct wireless_dev *wdev; |
1250 | 1243 | ||
1251 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | 1244 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); |
@@ -1257,8 +1250,10 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, | |||
1257 | wdev->wiphy = | 1250 | wdev->wiphy = |
1258 | wiphy_new(&mwifiex_cfg80211_ops, | 1251 | wiphy_new(&mwifiex_cfg80211_ops, |
1259 | sizeof(struct mwifiex_private *)); | 1252 | sizeof(struct mwifiex_private *)); |
1260 | if (!wdev->wiphy) | 1253 | if (!wdev->wiphy) { |
1254 | kfree(wdev); | ||
1261 | return -ENOMEM; | 1255 | return -ENOMEM; |
1256 | } | ||
1262 | wdev->iftype = NL80211_IFTYPE_STATION; | 1257 | wdev->iftype = NL80211_IFTYPE_STATION; |
1263 | wdev->wiphy->max_scan_ssids = 10; | 1258 | wdev->wiphy->max_scan_ssids = 10; |
1264 | wdev->wiphy->interface_modes = | 1259 | wdev->wiphy->interface_modes = |
@@ -1298,6 +1293,7 @@ int mwifiex_register_cfg80211(struct net_device *dev, u8 *mac, | |||
1298 | dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n", | 1293 | dev_err(priv->adapter->dev, "%s: registering cfg80211 device\n", |
1299 | __func__); | 1294 | __func__); |
1300 | wiphy_free(wdev->wiphy); | 1295 | wiphy_free(wdev->wiphy); |
1296 | kfree(wdev); | ||
1301 | return ret; | 1297 | return ret; |
1302 | } else { | 1298 | } else { |
1303 | dev_dbg(priv->adapter->dev, | 1299 | dev_dbg(priv->adapter->dev, |
@@ -1380,7 +1376,7 @@ done: | |||
1380 | kfree(scan_req); | 1376 | kfree(scan_req); |
1381 | } | 1377 | } |
1382 | 1378 | ||
1383 | if (priv->assoc_request) { | 1379 | if (priv->assoc_request == 1) { |
1384 | if (!priv->assoc_result) { | 1380 | if (!priv->assoc_result) { |
1385 | cfg80211_connect_result(priv->netdev, priv->cfg_bssid, | 1381 | cfg80211_connect_result(priv->netdev, priv->cfg_bssid, |
1386 | NULL, 0, NULL, 0, | 1382 | NULL, 0, NULL, 0, |
@@ -1399,7 +1395,7 @@ done: | |||
1399 | priv->assoc_result = 0; | 1395 | priv->assoc_result = 0; |
1400 | } | 1396 | } |
1401 | 1397 | ||
1402 | if (priv->ibss_join_request) { | 1398 | if (priv->ibss_join_request == 1) { |
1403 | if (!priv->ibss_join_result) { | 1399 | if (!priv->ibss_join_result) { |
1404 | cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, | 1400 | cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, |
1405 | GFP_KERNEL); | 1401 | GFP_KERNEL); |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 776146a104ec..cd89fed206ae 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -91,7 +91,7 @@ mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter, | |||
91 | cmd_node->wait_q_enabled = false; | 91 | cmd_node->wait_q_enabled = false; |
92 | 92 | ||
93 | if (cmd_node->resp_skb) { | 93 | if (cmd_node->resp_skb) { |
94 | mwifiex_recv_complete(adapter, cmd_node->resp_skb, 0); | 94 | dev_kfree_skb_any(cmd_node->resp_skb); |
95 | cmd_node->resp_skb = NULL; | 95 | cmd_node->resp_skb = NULL; |
96 | } | 96 | } |
97 | } | 97 | } |
@@ -128,7 +128,7 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, | |||
128 | { | 128 | { |
129 | 129 | ||
130 | struct mwifiex_adapter *adapter = priv->adapter; | 130 | struct mwifiex_adapter *adapter = priv->adapter; |
131 | int ret = 0; | 131 | int ret; |
132 | struct host_cmd_ds_command *host_cmd; | 132 | struct host_cmd_ds_command *host_cmd; |
133 | uint16_t cmd_code; | 133 | uint16_t cmd_code; |
134 | uint16_t cmd_size; | 134 | uint16_t cmd_size; |
@@ -222,25 +222,24 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, | |||
222 | */ | 222 | */ |
223 | static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) | 223 | static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) |
224 | { | 224 | { |
225 | int ret = 0; | 225 | int ret; |
226 | u16 cmd_len = 0; | ||
227 | struct mwifiex_private *priv; | 226 | struct mwifiex_private *priv; |
228 | struct mwifiex_opt_sleep_confirm_buffer *sleep_cfm_buf = | 227 | struct mwifiex_opt_sleep_confirm *sleep_cfm_buf = |
229 | (struct mwifiex_opt_sleep_confirm_buffer *) | 228 | (struct mwifiex_opt_sleep_confirm *) |
230 | adapter->sleep_cfm->data; | 229 | adapter->sleep_cfm->data; |
231 | cmd_len = sizeof(struct mwifiex_opt_sleep_confirm); | ||
232 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | 230 | priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); |
233 | 231 | ||
234 | sleep_cfm_buf->ps_cfm_sleep.seq_num = | 232 | sleep_cfm_buf->seq_num = |
235 | cpu_to_le16((HostCmd_SET_SEQ_NO_BSS_INFO | 233 | cpu_to_le16((HostCmd_SET_SEQ_NO_BSS_INFO |
236 | (adapter->seq_num, priv->bss_num, | 234 | (adapter->seq_num, priv->bss_num, |
237 | priv->bss_type))); | 235 | priv->bss_type))); |
238 | adapter->seq_num++; | 236 | adapter->seq_num++; |
239 | 237 | ||
238 | skb_push(adapter->sleep_cfm, INTF_HEADER_LEN); | ||
240 | ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD, | 239 | ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD, |
241 | adapter->sleep_cfm->data, | 240 | adapter->sleep_cfm->data, |
242 | adapter->sleep_cfm->len + | 241 | adapter->sleep_cfm->len, NULL); |
243 | INTF_HEADER_LEN, NULL); | 242 | skb_pull(adapter->sleep_cfm, INTF_HEADER_LEN); |
244 | 243 | ||
245 | if (ret == -1) { | 244 | if (ret == -1) { |
246 | dev_err(adapter->dev, "SLEEP_CFM: failed\n"); | 245 | dev_err(adapter->dev, "SLEEP_CFM: failed\n"); |
@@ -249,14 +248,14 @@ static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) | |||
249 | } | 248 | } |
250 | if (GET_BSS_ROLE(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY)) | 249 | if (GET_BSS_ROLE(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY)) |
251 | == MWIFIEX_BSS_ROLE_STA) { | 250 | == MWIFIEX_BSS_ROLE_STA) { |
252 | if (!sleep_cfm_buf->ps_cfm_sleep.resp_ctrl) | 251 | if (!sleep_cfm_buf->resp_ctrl) |
253 | /* Response is not needed for sleep | 252 | /* Response is not needed for sleep |
254 | confirm command */ | 253 | confirm command */ |
255 | adapter->ps_state = PS_STATE_SLEEP; | 254 | adapter->ps_state = PS_STATE_SLEEP; |
256 | else | 255 | else |
257 | adapter->ps_state = PS_STATE_SLEEP_CFM; | 256 | adapter->ps_state = PS_STATE_SLEEP_CFM; |
258 | 257 | ||
259 | if (!sleep_cfm_buf->ps_cfm_sleep.resp_ctrl | 258 | if (!sleep_cfm_buf->resp_ctrl |
260 | && (adapter->is_hs_configured | 259 | && (adapter->is_hs_configured |
261 | && !adapter->sleep_period.period)) { | 260 | && !adapter->sleep_period.period)) { |
262 | adapter->pm_wakeup_card_req = true; | 261 | adapter->pm_wakeup_card_req = true; |
@@ -292,7 +291,7 @@ int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter) | |||
292 | if (!cmd_array) { | 291 | if (!cmd_array) { |
293 | dev_err(adapter->dev, "%s: failed to alloc cmd_array\n", | 292 | dev_err(adapter->dev, "%s: failed to alloc cmd_array\n", |
294 | __func__); | 293 | __func__); |
295 | return -1; | 294 | return -ENOMEM; |
296 | } | 295 | } |
297 | 296 | ||
298 | adapter->cmd_pool = cmd_array; | 297 | adapter->cmd_pool = cmd_array; |
@@ -340,7 +339,7 @@ int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter) | |||
340 | } | 339 | } |
341 | if (!cmd_array[i].resp_skb) | 340 | if (!cmd_array[i].resp_skb) |
342 | continue; | 341 | continue; |
343 | mwifiex_recv_complete(adapter, cmd_array[i].resp_skb, 0); | 342 | dev_kfree_skb_any(cmd_array[i].resp_skb); |
344 | } | 343 | } |
345 | /* Release struct cmd_ctrl_node */ | 344 | /* Release struct cmd_ctrl_node */ |
346 | if (adapter->cmd_pool) { | 345 | if (adapter->cmd_pool) { |
@@ -364,13 +363,13 @@ int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter) | |||
364 | */ | 363 | */ |
365 | int mwifiex_process_event(struct mwifiex_adapter *adapter) | 364 | int mwifiex_process_event(struct mwifiex_adapter *adapter) |
366 | { | 365 | { |
367 | int ret = 0; | 366 | int ret; |
368 | struct mwifiex_private *priv = | 367 | struct mwifiex_private *priv = |
369 | mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | 368 | mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); |
370 | struct sk_buff *skb = adapter->event_skb; | 369 | struct sk_buff *skb = adapter->event_skb; |
371 | u32 eventcause = adapter->event_cause; | 370 | u32 eventcause = adapter->event_cause; |
372 | struct timeval tstamp; | 371 | struct timeval tstamp; |
373 | struct mwifiex_rxinfo *rx_info = NULL; | 372 | struct mwifiex_rxinfo *rx_info; |
374 | 373 | ||
375 | /* Save the last event to debug log */ | 374 | /* Save the last event to debug log */ |
376 | adapter->dbg.last_event_index = | 375 | adapter->dbg.last_event_index = |
@@ -403,7 +402,7 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter) | |||
403 | adapter->event_cause = 0; | 402 | adapter->event_cause = 0; |
404 | adapter->event_skb = NULL; | 403 | adapter->event_skb = NULL; |
405 | 404 | ||
406 | mwifiex_recv_complete(adapter, skb, 0); | 405 | dev_kfree_skb_any(skb); |
407 | 406 | ||
408 | return ret; | 407 | return ret; |
409 | } | 408 | } |
@@ -446,10 +445,10 @@ int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no, | |||
446 | int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, | 445 | int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, |
447 | u16 cmd_action, u32 cmd_oid, void *data_buf) | 446 | u16 cmd_action, u32 cmd_oid, void *data_buf) |
448 | { | 447 | { |
449 | int ret = 0; | 448 | int ret; |
450 | struct mwifiex_adapter *adapter = priv->adapter; | 449 | struct mwifiex_adapter *adapter = priv->adapter; |
451 | struct cmd_ctrl_node *cmd_node = NULL; | 450 | struct cmd_ctrl_node *cmd_node; |
452 | struct host_cmd_ds_command *cmd_ptr = NULL; | 451 | struct host_cmd_ds_command *cmd_ptr; |
453 | 452 | ||
454 | if (!adapter) { | 453 | if (!adapter) { |
455 | pr_err("PREP_CMD: adapter is NULL\n"); | 454 | pr_err("PREP_CMD: adapter is NULL\n"); |
@@ -605,8 +604,8 @@ mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, | |||
605 | */ | 604 | */ |
606 | int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter) | 605 | int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter) |
607 | { | 606 | { |
608 | struct mwifiex_private *priv = NULL; | 607 | struct mwifiex_private *priv; |
609 | struct cmd_ctrl_node *cmd_node = NULL; | 608 | struct cmd_ctrl_node *cmd_node; |
610 | int ret = 0; | 609 | int ret = 0; |
611 | struct host_cmd_ds_command *host_cmd; | 610 | struct host_cmd_ds_command *host_cmd; |
612 | unsigned long cmd_flags; | 611 | unsigned long cmd_flags; |
@@ -673,7 +672,7 @@ int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter) | |||
673 | */ | 672 | */ |
674 | int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) | 673 | int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) |
675 | { | 674 | { |
676 | struct host_cmd_ds_command *resp = NULL; | 675 | struct host_cmd_ds_command *resp; |
677 | struct mwifiex_private *priv = | 676 | struct mwifiex_private *priv = |
678 | mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); | 677 | mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); |
679 | int ret = 0; | 678 | int ret = 0; |
@@ -805,7 +804,7 @@ mwifiex_cmd_timeout_func(unsigned long function_context) | |||
805 | { | 804 | { |
806 | struct mwifiex_adapter *adapter = | 805 | struct mwifiex_adapter *adapter = |
807 | (struct mwifiex_adapter *) function_context; | 806 | (struct mwifiex_adapter *) function_context; |
808 | struct cmd_ctrl_node *cmd_node = NULL; | 807 | struct cmd_ctrl_node *cmd_node; |
809 | struct timeval tstamp; | 808 | struct timeval tstamp; |
810 | 809 | ||
811 | adapter->num_cmd_timeout++; | 810 | adapter->num_cmd_timeout++; |
@@ -877,7 +876,7 @@ mwifiex_cmd_timeout_func(unsigned long function_context) | |||
877 | void | 876 | void |
878 | mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) | 877 | mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) |
879 | { | 878 | { |
880 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; | 879 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; |
881 | unsigned long flags; | 880 | unsigned long flags; |
882 | 881 | ||
883 | /* Cancel current cmd */ | 882 | /* Cancel current cmd */ |
@@ -1160,7 +1159,7 @@ int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv, | |||
1160 | { | 1159 | { |
1161 | struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh = | 1160 | struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh = |
1162 | &cmd->params.psmode_enh; | 1161 | &cmd->params.psmode_enh; |
1163 | u8 *tlv = NULL; | 1162 | u8 *tlv; |
1164 | u16 cmd_size = 0; | 1163 | u16 cmd_size = 0; |
1165 | 1164 | ||
1166 | cmd->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); | 1165 | cmd->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); |
diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c index 7ddcb062f103..46d65e02c7ba 100644 --- a/drivers/net/wireless/mwifiex/debugfs.c +++ b/drivers/net/wireless/mwifiex/debugfs.c | |||
@@ -193,7 +193,7 @@ mwifiex_info_read(struct file *file, char __user *ubuf, | |||
193 | unsigned long page = get_zeroed_page(GFP_KERNEL); | 193 | unsigned long page = get_zeroed_page(GFP_KERNEL); |
194 | char *p = (char *) page, fmt[64]; | 194 | char *p = (char *) page, fmt[64]; |
195 | struct mwifiex_bss_info info; | 195 | struct mwifiex_bss_info info; |
196 | ssize_t ret = 0; | 196 | ssize_t ret; |
197 | int i = 0; | 197 | int i = 0; |
198 | 198 | ||
199 | if (!p) | 199 | if (!p) |
@@ -288,7 +288,7 @@ mwifiex_getlog_read(struct file *file, char __user *ubuf, | |||
288 | (struct mwifiex_private *) file->private_data; | 288 | (struct mwifiex_private *) file->private_data; |
289 | unsigned long page = get_zeroed_page(GFP_KERNEL); | 289 | unsigned long page = get_zeroed_page(GFP_KERNEL); |
290 | char *p = (char *) page; | 290 | char *p = (char *) page; |
291 | ssize_t ret = 0; | 291 | ssize_t ret; |
292 | struct mwifiex_ds_get_stats stats; | 292 | struct mwifiex_ds_get_stats stats; |
293 | 293 | ||
294 | if (!p) | 294 | if (!p) |
@@ -400,7 +400,7 @@ mwifiex_debug_read(struct file *file, char __user *ubuf, | |||
400 | struct mwifiex_debug_data *d = &items[0]; | 400 | struct mwifiex_debug_data *d = &items[0]; |
401 | unsigned long page = get_zeroed_page(GFP_KERNEL); | 401 | unsigned long page = get_zeroed_page(GFP_KERNEL); |
402 | char *p = (char *) page; | 402 | char *p = (char *) page; |
403 | ssize_t ret = 0; | 403 | ssize_t ret; |
404 | size_t size, addr; | 404 | size_t size, addr; |
405 | long val; | 405 | long val; |
406 | int i, j; | 406 | int i, j; |
@@ -507,7 +507,7 @@ mwifiex_regrdwr_write(struct file *file, | |||
507 | unsigned long addr = get_zeroed_page(GFP_KERNEL); | 507 | unsigned long addr = get_zeroed_page(GFP_KERNEL); |
508 | char *buf = (char *) addr; | 508 | char *buf = (char *) addr; |
509 | size_t buf_size = min(count, (size_t) (PAGE_SIZE - 1)); | 509 | size_t buf_size = min(count, (size_t) (PAGE_SIZE - 1)); |
510 | int ret = 0; | 510 | int ret; |
511 | u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX; | 511 | u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX; |
512 | 512 | ||
513 | if (!buf) | 513 | if (!buf) |
@@ -650,7 +650,7 @@ mwifiex_rdeeprom_read(struct file *file, char __user *ubuf, | |||
650 | (struct mwifiex_private *) file->private_data; | 650 | (struct mwifiex_private *) file->private_data; |
651 | unsigned long addr = get_zeroed_page(GFP_KERNEL); | 651 | unsigned long addr = get_zeroed_page(GFP_KERNEL); |
652 | char *buf = (char *) addr; | 652 | char *buf = (char *) addr; |
653 | int pos = 0, ret = 0, i = 0; | 653 | int pos = 0, ret = 0, i; |
654 | u8 value[MAX_EEPROM_DATA]; | 654 | u8 value[MAX_EEPROM_DATA]; |
655 | 655 | ||
656 | if (!buf) | 656 | if (!buf) |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 6d1c4545eda6..afdd145dff0b 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -816,14 +816,7 @@ struct host_cmd_ds_txpwr_cfg { | |||
816 | 816 | ||
817 | struct mwifiex_scan_cmd_config { | 817 | struct mwifiex_scan_cmd_config { |
818 | /* | 818 | /* |
819 | * BSS Type to be sent in the firmware command | 819 | * BSS mode to be sent in the firmware command |
820 | * | ||
821 | * Field can be used to restrict the types of networks returned in the | ||
822 | * scan. Valid settings are: | ||
823 | * | ||
824 | * - MWIFIEX_SCAN_MODE_BSS (infrastructure) | ||
825 | * - MWIFIEX_SCAN_MODE_IBSS (adhoc) | ||
826 | * - MWIFIEX_SCAN_MODE_ANY (unrestricted, adhoc and infrastructure) | ||
827 | */ | 820 | */ |
828 | u8 bss_mode; | 821 | u8 bss_mode; |
829 | 822 | ||
@@ -866,13 +859,6 @@ struct mwifiex_user_scan_cfg { | |||
866 | u8 keep_previous_scan; | 859 | u8 keep_previous_scan; |
867 | /* | 860 | /* |
868 | * BSS mode to be sent in the firmware command | 861 | * BSS mode to be sent in the firmware command |
869 | * | ||
870 | * Field can be used to restrict the types of networks returned in the | ||
871 | * scan. Valid settings are: | ||
872 | * | ||
873 | * - MWIFIEX_SCAN_MODE_BSS (infrastructure) | ||
874 | * - MWIFIEX_SCAN_MODE_IBSS (adhoc) | ||
875 | * - MWIFIEX_SCAN_MODE_ANY (unrestricted, adhoc and infrastructure) | ||
876 | */ | 862 | */ |
877 | u8 bss_mode; | 863 | u8 bss_mode; |
878 | /* Configure the number of probe requests for active chan scans */ | 864 | /* Configure the number of probe requests for active chan scans */ |
@@ -1198,9 +1184,4 @@ struct mwifiex_opt_sleep_confirm { | |||
1198 | __le16 action; | 1184 | __le16 action; |
1199 | __le16 resp_ctrl; | 1185 | __le16 resp_ctrl; |
1200 | } __packed; | 1186 | } __packed; |
1201 | |||
1202 | struct mwifiex_opt_sleep_confirm_buffer { | ||
1203 | u8 hdr[4]; | ||
1204 | struct mwifiex_opt_sleep_confirm ps_cfm_sleep; | ||
1205 | } __packed; | ||
1206 | #endif /* !_MWIFIEX_FW_H_ */ | 1187 | #endif /* !_MWIFIEX_FW_H_ */ |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index fc2c0c5728d9..3f1559e61320 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -41,7 +41,7 @@ static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv) | |||
41 | if (!bss_prio) { | 41 | if (!bss_prio) { |
42 | dev_err(adapter->dev, "%s: failed to alloc bss_prio\n", | 42 | dev_err(adapter->dev, "%s: failed to alloc bss_prio\n", |
43 | __func__); | 43 | __func__); |
44 | return -1; | 44 | return -ENOMEM; |
45 | } | 45 | } |
46 | 46 | ||
47 | bss_prio->priv = priv; | 47 | bss_prio->priv = priv; |
@@ -151,7 +151,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) | |||
151 | */ | 151 | */ |
152 | static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter) | 152 | static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter) |
153 | { | 153 | { |
154 | int ret = 0; | 154 | int ret; |
155 | u32 buf_size; | 155 | u32 buf_size; |
156 | struct mwifiex_bssdescriptor *temp_scan_table; | 156 | struct mwifiex_bssdescriptor *temp_scan_table; |
157 | 157 | ||
@@ -161,7 +161,7 @@ static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter) | |||
161 | if (!temp_scan_table) { | 161 | if (!temp_scan_table) { |
162 | dev_err(adapter->dev, "%s: failed to alloc temp_scan_table\n", | 162 | dev_err(adapter->dev, "%s: failed to alloc temp_scan_table\n", |
163 | __func__); | 163 | __func__); |
164 | return -1; | 164 | return -ENOMEM; |
165 | } | 165 | } |
166 | 166 | ||
167 | adapter->scan_table = temp_scan_table; | 167 | adapter->scan_table = temp_scan_table; |
@@ -175,7 +175,7 @@ static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter) | |||
175 | } | 175 | } |
176 | 176 | ||
177 | adapter->sleep_cfm = | 177 | adapter->sleep_cfm = |
178 | dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm_buffer) | 178 | dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm) |
179 | + INTF_HEADER_LEN); | 179 | + INTF_HEADER_LEN); |
180 | 180 | ||
181 | if (!adapter->sleep_cfm) { | 181 | if (!adapter->sleep_cfm) { |
@@ -197,10 +197,10 @@ static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter) | |||
197 | */ | 197 | */ |
198 | static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) | 198 | static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) |
199 | { | 199 | { |
200 | struct mwifiex_opt_sleep_confirm_buffer *sleep_cfm_buf = NULL; | 200 | struct mwifiex_opt_sleep_confirm *sleep_cfm_buf = NULL; |
201 | 201 | ||
202 | skb_put(adapter->sleep_cfm, sizeof(sleep_cfm_buf->ps_cfm_sleep)); | 202 | skb_put(adapter->sleep_cfm, sizeof(struct mwifiex_opt_sleep_confirm)); |
203 | sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm_buffer *) | 203 | sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm *) |
204 | (adapter->sleep_cfm->data); | 204 | (adapter->sleep_cfm->data); |
205 | 205 | ||
206 | adapter->cmd_sent = false; | 206 | adapter->cmd_sent = false; |
@@ -268,16 +268,14 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) | |||
268 | mwifiex_wmm_init(adapter); | 268 | mwifiex_wmm_init(adapter); |
269 | 269 | ||
270 | if (adapter->sleep_cfm) { | 270 | if (adapter->sleep_cfm) { |
271 | memset(&sleep_cfm_buf->ps_cfm_sleep, 0, | 271 | memset(sleep_cfm_buf, 0, adapter->sleep_cfm->len); |
272 | adapter->sleep_cfm->len); | 272 | sleep_cfm_buf->command = |
273 | sleep_cfm_buf->ps_cfm_sleep.command = | 273 | cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); |
274 | cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); | 274 | sleep_cfm_buf->size = |
275 | sleep_cfm_buf->ps_cfm_sleep.size = | 275 | cpu_to_le16(adapter->sleep_cfm->len); |
276 | cpu_to_le16(adapter->sleep_cfm->len); | 276 | sleep_cfm_buf->result = 0; |
277 | sleep_cfm_buf->ps_cfm_sleep.result = 0; | 277 | sleep_cfm_buf->action = cpu_to_le16(SLEEP_CONFIRM); |
278 | sleep_cfm_buf->ps_cfm_sleep.action = cpu_to_le16(SLEEP_CONFIRM); | 278 | sleep_cfm_buf->resp_ctrl = cpu_to_le16(RESP_NEEDED); |
279 | sleep_cfm_buf->ps_cfm_sleep.resp_ctrl = | ||
280 | cpu_to_le16(RESP_NEEDED); | ||
281 | } | 279 | } |
282 | memset(&adapter->sleep_params, 0, sizeof(adapter->sleep_params)); | 280 | memset(&adapter->sleep_params, 0, sizeof(adapter->sleep_params)); |
283 | memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period)); | 281 | memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period)); |
@@ -342,9 +340,8 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter) | |||
342 | */ | 340 | */ |
343 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) | 341 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) |
344 | { | 342 | { |
345 | struct mwifiex_private *priv = NULL; | 343 | struct mwifiex_private *priv; |
346 | s32 i = 0; | 344 | s32 i, j; |
347 | u32 j = 0; | ||
348 | 345 | ||
349 | spin_lock_init(&adapter->mwifiex_lock); | 346 | spin_lock_init(&adapter->mwifiex_lock); |
350 | spin_lock_init(&adapter->int_lock); | 347 | spin_lock_init(&adapter->int_lock); |
@@ -400,9 +397,8 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) | |||
400 | */ | 397 | */ |
401 | void mwifiex_free_lock_list(struct mwifiex_adapter *adapter) | 398 | void mwifiex_free_lock_list(struct mwifiex_adapter *adapter) |
402 | { | 399 | { |
403 | struct mwifiex_private *priv = NULL; | 400 | struct mwifiex_private *priv; |
404 | s32 i = 0; | 401 | s32 i, j; |
405 | s32 j = 0; | ||
406 | 402 | ||
407 | /* Free lists */ | 403 | /* Free lists */ |
408 | list_del(&adapter->cmd_free_q); | 404 | list_del(&adapter->cmd_free_q); |
@@ -436,10 +432,9 @@ void mwifiex_free_lock_list(struct mwifiex_adapter *adapter) | |||
436 | */ | 432 | */ |
437 | int mwifiex_init_fw(struct mwifiex_adapter *adapter) | 433 | int mwifiex_init_fw(struct mwifiex_adapter *adapter) |
438 | { | 434 | { |
439 | int ret = 0; | 435 | int ret; |
440 | struct mwifiex_private *priv = NULL; | 436 | struct mwifiex_private *priv; |
441 | u8 i = 0; | 437 | u8 i, first_sta = true; |
442 | u8 first_sta = true; | ||
443 | int is_cmd_pend_q_empty; | 438 | int is_cmd_pend_q_empty; |
444 | unsigned long flags; | 439 | unsigned long flags; |
445 | 440 | ||
@@ -497,8 +492,7 @@ static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv) | |||
497 | { | 492 | { |
498 | int i; | 493 | int i; |
499 | struct mwifiex_adapter *adapter = priv->adapter; | 494 | struct mwifiex_adapter *adapter = priv->adapter; |
500 | struct mwifiex_bss_prio_node *bssprio_node = NULL, *tmp_node = NULL, | 495 | struct mwifiex_bss_prio_node *bssprio_node, *tmp_node, **cur; |
501 | **cur = NULL; | ||
502 | struct list_head *head; | 496 | struct list_head *head; |
503 | spinlock_t *lock; | 497 | spinlock_t *lock; |
504 | unsigned long flags; | 498 | unsigned long flags; |
@@ -552,8 +546,8 @@ int | |||
552 | mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) | 546 | mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) |
553 | { | 547 | { |
554 | int ret = -EINPROGRESS; | 548 | int ret = -EINPROGRESS; |
555 | struct mwifiex_private *priv = NULL; | 549 | struct mwifiex_private *priv; |
556 | s32 i = 0; | 550 | s32 i; |
557 | unsigned long flags; | 551 | unsigned long flags; |
558 | 552 | ||
559 | /* mwifiex already shutdown */ | 553 | /* mwifiex already shutdown */ |
@@ -608,9 +602,8 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) | |||
608 | int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, | 602 | int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, |
609 | struct mwifiex_fw_image *pmfw) | 603 | struct mwifiex_fw_image *pmfw) |
610 | { | 604 | { |
611 | int ret = 0; | 605 | int ret, winner; |
612 | u32 poll_num = 1; | 606 | u32 poll_num = 1; |
613 | int winner; | ||
614 | 607 | ||
615 | /* Check if firmware is already running */ | 608 | /* Check if firmware is already running */ |
616 | ret = adapter->if_ops.check_fw_status(adapter, poll_num, &winner); | 609 | ret = adapter->if_ops.check_fw_status(adapter, poll_num, &winner); |
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 5488e111fd2c..7c1c5ee40eb9 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h | |||
@@ -23,49 +23,16 @@ | |||
23 | #include <net/mac80211.h> | 23 | #include <net/mac80211.h> |
24 | 24 | ||
25 | enum { | 25 | enum { |
26 | MWIFIEX_SCAN_MODE_UNCHANGED = 0, | ||
27 | MWIFIEX_SCAN_MODE_BSS, | ||
28 | MWIFIEX_SCAN_MODE_IBSS, | ||
29 | MWIFIEX_SCAN_MODE_ANY | ||
30 | }; | ||
31 | |||
32 | enum { | ||
33 | MWIFIEX_SCAN_TYPE_UNCHANGED = 0, | 26 | MWIFIEX_SCAN_TYPE_UNCHANGED = 0, |
34 | MWIFIEX_SCAN_TYPE_ACTIVE, | 27 | MWIFIEX_SCAN_TYPE_ACTIVE, |
35 | MWIFIEX_SCAN_TYPE_PASSIVE | 28 | MWIFIEX_SCAN_TYPE_PASSIVE |
36 | }; | 29 | }; |
37 | 30 | ||
38 | struct mwifiex_get_scan_table_fixed { | ||
39 | u8 bssid[ETH_ALEN]; | ||
40 | u8 channel; | ||
41 | u8 rssi; | ||
42 | long long network_tsf; | ||
43 | }; | ||
44 | |||
45 | struct mwifiex_scan_time_params { | ||
46 | u32 specific_scan_time; | ||
47 | u32 active_scan_time; | ||
48 | u32 passive_scan_time; | ||
49 | }; | ||
50 | |||
51 | struct mwifiex_user_scan { | 31 | struct mwifiex_user_scan { |
52 | u32 scan_cfg_len; | 32 | u32 scan_cfg_len; |
53 | u8 scan_cfg_buf[1]; | 33 | u8 scan_cfg_buf[1]; |
54 | }; | 34 | }; |
55 | 35 | ||
56 | struct mwifiex_scan_req { | ||
57 | u32 scan_mode; | ||
58 | u32 scan_type; | ||
59 | struct mwifiex_802_11_ssid scan_ssid; | ||
60 | struct mwifiex_scan_time_params scan_time; | ||
61 | struct mwifiex_user_scan user_scan; | ||
62 | }; | ||
63 | |||
64 | struct mwifiex_scan_resp { | ||
65 | u32 num_in_scan_table; | ||
66 | u8 *scan_table; | ||
67 | }; | ||
68 | |||
69 | #define MWIFIEX_PROMISC_MODE 1 | 36 | #define MWIFIEX_PROMISC_MODE 1 |
70 | #define MWIFIEX_MULTICAST_MODE 2 | 37 | #define MWIFIEX_MULTICAST_MODE 2 |
71 | #define MWIFIEX_ALL_MULTI_MODE 4 | 38 | #define MWIFIEX_ALL_MULTI_MODE 4 |
@@ -77,18 +44,11 @@ struct mwifiex_multicast_list { | |||
77 | u8 mac_list[MWIFIEX_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; | 44 | u8 mac_list[MWIFIEX_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; |
78 | }; | 45 | }; |
79 | 46 | ||
80 | #define MWIFIEX_MAX_CHANNEL_NUM 128 | ||
81 | |||
82 | struct mwifiex_chan_freq { | 47 | struct mwifiex_chan_freq { |
83 | u32 channel; | 48 | u32 channel; |
84 | u32 freq; | 49 | u32 freq; |
85 | }; | 50 | }; |
86 | 51 | ||
87 | struct mwifiex_chan_list { | ||
88 | u32 num_of_chan; | ||
89 | struct mwifiex_chan_freq cf[MWIFIEX_MAX_CHANNEL_NUM]; | ||
90 | }; | ||
91 | |||
92 | struct mwifiex_ssid_bssid { | 52 | struct mwifiex_ssid_bssid { |
93 | struct mwifiex_802_11_ssid ssid; | 53 | struct mwifiex_802_11_ssid ssid; |
94 | u8 bssid[ETH_ALEN]; | 54 | u8 bssid[ETH_ALEN]; |
@@ -136,18 +96,8 @@ struct mwifiex_ds_get_stats { | |||
136 | u32 wep_icv_error[4]; | 96 | u32 wep_icv_error[4]; |
137 | }; | 97 | }; |
138 | 98 | ||
139 | #define BCN_RSSI_LAST_MASK 0x00000001 | ||
140 | #define BCN_RSSI_AVG_MASK 0x00000002 | 99 | #define BCN_RSSI_AVG_MASK 0x00000002 |
141 | #define DATA_RSSI_LAST_MASK 0x00000004 | ||
142 | #define DATA_RSSI_AVG_MASK 0x00000008 | ||
143 | #define BCN_SNR_LAST_MASK 0x00000010 | ||
144 | #define BCN_SNR_AVG_MASK 0x00000020 | ||
145 | #define DATA_SNR_LAST_MASK 0x00000040 | ||
146 | #define DATA_SNR_AVG_MASK 0x00000080 | ||
147 | #define BCN_NF_LAST_MASK 0x00000100 | ||
148 | #define BCN_NF_AVG_MASK 0x00000200 | 100 | #define BCN_NF_AVG_MASK 0x00000200 |
149 | #define DATA_NF_LAST_MASK 0x00000400 | ||
150 | #define DATA_NF_AVG_MASK 0x00000800 | ||
151 | #define ALL_RSSI_INFO_MASK 0x00000fff | 101 | #define ALL_RSSI_INFO_MASK 0x00000fff |
152 | 102 | ||
153 | struct mwifiex_ds_get_signal { | 103 | struct mwifiex_ds_get_signal { |
@@ -174,11 +124,6 @@ struct mwifiex_ds_get_signal { | |||
174 | s16 data_nf_avg; | 124 | s16 data_nf_avg; |
175 | }; | 125 | }; |
176 | 126 | ||
177 | struct mwifiex_fw_info { | ||
178 | u32 fw_ver; | ||
179 | u8 mac_addr[ETH_ALEN]; | ||
180 | }; | ||
181 | |||
182 | #define MWIFIEX_MAX_VER_STR_LEN 128 | 127 | #define MWIFIEX_MAX_VER_STR_LEN 128 |
183 | 128 | ||
184 | struct mwifiex_ver_ext { | 129 | struct mwifiex_ver_ext { |
@@ -286,11 +231,6 @@ struct mwifiex_rate_cfg { | |||
286 | u32 rate; | 231 | u32 rate; |
287 | }; | 232 | }; |
288 | 233 | ||
289 | struct mwifiex_data_rate { | ||
290 | u32 tx_data_rate; | ||
291 | u32 rx_data_rate; | ||
292 | }; | ||
293 | |||
294 | struct mwifiex_power_cfg { | 234 | struct mwifiex_power_cfg { |
295 | u32 is_power_auto; | 235 | u32 is_power_auto; |
296 | u32 power_level; | 236 | u32 power_level; |
@@ -309,21 +249,14 @@ struct mwifiex_ds_hs_cfg { | |||
309 | }; | 249 | }; |
310 | 250 | ||
311 | #define DEEP_SLEEP_ON 1 | 251 | #define DEEP_SLEEP_ON 1 |
312 | #define DEEP_SLEEP_OFF 0 | ||
313 | |||
314 | #define DEEP_SLEEP_IDLE_TIME 100 | 252 | #define DEEP_SLEEP_IDLE_TIME 100 |
253 | #define PS_MODE_AUTO 1 | ||
315 | 254 | ||
316 | struct mwifiex_ds_auto_ds { | 255 | struct mwifiex_ds_auto_ds { |
317 | u16 auto_ds; | 256 | u16 auto_ds; |
318 | u16 idle_time; | 257 | u16 idle_time; |
319 | }; | 258 | }; |
320 | 259 | ||
321 | #define PS_MODE_UNCHANGED 0 | ||
322 | #define PS_MODE_AUTO 1 | ||
323 | #define PS_MODE_POLL 2 | ||
324 | #define PS_MODE_NULL 3 | ||
325 | |||
326 | |||
327 | struct mwifiex_ds_pm_cfg { | 260 | struct mwifiex_ds_pm_cfg { |
328 | union { | 261 | union { |
329 | u32 ps_mode; | 262 | u32 ps_mode; |
@@ -333,18 +266,6 @@ struct mwifiex_ds_pm_cfg { | |||
333 | } param; | 266 | } param; |
334 | }; | 267 | }; |
335 | 268 | ||
336 | struct mwifiex_ioctl_wmm_queue_status_ac { | ||
337 | u8 wmm_acm; | ||
338 | u8 flow_required; | ||
339 | u8 flow_created; | ||
340 | u8 disabled; | ||
341 | }; | ||
342 | |||
343 | struct mwifiex_ds_wmm_queue_status { | ||
344 | struct mwifiex_ioctl_wmm_queue_status_ac | ||
345 | ac_status[IEEE80211_MAX_QUEUES]; | ||
346 | }; | ||
347 | |||
348 | struct mwifiex_ds_11n_tx_cfg { | 269 | struct mwifiex_ds_11n_tx_cfg { |
349 | u16 tx_htcap; | 270 | u16 tx_htcap; |
350 | u16 tx_htinfo; | 271 | u16 tx_htinfo; |
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 85fca5eb4195..5eab3dc29b1c 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c | |||
@@ -143,9 +143,8 @@ mwifiex_cmd_append_tsf_tlv(struct mwifiex_private *priv, u8 **buffer, | |||
143 | static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1, | 143 | static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1, |
144 | u32 rate1_size, u8 *rate2, u32 rate2_size) | 144 | u32 rate1_size, u8 *rate2, u32 rate2_size) |
145 | { | 145 | { |
146 | int ret = 0; | 146 | int ret; |
147 | u8 *ptr = rate1; | 147 | u8 *ptr = rate1, *tmp; |
148 | u8 *tmp = NULL; | ||
149 | u32 i, j; | 148 | u32 i, j; |
150 | 149 | ||
151 | tmp = kmalloc(rate1_size, GFP_KERNEL); | 150 | tmp = kmalloc(rate1_size, GFP_KERNEL); |
@@ -203,7 +202,7 @@ mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv, | |||
203 | u8 *out_rates, u32 *out_rates_size) | 202 | u8 *out_rates, u32 *out_rates_size) |
204 | { | 203 | { |
205 | u8 card_rates[MWIFIEX_SUPPORTED_RATES]; | 204 | u8 card_rates[MWIFIEX_SUPPORTED_RATES]; |
206 | u32 card_rates_size = 0; | 205 | u32 card_rates_size; |
207 | 206 | ||
208 | /* Copy AP supported rates */ | 207 | /* Copy AP supported rates */ |
209 | memcpy(out_rates, bss_desc->supported_rates, MWIFIEX_SUPPORTED_RATES); | 208 | memcpy(out_rates, bss_desc->supported_rates, MWIFIEX_SUPPORTED_RATES); |
@@ -1359,7 +1358,7 @@ int mwifiex_adhoc_join(struct mwifiex_private *priv, | |||
1359 | static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac) | 1358 | static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac) |
1360 | { | 1359 | { |
1361 | u8 mac_address[ETH_ALEN]; | 1360 | u8 mac_address[ETH_ALEN]; |
1362 | int ret = 0; | 1361 | int ret; |
1363 | u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; | 1362 | u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; |
1364 | 1363 | ||
1365 | if (mac) { | 1364 | if (mac) { |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index d16cea770fa3..f0582259c935 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -69,7 +69,7 @@ static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, | |||
69 | 69 | ||
70 | adapter = kzalloc(sizeof(struct mwifiex_adapter), GFP_KERNEL); | 70 | adapter = kzalloc(sizeof(struct mwifiex_adapter), GFP_KERNEL); |
71 | if (!adapter) | 71 | if (!adapter) |
72 | return -1; | 72 | return -ENOMEM; |
73 | 73 | ||
74 | g_adapter = adapter; | 74 | g_adapter = adapter; |
75 | adapter->card = card; | 75 | adapter->card = card; |
@@ -150,7 +150,7 @@ error: | |||
150 | */ | 150 | */ |
151 | static int mwifiex_unregister(struct mwifiex_adapter *adapter) | 151 | static int mwifiex_unregister(struct mwifiex_adapter *adapter) |
152 | { | 152 | { |
153 | s32 i = 0; | 153 | s32 i; |
154 | 154 | ||
155 | del_timer(&adapter->cmd_timer); | 155 | del_timer(&adapter->cmd_timer); |
156 | 156 | ||
@@ -379,8 +379,7 @@ static void mwifiex_free_adapter(struct mwifiex_adapter *adapter) | |||
379 | */ | 379 | */ |
380 | static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter) | 380 | static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter) |
381 | { | 381 | { |
382 | int ret = 0; | 382 | int ret, err; |
383 | int err; | ||
384 | struct mwifiex_fw_image fw; | 383 | struct mwifiex_fw_image fw; |
385 | 384 | ||
386 | memset(&fw, 0, sizeof(struct mwifiex_fw_image)); | 385 | memset(&fw, 0, sizeof(struct mwifiex_fw_image)); |
@@ -449,7 +448,7 @@ done: | |||
449 | static void | 448 | static void |
450 | mwifiex_fill_buffer(struct sk_buff *skb) | 449 | mwifiex_fill_buffer(struct sk_buff *skb) |
451 | { | 450 | { |
452 | struct ethhdr *eth = NULL; | 451 | struct ethhdr *eth; |
453 | struct iphdr *iph; | 452 | struct iphdr *iph; |
454 | struct timeval tv; | 453 | struct timeval tv; |
455 | u8 tid = 0; | 454 | u8 tid = 0; |
@@ -510,20 +509,20 @@ static int | |||
510 | mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | 509 | mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) |
511 | { | 510 | { |
512 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 511 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
513 | struct sk_buff *new_skb = NULL; | 512 | struct sk_buff *new_skb; |
514 | struct mwifiex_txinfo *tx_info; | 513 | struct mwifiex_txinfo *tx_info; |
515 | 514 | ||
516 | dev_dbg(priv->adapter->dev, "data: %lu BSS(%d): Data <= kernel\n", | 515 | dev_dbg(priv->adapter->dev, "data: %lu BSS(%d): Data <= kernel\n", |
517 | jiffies, priv->bss_index); | 516 | jiffies, priv->bss_index); |
518 | 517 | ||
519 | if (priv->adapter->surprise_removed) { | 518 | if (priv->adapter->surprise_removed) { |
520 | kfree(skb); | 519 | kfree_skb(skb); |
521 | priv->stats.tx_dropped++; | 520 | priv->stats.tx_dropped++; |
522 | return 0; | 521 | return 0; |
523 | } | 522 | } |
524 | if (!skb->len || (skb->len > ETH_FRAME_LEN)) { | 523 | if (!skb->len || (skb->len > ETH_FRAME_LEN)) { |
525 | dev_err(priv->adapter->dev, "Tx: bad skb len %d\n", skb->len); | 524 | dev_err(priv->adapter->dev, "Tx: bad skb len %d\n", skb->len); |
526 | kfree(skb); | 525 | kfree_skb(skb); |
527 | priv->stats.tx_dropped++; | 526 | priv->stats.tx_dropped++; |
528 | return 0; | 527 | return 0; |
529 | } | 528 | } |
@@ -536,7 +535,7 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
536 | skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN); | 535 | skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN); |
537 | if (unlikely(!new_skb)) { | 536 | if (unlikely(!new_skb)) { |
538 | dev_err(priv->adapter->dev, "Tx: cannot alloca new_skb\n"); | 537 | dev_err(priv->adapter->dev, "Tx: cannot alloca new_skb\n"); |
539 | kfree(skb); | 538 | kfree_skb(skb); |
540 | priv->stats.tx_dropped++; | 539 | priv->stats.tx_dropped++; |
541 | return 0; | 540 | return 0; |
542 | } | 541 | } |
@@ -571,7 +570,7 @@ mwifiex_set_mac_address(struct net_device *dev, void *addr) | |||
571 | { | 570 | { |
572 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 571 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
573 | struct sockaddr *hw_addr = (struct sockaddr *) addr; | 572 | struct sockaddr *hw_addr = (struct sockaddr *) addr; |
574 | int ret = 0; | 573 | int ret; |
575 | 574 | ||
576 | memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN); | 575 | memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN); |
577 | 576 | ||
@@ -696,9 +695,9 @@ static struct mwifiex_private *mwifiex_add_interface( | |||
696 | struct mwifiex_adapter *adapter, | 695 | struct mwifiex_adapter *adapter, |
697 | u8 bss_index, u8 bss_type) | 696 | u8 bss_index, u8 bss_type) |
698 | { | 697 | { |
699 | struct net_device *dev = NULL; | 698 | struct net_device *dev; |
700 | struct mwifiex_private *priv = NULL; | 699 | struct mwifiex_private *priv; |
701 | void *mdev_priv = NULL; | 700 | void *mdev_priv; |
702 | 701 | ||
703 | dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), "mlan%d", | 702 | dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), "mlan%d", |
704 | ether_setup, 1); | 703 | ether_setup, 1); |
@@ -759,7 +758,7 @@ error: | |||
759 | static void | 758 | static void |
760 | mwifiex_remove_interface(struct mwifiex_adapter *adapter, u8 bss_index) | 759 | mwifiex_remove_interface(struct mwifiex_adapter *adapter, u8 bss_index) |
761 | { | 760 | { |
762 | struct net_device *dev = NULL; | 761 | struct net_device *dev; |
763 | struct mwifiex_private *priv = adapter->priv[bss_index]; | 762 | struct mwifiex_private *priv = adapter->priv[bss_index]; |
764 | 763 | ||
765 | if (!priv) | 764 | if (!priv) |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 5043fcd22565..672701dc2721 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -479,9 +479,9 @@ struct mwifiex_private { | |||
479 | u8 report_scan_result; | 479 | u8 report_scan_result; |
480 | struct cfg80211_scan_request *scan_request; | 480 | struct cfg80211_scan_request *scan_request; |
481 | int scan_result_status; | 481 | int scan_result_status; |
482 | bool assoc_request; | 482 | int assoc_request; |
483 | u16 assoc_result; | 483 | u16 assoc_result; |
484 | bool ibss_join_request; | 484 | int ibss_join_request; |
485 | u16 ibss_join_result; | 485 | u16 ibss_join_result; |
486 | bool disconnect; | 486 | bool disconnect; |
487 | u8 cfg_bssid[6]; | 487 | u8 cfg_bssid[6]; |
@@ -692,10 +692,6 @@ int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter); | |||
692 | 692 | ||
693 | int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *); | 693 | int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *); |
694 | 694 | ||
695 | int mwifiex_recv_complete(struct mwifiex_adapter *, | ||
696 | struct sk_buff *skb, | ||
697 | int status); | ||
698 | |||
699 | int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb); | 695 | int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb); |
700 | 696 | ||
701 | int mwifiex_process_event(struct mwifiex_adapter *adapter); | 697 | int mwifiex_process_event(struct mwifiex_adapter *adapter); |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 31a529578805..5c22860fb40a 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -117,8 +117,8 @@ mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui) | |||
117 | static u8 | 117 | static u8 |
118 | mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) | 118 | mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) |
119 | { | 119 | { |
120 | u8 *oui = NULL; | 120 | u8 *oui; |
121 | struct ie_body *iebody = NULL; | 121 | struct ie_body *iebody; |
122 | u8 ret = MWIFIEX_OUI_NOT_PRESENT; | 122 | u8 ret = MWIFIEX_OUI_NOT_PRESENT; |
123 | 123 | ||
124 | if (((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)). | 124 | if (((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)). |
@@ -144,8 +144,8 @@ mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) | |||
144 | static u8 | 144 | static u8 |
145 | mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) | 145 | mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) |
146 | { | 146 | { |
147 | u8 *oui = NULL; | 147 | u8 *oui; |
148 | struct ie_body *iebody = NULL; | 148 | struct ie_body *iebody; |
149 | u8 ret = MWIFIEX_OUI_NOT_PRESENT; | 149 | u8 ret = MWIFIEX_OUI_NOT_PRESENT; |
150 | 150 | ||
151 | if (((bss_desc->bcn_wpa_ie) && ((*(bss_desc->bcn_wpa_ie)). | 151 | if (((bss_desc->bcn_wpa_ie) && ((*(bss_desc->bcn_wpa_ie)). |
@@ -181,7 +181,7 @@ int mwifiex_find_best_bss(struct mwifiex_private *priv, | |||
181 | struct mwifiex_ssid_bssid *ssid_bssid) | 181 | struct mwifiex_ssid_bssid *ssid_bssid) |
182 | { | 182 | { |
183 | struct mwifiex_ssid_bssid tmp_ssid_bssid; | 183 | struct mwifiex_ssid_bssid tmp_ssid_bssid; |
184 | u8 *mac = NULL; | 184 | u8 *mac; |
185 | 185 | ||
186 | if (!ssid_bssid) | 186 | if (!ssid_bssid) |
187 | return -1; | 187 | return -1; |
@@ -213,7 +213,7 @@ int mwifiex_find_best_bss(struct mwifiex_private *priv, | |||
213 | int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv, | 213 | int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv, |
214 | struct mwifiex_user_scan_cfg *scan_req) | 214 | struct mwifiex_user_scan_cfg *scan_req) |
215 | { | 215 | { |
216 | int status = 0; | 216 | int status; |
217 | 217 | ||
218 | priv->adapter->cmd_wait_q.condition = false; | 218 | priv->adapter->cmd_wait_q.condition = false; |
219 | 219 | ||
@@ -2253,8 +2253,8 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, | |||
2253 | { | 2253 | { |
2254 | int ret = 0; | 2254 | int ret = 0; |
2255 | struct mwifiex_adapter *adapter = priv->adapter; | 2255 | struct mwifiex_adapter *adapter = priv->adapter; |
2256 | struct cmd_ctrl_node *cmd_node = NULL; | 2256 | struct cmd_ctrl_node *cmd_node; |
2257 | union mwifiex_scan_cmd_config_tlv *scan_cfg_out = NULL; | 2257 | union mwifiex_scan_cmd_config_tlv *scan_cfg_out; |
2258 | struct mwifiex_ie_types_chan_list_param_set *chan_list_out; | 2258 | struct mwifiex_ie_types_chan_list_param_set *chan_list_out; |
2259 | u32 buf_size; | 2259 | u32 buf_size; |
2260 | struct mwifiex_chan_scan_param_set *scan_chan_list; | 2260 | struct mwifiex_chan_scan_param_set *scan_chan_list; |
@@ -2283,7 +2283,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, | |||
2283 | GFP_KERNEL); | 2283 | GFP_KERNEL); |
2284 | if (!scan_cfg_out) { | 2284 | if (!scan_cfg_out) { |
2285 | dev_err(adapter->dev, "failed to alloc scan_cfg_out\n"); | 2285 | dev_err(adapter->dev, "failed to alloc scan_cfg_out\n"); |
2286 | return -1; | 2286 | return -ENOMEM; |
2287 | } | 2287 | } |
2288 | 2288 | ||
2289 | buf_size = sizeof(struct mwifiex_chan_scan_param_set) * | 2289 | buf_size = sizeof(struct mwifiex_chan_scan_param_set) * |
@@ -2292,7 +2292,7 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, | |||
2292 | if (!scan_chan_list) { | 2292 | if (!scan_chan_list) { |
2293 | dev_err(adapter->dev, "failed to alloc scan_chan_list\n"); | 2293 | dev_err(adapter->dev, "failed to alloc scan_chan_list\n"); |
2294 | kfree(scan_cfg_out); | 2294 | kfree(scan_cfg_out); |
2295 | return -1; | 2295 | return -ENOMEM; |
2296 | } | 2296 | } |
2297 | 2297 | ||
2298 | keep_previous_scan = false; | 2298 | keep_previous_scan = false; |
@@ -2404,8 +2404,8 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
2404 | { | 2404 | { |
2405 | int ret = 0; | 2405 | int ret = 0; |
2406 | struct mwifiex_adapter *adapter = priv->adapter; | 2406 | struct mwifiex_adapter *adapter = priv->adapter; |
2407 | struct cmd_ctrl_node *cmd_node = NULL; | 2407 | struct cmd_ctrl_node *cmd_node; |
2408 | struct host_cmd_ds_802_11_scan_rsp *scan_rsp = NULL; | 2408 | struct host_cmd_ds_802_11_scan_rsp *scan_rsp; |
2409 | struct mwifiex_bssdescriptor *bss_new_entry = NULL; | 2409 | struct mwifiex_bssdescriptor *bss_new_entry = NULL; |
2410 | struct mwifiex_ie_types_data *tlv_data; | 2410 | struct mwifiex_ie_types_data *tlv_data; |
2411 | struct mwifiex_ie_types_tsf_timestamp *tsf_tlv; | 2411 | struct mwifiex_ie_types_tsf_timestamp *tsf_tlv; |
@@ -2491,7 +2491,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
2491 | GFP_KERNEL); | 2491 | GFP_KERNEL); |
2492 | if (!bss_new_entry) { | 2492 | if (!bss_new_entry) { |
2493 | dev_err(adapter->dev, " failed to alloc bss_new_entry\n"); | 2493 | dev_err(adapter->dev, " failed to alloc bss_new_entry\n"); |
2494 | return -1; | 2494 | return -ENOMEM; |
2495 | } | 2495 | } |
2496 | 2496 | ||
2497 | for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { | 2497 | for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { |
@@ -2881,7 +2881,7 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, | |||
2881 | scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); | 2881 | scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); |
2882 | if (!scan_cfg) { | 2882 | if (!scan_cfg) { |
2883 | dev_err(adapter->dev, "failed to alloc scan_cfg\n"); | 2883 | dev_err(adapter->dev, "failed to alloc scan_cfg\n"); |
2884 | return -1; | 2884 | return -ENOMEM; |
2885 | } | 2885 | } |
2886 | 2886 | ||
2887 | memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid, | 2887 | memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid, |
@@ -2906,7 +2906,7 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, | |||
2906 | int mwifiex_request_scan(struct mwifiex_private *priv, | 2906 | int mwifiex_request_scan(struct mwifiex_private *priv, |
2907 | struct mwifiex_802_11_ssid *req_ssid) | 2907 | struct mwifiex_802_11_ssid *req_ssid) |
2908 | { | 2908 | { |
2909 | int ret = 0; | 2909 | int ret; |
2910 | 2910 | ||
2911 | if (down_interruptible(&priv->async_sem)) { | 2911 | if (down_interruptible(&priv->async_sem)) { |
2912 | dev_err(priv->adapter->dev, "%s: acquire semaphore\n", | 2912 | dev_err(priv->adapter->dev, "%s: acquire semaphore\n", |
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 5148d0e0fad6..d425dbd91d19 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c | |||
@@ -46,7 +46,7 @@ static struct semaphore add_remove_card_sem; | |||
46 | static int | 46 | static int |
47 | mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) | 47 | mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) |
48 | { | 48 | { |
49 | int ret = 0; | 49 | int ret; |
50 | struct sdio_mmc_card *card = NULL; | 50 | struct sdio_mmc_card *card = NULL; |
51 | 51 | ||
52 | pr_debug("info: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n", | 52 | pr_debug("info: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n", |
@@ -68,6 +68,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) | |||
68 | 68 | ||
69 | if (ret) { | 69 | if (ret) { |
70 | pr_err("%s: failed to enable function\n", __func__); | 70 | pr_err("%s: failed to enable function\n", __func__); |
71 | kfree(card); | ||
71 | return -EIO; | 72 | return -EIO; |
72 | } | 73 | } |
73 | 74 | ||
@@ -119,7 +120,7 @@ static int mwifiex_sdio_suspend(struct device *dev) | |||
119 | { | 120 | { |
120 | struct sdio_func *func = dev_to_sdio_func(dev); | 121 | struct sdio_func *func = dev_to_sdio_func(dev); |
121 | struct sdio_mmc_card *card; | 122 | struct sdio_mmc_card *card; |
122 | struct mwifiex_adapter *adapter = NULL; | 123 | struct mwifiex_adapter *adapter; |
123 | mmc_pm_flag_t pm_flag = 0; | 124 | mmc_pm_flag_t pm_flag = 0; |
124 | int hs_actived = 0; | 125 | int hs_actived = 0; |
125 | int i; | 126 | int i; |
@@ -177,7 +178,7 @@ static int mwifiex_sdio_resume(struct device *dev) | |||
177 | { | 178 | { |
178 | struct sdio_func *func = dev_to_sdio_func(dev); | 179 | struct sdio_func *func = dev_to_sdio_func(dev); |
179 | struct sdio_mmc_card *card; | 180 | struct sdio_mmc_card *card; |
180 | struct mwifiex_adapter *adapter = NULL; | 181 | struct mwifiex_adapter *adapter; |
181 | mmc_pm_flag_t pm_flag = 0; | 182 | mmc_pm_flag_t pm_flag = 0; |
182 | int i; | 183 | int i; |
183 | 184 | ||
@@ -420,7 +421,7 @@ static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter, | |||
420 | u8 *payload, u32 pkt_len, u32 port) | 421 | u8 *payload, u32 pkt_len, u32 port) |
421 | { | 422 | { |
422 | u32 i = 0; | 423 | u32 i = 0; |
423 | int ret = 0; | 424 | int ret; |
424 | 425 | ||
425 | do { | 426 | do { |
426 | ret = mwifiex_write_data_sync(adapter, payload, pkt_len, port); | 427 | ret = mwifiex_write_data_sync(adapter, payload, pkt_len, port); |
@@ -531,7 +532,7 @@ static int | |||
531 | mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits) | 532 | mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits) |
532 | { | 533 | { |
533 | u32 tries; | 534 | u32 tries; |
534 | u32 cs = 0; | 535 | u32 cs; |
535 | 536 | ||
536 | for (tries = 0; tries < MAX_POLL_TRIES; tries++) { | 537 | for (tries = 0; tries < MAX_POLL_TRIES; tries++) { |
537 | if (mwifiex_read_reg(adapter, CARD_STATUS_REG, &cs)) | 538 | if (mwifiex_read_reg(adapter, CARD_STATUS_REG, &cs)) |
@@ -553,7 +554,7 @@ mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits) | |||
553 | static int | 554 | static int |
554 | mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat) | 555 | mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat) |
555 | { | 556 | { |
556 | u32 fws0 = 0, fws1 = 0; | 557 | u32 fws0, fws1; |
557 | 558 | ||
558 | if (mwifiex_read_reg(adapter, CARD_FW_STATUS0_REG, &fws0)) | 559 | if (mwifiex_read_reg(adapter, CARD_FW_STATUS0_REG, &fws0)) |
559 | return -1; | 560 | return -1; |
@@ -574,7 +575,7 @@ mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat) | |||
574 | */ | 575 | */ |
575 | static int mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter) | 576 | static int mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter) |
576 | { | 577 | { |
577 | u32 host_int_mask = 0; | 578 | u32 host_int_mask; |
578 | 579 | ||
579 | /* Read back the host_int_mask register */ | 580 | /* Read back the host_int_mask register */ |
580 | if (mwifiex_read_reg(adapter, HOST_INT_MASK_REG, &host_int_mask)) | 581 | if (mwifiex_read_reg(adapter, HOST_INT_MASK_REG, &host_int_mask)) |
@@ -614,7 +615,7 @@ static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter, | |||
614 | u32 *type, u8 *buffer, | 615 | u32 *type, u8 *buffer, |
615 | u32 npayload, u32 ioport) | 616 | u32 npayload, u32 ioport) |
616 | { | 617 | { |
617 | int ret = 0; | 618 | int ret; |
618 | u32 nb; | 619 | u32 nb; |
619 | 620 | ||
620 | if (!buffer) { | 621 | if (!buffer) { |
@@ -652,14 +653,14 @@ static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter, | |||
652 | static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | 653 | static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, |
653 | struct mwifiex_fw_image *fw) | 654 | struct mwifiex_fw_image *fw) |
654 | { | 655 | { |
655 | int ret = 0; | 656 | int ret; |
656 | u8 *firmware = fw->fw_buf; | 657 | u8 *firmware = fw->fw_buf; |
657 | u32 firmware_len = fw->fw_len; | 658 | u32 firmware_len = fw->fw_len; |
658 | u32 offset = 0; | 659 | u32 offset = 0; |
659 | u32 base0, base1; | 660 | u32 base0, base1; |
660 | u8 *fwbuf; | 661 | u8 *fwbuf; |
661 | u16 len = 0; | 662 | u16 len = 0; |
662 | u32 txlen = 0, tx_blocks = 0, tries = 0; | 663 | u32 txlen, tx_blocks = 0, tries; |
663 | u32 i = 0; | 664 | u32 i = 0; |
664 | 665 | ||
665 | if (!firmware_len) { | 666 | if (!firmware_len) { |
@@ -676,7 +677,7 @@ static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, | |||
676 | if (!fwbuf) { | 677 | if (!fwbuf) { |
677 | dev_err(adapter->dev, "unable to alloc buffer for firmware." | 678 | dev_err(adapter->dev, "unable to alloc buffer for firmware." |
678 | " Terminating download\n"); | 679 | " Terminating download\n"); |
679 | return -1; | 680 | return -ENOMEM; |
680 | } | 681 | } |
681 | 682 | ||
682 | /* Perform firmware data transfer */ | 683 | /* Perform firmware data transfer */ |
@@ -830,7 +831,7 @@ static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, | |||
830 | static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) | 831 | static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) |
831 | { | 832 | { |
832 | struct sdio_mmc_card *card = adapter->card; | 833 | struct sdio_mmc_card *card = adapter->card; |
833 | u32 sdio_ireg = 0; | 834 | u32 sdio_ireg; |
834 | unsigned long flags; | 835 | unsigned long flags; |
835 | 836 | ||
836 | if (mwifiex_read_data_sync(adapter, card->mp_regs, MAX_MP_REGS, | 837 | if (mwifiex_read_data_sync(adapter, card->mp_regs, MAX_MP_REGS, |
@@ -964,7 +965,7 @@ static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, | |||
964 | s32 f_do_rx_cur = 0; | 965 | s32 f_do_rx_cur = 0; |
965 | s32 f_aggr_cur = 0; | 966 | s32 f_aggr_cur = 0; |
966 | struct sk_buff *skb_deaggr; | 967 | struct sk_buff *skb_deaggr; |
967 | u32 pind = 0; | 968 | u32 pind; |
968 | u32 pkt_len, pkt_type = 0; | 969 | u32 pkt_len, pkt_type = 0; |
969 | u8 *curr_ptr; | 970 | u8 *curr_ptr; |
970 | u32 rx_len = skb->len; | 971 | u32 rx_len = skb->len; |
@@ -1114,7 +1115,7 @@ static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) | |||
1114 | struct sdio_mmc_card *card = adapter->card; | 1115 | struct sdio_mmc_card *card = adapter->card; |
1115 | int ret = 0; | 1116 | int ret = 0; |
1116 | u8 sdio_ireg; | 1117 | u8 sdio_ireg; |
1117 | struct sk_buff *skb = NULL; | 1118 | struct sk_buff *skb; |
1118 | u8 port = CTRL_PORT; | 1119 | u8 port = CTRL_PORT; |
1119 | u32 len_reg_l, len_reg_u; | 1120 | u32 len_reg_l, len_reg_u; |
1120 | u32 rx_blocks; | 1121 | u32 rx_blocks; |
@@ -1377,7 +1378,7 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter, | |||
1377 | struct mwifiex_tx_param *tx_param) | 1378 | struct mwifiex_tx_param *tx_param) |
1378 | { | 1379 | { |
1379 | struct sdio_mmc_card *card = adapter->card; | 1380 | struct sdio_mmc_card *card = adapter->card; |
1380 | int ret = 0; | 1381 | int ret; |
1381 | u32 buf_block_len; | 1382 | u32 buf_block_len; |
1382 | u32 blk_size; | 1383 | u32 blk_size; |
1383 | u8 port = CTRL_PORT; | 1384 | u8 port = CTRL_PORT; |
@@ -1560,7 +1561,7 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) | |||
1560 | { | 1561 | { |
1561 | struct sdio_mmc_card *card = adapter->card; | 1562 | struct sdio_mmc_card *card = adapter->card; |
1562 | int ret; | 1563 | int ret; |
1563 | u32 sdio_ireg = 0; | 1564 | u32 sdio_ireg; |
1564 | 1565 | ||
1565 | /* | 1566 | /* |
1566 | * Read the HOST_INT_STATUS_REG for ACK the first interrupt got | 1567 | * Read the HOST_INT_STATUS_REG for ACK the first interrupt got |
@@ -1605,7 +1606,7 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) | |||
1605 | card->mp_regs = kzalloc(MAX_MP_REGS, GFP_KERNEL); | 1606 | card->mp_regs = kzalloc(MAX_MP_REGS, GFP_KERNEL); |
1606 | if (!card->mp_regs) { | 1607 | if (!card->mp_regs) { |
1607 | dev_err(adapter->dev, "failed to alloc mp_regs\n"); | 1608 | dev_err(adapter->dev, "failed to alloc mp_regs\n"); |
1608 | return -1; | 1609 | return -ENOMEM; |
1609 | } | 1610 | } |
1610 | 1611 | ||
1611 | ret = mwifiex_alloc_sdio_mpa_buffers(adapter, | 1612 | ret = mwifiex_alloc_sdio_mpa_buffers(adapter, |
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 33c8ba1f5e33..8af3a78d2723 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c | |||
@@ -274,8 +274,8 @@ static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv, | |||
274 | static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd, | 274 | static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd, |
275 | u16 cmd_action, void *data_buf) | 275 | u16 cmd_action, void *data_buf) |
276 | { | 276 | { |
277 | struct mwifiex_types_power_group *pg_tlv = NULL; | 277 | struct mwifiex_types_power_group *pg_tlv; |
278 | struct host_cmd_ds_txpwr_cfg *txp = NULL; | 278 | struct host_cmd_ds_txpwr_cfg *txp; |
279 | struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg; | 279 | struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg; |
280 | 280 | ||
281 | cmd->command = cpu_to_le16(HostCmd_CMD_TXPWR_CFG); | 281 | cmd->command = cpu_to_le16(HostCmd_CMD_TXPWR_CFG); |
@@ -478,7 +478,7 @@ mwifiex_set_keyparamset_wep(struct mwifiex_private *priv, | |||
478 | struct mwifiex_ie_type_key_param_set *key_param_set, | 478 | struct mwifiex_ie_type_key_param_set *key_param_set, |
479 | u16 *key_param_len) | 479 | u16 *key_param_len) |
480 | { | 480 | { |
481 | int cur_key_param_len = 0; | 481 | int cur_key_param_len; |
482 | u8 i; | 482 | u8 i; |
483 | 483 | ||
484 | /* Multi-key_param_set TLV is supported */ | 484 | /* Multi-key_param_set TLV is supported */ |
@@ -1121,7 +1121,7 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, | |||
1121 | */ | 1121 | */ |
1122 | int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) | 1122 | int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) |
1123 | { | 1123 | { |
1124 | int ret = 0; | 1124 | int ret; |
1125 | u16 enable = true; | 1125 | u16 enable = true; |
1126 | struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl; | 1126 | struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl; |
1127 | struct mwifiex_ds_auto_ds auto_ds; | 1127 | struct mwifiex_ds_auto_ds auto_ds; |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 7f4f10b752fb..d08f76429a0a 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -43,7 +43,7 @@ static void | |||
43 | mwifiex_process_cmdresp_error(struct mwifiex_private *priv, | 43 | mwifiex_process_cmdresp_error(struct mwifiex_private *priv, |
44 | struct host_cmd_ds_command *resp) | 44 | struct host_cmd_ds_command *resp) |
45 | { | 45 | { |
46 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; | 46 | struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; |
47 | struct mwifiex_adapter *adapter = priv->adapter; | 47 | struct mwifiex_adapter *adapter = priv->adapter; |
48 | struct host_cmd_ds_802_11_ps_mode_enh *pm; | 48 | struct host_cmd_ds_802_11_ps_mode_enh *pm; |
49 | unsigned long flags; | 49 | unsigned long flags; |
@@ -124,7 +124,7 @@ static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv, | |||
124 | { | 124 | { |
125 | struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp = | 125 | struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp = |
126 | &resp->params.rssi_info_rsp; | 126 | &resp->params.rssi_info_rsp; |
127 | struct mwifiex_ds_get_signal *signal = NULL; | 127 | struct mwifiex_ds_get_signal *signal; |
128 | 128 | ||
129 | priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last); | 129 | priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last); |
130 | priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last); | 130 | priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last); |
@@ -232,7 +232,7 @@ static int mwifiex_ret_get_log(struct mwifiex_private *priv, | |||
232 | { | 232 | { |
233 | struct host_cmd_ds_802_11_get_log *get_log = | 233 | struct host_cmd_ds_802_11_get_log *get_log = |
234 | (struct host_cmd_ds_802_11_get_log *) &resp->params.get_log; | 234 | (struct host_cmd_ds_802_11_get_log *) &resp->params.get_log; |
235 | struct mwifiex_ds_get_stats *stats = NULL; | 235 | struct mwifiex_ds_get_stats *stats; |
236 | 236 | ||
237 | if (data_buf) { | 237 | if (data_buf) { |
238 | stats = (struct mwifiex_ds_get_stats *) data_buf; | 238 | stats = (struct mwifiex_ds_get_stats *) data_buf; |
@@ -280,10 +280,10 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv, | |||
280 | struct host_cmd_ds_command *resp, | 280 | struct host_cmd_ds_command *resp, |
281 | void *data_buf) | 281 | void *data_buf) |
282 | { | 282 | { |
283 | struct mwifiex_rate_cfg *ds_rate = NULL; | 283 | struct mwifiex_rate_cfg *ds_rate; |
284 | struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg; | 284 | struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg; |
285 | struct mwifiex_rate_scope *rate_scope; | 285 | struct mwifiex_rate_scope *rate_scope; |
286 | struct mwifiex_ie_types_header *head = NULL; | 286 | struct mwifiex_ie_types_header *head; |
287 | u16 tlv, tlv_buf_len; | 287 | u16 tlv, tlv_buf_len; |
288 | u8 *tlv_buf; | 288 | u8 *tlv_buf; |
289 | u32 i; | 289 | u32 i; |
@@ -368,9 +368,9 @@ static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv, | |||
368 | */ | 368 | */ |
369 | static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf) | 369 | static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf) |
370 | { | 370 | { |
371 | int length = -1, max_power = -1, min_power = -1; | 371 | int length, max_power = -1, min_power = -1; |
372 | struct mwifiex_types_power_group *pg_tlv_hdr = NULL; | 372 | struct mwifiex_types_power_group *pg_tlv_hdr; |
373 | struct mwifiex_power_group *pg = NULL; | 373 | struct mwifiex_power_group *pg; |
374 | 374 | ||
375 | if (data_buf) { | 375 | if (data_buf) { |
376 | pg_tlv_hdr = | 376 | pg_tlv_hdr = |
@@ -418,8 +418,8 @@ static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv, | |||
418 | { | 418 | { |
419 | struct mwifiex_adapter *adapter = priv->adapter; | 419 | struct mwifiex_adapter *adapter = priv->adapter; |
420 | struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg; | 420 | struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg; |
421 | struct mwifiex_types_power_group *pg_tlv_hdr = NULL; | 421 | struct mwifiex_types_power_group *pg_tlv_hdr; |
422 | struct mwifiex_power_group *pg = NULL; | 422 | struct mwifiex_power_group *pg; |
423 | u16 action = le16_to_cpu(txp_cfg->action); | 423 | u16 action = le16_to_cpu(txp_cfg->action); |
424 | 424 | ||
425 | switch (action) { | 425 | switch (action) { |
@@ -593,7 +593,7 @@ static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv, | |||
593 | &resp->params.domain_info_resp; | 593 | &resp->params.domain_info_resp; |
594 | struct mwifiex_ietypes_domain_param_set *domain = &domain_info->domain; | 594 | struct mwifiex_ietypes_domain_param_set *domain = &domain_info->domain; |
595 | u16 action = le16_to_cpu(domain_info->action); | 595 | u16 action = le16_to_cpu(domain_info->action); |
596 | u8 no_of_triplet = 0; | 596 | u8 no_of_triplet; |
597 | 597 | ||
598 | no_of_triplet = (u8) ((le16_to_cpu(domain->header.len) - | 598 | no_of_triplet = (u8) ((le16_to_cpu(domain->header.len) - |
599 | IEEE80211_COUNTRY_STRING_LEN) / | 599 | IEEE80211_COUNTRY_STRING_LEN) / |
@@ -661,7 +661,7 @@ static int mwifiex_ret_ver_ext(struct mwifiex_private *priv, | |||
661 | void *data_buf) | 661 | void *data_buf) |
662 | { | 662 | { |
663 | struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext; | 663 | struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext; |
664 | struct host_cmd_ds_version_ext *version_ext = NULL; | 664 | struct host_cmd_ds_version_ext *version_ext; |
665 | 665 | ||
666 | if (data_buf) { | 666 | if (data_buf) { |
667 | version_ext = (struct host_cmd_ds_version_ext *)data_buf; | 667 | version_ext = (struct host_cmd_ds_version_ext *)data_buf; |
@@ -682,8 +682,8 @@ static int mwifiex_ret_ver_ext(struct mwifiex_private *priv, | |||
682 | static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp, | 682 | static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp, |
683 | void *data_buf) | 683 | void *data_buf) |
684 | { | 684 | { |
685 | struct mwifiex_ds_reg_rw *reg_rw = NULL; | 685 | struct mwifiex_ds_reg_rw *reg_rw; |
686 | struct mwifiex_ds_read_eeprom *eeprom = NULL; | 686 | struct mwifiex_ds_read_eeprom *eeprom; |
687 | 687 | ||
688 | if (data_buf) { | 688 | if (data_buf) { |
689 | reg_rw = (struct mwifiex_ds_reg_rw *) data_buf; | 689 | reg_rw = (struct mwifiex_ds_reg_rw *) data_buf; |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index e7adaab35226..d05907d05039 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -149,7 +149,7 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, | |||
149 | int mwifiex_bss_start(struct mwifiex_private *priv, | 149 | int mwifiex_bss_start(struct mwifiex_private *priv, |
150 | struct mwifiex_ssid_bssid *ssid_bssid) | 150 | struct mwifiex_ssid_bssid *ssid_bssid) |
151 | { | 151 | { |
152 | int ret = 0; | 152 | int ret; |
153 | struct mwifiex_adapter *adapter = priv->adapter; | 153 | struct mwifiex_adapter *adapter = priv->adapter; |
154 | s32 i = -1; | 154 | s32 i = -1; |
155 | 155 | ||
@@ -376,7 +376,7 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv, | |||
376 | { | 376 | { |
377 | struct mwifiex_adapter *adapter = priv->adapter; | 377 | struct mwifiex_adapter *adapter = priv->adapter; |
378 | struct mwifiex_bssdescriptor *bss_desc; | 378 | struct mwifiex_bssdescriptor *bss_desc; |
379 | s32 tbl_idx = 0; | 379 | s32 tbl_idx; |
380 | 380 | ||
381 | if (!info) | 381 | if (!info) |
382 | return -1; | 382 | return -1; |
@@ -436,9 +436,8 @@ int mwifiex_set_radio_band_cfg(struct mwifiex_private *priv, | |||
436 | struct mwifiex_ds_band_cfg *radio_cfg) | 436 | struct mwifiex_ds_band_cfg *radio_cfg) |
437 | { | 437 | { |
438 | struct mwifiex_adapter *adapter = priv->adapter; | 438 | struct mwifiex_adapter *adapter = priv->adapter; |
439 | u8 infra_band = 0; | 439 | u8 infra_band, adhoc_band; |
440 | u8 adhoc_band = 0; | 440 | u32 adhoc_channel; |
441 | u32 adhoc_channel = 0; | ||
442 | 441 | ||
443 | infra_band = (u8) radio_cfg->config_bands; | 442 | infra_band = (u8) radio_cfg->config_bands; |
444 | adhoc_band = (u8) radio_cfg->adhoc_start_band; | 443 | adhoc_band = (u8) radio_cfg->adhoc_start_band; |
@@ -636,7 +635,7 @@ int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv, | |||
636 | int | 635 | int |
637 | mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) | 636 | mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel) |
638 | { | 637 | { |
639 | int ret = 0; | 638 | int ret; |
640 | struct mwifiex_bss_info bss_info; | 639 | struct mwifiex_bss_info bss_info; |
641 | struct mwifiex_ssid_bssid ssid_bssid; | 640 | struct mwifiex_ssid_bssid ssid_bssid; |
642 | u16 curr_chan = 0; | 641 | u16 curr_chan = 0; |
@@ -755,11 +754,10 @@ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv, | |||
755 | struct mwifiex_rate_cfg *rate_cfg) | 754 | struct mwifiex_rate_cfg *rate_cfg) |
756 | { | 755 | { |
757 | u8 rates[MWIFIEX_SUPPORTED_RATES]; | 756 | u8 rates[MWIFIEX_SUPPORTED_RATES]; |
758 | u8 *rate = NULL; | 757 | u8 *rate; |
759 | int rate_index = 0; | 758 | int rate_index, ret; |
760 | u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; | 759 | u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; |
761 | u32 i = 0; | 760 | u32 i; |
762 | int ret = 0; | ||
763 | struct mwifiex_adapter *adapter = priv->adapter; | 761 | struct mwifiex_adapter *adapter = priv->adapter; |
764 | 762 | ||
765 | if (rate_cfg->is_rate_auto) { | 763 | if (rate_cfg->is_rate_auto) { |
@@ -819,7 +817,7 @@ static int mwifiex_rate_ioctl_set_rate_value(struct mwifiex_private *priv, | |||
819 | static int mwifiex_rate_ioctl_cfg(struct mwifiex_private *priv, | 817 | static int mwifiex_rate_ioctl_cfg(struct mwifiex_private *priv, |
820 | struct mwifiex_rate_cfg *rate_cfg) | 818 | struct mwifiex_rate_cfg *rate_cfg) |
821 | { | 819 | { |
822 | int status = 0; | 820 | int status; |
823 | 821 | ||
824 | if (!rate_cfg) | 822 | if (!rate_cfg) |
825 | return -1; | 823 | return -1; |
@@ -841,7 +839,7 @@ static int mwifiex_rate_ioctl_cfg(struct mwifiex_private *priv, | |||
841 | int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, | 839 | int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, |
842 | struct mwifiex_rate_cfg *rate) | 840 | struct mwifiex_rate_cfg *rate) |
843 | { | 841 | { |
844 | int ret = 0; | 842 | int ret; |
845 | 843 | ||
846 | memset(rate, 0, sizeof(struct mwifiex_rate_cfg)); | 844 | memset(rate, 0, sizeof(struct mwifiex_rate_cfg)); |
847 | rate->action = HostCmd_ACT_GEN_GET; | 845 | rate->action = HostCmd_ACT_GEN_GET; |
@@ -875,11 +873,11 @@ int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, | |||
875 | int mwifiex_set_tx_power(struct mwifiex_private *priv, | 873 | int mwifiex_set_tx_power(struct mwifiex_private *priv, |
876 | struct mwifiex_power_cfg *power_cfg) | 874 | struct mwifiex_power_cfg *power_cfg) |
877 | { | 875 | { |
878 | int ret = 0; | 876 | int ret; |
879 | struct host_cmd_ds_txpwr_cfg *txp_cfg = NULL; | 877 | struct host_cmd_ds_txpwr_cfg *txp_cfg; |
880 | struct mwifiex_types_power_group *pg_tlv = NULL; | 878 | struct mwifiex_types_power_group *pg_tlv; |
881 | struct mwifiex_power_group *pg = NULL; | 879 | struct mwifiex_power_group *pg; |
882 | u8 *buf = NULL; | 880 | u8 *buf; |
883 | u16 dbm = 0; | 881 | u16 dbm = 0; |
884 | 882 | ||
885 | if (!power_cfg->is_power_auto) { | 883 | if (!power_cfg->is_power_auto) { |
@@ -897,7 +895,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, | |||
897 | if (!buf) { | 895 | if (!buf) { |
898 | dev_err(priv->adapter->dev, "%s: failed to alloc cmd buffer\n", | 896 | dev_err(priv->adapter->dev, "%s: failed to alloc cmd buffer\n", |
899 | __func__); | 897 | __func__); |
900 | return -1; | 898 | return -ENOMEM; |
901 | } | 899 | } |
902 | 900 | ||
903 | txp_cfg = (struct host_cmd_ds_txpwr_cfg *) buf; | 901 | txp_cfg = (struct host_cmd_ds_txpwr_cfg *) buf; |
@@ -960,7 +958,7 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, | |||
960 | */ | 958 | */ |
961 | int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode) | 959 | int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode) |
962 | { | 960 | { |
963 | int ret = 0; | 961 | int ret; |
964 | struct mwifiex_adapter *adapter = priv->adapter; | 962 | struct mwifiex_adapter *adapter = priv->adapter; |
965 | u16 sub_cmd; | 963 | u16 sub_cmd; |
966 | 964 | ||
@@ -1078,8 +1076,8 @@ static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_private *priv, | |||
1078 | static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, | 1076 | static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, |
1079 | struct mwifiex_ds_encrypt_key *encrypt_key) | 1077 | struct mwifiex_ds_encrypt_key *encrypt_key) |
1080 | { | 1078 | { |
1081 | int ret = 0; | 1079 | int ret; |
1082 | struct mwifiex_wep_key *wep_key = NULL; | 1080 | struct mwifiex_wep_key *wep_key; |
1083 | int index; | 1081 | int index; |
1084 | 1082 | ||
1085 | if (priv->wep_key_curr_index >= NUM_WEP_KEYS) | 1083 | if (priv->wep_key_curr_index >= NUM_WEP_KEYS) |
@@ -1142,7 +1140,7 @@ static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, | |||
1142 | static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv, | 1140 | static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv, |
1143 | struct mwifiex_ds_encrypt_key *encrypt_key) | 1141 | struct mwifiex_ds_encrypt_key *encrypt_key) |
1144 | { | 1142 | { |
1145 | int ret = 0; | 1143 | int ret; |
1146 | u8 remove_key = false; | 1144 | u8 remove_key = false; |
1147 | struct host_cmd_ds_802_11_key_material *ibss_key; | 1145 | struct host_cmd_ds_802_11_key_material *ibss_key; |
1148 | 1146 | ||
@@ -1209,7 +1207,7 @@ static int | |||
1209 | mwifiex_sec_ioctl_encrypt_key(struct mwifiex_private *priv, | 1207 | mwifiex_sec_ioctl_encrypt_key(struct mwifiex_private *priv, |
1210 | struct mwifiex_ds_encrypt_key *encrypt_key) | 1208 | struct mwifiex_ds_encrypt_key *encrypt_key) |
1211 | { | 1209 | { |
1212 | int status = 0; | 1210 | int status; |
1213 | 1211 | ||
1214 | if (encrypt_key->is_wapi_key) | 1212 | if (encrypt_key->is_wapi_key) |
1215 | status = mwifiex_sec_ioctl_set_wapi_key(priv, encrypt_key); | 1213 | status = mwifiex_sec_ioctl_set_wapi_key(priv, encrypt_key); |
@@ -1252,11 +1250,9 @@ mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version, | |||
1252 | int mwifiex_get_signal_info(struct mwifiex_private *priv, | 1250 | int mwifiex_get_signal_info(struct mwifiex_private *priv, |
1253 | struct mwifiex_ds_get_signal *signal) | 1251 | struct mwifiex_ds_get_signal *signal) |
1254 | { | 1252 | { |
1255 | struct mwifiex_ds_get_signal info; | 1253 | int status; |
1256 | int status = 0; | ||
1257 | 1254 | ||
1258 | memset(&info, 0, sizeof(struct mwifiex_ds_get_signal)); | 1255 | signal->selector = ALL_RSSI_INFO_MASK; |
1259 | info.selector = ALL_RSSI_INFO_MASK; | ||
1260 | 1256 | ||
1261 | /* Signal info can be obtained only if connected */ | 1257 | /* Signal info can be obtained only if connected */ |
1262 | if (!priv->media_connected) { | 1258 | if (!priv->media_connected) { |
@@ -1269,13 +1265,10 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv, | |||
1269 | HostCmd_ACT_GEN_GET, 0, signal); | 1265 | HostCmd_ACT_GEN_GET, 0, signal); |
1270 | 1266 | ||
1271 | if (!status) { | 1267 | if (!status) { |
1272 | if (signal) | 1268 | if (signal->selector & BCN_RSSI_AVG_MASK) |
1273 | memcpy(signal, &info, | 1269 | priv->w_stats.qual.level = signal->bcn_rssi_avg; |
1274 | sizeof(struct mwifiex_ds_get_signal)); | 1270 | if (signal->selector & BCN_NF_AVG_MASK) |
1275 | if (info.selector & BCN_RSSI_AVG_MASK) | 1271 | priv->w_stats.qual.noise = signal->bcn_nf_avg; |
1276 | priv->w_stats.qual.level = info.bcn_rssi_avg; | ||
1277 | if (info.selector & BCN_NF_AVG_MASK) | ||
1278 | priv->w_stats.qual.noise = info.bcn_nf_avg; | ||
1279 | } | 1272 | } |
1280 | 1273 | ||
1281 | return status; | 1274 | return status; |
@@ -1334,20 +1327,15 @@ int | |||
1334 | mwifiex_get_stats_info(struct mwifiex_private *priv, | 1327 | mwifiex_get_stats_info(struct mwifiex_private *priv, |
1335 | struct mwifiex_ds_get_stats *log) | 1328 | struct mwifiex_ds_get_stats *log) |
1336 | { | 1329 | { |
1337 | int ret = 0; | 1330 | int ret; |
1338 | struct mwifiex_ds_get_stats get_log; | ||
1339 | 1331 | ||
1340 | memset(&get_log, 0, sizeof(struct mwifiex_ds_get_stats)); | ||
1341 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG, | 1332 | ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG, |
1342 | HostCmd_ACT_GEN_GET, 0, &get_log); | 1333 | HostCmd_ACT_GEN_GET, 0, log); |
1343 | 1334 | ||
1344 | if (!ret) { | 1335 | if (!ret) { |
1345 | if (log) | 1336 | priv->w_stats.discard.fragment = log->fcs_error; |
1346 | memcpy(log, &get_log, sizeof(struct | 1337 | priv->w_stats.discard.retries = log->retry; |
1347 | mwifiex_ds_get_stats)); | 1338 | priv->w_stats.discard.misc = log->ack_failure; |
1348 | priv->w_stats.discard.fragment = get_log.fcs_error; | ||
1349 | priv->w_stats.discard.retries = get_log.retry; | ||
1350 | priv->w_stats.discard.misc = get_log.ack_failure; | ||
1351 | } | 1339 | } |
1352 | 1340 | ||
1353 | return ret; | 1341 | return ret; |
@@ -1425,7 +1413,7 @@ int | |||
1425 | mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type, | 1413 | mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type, |
1426 | u32 reg_offset, u32 *value) | 1414 | u32 reg_offset, u32 *value) |
1427 | { | 1415 | { |
1428 | int ret = 0; | 1416 | int ret; |
1429 | struct mwifiex_ds_reg_rw reg_rw; | 1417 | struct mwifiex_ds_reg_rw reg_rw; |
1430 | 1418 | ||
1431 | reg_rw.type = cpu_to_le32(reg_type); | 1419 | reg_rw.type = cpu_to_le32(reg_type); |
@@ -1451,7 +1439,7 @@ int | |||
1451 | mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes, | 1439 | mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes, |
1452 | u8 *value) | 1440 | u8 *value) |
1453 | { | 1441 | { |
1454 | int ret = 0; | 1442 | int ret; |
1455 | struct mwifiex_ds_read_eeprom rd_eeprom; | 1443 | struct mwifiex_ds_read_eeprom rd_eeprom; |
1456 | 1444 | ||
1457 | rd_eeprom.offset = cpu_to_le16((u16) offset); | 1445 | rd_eeprom.offset = cpu_to_le16((u16) offset); |
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c index 8282679e64fd..1fdddece7479 100644 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ b/drivers/net/wireless/mwifiex/sta_rx.c | |||
@@ -41,7 +41,7 @@ | |||
41 | int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, | 41 | int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter, |
42 | struct sk_buff *skb) | 42 | struct sk_buff *skb) |
43 | { | 43 | { |
44 | int ret = 0; | 44 | int ret; |
45 | struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); | 45 | struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); |
46 | struct mwifiex_private *priv = adapter->priv[rx_info->bss_index]; | 46 | struct mwifiex_private *priv = adapter->priv[rx_info->bss_index]; |
47 | struct rx_packet_hdr *rx_pkt_hdr; | 47 | struct rx_packet_hdr *rx_pkt_hdr; |
@@ -123,7 +123,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, | |||
123 | struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); | 123 | struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); |
124 | struct rx_packet_hdr *rx_pkt_hdr; | 124 | struct rx_packet_hdr *rx_pkt_hdr; |
125 | u8 ta[ETH_ALEN]; | 125 | u8 ta[ETH_ALEN]; |
126 | u16 rx_pkt_type = 0; | 126 | u16 rx_pkt_type; |
127 | struct mwifiex_private *priv = adapter->priv[rx_info->bss_index]; | 127 | struct mwifiex_private *priv = adapter->priv[rx_info->bss_index]; |
128 | 128 | ||
129 | local_rx_pd = (struct rxpd *) (skb->data); | 129 | local_rx_pd = (struct rxpd *) (skb->data); |
@@ -141,10 +141,28 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, | |||
141 | dev_kfree_skb_any(skb); | 141 | dev_kfree_skb_any(skb); |
142 | return ret; | 142 | return ret; |
143 | } | 143 | } |
144 | |||
144 | if (local_rx_pd->rx_pkt_type == PKT_TYPE_AMSDU) { | 145 | if (local_rx_pd->rx_pkt_type == PKT_TYPE_AMSDU) { |
145 | mwifiex_11n_deaggregate_pkt(priv, skb); | 146 | struct sk_buff_head list; |
146 | return ret; | 147 | struct sk_buff *rx_skb; |
148 | |||
149 | __skb_queue_head_init(&list); | ||
150 | |||
151 | skb_pull(skb, local_rx_pd->rx_pkt_offset); | ||
152 | skb_trim(skb, local_rx_pd->rx_pkt_length); | ||
153 | |||
154 | ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, | ||
155 | priv->wdev->iftype, 0, false); | ||
156 | |||
157 | while (!skb_queue_empty(&list)) { | ||
158 | rx_skb = __skb_dequeue(&list); | ||
159 | ret = mwifiex_recv_packet(adapter, rx_skb); | ||
160 | if (ret == -1) | ||
161 | dev_err(adapter->dev, "Rx of A-MSDU failed"); | ||
162 | } | ||
163 | return 0; | ||
147 | } | 164 | } |
165 | |||
148 | /* | 166 | /* |
149 | * If the packet is not an unicast packet then send the packet | 167 | * If the packet is not an unicast packet then send the packet |
150 | * directly to os. Don't pass thru rx reordering | 168 | * directly to os. Don't pass thru rx reordering |
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index 5d37ef160121..fa6221bc9104 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c | |||
@@ -113,8 +113,8 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) | |||
113 | /* sizeof(struct txpd) + Interface specific header */ | 113 | /* sizeof(struct txpd) + Interface specific header */ |
114 | #define NULL_PACKET_HDR 64 | 114 | #define NULL_PACKET_HDR 64 |
115 | u32 data_len = NULL_PACKET_HDR; | 115 | u32 data_len = NULL_PACKET_HDR; |
116 | struct sk_buff *skb = NULL; | 116 | struct sk_buff *skb; |
117 | int ret = 0; | 117 | int ret; |
118 | struct mwifiex_txinfo *tx_info = NULL; | 118 | struct mwifiex_txinfo *tx_info = NULL; |
119 | 119 | ||
120 | if (adapter->surprise_removed) | 120 | if (adapter->surprise_removed) |
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index ce772e078db8..210120889dfe 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c | |||
@@ -68,7 +68,7 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, | |||
68 | { | 68 | { |
69 | int ret = -1; | 69 | int ret = -1; |
70 | struct mwifiex_adapter *adapter = priv->adapter; | 70 | struct mwifiex_adapter *adapter = priv->adapter; |
71 | u8 *head_ptr = NULL; | 71 | u8 *head_ptr; |
72 | struct txpd *local_tx_pd = NULL; | 72 | struct txpd *local_tx_pd = NULL; |
73 | 73 | ||
74 | head_ptr = (u8 *) mwifiex_process_sta_txpd(priv, skb); | 74 | head_ptr = (u8 *) mwifiex_process_sta_txpd(priv, skb); |
@@ -121,8 +121,8 @@ int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, | |||
121 | int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, | 121 | int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, |
122 | struct sk_buff *skb, int status) | 122 | struct sk_buff *skb, int status) |
123 | { | 123 | { |
124 | struct mwifiex_private *priv = NULL, *tpriv = NULL; | 124 | struct mwifiex_private *priv, *tpriv; |
125 | struct mwifiex_txinfo *tx_info = NULL; | 125 | struct mwifiex_txinfo *tx_info; |
126 | int i; | 126 | int i; |
127 | 127 | ||
128 | if (!skb) | 128 | if (!skb) |
@@ -169,9 +169,9 @@ int mwifiex_recv_packet_complete(struct mwifiex_adapter *adapter, | |||
169 | struct sk_buff *skb, int status) | 169 | struct sk_buff *skb, int status) |
170 | { | 170 | { |
171 | struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); | 171 | struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); |
172 | struct mwifiex_rxinfo *rx_info_parent = NULL; | 172 | struct mwifiex_rxinfo *rx_info_parent; |
173 | struct mwifiex_private *priv; | 173 | struct mwifiex_private *priv; |
174 | struct sk_buff *skb_parent = NULL; | 174 | struct sk_buff *skb_parent; |
175 | unsigned long flags; | 175 | unsigned long flags; |
176 | 176 | ||
177 | priv = adapter->priv[rx_info->bss_index]; | 177 | priv = adapter->priv[rx_info->bss_index]; |
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index 7ab4fb279f8a..d41291529bc0 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c | |||
@@ -152,8 +152,8 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv, | |||
152 | */ | 152 | */ |
153 | int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb) | 153 | int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb) |
154 | { | 154 | { |
155 | struct mwifiex_rxinfo *rx_info = NULL; | 155 | struct mwifiex_rxinfo *rx_info; |
156 | struct mwifiex_private *priv = NULL; | 156 | struct mwifiex_private *priv; |
157 | 157 | ||
158 | if (!skb) | 158 | if (!skb) |
159 | return -1; | 159 | return -1; |
@@ -177,31 +177,6 @@ int mwifiex_recv_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb) | |||
177 | } | 177 | } |
178 | 178 | ||
179 | /* | 179 | /* |
180 | * Receive packet completion callback handler. | ||
181 | * | ||
182 | * This function updates the statistics and frees the buffer SKB. | ||
183 | */ | ||
184 | int mwifiex_recv_complete(struct mwifiex_adapter *adapter, | ||
185 | struct sk_buff *skb, int status) | ||
186 | { | ||
187 | struct mwifiex_private *priv = NULL; | ||
188 | struct mwifiex_rxinfo *rx_info = NULL; | ||
189 | |||
190 | if (!skb) | ||
191 | return 0; | ||
192 | |||
193 | rx_info = MWIFIEX_SKB_RXCB(skb); | ||
194 | priv = mwifiex_bss_index_to_priv(adapter, rx_info->bss_index); | ||
195 | |||
196 | if (priv && (status == -1)) | ||
197 | priv->stats.rx_dropped++; | ||
198 | |||
199 | dev_kfree_skb_any(skb); | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * IOCTL completion callback handler. | 180 | * IOCTL completion callback handler. |
206 | * | 181 | * |
207 | * This function is called when a pending IOCTL is completed. | 182 | * This function is called when a pending IOCTL is completed. |
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index c009370f309e..faa09e32902e 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c | |||
@@ -799,7 +799,7 @@ u8 | |||
799 | mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv, | 799 | mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv, |
800 | const struct sk_buff *skb) | 800 | const struct sk_buff *skb) |
801 | { | 801 | { |
802 | u8 ret_val = 0; | 802 | u8 ret_val; |
803 | struct timeval out_tstamp, in_tstamp; | 803 | struct timeval out_tstamp, in_tstamp; |
804 | u32 queue_delay; | 804 | u32 queue_delay; |
805 | 805 | ||
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index 9f5ecef297e5..32261189bcef 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -784,7 +784,8 @@ static inline void mwl8k_remove_dma_header(struct sk_buff *skb, __le16 qos) | |||
784 | #define REDUCED_TX_HEADROOM 8 | 784 | #define REDUCED_TX_HEADROOM 8 |
785 | 785 | ||
786 | static void | 786 | static void |
787 | mwl8k_add_dma_header(struct mwl8k_priv *priv, struct sk_buff *skb, int tail_pad) | 787 | mwl8k_add_dma_header(struct mwl8k_priv *priv, struct sk_buff *skb, |
788 | int head_pad, int tail_pad) | ||
788 | { | 789 | { |
789 | struct ieee80211_hdr *wh; | 790 | struct ieee80211_hdr *wh; |
790 | int hdrlen; | 791 | int hdrlen; |
@@ -816,7 +817,7 @@ mwl8k_add_dma_header(struct mwl8k_priv *priv, struct sk_buff *skb, int tail_pad) | |||
816 | skb->truesize += REDUCED_TX_HEADROOM; | 817 | skb->truesize += REDUCED_TX_HEADROOM; |
817 | } | 818 | } |
818 | 819 | ||
819 | reqd_hdrlen = sizeof(*tr); | 820 | reqd_hdrlen = sizeof(*tr) + head_pad; |
820 | 821 | ||
821 | if (hdrlen != reqd_hdrlen) | 822 | if (hdrlen != reqd_hdrlen) |
822 | skb_push(skb, reqd_hdrlen - hdrlen); | 823 | skb_push(skb, reqd_hdrlen - hdrlen); |
@@ -845,6 +846,7 @@ static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv, | |||
845 | struct ieee80211_tx_info *tx_info; | 846 | struct ieee80211_tx_info *tx_info; |
846 | struct ieee80211_key_conf *key_conf; | 847 | struct ieee80211_key_conf *key_conf; |
847 | int data_pad; | 848 | int data_pad; |
849 | int head_pad = 0; | ||
848 | 850 | ||
849 | wh = (struct ieee80211_hdr *)skb->data; | 851 | wh = (struct ieee80211_hdr *)skb->data; |
850 | 852 | ||
@@ -856,9 +858,7 @@ static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv, | |||
856 | 858 | ||
857 | /* | 859 | /* |
858 | * Make sure the packet header is in the DMA header format (4-address | 860 | * Make sure the packet header is in the DMA header format (4-address |
859 | * without QoS), the necessary crypto padding between the header and the | 861 | * without QoS), and add head & tail padding when HW crypto is enabled. |
860 | * payload has already been provided by mac80211, but it doesn't add | ||
861 | * tail padding when HW crypto is enabled. | ||
862 | * | 862 | * |
863 | * We have the following trailer padding requirements: | 863 | * We have the following trailer padding requirements: |
864 | * - WEP: 4 trailer bytes (ICV) | 864 | * - WEP: 4 trailer bytes (ICV) |
@@ -867,6 +867,7 @@ static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv, | |||
867 | */ | 867 | */ |
868 | data_pad = 0; | 868 | data_pad = 0; |
869 | if (key_conf != NULL) { | 869 | if (key_conf != NULL) { |
870 | head_pad = key_conf->iv_len; | ||
870 | switch (key_conf->cipher) { | 871 | switch (key_conf->cipher) { |
871 | case WLAN_CIPHER_SUITE_WEP40: | 872 | case WLAN_CIPHER_SUITE_WEP40: |
872 | case WLAN_CIPHER_SUITE_WEP104: | 873 | case WLAN_CIPHER_SUITE_WEP104: |
@@ -880,7 +881,7 @@ static void mwl8k_encapsulate_tx_frame(struct mwl8k_priv *priv, | |||
880 | break; | 881 | break; |
881 | } | 882 | } |
882 | } | 883 | } |
883 | mwl8k_add_dma_header(priv, skb, data_pad); | 884 | mwl8k_add_dma_header(priv, skb, head_pad, data_pad); |
884 | } | 885 | } |
885 | 886 | ||
886 | /* | 887 | /* |
@@ -1837,7 +1838,7 @@ mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) | |||
1837 | if (priv->ap_fw) | 1838 | if (priv->ap_fw) |
1838 | mwl8k_encapsulate_tx_frame(priv, skb); | 1839 | mwl8k_encapsulate_tx_frame(priv, skb); |
1839 | else | 1840 | else |
1840 | mwl8k_add_dma_header(priv, skb, 0); | 1841 | mwl8k_add_dma_header(priv, skb, 0, 0); |
1841 | 1842 | ||
1842 | wh = &((struct mwl8k_dma_data *)skb->data)->wh; | 1843 | wh = &((struct mwl8k_dma_data *)skb->data)->wh; |
1843 | 1844 | ||
@@ -3997,7 +3998,7 @@ static int mwl8k_cmd_encryption_set_key(struct ieee80211_hw *hw, | |||
3997 | mwl8k_vif->wep_key_conf[idx].enabled = 1; | 3998 | mwl8k_vif->wep_key_conf[idx].enabled = 1; |
3998 | } | 3999 | } |
3999 | 4000 | ||
4000 | keymlen = 0; | 4001 | keymlen = key->keylen; |
4001 | action = MWL8K_ENCR_SET_KEY; | 4002 | action = MWL8K_ENCR_SET_KEY; |
4002 | break; | 4003 | break; |
4003 | case WLAN_CIPHER_SUITE_TKIP: | 4004 | case WLAN_CIPHER_SUITE_TKIP: |
@@ -4071,7 +4072,6 @@ static int mwl8k_set_key(struct ieee80211_hw *hw, | |||
4071 | addr = sta->addr; | 4072 | addr = sta->addr; |
4072 | 4073 | ||
4073 | if (cmd_param == SET_KEY) { | 4074 | if (cmd_param == SET_KEY) { |
4074 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | ||
4075 | rc = mwl8k_cmd_encryption_set_key(hw, vif, addr, key); | 4075 | rc = mwl8k_cmd_encryption_set_key(hw, vif, addr, key); |
4076 | if (rc) | 4076 | if (rc) |
4077 | goto out; | 4077 | goto out; |
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 0494d7b102d4..1b753173680f 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
@@ -331,10 +331,9 @@ static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
331 | struct p54p_ring_control *ring_control = priv->ring_control; | 331 | struct p54p_ring_control *ring_control = priv->ring_control; |
332 | struct p54p_desc *desc; | 332 | struct p54p_desc *desc; |
333 | dma_addr_t mapping; | 333 | dma_addr_t mapping; |
334 | u32 device_idx, idx, i; | 334 | u32 idx, i; |
335 | 335 | ||
336 | spin_lock_irqsave(&priv->lock, flags); | 336 | spin_lock_irqsave(&priv->lock, flags); |
337 | device_idx = le32_to_cpu(ring_control->device_idx[1]); | ||
338 | idx = le32_to_cpu(ring_control->host_idx[1]); | 337 | idx = le32_to_cpu(ring_control->host_idx[1]); |
339 | i = idx % ARRAY_SIZE(ring_control->tx_data); | 338 | i = idx % ARRAY_SIZE(ring_control->tx_data); |
340 | 339 | ||
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index c45773108283..9def1e5369a1 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
@@ -93,7 +93,7 @@ config RT2800PCI_RT35XX | |||
93 | intended for testers and developers. | 93 | intended for testers and developers. |
94 | 94 | ||
95 | config RT2800PCI_RT53XX | 95 | config RT2800PCI_RT53XX |
96 | bool "rt2800-pci - Include support for rt53xx devices (EXPERIMENTAL)" | 96 | bool "rt2800pci - Include support for rt53xx devices (EXPERIMENTAL)" |
97 | depends on EXPERIMENTAL | 97 | depends on EXPERIMENTAL |
98 | default y | 98 | default y |
99 | ---help--- | 99 | ---help--- |
@@ -163,6 +163,15 @@ config RT2800USB_RT35XX | |||
163 | Support for these devices is non-functional at the moment and is | 163 | Support for these devices is non-functional at the moment and is |
164 | intended for testers and developers. | 164 | intended for testers and developers. |
165 | 165 | ||
166 | config RT2800USB_RT53XX | ||
167 | bool "rt2800usb - Include support for rt53xx devices (EXPERIMENTAL)" | ||
168 | depends on EXPERIMENTAL | ||
169 | default y | ||
170 | ---help--- | ||
171 | This adds support for rt53xx wireless chipset family to the | ||
172 | rt2800pci driver. | ||
173 | Supported chips: RT5370 | ||
174 | |||
166 | config RT2800USB_UNKNOWN | 175 | config RT2800USB_UNKNOWN |
167 | bool "rt2800usb - Include support for unknown (USB) devices" | 176 | bool "rt2800usb - Include support for unknown (USB) devices" |
168 | default n | 177 | default n |
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h index ce2010952886..f67bc9b31b28 100644 --- a/drivers/net/wireless/rt2x00/rt2800.h +++ b/drivers/net/wireless/rt2x00/rt2800.h | |||
@@ -51,6 +51,7 @@ | |||
51 | * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390) | 51 | * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390) |
52 | * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) | 52 | * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392) |
53 | * RF3853 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) | 53 | * RF3853 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662) |
54 | * RF5370 2.4G 1T1R | ||
54 | * RF5390 2.4G 1T1R | 55 | * RF5390 2.4G 1T1R |
55 | */ | 56 | */ |
56 | #define RF2820 0x0001 | 57 | #define RF2820 0x0001 |
@@ -66,6 +67,7 @@ | |||
66 | #define RF3320 0x000b | 67 | #define RF3320 0x000b |
67 | #define RF3322 0x000c | 68 | #define RF3322 0x000c |
68 | #define RF3853 0x000d | 69 | #define RF3853 0x000d |
70 | #define RF5370 0x5370 | ||
69 | #define RF5390 0x5390 | 71 | #define RF5390 0x5390 |
70 | 72 | ||
71 | /* | 73 | /* |
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 790afd3ed946..2a6aa85cc6c9 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c | |||
@@ -1751,7 +1751,8 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev, | |||
1751 | rt2x00_rf(rt2x00dev, RF3052) || | 1751 | rt2x00_rf(rt2x00dev, RF3052) || |
1752 | rt2x00_rf(rt2x00dev, RF3320)) | 1752 | rt2x00_rf(rt2x00dev, RF3320)) |
1753 | rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info); | 1753 | rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info); |
1754 | else if (rt2x00_rf(rt2x00dev, RF5390)) | 1754 | else if (rt2x00_rf(rt2x00dev, RF5370) || |
1755 | rt2x00_rf(rt2x00dev, RF5390)) | ||
1755 | rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info); | 1756 | rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info); |
1756 | else | 1757 | else |
1757 | rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); | 1758 | rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info); |
@@ -3686,6 +3687,7 @@ int rt2800_init_eeprom(struct rt2x00_dev *rt2x00dev) | |||
3686 | !rt2x00_rf(rt2x00dev, RF3022) && | 3687 | !rt2x00_rf(rt2x00dev, RF3022) && |
3687 | !rt2x00_rf(rt2x00dev, RF3052) && | 3688 | !rt2x00_rf(rt2x00dev, RF3052) && |
3688 | !rt2x00_rf(rt2x00dev, RF3320) && | 3689 | !rt2x00_rf(rt2x00dev, RF3320) && |
3690 | !rt2x00_rf(rt2x00dev, RF5370) && | ||
3689 | !rt2x00_rf(rt2x00dev, RF5390)) { | 3691 | !rt2x00_rf(rt2x00dev, RF5390)) { |
3690 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); | 3692 | ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); |
3691 | return -ENODEV; | 3693 | return -ENODEV; |
@@ -3988,6 +3990,7 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) | |||
3988 | rt2x00_rf(rt2x00dev, RF3021) || | 3990 | rt2x00_rf(rt2x00dev, RF3021) || |
3989 | rt2x00_rf(rt2x00dev, RF3022) || | 3991 | rt2x00_rf(rt2x00dev, RF3022) || |
3990 | rt2x00_rf(rt2x00dev, RF3320) || | 3992 | rt2x00_rf(rt2x00dev, RF3320) || |
3993 | rt2x00_rf(rt2x00dev, RF5370) || | ||
3991 | rt2x00_rf(rt2x00dev, RF5390)) { | 3994 | rt2x00_rf(rt2x00dev, RF5390)) { |
3992 | spec->num_channels = 14; | 3995 | spec->num_channels = 14; |
3993 | spec->channels = rf_vals_3x; | 3996 | spec->channels = rf_vals_3x; |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 0eb44cf2f44a..ba82c972703a 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -1000,6 +1000,14 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1000 | /* Zinwell */ | 1000 | /* Zinwell */ |
1001 | { USB_DEVICE(0x5a57, 0x0284) }, | 1001 | { USB_DEVICE(0x5a57, 0x0284) }, |
1002 | #endif | 1002 | #endif |
1003 | #ifdef CONFIG_RT2800USB_RT53XX | ||
1004 | /* Azurewave */ | ||
1005 | { USB_DEVICE(0x13d3, 0x3329) }, | ||
1006 | { USB_DEVICE(0x13d3, 0x3365) }, | ||
1007 | /* Ralink */ | ||
1008 | { USB_DEVICE(0x148f, 0x5370) }, | ||
1009 | { USB_DEVICE(0x148f, 0x5372) }, | ||
1010 | #endif | ||
1003 | #ifdef CONFIG_RT2800USB_UNKNOWN | 1011 | #ifdef CONFIG_RT2800USB_UNKNOWN |
1004 | /* | 1012 | /* |
1005 | * Unclear what kind of devices these are (they aren't supported by the | 1013 | * Unclear what kind of devices these are (they aren't supported by the |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 2eb5196977fd..c018d67aab8e 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -1159,9 +1159,9 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) | |||
1159 | /* | 1159 | /* |
1160 | * Stop all work. | 1160 | * Stop all work. |
1161 | */ | 1161 | */ |
1162 | del_timer_sync(&rt2x00dev->txstatus_timer); | ||
1163 | cancel_work_sync(&rt2x00dev->intf_work); | 1162 | cancel_work_sync(&rt2x00dev->intf_work); |
1164 | if (rt2x00_is_usb(rt2x00dev)) { | 1163 | if (rt2x00_is_usb(rt2x00dev)) { |
1164 | del_timer_sync(&rt2x00dev->txstatus_timer); | ||
1165 | cancel_work_sync(&rt2x00dev->rxdone_work); | 1165 | cancel_work_sync(&rt2x00dev->rxdone_work); |
1166 | cancel_work_sync(&rt2x00dev->txdone_work); | 1166 | cancel_work_sync(&rt2x00dev->txdone_work); |
1167 | } | 1167 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 39e1052123e3..8f90f6268077 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -298,7 +298,7 @@ static bool rt2x00usb_kick_tx_entry(struct queue_entry *entry, void* data) | |||
298 | 298 | ||
299 | if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) || | 299 | if (!test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags) || |
300 | test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) | 300 | test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) |
301 | return true; | 301 | return false; |
302 | 302 | ||
303 | /* | 303 | /* |
304 | * USB devices cannot blindly pass the skb->len as the | 304 | * USB devices cannot blindly pass the skb->len as the |
@@ -392,7 +392,7 @@ static bool rt2x00usb_kick_rx_entry(struct queue_entry *entry, void* data) | |||
392 | 392 | ||
393 | if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || | 393 | if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags) || |
394 | test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) | 394 | test_bit(ENTRY_DATA_STATUS_PENDING, &entry->flags)) |
395 | return true; | 395 | return false; |
396 | 396 | ||
397 | rt2x00lib_dmastart(entry); | 397 | rt2x00lib_dmastart(entry); |
398 | 398 | ||
@@ -447,7 +447,7 @@ static bool rt2x00usb_flush_entry(struct queue_entry *entry, void* data) | |||
447 | struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; | 447 | struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; |
448 | 448 | ||
449 | if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) | 449 | if (!test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) |
450 | return true; | 450 | return false; |
451 | 451 | ||
452 | usb_kill_urb(entry_priv->urb); | 452 | usb_kill_urb(entry_priv->urb); |
453 | 453 | ||
diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig index ce49e0ce7cad..5aee8b22d74e 100644 --- a/drivers/net/wireless/rtlwifi/Kconfig +++ b/drivers/net/wireless/rtlwifi/Kconfig | |||
@@ -10,6 +10,17 @@ config RTL8192CE | |||
10 | 10 | ||
11 | If you choose to build it as a module, it will be called rtl8192ce | 11 | If you choose to build it as a module, it will be called rtl8192ce |
12 | 12 | ||
13 | config RTL8192SE | ||
14 | tristate "Realtek RTL8192SE/RTL8191SE PCIe Wireless Network Adapter" | ||
15 | depends on MAC80211 && EXPERIMENTAL | ||
16 | select FW_LOADER | ||
17 | select RTLWIFI | ||
18 | ---help--- | ||
19 | This is the driver for Realtek RTL8192SE/RTL8191SE 802.11n PCIe | ||
20 | wireless network adapters. | ||
21 | |||
22 | If you choose to build it as a module, it will be called rtl8192se | ||
23 | |||
13 | config RTL8192CU | 24 | config RTL8192CU |
14 | tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter" | 25 | tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter" |
15 | depends on MAC80211 && USB && EXPERIMENTAL | 26 | depends on MAC80211 && USB && EXPERIMENTAL |
@@ -24,10 +35,10 @@ config RTL8192CU | |||
24 | 35 | ||
25 | config RTLWIFI | 36 | config RTLWIFI |
26 | tristate | 37 | tristate |
27 | depends on RTL8192CE || RTL8192CU | 38 | depends on RTL8192CE || RTL8192CU || RTL8192SE |
28 | default m | 39 | default m |
29 | 40 | ||
30 | config RTL8192C_COMMON | 41 | config RTL8192C_COMMON |
31 | tristate | 42 | tristate |
32 | depends on RTL8192CE || RTL8192CU | 43 | depends on RTL8192CE || RTL8192CU || RTL8192SE |
33 | default m | 44 | default m |
diff --git a/drivers/net/wireless/rtlwifi/Makefile b/drivers/net/wireless/rtlwifi/Makefile index ec9393f24799..7acce83c3785 100644 --- a/drivers/net/wireless/rtlwifi/Makefile +++ b/drivers/net/wireless/rtlwifi/Makefile | |||
@@ -22,5 +22,6 @@ endif | |||
22 | obj-$(CONFIG_RTL8192C_COMMON) += rtl8192c/ | 22 | obj-$(CONFIG_RTL8192C_COMMON) += rtl8192c/ |
23 | obj-$(CONFIG_RTL8192CE) += rtl8192ce/ | 23 | obj-$(CONFIG_RTL8192CE) += rtl8192ce/ |
24 | obj-$(CONFIG_RTL8192CU) += rtl8192cu/ | 24 | obj-$(CONFIG_RTL8192CU) += rtl8192cu/ |
25 | obj-$(CONFIG_RTL8192SE) += rtl8192se/ | ||
25 | 26 | ||
26 | ccflags-y += -D__CHECK_ENDIAN__ | 27 | ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/drivers/net/wireless/rtlwifi/efuse.c b/drivers/net/wireless/rtlwifi/efuse.c index 510d42edb8ca..50de6f5d8a56 100644 --- a/drivers/net/wireless/rtlwifi/efuse.c +++ b/drivers/net/wireless/rtlwifi/efuse.c | |||
@@ -235,7 +235,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) | |||
235 | { | 235 | { |
236 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 236 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
237 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | 237 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); |
238 | u8 efuse_tbl[HWSET_MAX_SIZE]; | 238 | u8 *efuse_tbl; |
239 | u8 rtemp8[1]; | 239 | u8 rtemp8[1]; |
240 | u16 efuse_addr = 0; | 240 | u16 efuse_addr = 0; |
241 | u8 offset, wren; | 241 | u8 offset, wren; |
@@ -245,7 +245,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) | |||
245 | rtlpriv->cfg->maps[EFUSE_MAX_SECTION_MAP]; | 245 | rtlpriv->cfg->maps[EFUSE_MAX_SECTION_MAP]; |
246 | const u32 efuse_len = | 246 | const u32 efuse_len = |
247 | rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; | 247 | rtlpriv->cfg->maps[EFUSE_REAL_CONTENT_SIZE]; |
248 | u16 efuse_word[EFUSE_MAX_SECTION][EFUSE_MAX_WORD_UNIT]; | 248 | u16 **efuse_word; |
249 | u16 efuse_utilized = 0; | 249 | u16 efuse_utilized = 0; |
250 | u8 efuse_usage; | 250 | u8 efuse_usage; |
251 | 251 | ||
@@ -256,9 +256,24 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) | |||
256 | return; | 256 | return; |
257 | } | 257 | } |
258 | 258 | ||
259 | /* allocate memory for efuse_tbl and efuse_word */ | ||
260 | efuse_tbl = kmalloc(rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE] * | ||
261 | sizeof(u8), GFP_ATOMIC); | ||
262 | if (!efuse_tbl) | ||
263 | return; | ||
264 | efuse_word = kmalloc(EFUSE_MAX_WORD_UNIT * sizeof(u16 *), GFP_ATOMIC); | ||
265 | if (!efuse_word) | ||
266 | goto done; | ||
267 | for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) { | ||
268 | efuse_word[i] = kmalloc(efuse_max_section * sizeof(u16), | ||
269 | GFP_ATOMIC); | ||
270 | if (!efuse_word[i]) | ||
271 | goto done; | ||
272 | } | ||
273 | |||
259 | for (i = 0; i < efuse_max_section; i++) | 274 | for (i = 0; i < efuse_max_section; i++) |
260 | for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) | 275 | for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) |
261 | efuse_word[i][j] = 0xFFFF; | 276 | efuse_word[j][i] = 0xFFFF; |
262 | 277 | ||
263 | read_efuse_byte(hw, efuse_addr, rtemp8); | 278 | read_efuse_byte(hw, efuse_addr, rtemp8); |
264 | if (*rtemp8 != 0xFF) { | 279 | if (*rtemp8 != 0xFF) { |
@@ -285,7 +300,8 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) | |||
285 | read_efuse_byte(hw, efuse_addr, rtemp8); | 300 | read_efuse_byte(hw, efuse_addr, rtemp8); |
286 | efuse_addr++; | 301 | efuse_addr++; |
287 | efuse_utilized++; | 302 | efuse_utilized++; |
288 | efuse_word[offset][i] = (*rtemp8 & 0xff); | 303 | efuse_word[i][offset] = |
304 | (*rtemp8 & 0xff); | ||
289 | 305 | ||
290 | if (efuse_addr >= efuse_len) | 306 | if (efuse_addr >= efuse_len) |
291 | break; | 307 | break; |
@@ -297,7 +313,7 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) | |||
297 | read_efuse_byte(hw, efuse_addr, rtemp8); | 313 | read_efuse_byte(hw, efuse_addr, rtemp8); |
298 | efuse_addr++; | 314 | efuse_addr++; |
299 | efuse_utilized++; | 315 | efuse_utilized++; |
300 | efuse_word[offset][i] |= | 316 | efuse_word[i][offset] |= |
301 | (((u16)*rtemp8 << 8) & 0xff00); | 317 | (((u16)*rtemp8 << 8) & 0xff00); |
302 | 318 | ||
303 | if (efuse_addr >= efuse_len) | 319 | if (efuse_addr >= efuse_len) |
@@ -320,9 +336,9 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) | |||
320 | for (i = 0; i < efuse_max_section; i++) { | 336 | for (i = 0; i < efuse_max_section; i++) { |
321 | for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { | 337 | for (j = 0; j < EFUSE_MAX_WORD_UNIT; j++) { |
322 | efuse_tbl[(i * 8) + (j * 2)] = | 338 | efuse_tbl[(i * 8) + (j * 2)] = |
323 | (efuse_word[i][j] & 0xff); | 339 | (efuse_word[j][i] & 0xff); |
324 | efuse_tbl[(i * 8) + ((j * 2) + 1)] = | 340 | efuse_tbl[(i * 8) + ((j * 2) + 1)] = |
325 | ((efuse_word[i][j] >> 8) & 0xff); | 341 | ((efuse_word[j][i] >> 8) & 0xff); |
326 | } | 342 | } |
327 | } | 343 | } |
328 | 344 | ||
@@ -336,6 +352,11 @@ void read_efuse(struct ieee80211_hw *hw, u16 _offset, u16 _size_byte, u8 *pbuf) | |||
336 | (u8 *)&efuse_utilized); | 352 | (u8 *)&efuse_utilized); |
337 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_USAGE, | 353 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_EFUSE_USAGE, |
338 | (u8 *)&efuse_usage); | 354 | (u8 *)&efuse_usage); |
355 | done: | ||
356 | for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) | ||
357 | kfree(efuse_word[i]); | ||
358 | kfree(efuse_word); | ||
359 | kfree(efuse_tbl); | ||
339 | } | 360 | } |
340 | 361 | ||
341 | bool efuse_shadow_update_chk(struct ieee80211_hw *hw) | 362 | bool efuse_shadow_update_chk(struct ieee80211_hw *hw) |
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 3550c9fb96e5..a40952845436 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
@@ -1611,6 +1611,7 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev, | |||
1611 | u16 irqline; | 1611 | u16 irqline; |
1612 | u8 tmp; | 1612 | u8 tmp; |
1613 | 1613 | ||
1614 | pcipriv->ndis_adapter.pcibridge_vendor = PCI_BRIDGE_VENDOR_UNKNOWN; | ||
1614 | venderid = pdev->vendor; | 1615 | venderid = pdev->vendor; |
1615 | deviceid = pdev->device; | 1616 | deviceid = pdev->device; |
1616 | pci_read_config_byte(pdev, 0x8, &revisionid); | 1617 | pci_read_config_byte(pdev, 0x8, &revisionid); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 79c98f62175f..3a92ba3c4a1e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | |||
@@ -372,7 +372,7 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
372 | __le16 fc; | 372 | __le16 fc; |
373 | struct ieee80211_hdr *hdr; | 373 | struct ieee80211_hdr *hdr; |
374 | 374 | ||
375 | memset(rx_status, 0, sizeof(rx_status)); | 375 | memset(rx_status, 0, sizeof(*rx_status)); |
376 | rxdesc = skb->data; | 376 | rxdesc = skb->data; |
377 | skb_len = skb->len; | 377 | skb_len = skb->len; |
378 | drvinfo_len = (GET_RX_DESC_DRVINFO_SIZE(rxdesc) * RTL_RX_DRV_INFO_UNIT); | 378 | drvinfo_len = (GET_RX_DESC_DRVINFO_SIZE(rxdesc) * RTL_RX_DRV_INFO_UNIT); |
@@ -434,7 +434,7 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
434 | "0x%02X\n", fc, (u32)hdr->addr1[0], (u32)hdr->addr1[1], | 434 | "0x%02X\n", fc, (u32)hdr->addr1[0], (u32)hdr->addr1[1], |
435 | (u32)hdr->addr1[2], (u32)hdr->addr1[3], (u32)hdr->addr1[4], | 435 | (u32)hdr->addr1[2], (u32)hdr->addr1[3], (u32)hdr->addr1[4], |
436 | (u32)hdr->addr1[5])); | 436 | (u32)hdr->addr1[5])); |
437 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); | 437 | memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status)); |
438 | ieee80211_rx_irqsafe(hw, skb); | 438 | ieee80211_rx_irqsafe(hw, skb); |
439 | } | 439 | } |
440 | 440 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/Makefile b/drivers/net/wireless/rtlwifi/rtl8192se/Makefile new file mode 100644 index 000000000000..b7eb13819cbc --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/Makefile | |||
@@ -0,0 +1,15 @@ | |||
1 | rtl8192se-objs := \ | ||
2 | dm.o \ | ||
3 | fw.o \ | ||
4 | hw.o \ | ||
5 | led.o \ | ||
6 | phy.o \ | ||
7 | rf.o \ | ||
8 | sw.o \ | ||
9 | table.o \ | ||
10 | trx.o | ||
11 | |||
12 | obj-$(CONFIG_RTL8192SE) += rtl8192se.o | ||
13 | |||
14 | ccflags-y += -D__CHECK_ENDIAN__ | ||
15 | |||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/rtlwifi/rtl8192se/def.h new file mode 100644 index 000000000000..69828f2b3fab --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/def.h | |||
@@ -0,0 +1,598 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | #ifndef __REALTEK_92S_DEF_H__ | ||
30 | #define __REALTEK_92S_DEF_H__ | ||
31 | |||
32 | #define RX_MPDU_QUEUE 0 | ||
33 | #define RX_CMD_QUEUE 1 | ||
34 | #define RX_MAX_QUEUE 2 | ||
35 | |||
36 | #define DESC92S_RATE1M 0x00 | ||
37 | #define DESC92S_RATE2M 0x01 | ||
38 | #define DESC92S_RATE5_5M 0x02 | ||
39 | #define DESC92S_RATE11M 0x03 | ||
40 | #define DESC92S_RATE6M 0x04 | ||
41 | #define DESC92S_RATE9M 0x05 | ||
42 | #define DESC92S_RATE12M 0x06 | ||
43 | #define DESC92S_RATE18M 0x07 | ||
44 | #define DESC92S_RATE24M 0x08 | ||
45 | #define DESC92S_RATE36M 0x09 | ||
46 | #define DESC92S_RATE48M 0x0a | ||
47 | #define DESC92S_RATE54M 0x0b | ||
48 | #define DESC92S_RATEMCS0 0x0c | ||
49 | #define DESC92S_RATEMCS1 0x0d | ||
50 | #define DESC92S_RATEMCS2 0x0e | ||
51 | #define DESC92S_RATEMCS3 0x0f | ||
52 | #define DESC92S_RATEMCS4 0x10 | ||
53 | #define DESC92S_RATEMCS5 0x11 | ||
54 | #define DESC92S_RATEMCS6 0x12 | ||
55 | #define DESC92S_RATEMCS7 0x13 | ||
56 | #define DESC92S_RATEMCS8 0x14 | ||
57 | #define DESC92S_RATEMCS9 0x15 | ||
58 | #define DESC92S_RATEMCS10 0x16 | ||
59 | #define DESC92S_RATEMCS11 0x17 | ||
60 | #define DESC92S_RATEMCS12 0x18 | ||
61 | #define DESC92S_RATEMCS13 0x19 | ||
62 | #define DESC92S_RATEMCS14 0x1a | ||
63 | #define DESC92S_RATEMCS15 0x1b | ||
64 | #define DESC92S_RATEMCS15_SG 0x1c | ||
65 | #define DESC92S_RATEMCS32 0x20 | ||
66 | |||
67 | #define SHORT_SLOT_TIME 9 | ||
68 | #define NON_SHORT_SLOT_TIME 20 | ||
69 | |||
70 | /* Rx smooth factor */ | ||
71 | #define RX_SMOOTH_FACTOR 20 | ||
72 | |||
73 | /* Queue Select Value in TxDesc */ | ||
74 | #define QSLT_BK 0x2 | ||
75 | #define QSLT_BE 0x0 | ||
76 | #define QSLT_VI 0x5 | ||
77 | #define QSLT_VO 0x6 | ||
78 | #define QSLT_BEACON 0x10 | ||
79 | #define QSLT_HIGH 0x11 | ||
80 | #define QSLT_MGNT 0x12 | ||
81 | #define QSLT_CMD 0x13 | ||
82 | |||
83 | #define PHY_RSSI_SLID_WIN_MAX 100 | ||
84 | #define PHY_LINKQUALITY_SLID_WIN_MAX 20 | ||
85 | #define PHY_BEACON_RSSI_SLID_WIN_MAX 10 | ||
86 | |||
87 | /* Tx Desc */ | ||
88 | #define TX_DESC_SIZE_RTL8192S (16 * 4) | ||
89 | #define TX_CMDDESC_SIZE_RTL8192S (16 * 4) | ||
90 | |||
91 | /* Define a macro that takes a le32 word, converts it to host ordering, | ||
92 | * right shifts by a specified count, creates a mask of the specified | ||
93 | * bit count, and extracts that number of bits. | ||
94 | */ | ||
95 | |||
96 | #define SHIFT_AND_MASK_LE(__pdesc, __shift, __mask) \ | ||
97 | ((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) & \ | ||
98 | BIT_LEN_MASK_32(__mask)) | ||
99 | |||
100 | /* Define a macro that clears a bit field in an le32 word and | ||
101 | * sets the specified value into that bit field. The resulting | ||
102 | * value remains in le32 ordering; however, it is properly converted | ||
103 | * to host ordering for the clear and set operations before conversion | ||
104 | * back to le32. | ||
105 | */ | ||
106 | |||
107 | #define SET_BITS_OFFSET_LE(__pdesc, __shift, __len, __val) \ | ||
108 | (*(__le32 *)(__pdesc) = \ | ||
109 | (cpu_to_le32((le32_to_cpu(*((__le32 *)(__pdesc))) & \ | ||
110 | (~(BIT_OFFSET_LEN_MASK_32((__shift), __len)))) | \ | ||
111 | (((u32)(__val) & BIT_LEN_MASK_32(__len)) << (__shift))))); | ||
112 | |||
113 | /* macros to read/write various fields in RX or TX descriptors */ | ||
114 | |||
115 | /* Dword 0 */ | ||
116 | #define SET_TX_DESC_PKT_SIZE(__pdesc, __val) \ | ||
117 | SET_BITS_OFFSET_LE(__pdesc, 0, 16, __val) | ||
118 | #define SET_TX_DESC_OFFSET(__pdesc, __val) \ | ||
119 | SET_BITS_OFFSET_LE(__pdesc, 16, 8, __val) | ||
120 | #define SET_TX_DESC_TYPE(__pdesc, __val) \ | ||
121 | SET_BITS_OFFSET_LE(__pdesc, 24, 2, __val) | ||
122 | #define SET_TX_DESC_LAST_SEG(__pdesc, __val) \ | ||
123 | SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val) | ||
124 | #define SET_TX_DESC_FIRST_SEG(__pdesc, __val) \ | ||
125 | SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val) | ||
126 | #define SET_TX_DESC_LINIP(__pdesc, __val) \ | ||
127 | SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val) | ||
128 | #define SET_TX_DESC_AMSDU(__pdesc, __val) \ | ||
129 | SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val) | ||
130 | #define SET_TX_DESC_GREEN_FIELD(__pdesc, __val) \ | ||
131 | SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) | ||
132 | #define SET_TX_DESC_OWN(__pdesc, __val) \ | ||
133 | SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) | ||
134 | |||
135 | #define GET_TX_DESC_OWN(__pdesc) \ | ||
136 | SHIFT_AND_MASK_LE(__pdesc, 31, 1) | ||
137 | |||
138 | /* Dword 1 */ | ||
139 | #define SET_TX_DESC_MACID(__pdesc, __val) \ | ||
140 | SET_BITS_OFFSET_LE(__pdesc + 4, 0, 5, __val) | ||
141 | #define SET_TX_DESC_MORE_DATA(__pdesc, __val) \ | ||
142 | SET_BITS_OFFSET_LE(__pdesc + 4, 5, 1, __val) | ||
143 | #define SET_TX_DESC_MORE_FRAG(__pdesc, __val) \ | ||
144 | SET_BITS_OFFSET_LE(__pdesc + 4, 6, 1, __val) | ||
145 | #define SET_TX_DESC_PIFS(__pdesc, __val) \ | ||
146 | SET_BITS_OFFSET_LE(__pdesc + 4, 7, 1, __val) | ||
147 | #define SET_TX_DESC_QUEUE_SEL(__pdesc, __val) \ | ||
148 | SET_BITS_OFFSET_LE(__pdesc + 4, 8, 5, __val) | ||
149 | #define SET_TX_DESC_ACK_POLICY(__pdesc, __val) \ | ||
150 | SET_BITS_OFFSET_LE(__pdesc + 4, 13, 2, __val) | ||
151 | #define SET_TX_DESC_NO_ACM(__pdesc, __val) \ | ||
152 | SET_BITS_OFFSET_LE(__pdesc + 4, 15, 1, __val) | ||
153 | #define SET_TX_DESC_NON_QOS(__pdesc, __val) \ | ||
154 | SET_BITS_OFFSET_LE(__pdesc + 4, 16, 1, __val) | ||
155 | #define SET_TX_DESC_KEY_ID(__pdesc, __val) \ | ||
156 | SET_BITS_OFFSET_LE(__pdesc + 4, 17, 2, __val) | ||
157 | #define SET_TX_DESC_OUI(__pdesc, __val) \ | ||
158 | SET_BITS_OFFSET_LE(__pdesc + 4, 19, 1, __val) | ||
159 | #define SET_TX_DESC_PKT_TYPE(__pdesc, __val) \ | ||
160 | SET_BITS_OFFSET_LE(__pdesc + 4, 20, 1, __val) | ||
161 | #define SET_TX_DESC_EN_DESC_ID(__pdesc, __val) \ | ||
162 | SET_BITS_OFFSET_LE(__pdesc + 4, 21, 1, __val) | ||
163 | #define SET_TX_DESC_SEC_TYPE(__pdesc, __val) \ | ||
164 | SET_BITS_OFFSET_LE(__pdesc + 4, 22, 2, __val) | ||
165 | #define SET_TX_DESC_WDS(__pdesc, __val) \ | ||
166 | SET_BITS_OFFSET_LE(__pdesc + 4, 24, 1, __val) | ||
167 | #define SET_TX_DESC_HTC(__pdesc, __val) \ | ||
168 | SET_BITS_OFFSET_LE(__pdesc + 4, 25, 1, __val) | ||
169 | #define SET_TX_DESC_PKT_OFFSET(__pdesc, __val) \ | ||
170 | SET_BITS_OFFSET_LE(__pdesc + 4, 26, 5, __val) | ||
171 | #define SET_TX_DESC_HWPC(__pdesc, __val) \ | ||
172 | SET_BITS_OFFSET_LE(__pdesc + 4, 27, 1, __val) | ||
173 | |||
174 | /* Dword 2 */ | ||
175 | #define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val) \ | ||
176 | SET_BITS_OFFSET_LE(__pdesc + 8, 0, 6, __val) | ||
177 | #define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val) \ | ||
178 | SET_BITS_OFFSET_LE(__pdesc + 8, 6, 1, __val) | ||
179 | #define SET_TX_DESC_TSFL(__pdesc, __val) \ | ||
180 | SET_BITS_OFFSET_LE(__pdesc + 8, 7, 5, __val) | ||
181 | #define SET_TX_DESC_RTS_RETRY_COUNT(__pdesc, __val) \ | ||
182 | SET_BITS_OFFSET_LE(__pdesc + 8, 12, 6, __val) | ||
183 | #define SET_TX_DESC_DATA_RETRY_COUNT(__pdesc, __val) \ | ||
184 | SET_BITS_OFFSET_LE(__pdesc + 8, 18, 6, __val) | ||
185 | #define SET_TX_DESC_RSVD_MACID(__pdesc, __val) \ | ||
186 | SET_BITS_OFFSET_LE(((__pdesc) + 8), 24, 5, __val) | ||
187 | #define SET_TX_DESC_AGG_ENABLE(__pdesc, __val) \ | ||
188 | SET_BITS_OFFSET_LE(__pdesc + 8, 29, 1, __val) | ||
189 | #define SET_TX_DESC_AGG_BREAK(__pdesc, __val) \ | ||
190 | SET_BITS_OFFSET_LE(__pdesc + 8, 30, 1, __val) | ||
191 | #define SET_TX_DESC_OWN_MAC(__pdesc, __val) \ | ||
192 | SET_BITS_OFFSET_LE(__pdesc + 8, 31, 1, __val) | ||
193 | |||
194 | /* Dword 3 */ | ||
195 | #define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val) \ | ||
196 | SET_BITS_OFFSET_LE(__pdesc + 12, 0, 8, __val) | ||
197 | #define SET_TX_DESC_TAIL_PAGE(__pdesc, __val) \ | ||
198 | SET_BITS_OFFSET_LE(__pdesc + 12, 8, 8, __val) | ||
199 | #define SET_TX_DESC_SEQ(__pdesc, __val) \ | ||
200 | SET_BITS_OFFSET_LE(__pdesc + 12, 16, 12, __val) | ||
201 | #define SET_TX_DESC_FRAG(__pdesc, __val) \ | ||
202 | SET_BITS_OFFSET_LE(__pdesc + 12, 28, 4, __val) | ||
203 | |||
204 | /* Dword 4 */ | ||
205 | #define SET_TX_DESC_RTS_RATE(__pdesc, __val) \ | ||
206 | SET_BITS_OFFSET_LE(__pdesc + 16, 0, 6, __val) | ||
207 | #define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val) \ | ||
208 | SET_BITS_OFFSET_LE(__pdesc + 16, 6, 1, __val) | ||
209 | #define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val) \ | ||
210 | SET_BITS_OFFSET_LE(__pdesc + 16, 7, 4, __val) | ||
211 | #define SET_TX_DESC_CTS_ENABLE(__pdesc, __val) \ | ||
212 | SET_BITS_OFFSET_LE(__pdesc + 16, 11, 1, __val) | ||
213 | #define SET_TX_DESC_RTS_ENABLE(__pdesc, __val) \ | ||
214 | SET_BITS_OFFSET_LE(__pdesc + 16, 12, 1, __val) | ||
215 | #define SET_TX_DESC_RA_BRSR_ID(__pdesc, __val) \ | ||
216 | SET_BITS_OFFSET_LE(__pdesc + 16, 13, 3, __val) | ||
217 | #define SET_TX_DESC_TXHT(__pdesc, __val) \ | ||
218 | SET_BITS_OFFSET_LE(__pdesc + 16, 16, 1, __val) | ||
219 | #define SET_TX_DESC_TX_SHORT(__pdesc, __val) \ | ||
220 | SET_BITS_OFFSET_LE(__pdesc + 16, 17, 1, __val) | ||
221 | #define SET_TX_DESC_TX_BANDWIDTH(__pdesc, __val) \ | ||
222 | SET_BITS_OFFSET_LE(__pdesc + 16, 18, 1, __val) | ||
223 | #define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val) \ | ||
224 | SET_BITS_OFFSET_LE(__pdesc + 16, 19, 2, __val) | ||
225 | #define SET_TX_DESC_TX_STBC(__pdesc, __val) \ | ||
226 | SET_BITS_OFFSET_LE(__pdesc + 16, 21, 2, __val) | ||
227 | #define SET_TX_DESC_TX_REVERSE_DIRECTION(__pdesc, __val) \ | ||
228 | SET_BITS_OFFSET_LE(__pdesc + 16, 23, 1, __val) | ||
229 | #define SET_TX_DESC_RTS_HT(__pdesc, __val) \ | ||
230 | SET_BITS_OFFSET_LE(__pdesc + 16, 24, 1, __val) | ||
231 | #define SET_TX_DESC_RTS_SHORT(__pdesc, __val) \ | ||
232 | SET_BITS_OFFSET_LE(__pdesc + 16, 25, 1, __val) | ||
233 | #define SET_TX_DESC_RTS_BANDWIDTH(__pdesc, __val) \ | ||
234 | SET_BITS_OFFSET_LE(__pdesc + 16, 26, 1, __val) | ||
235 | #define SET_TX_DESC_RTS_SUB_CARRIER(__pdesc, __val) \ | ||
236 | SET_BITS_OFFSET_LE(__pdesc + 16, 27, 2, __val) | ||
237 | #define SET_TX_DESC_RTS_STBC(__pdesc, __val) \ | ||
238 | SET_BITS_OFFSET_LE(__pdesc + 16, 29, 2, __val) | ||
239 | #define SET_TX_DESC_USER_RATE(__pdesc, __val) \ | ||
240 | SET_BITS_OFFSET_LE(__pdesc + 16, 31, 1, __val) | ||
241 | |||
242 | /* Dword 5 */ | ||
243 | #define SET_TX_DESC_PACKET_ID(__pdesc, __val) \ | ||
244 | SET_BITS_OFFSET_LE(__pdesc + 20, 0, 9, __val) | ||
245 | #define SET_TX_DESC_TX_RATE(__pdesc, __val) \ | ||
246 | SET_BITS_OFFSET_LE(__pdesc + 20, 9, 6, __val) | ||
247 | #define SET_TX_DESC_DISABLE_FB(__pdesc, __val) \ | ||
248 | SET_BITS_OFFSET_LE(__pdesc + 20, 15, 1, __val) | ||
249 | #define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val) \ | ||
250 | SET_BITS_OFFSET_LE(__pdesc + 20, 16, 5, __val) | ||
251 | #define SET_TX_DESC_TX_AGC(__pdesc, __val) \ | ||
252 | SET_BITS_OFFSET_LE(__pdesc + 20, 21, 11, __val) | ||
253 | |||
254 | /* Dword 6 */ | ||
255 | #define SET_TX_DESC_IP_CHECK_SUM(__pdesc, __val) \ | ||
256 | SET_BITS_OFFSET_LE(__pdesc + 24, 0, 16, __val) | ||
257 | #define SET_TX_DESC_TCP_CHECK_SUM(__pdesc, __val) \ | ||
258 | SET_BITS_OFFSET_LE(__pdesc + 24, 16, 16, __val) | ||
259 | |||
260 | /* Dword 7 */ | ||
261 | #define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val) \ | ||
262 | SET_BITS_OFFSET_LE(__pdesc + 28, 0, 16, __val) | ||
263 | #define SET_TX_DESC_IP_HEADER_OFFSET(__pdesc, __val) \ | ||
264 | SET_BITS_OFFSET_LE(__pdesc + 28, 16, 8, __val) | ||
265 | #define SET_TX_DESC_TCP_ENABLE(__pdesc, __val) \ | ||
266 | SET_BITS_OFFSET_LE(__pdesc + 28, 31, 1, __val) | ||
267 | |||
268 | /* Dword 8 */ | ||
269 | #define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val) \ | ||
270 | SET_BITS_OFFSET_LE(__pdesc + 32, 0, 32, __val) | ||
271 | #define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc) \ | ||
272 | SHIFT_AND_MASK_LE(__pdesc + 32, 0, 32) | ||
273 | |||
274 | /* Dword 9 */ | ||
275 | #define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val) \ | ||
276 | SET_BITS_OFFSET_LE(__pdesc + 36, 0, 32, __val) | ||
277 | |||
278 | /* Because the PCI Tx descriptors are chaied at the | ||
279 | * initialization and all the NextDescAddresses in | ||
280 | * these descriptors cannot not be cleared (,or | ||
281 | * driver/HW cannot find the next descriptor), the | ||
282 | * offset 36 (NextDescAddresses) is reserved when | ||
283 | * the desc is cleared. */ | ||
284 | #define TX_DESC_NEXT_DESC_OFFSET 36 | ||
285 | #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size) \ | ||
286 | do { \ | ||
287 | if (_size > TX_DESC_NEXT_DESC_OFFSET) \ | ||
288 | memset(__pdesc, 0, TX_DESC_NEXT_DESC_OFFSET); \ | ||
289 | else \ | ||
290 | memset(__pdesc, 0, _size); \ | ||
291 | } while (0); | ||
292 | |||
293 | /* Rx Desc */ | ||
294 | #define RX_STATUS_DESC_SIZE 24 | ||
295 | #define RX_DRV_INFO_SIZE_UNIT 8 | ||
296 | |||
297 | /* DWORD 0 */ | ||
298 | #define SET_RX_STATUS_DESC_PKT_LEN(__pdesc, __val) \ | ||
299 | SET_BITS_OFFSET_LE(__pdesc, 0, 14, __val) | ||
300 | #define SET_RX_STATUS_DESC_CRC32(__pdesc, __val) \ | ||
301 | SET_BITS_OFFSET_LE(__pdesc, 14, 1, __val) | ||
302 | #define SET_RX_STATUS_DESC_ICV(__pdesc, __val) \ | ||
303 | SET_BITS_OFFSET_LE(__pdesc, 15, 1, __val) | ||
304 | #define SET_RX_STATUS_DESC_DRVINFO_SIZE(__pdesc, __val) \ | ||
305 | SET_BITS_OFFSET_LE(__pdesc, 16, 4, __val) | ||
306 | #define SET_RX_STATUS_DESC_SECURITY(__pdesc, __val) \ | ||
307 | SET_BITS_OFFSET_LE(__pdesc, 20, 3, __val) | ||
308 | #define SET_RX_STATUS_DESC_QOS(__pdesc, __val) \ | ||
309 | SET_BITS_OFFSET_LE(__pdesc, 23, 1, __val) | ||
310 | #define SET_RX_STATUS_DESC_SHIFT(__pdesc, __val) \ | ||
311 | SET_BITS_OFFSET_LE(__pdesc, 24, 2, __val) | ||
312 | #define SET_RX_STATUS_DESC_PHY_STATUS(__pdesc, __val) \ | ||
313 | SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val) | ||
314 | #define SET_RX_STATUS_DESC_SWDEC(__pdesc, __val) \ | ||
315 | SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val) | ||
316 | #define SET_RX_STATUS_DESC_LAST_SEG(__pdesc, __val) \ | ||
317 | SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val) | ||
318 | #define SET_RX_STATUS_DESC_FIRST_SEG(__pdesc, __val) \ | ||
319 | SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val) | ||
320 | #define SET_RX_STATUS_DESC_EOR(__pdesc, __val) \ | ||
321 | SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val) | ||
322 | #define SET_RX_STATUS_DESC_OWN(__pdesc, __val) \ | ||
323 | SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val) | ||
324 | |||
325 | #define GET_RX_STATUS_DESC_PKT_LEN(__pdesc) \ | ||
326 | SHIFT_AND_MASK_LE(__pdesc, 0, 14) | ||
327 | #define GET_RX_STATUS_DESC_CRC32(__pdesc) \ | ||
328 | SHIFT_AND_MASK_LE(__pdesc, 14, 1) | ||
329 | #define GET_RX_STATUS_DESC_ICV(__pdesc) \ | ||
330 | SHIFT_AND_MASK_LE(__pdesc, 15, 1) | ||
331 | #define GET_RX_STATUS_DESC_DRVINFO_SIZE(__pdesc) \ | ||
332 | SHIFT_AND_MASK_LE(__pdesc, 16, 4) | ||
333 | #define GET_RX_STATUS_DESC_SECURITY(__pdesc) \ | ||
334 | SHIFT_AND_MASK_LE(__pdesc, 20, 3) | ||
335 | #define GET_RX_STATUS_DESC_QOS(__pdesc) \ | ||
336 | SHIFT_AND_MASK_LE(__pdesc, 23, 1) | ||
337 | #define GET_RX_STATUS_DESC_SHIFT(__pdesc) \ | ||
338 | SHIFT_AND_MASK_LE(__pdesc, 24, 2) | ||
339 | #define GET_RX_STATUS_DESC_PHY_STATUS(__pdesc) \ | ||
340 | SHIFT_AND_MASK_LE(__pdesc, 26, 1) | ||
341 | #define GET_RX_STATUS_DESC_SWDEC(__pdesc) \ | ||
342 | SHIFT_AND_MASK_LE(__pdesc, 27, 1) | ||
343 | #define GET_RX_STATUS_DESC_LAST_SEG(__pdesc) \ | ||
344 | SHIFT_AND_MASK_LE(__pdesc, 28, 1) | ||
345 | #define GET_RX_STATUS_DESC_FIRST_SEG(__pdesc) \ | ||
346 | SHIFT_AND_MASK_LE(__pdesc, 29, 1) | ||
347 | #define GET_RX_STATUS_DESC_EOR(__pdesc) \ | ||
348 | SHIFT_AND_MASK_LE(__pdesc, 30, 1) | ||
349 | #define GET_RX_STATUS_DESC_OWN(__pdesc) \ | ||
350 | SHIFT_AND_MASK_LE(__pdesc, 31, 1) | ||
351 | |||
352 | /* DWORD 1 */ | ||
353 | #define SET_RX_STATUS_DESC_MACID(__pdesc, __val) \ | ||
354 | SET_BITS_OFFSET_LE(__pdesc + 4, 0, 5, __val) | ||
355 | #define SET_RX_STATUS_DESC_TID(__pdesc, __val) \ | ||
356 | SET_BITS_OFFSET_LE(__pdesc + 4, 5, 4, __val) | ||
357 | #define SET_RX_STATUS_DESC_PAGGR(__pdesc, __val) \ | ||
358 | SET_BITS_OFFSET_LE(__pdesc + 4, 14, 1, __val) | ||
359 | #define SET_RX_STATUS_DESC_FAGGR(__pdesc, __val) \ | ||
360 | SET_BITS_OFFSET_LE(__pdesc + 4, 15, 1, __val) | ||
361 | #define SET_RX_STATUS_DESC_A1_FIT(__pdesc, __val) \ | ||
362 | SET_BITS_OFFSET_LE(__pdesc + 4, 16, 4, __val) | ||
363 | #define SET_RX_STATUS_DESC_A2_FIT(__pdesc, __val) \ | ||
364 | SET_BITS_OFFSET_LE(__pdesc + 4, 20, 4, __val) | ||
365 | #define SET_RX_STATUS_DESC_PAM(__pdesc, __val) \ | ||
366 | SET_BITS_OFFSET_LE(__pdesc + 4, 24, 1, __val) | ||
367 | #define SET_RX_STATUS_DESC_PWR(__pdesc, __val) \ | ||
368 | SET_BITS_OFFSET_LE(__pdesc + 4, 25, 1, __val) | ||
369 | #define SET_RX_STATUS_DESC_MOREDATA(__pdesc, __val) \ | ||
370 | SET_BITS_OFFSET_LE(__pdesc + 4, 26, 1, __val) | ||
371 | #define SET_RX_STATUS_DESC_MOREFRAG(__pdesc, __val) \ | ||
372 | SET_BITS_OFFSET_LE(__pdesc + 4, 27, 1, __val) | ||
373 | #define SET_RX_STATUS_DESC_TYPE(__pdesc, __val) \ | ||
374 | SET_BITS_OFFSET_LE(__pdesc + 4, 28, 2, __val) | ||
375 | #define SET_RX_STATUS_DESC_MC(__pdesc, __val) \ | ||
376 | SET_BITS_OFFSET_LE(__pdesc + 4, 30, 1, __val) | ||
377 | #define SET_RX_STATUS_DESC_BC(__pdesc, __val) \ | ||
378 | SET_BITS_OFFSET_LE(__pdesc + 4, 31, 1, __val) | ||
379 | |||
380 | #define GET_RX_STATUS_DEC_MACID(__pdesc) \ | ||
381 | SHIFT_AND_MASK_LE(__pdesc + 4, 0, 5) | ||
382 | #define GET_RX_STATUS_DESC_TID(__pdesc) \ | ||
383 | SHIFT_AND_MASK_LE(__pdesc + 4, 5, 4) | ||
384 | #define GET_RX_STATUS_DESC_PAGGR(__pdesc) \ | ||
385 | SHIFT_AND_MASK_LE(__pdesc + 4, 14, 1) | ||
386 | #define GET_RX_STATUS_DESC_FAGGR(__pdesc) \ | ||
387 | SHIFT_AND_MASK_LE(__pdesc + 4, 15, 1) | ||
388 | #define GET_RX_STATUS_DESC_A1_FIT(__pdesc) \ | ||
389 | SHIFT_AND_MASK_LE(__pdesc + 4, 16, 4) | ||
390 | #define GET_RX_STATUS_DESC_A2_FIT(__pdesc) \ | ||
391 | SHIFT_AND_MASK_LE(__pdesc + 4, 20, 4) | ||
392 | #define GET_RX_STATUS_DESC_PAM(__pdesc) \ | ||
393 | SHIFT_AND_MASK_LE(__pdesc + 4, 24, 1) | ||
394 | #define GET_RX_STATUS_DESC_PWR(__pdesc) \ | ||
395 | SHIFT_AND_MASK_LE(__pdesc + 4, 25, 1) | ||
396 | #define GET_RX_STATUS_DESC_MORE_DATA(__pdesc) \ | ||
397 | SHIFT_AND_MASK_LE(__pdesc + 4, 26, 1) | ||
398 | #define GET_RX_STATUS_DESC_MORE_FRAG(__pdesc) \ | ||
399 | SHIFT_AND_MASK_LE(__pdesc + 4, 27, 1) | ||
400 | #define GET_RX_STATUS_DESC_TYPE(__pdesc) \ | ||
401 | SHIFT_AND_MASK_LE(__pdesc + 4, 28, 2) | ||
402 | #define GET_RX_STATUS_DESC_MC(__pdesc) \ | ||
403 | SHIFT_AND_MASK_LE(__pdesc + 4, 30, 1) | ||
404 | #define GET_RX_STATUS_DESC_BC(__pdesc) \ | ||
405 | SHIFT_AND_MASK_LE(__pdesc + 4, 31, 1) | ||
406 | |||
407 | /* DWORD 2 */ | ||
408 | #define SET_RX_STATUS_DESC_SEQ(__pdesc, __val) \ | ||
409 | SET_BITS_OFFSET_LE(__pdesc + 8, 0, 12, __val) | ||
410 | #define SET_RX_STATUS_DESC_FRAG(__pdesc, __val) \ | ||
411 | SET_BITS_OFFSET_LE(__pdesc + 8, 12, 4, __val) | ||
412 | #define SET_RX_STATUS_DESC_NEXT_PKTLEN(__pdesc, __val) \ | ||
413 | SET_BITS_OFFSET_LE(__pdesc + 8, 16, 8, __val) | ||
414 | #define SET_RX_STATUS_DESC_NEXT_IND(__pdesc, __val) \ | ||
415 | SET_BITS_OFFSET_LE(__pdesc + 8, 30, 1, __val) | ||
416 | |||
417 | #define GET_RX_STATUS_DESC_SEQ(__pdesc) \ | ||
418 | SHIFT_AND_MASK_LE(__pdesc + 8, 0, 12) | ||
419 | #define GET_RX_STATUS_DESC_FRAG(__pdesc) \ | ||
420 | SHIFT_AND_MASK_LE(__pdesc + 8, 12, 4) | ||
421 | #define GET_RX_STATUS_DESC_NEXT_PKTLEN(__pdesc) \ | ||
422 | SHIFT_AND_MASK_LE(__pdesc + 8, 16, 8) | ||
423 | #define GET_RX_STATUS_DESC_NEXT_IND(__pdesc) \ | ||
424 | SHIFT_AND_MASK_LE(__pdesc + 8, 30, 1) | ||
425 | |||
426 | /* DWORD 3 */ | ||
427 | #define SET_RX_STATUS_DESC_RX_MCS(__pdesc, __val) \ | ||
428 | SET_BITS_OFFSET_LE(__pdesc + 12, 0, 6, __val) | ||
429 | #define SET_RX_STATUS_DESC_RX_HT(__pdesc, __val) \ | ||
430 | SET_BITS_OFFSET_LE(__pdesc + 12, 6, 1, __val) | ||
431 | #define SET_RX_STATUS_DESC_AMSDU(__pdesc, __val) \ | ||
432 | SET_BITS_OFFSET_LE(__pdesc + 12, 7, 1, __val) | ||
433 | #define SET_RX_STATUS_DESC_SPLCP(__pdesc, __val) \ | ||
434 | SET_BITS_OFFSET_LE(__pdesc + 12, 8, 1, __val) | ||
435 | #define SET_RX_STATUS_DESC_BW(__pdesc, __val) \ | ||
436 | SET_BITS_OFFSET_LE(__pdesc + 12, 9, 1, __val) | ||
437 | #define SET_RX_STATUS_DESC_HTC(__pdesc, __val) \ | ||
438 | SET_BITS_OFFSET_LE(__pdesc + 12, 10, 1, __val) | ||
439 | #define SET_RX_STATUS_DESC_TCP_CHK_RPT(__pdesc, __val) \ | ||
440 | SET_BITS_OFFSET_LE(__pdesc + 12, 11, 1, __val) | ||
441 | #define SET_RX_STATUS_DESC_IP_CHK_RPT(__pdesc, __val) \ | ||
442 | SET_BITS_OFFSET_LE(__pdesc + 12, 12, 1, __val) | ||
443 | #define SET_RX_STATUS_DESC_TCP_CHK_VALID(__pdesc, __val) \ | ||
444 | SET_BITS_OFFSET_LE(__pdesc + 12, 13, 1, __val) | ||
445 | #define SET_RX_STATUS_DESC_HWPC_ERR(__pdesc, __val) \ | ||
446 | SET_BITS_OFFSET_LE(__pdesc + 12, 14, 1, __val) | ||
447 | #define SET_RX_STATUS_DESC_HWPC_IND(__pdesc, __val) \ | ||
448 | SET_BITS_OFFSET_LE(__pdesc + 12, 15, 1, __val) | ||
449 | #define SET_RX_STATUS_DESC_IV0(__pdesc, __val) \ | ||
450 | SET_BITS_OFFSET_LE(__pdesc + 12, 16, 16, __val) | ||
451 | |||
452 | #define GET_RX_STATUS_DESC_RX_MCS(__pdesc) \ | ||
453 | SHIFT_AND_MASK_LE(__pdesc + 12, 0, 6) | ||
454 | #define GET_RX_STATUS_DESC_RX_HT(__pdesc) \ | ||
455 | SHIFT_AND_MASK_LE(__pdesc + 12, 6, 1) | ||
456 | #define GET_RX_STATUS_DESC_AMSDU(__pdesc) \ | ||
457 | SHIFT_AND_MASK_LE(__pdesc + 12, 7, 1) | ||
458 | #define GET_RX_STATUS_DESC_SPLCP(__pdesc) \ | ||
459 | SHIFT_AND_MASK_LE(__pdesc + 12, 8, 1) | ||
460 | #define GET_RX_STATUS_DESC_BW(__pdesc) \ | ||
461 | SHIFT_AND_MASK_LE(__pdesc + 12, 9, 1) | ||
462 | #define GET_RX_STATUS_DESC_HTC(__pdesc) \ | ||
463 | SHIFT_AND_MASK_LE(__pdesc + 12, 10, 1) | ||
464 | #define GET_RX_STATUS_DESC_TCP_CHK_RPT(__pdesc) \ | ||
465 | SHIFT_AND_MASK_LE(__pdesc + 12, 11, 1) | ||
466 | #define GET_RX_STATUS_DESC_IP_CHK_RPT(__pdesc) \ | ||
467 | SHIFT_AND_MASK_LE(__pdesc + 12, 12, 1) | ||
468 | #define GET_RX_STATUS_DESC_TCP_CHK_VALID(__pdesc) \ | ||
469 | SHIFT_AND_MASK_LE(__pdesc + 12, 13, 1) | ||
470 | #define GET_RX_STATUS_DESC_HWPC_ERR(__pdesc) \ | ||
471 | SHIFT_AND_MASK_LE(__pdesc + 12, 14, 1) | ||
472 | #define GET_RX_STATUS_DESC_HWPC_IND(__pdesc) \ | ||
473 | SHIFT_AND_MASK_LE(__pdesc + 12, 15, 1) | ||
474 | #define GET_RX_STATUS_DESC_IV0(__pdesc) \ | ||
475 | SHIFT_AND_MASK_LE(__pdesc + 12, 16, 16) | ||
476 | |||
477 | /* DWORD 4 */ | ||
478 | #define SET_RX_STATUS_DESC_IV1(__pdesc, __val) \ | ||
479 | SET_BITS_OFFSET_LE(__pdesc + 16, 0, 32, __val) | ||
480 | #define GET_RX_STATUS_DESC_IV1(__pdesc) \ | ||
481 | SHIFT_AND_MASK_LE(__pdesc + 16, 0, 32) | ||
482 | |||
483 | /* DWORD 5 */ | ||
484 | #define SET_RX_STATUS_DESC_TSFL(__pdesc, __val) \ | ||
485 | SET_BITS_OFFSET_LE(__pdesc + 20, 0, 32, __val) | ||
486 | #define GET_RX_STATUS_DESC_TSFL(__pdesc) \ | ||
487 | SHIFT_AND_MASK_LE(__pdesc + 20, 0, 32) | ||
488 | |||
489 | /* DWORD 6 */ | ||
490 | #define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val) \ | ||
491 | SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val) | ||
492 | |||
493 | #define RX_HAL_IS_CCK_RATE(_pdesc)\ | ||
494 | (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE1M || \ | ||
495 | GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE2M || \ | ||
496 | GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE5_5M ||\ | ||
497 | GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92S_RATE11M) | ||
498 | |||
499 | enum rf_optype { | ||
500 | RF_OP_BY_SW_3WIRE = 0, | ||
501 | RF_OP_BY_FW, | ||
502 | RF_OP_MAX | ||
503 | }; | ||
504 | |||
505 | enum ic_inferiority { | ||
506 | IC_INFERIORITY_A = 0, | ||
507 | IC_INFERIORITY_B = 1, | ||
508 | }; | ||
509 | |||
510 | enum fwcmd_iotype { | ||
511 | /* For DIG DM */ | ||
512 | FW_CMD_DIG_ENABLE = 0, | ||
513 | FW_CMD_DIG_DISABLE = 1, | ||
514 | FW_CMD_DIG_HALT = 2, | ||
515 | FW_CMD_DIG_RESUME = 3, | ||
516 | /* For High Power DM */ | ||
517 | FW_CMD_HIGH_PWR_ENABLE = 4, | ||
518 | FW_CMD_HIGH_PWR_DISABLE = 5, | ||
519 | /* For Rate adaptive DM */ | ||
520 | FW_CMD_RA_RESET = 6, | ||
521 | FW_CMD_RA_ACTIVE = 7, | ||
522 | FW_CMD_RA_REFRESH_N = 8, | ||
523 | FW_CMD_RA_REFRESH_BG = 9, | ||
524 | FW_CMD_RA_INIT = 10, | ||
525 | /* For FW supported IQK */ | ||
526 | FW_CMD_IQK_INIT = 11, | ||
527 | /* Tx power tracking switch, | ||
528 | * MP driver only */ | ||
529 | FW_CMD_TXPWR_TRACK_ENABLE = 12, | ||
530 | /* Tx power tracking switch, | ||
531 | * MP driver only */ | ||
532 | FW_CMD_TXPWR_TRACK_DISABLE = 13, | ||
533 | /* Tx power tracking with thermal | ||
534 | * indication, for Normal driver */ | ||
535 | FW_CMD_TXPWR_TRACK_THERMAL = 14, | ||
536 | FW_CMD_PAUSE_DM_BY_SCAN = 15, | ||
537 | FW_CMD_RESUME_DM_BY_SCAN = 16, | ||
538 | FW_CMD_RA_REFRESH_N_COMB = 17, | ||
539 | FW_CMD_RA_REFRESH_BG_COMB = 18, | ||
540 | FW_CMD_ANTENNA_SW_ENABLE = 19, | ||
541 | FW_CMD_ANTENNA_SW_DISABLE = 20, | ||
542 | /* Tx Status report for CCX from FW */ | ||
543 | FW_CMD_TX_FEEDBACK_CCX_ENABLE = 21, | ||
544 | /* Indifate firmware that driver | ||
545 | * enters LPS, For PS-Poll issue */ | ||
546 | FW_CMD_LPS_ENTER = 22, | ||
547 | /* Indicate firmware that driver | ||
548 | * leave LPS*/ | ||
549 | FW_CMD_LPS_LEAVE = 23, | ||
550 | /* Set DIG mode to signal strength */ | ||
551 | FW_CMD_DIG_MODE_SS = 24, | ||
552 | /* Set DIG mode to false alarm. */ | ||
553 | FW_CMD_DIG_MODE_FA = 25, | ||
554 | FW_CMD_ADD_A2_ENTRY = 26, | ||
555 | FW_CMD_CTRL_DM_BY_DRIVER = 27, | ||
556 | FW_CMD_CTRL_DM_BY_DRIVER_NEW = 28, | ||
557 | FW_CMD_PAPE_CONTROL = 29, | ||
558 | FW_CMD_IQK_ENABLE = 30, | ||
559 | }; | ||
560 | |||
561 | /* | ||
562 | * Driver info contain PHY status | ||
563 | * and other variabel size info | ||
564 | * PHY Status content as below | ||
565 | */ | ||
566 | struct rx_fwinfo { | ||
567 | /* DWORD 0 */ | ||
568 | u8 gain_trsw[4]; | ||
569 | /* DWORD 1 */ | ||
570 | u8 pwdb_all; | ||
571 | u8 cfosho[4]; | ||
572 | /* DWORD 2 */ | ||
573 | u8 cfotail[4]; | ||
574 | /* DWORD 3 */ | ||
575 | s8 rxevm[2]; | ||
576 | s8 rxsnr[4]; | ||
577 | /* DWORD 4 */ | ||
578 | u8 pdsnr[2]; | ||
579 | /* DWORD 5 */ | ||
580 | u8 csi_current[2]; | ||
581 | u8 csi_target[2]; | ||
582 | /* DWORD 6 */ | ||
583 | u8 sigevm; | ||
584 | u8 max_ex_pwr; | ||
585 | u8 ex_intf_flag:1; | ||
586 | u8 sgi_en:1; | ||
587 | u8 rxsc:2; | ||
588 | u8 reserve:4; | ||
589 | }; | ||
590 | |||
591 | struct phy_sts_cck_8192s_t { | ||
592 | u8 adc_pwdb_x[4]; | ||
593 | u8 sq_rpt; | ||
594 | u8 cck_agc_rpt; | ||
595 | }; | ||
596 | |||
597 | #endif | ||
598 | |||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.c b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c new file mode 100644 index 000000000000..da86db86fa4a --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/dm.c | |||
@@ -0,0 +1,733 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../base.h" | ||
32 | #include "reg.h" | ||
33 | #include "def.h" | ||
34 | #include "phy.h" | ||
35 | #include "dm.h" | ||
36 | #include "fw.h" | ||
37 | |||
38 | struct dig_t digtable; | ||
39 | static const u32 edca_setting_dl[PEER_MAX] = { | ||
40 | 0xa44f, /* 0 UNKNOWN */ | ||
41 | 0x5ea44f, /* 1 REALTEK_90 */ | ||
42 | 0x5ea44f, /* 2 REALTEK_92SE */ | ||
43 | 0xa630, /* 3 BROAD */ | ||
44 | 0xa44f, /* 4 RAL */ | ||
45 | 0xa630, /* 5 ATH */ | ||
46 | 0xa630, /* 6 CISCO */ | ||
47 | 0xa42b, /* 7 MARV */ | ||
48 | }; | ||
49 | |||
50 | static const u32 edca_setting_dl_gmode[PEER_MAX] = { | ||
51 | 0x4322, /* 0 UNKNOWN */ | ||
52 | 0xa44f, /* 1 REALTEK_90 */ | ||
53 | 0x5ea44f, /* 2 REALTEK_92SE */ | ||
54 | 0xa42b, /* 3 BROAD */ | ||
55 | 0x5e4322, /* 4 RAL */ | ||
56 | 0x4322, /* 5 ATH */ | ||
57 | 0xa430, /* 6 CISCO */ | ||
58 | 0x5ea44f, /* 7 MARV */ | ||
59 | }; | ||
60 | |||
61 | static const u32 edca_setting_ul[PEER_MAX] = { | ||
62 | 0x5e4322, /* 0 UNKNOWN */ | ||
63 | 0xa44f, /* 1 REALTEK_90 */ | ||
64 | 0x5ea44f, /* 2 REALTEK_92SE */ | ||
65 | 0x5ea322, /* 3 BROAD */ | ||
66 | 0x5ea422, /* 4 RAL */ | ||
67 | 0x5ea322, /* 5 ATH */ | ||
68 | 0x3ea44f, /* 6 CISCO */ | ||
69 | 0x5ea44f, /* 7 MARV */ | ||
70 | }; | ||
71 | |||
72 | static void _rtl92s_dm_check_edca_turbo(struct ieee80211_hw *hw) | ||
73 | { | ||
74 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
75 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
76 | |||
77 | static u64 last_txok_cnt; | ||
78 | static u64 last_rxok_cnt; | ||
79 | u64 cur_txok_cnt = 0; | ||
80 | u64 cur_rxok_cnt = 0; | ||
81 | |||
82 | u32 edca_be_ul = edca_setting_ul[mac->vendor]; | ||
83 | u32 edca_be_dl = edca_setting_dl[mac->vendor]; | ||
84 | u32 edca_gmode = edca_setting_dl_gmode[mac->vendor]; | ||
85 | |||
86 | if (mac->link_state != MAC80211_LINKED) { | ||
87 | rtlpriv->dm.current_turbo_edca = false; | ||
88 | goto dm_checkedcaturbo_exit; | ||
89 | } | ||
90 | |||
91 | if ((!rtlpriv->dm.is_any_nonbepkts) && | ||
92 | (!rtlpriv->dm.disable_framebursting)) { | ||
93 | cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt; | ||
94 | cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt; | ||
95 | |||
96 | if (rtlpriv->phy.rf_type == RF_1T2R) { | ||
97 | if (cur_txok_cnt > 4 * cur_rxok_cnt) { | ||
98 | /* Uplink TP is present. */ | ||
99 | if (rtlpriv->dm.is_cur_rdlstate || | ||
100 | !rtlpriv->dm.current_turbo_edca) { | ||
101 | rtl_write_dword(rtlpriv, EDCAPARA_BE, | ||
102 | edca_be_ul); | ||
103 | rtlpriv->dm.is_cur_rdlstate = false; | ||
104 | } | ||
105 | } else {/* Balance TP is present. */ | ||
106 | if (!rtlpriv->dm.is_cur_rdlstate || | ||
107 | !rtlpriv->dm.current_turbo_edca) { | ||
108 | if (mac->mode == WIRELESS_MODE_G || | ||
109 | mac->mode == WIRELESS_MODE_B) | ||
110 | rtl_write_dword(rtlpriv, | ||
111 | EDCAPARA_BE, | ||
112 | edca_gmode); | ||
113 | else | ||
114 | rtl_write_dword(rtlpriv, | ||
115 | EDCAPARA_BE, | ||
116 | edca_be_dl); | ||
117 | rtlpriv->dm.is_cur_rdlstate = true; | ||
118 | } | ||
119 | } | ||
120 | rtlpriv->dm.current_turbo_edca = true; | ||
121 | } else { | ||
122 | if (cur_rxok_cnt > 4 * cur_txok_cnt) { | ||
123 | if (!rtlpriv->dm.is_cur_rdlstate || | ||
124 | !rtlpriv->dm.current_turbo_edca) { | ||
125 | if (mac->mode == WIRELESS_MODE_G || | ||
126 | mac->mode == WIRELESS_MODE_B) | ||
127 | rtl_write_dword(rtlpriv, | ||
128 | EDCAPARA_BE, | ||
129 | edca_gmode); | ||
130 | else | ||
131 | rtl_write_dword(rtlpriv, | ||
132 | EDCAPARA_BE, | ||
133 | edca_be_dl); | ||
134 | rtlpriv->dm.is_cur_rdlstate = true; | ||
135 | } | ||
136 | } else { | ||
137 | if (rtlpriv->dm.is_cur_rdlstate || | ||
138 | !rtlpriv->dm.current_turbo_edca) { | ||
139 | rtl_write_dword(rtlpriv, EDCAPARA_BE, | ||
140 | edca_be_ul); | ||
141 | rtlpriv->dm.is_cur_rdlstate = false; | ||
142 | } | ||
143 | } | ||
144 | rtlpriv->dm.current_turbo_edca = true; | ||
145 | } | ||
146 | } else { | ||
147 | if (rtlpriv->dm.current_turbo_edca) { | ||
148 | u8 tmp = AC0_BE; | ||
149 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AC_PARAM, | ||
150 | (u8 *)(&tmp)); | ||
151 | rtlpriv->dm.current_turbo_edca = false; | ||
152 | } | ||
153 | } | ||
154 | |||
155 | dm_checkedcaturbo_exit: | ||
156 | rtlpriv->dm.is_any_nonbepkts = false; | ||
157 | last_txok_cnt = rtlpriv->stats.txbytesunicast; | ||
158 | last_rxok_cnt = rtlpriv->stats.rxbytesunicast; | ||
159 | } | ||
160 | |||
161 | static void _rtl92s_dm_txpowertracking_callback_thermalmeter( | ||
162 | struct ieee80211_hw *hw) | ||
163 | { | ||
164 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
165 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
166 | u8 thermalvalue = 0; | ||
167 | |||
168 | rtlpriv->dm.txpower_trackinginit = true; | ||
169 | |||
170 | thermalvalue = (u8)rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f); | ||
171 | |||
172 | RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, | ||
173 | ("Readback Thermal Meter = 0x%x pre thermal meter 0x%x " | ||
174 | "eeprom_thermalmeter 0x%x\n", thermalvalue, | ||
175 | rtlpriv->dm.thermalvalue, rtlefuse->eeprom_thermalmeter)); | ||
176 | |||
177 | if (thermalvalue) { | ||
178 | rtlpriv->dm.thermalvalue = thermalvalue; | ||
179 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_TXPWR_TRACK_THERMAL); | ||
180 | } | ||
181 | |||
182 | rtlpriv->dm.txpowercount = 0; | ||
183 | } | ||
184 | |||
185 | static void _rtl92s_dm_check_txpowertracking_thermalmeter( | ||
186 | struct ieee80211_hw *hw) | ||
187 | { | ||
188 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
189 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
190 | static u8 tm_trigger; | ||
191 | u8 tx_power_checkcnt = 5; | ||
192 | |||
193 | /* 2T2R TP issue */ | ||
194 | if (rtlphy->rf_type == RF_2T2R) | ||
195 | return; | ||
196 | |||
197 | if (!rtlpriv->dm.txpower_tracking) | ||
198 | return; | ||
199 | |||
200 | if (rtlpriv->dm.txpowercount <= tx_power_checkcnt) { | ||
201 | rtlpriv->dm.txpowercount++; | ||
202 | return; | ||
203 | } | ||
204 | |||
205 | if (!tm_trigger) { | ||
206 | rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, | ||
207 | RFREG_OFFSET_MASK, 0x60); | ||
208 | tm_trigger = 1; | ||
209 | } else { | ||
210 | _rtl92s_dm_txpowertracking_callback_thermalmeter(hw); | ||
211 | tm_trigger = 0; | ||
212 | } | ||
213 | } | ||
214 | |||
215 | static void _rtl92s_dm_refresh_rateadaptive_mask(struct ieee80211_hw *hw) | ||
216 | { | ||
217 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
218 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
219 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
220 | struct rate_adaptive *ra = &(rtlpriv->ra); | ||
221 | |||
222 | u32 low_rssi_thresh = 0; | ||
223 | u32 middle_rssi_thresh = 0; | ||
224 | u32 high_rssi_thresh = 0; | ||
225 | u8 rssi_level; | ||
226 | struct ieee80211_sta *sta = NULL; | ||
227 | |||
228 | if (is_hal_stop(rtlhal)) | ||
229 | return; | ||
230 | |||
231 | if (!rtlpriv->dm.useramask) | ||
232 | return; | ||
233 | |||
234 | if (!rtlpriv->dm.inform_fw_driverctrldm) { | ||
235 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_CTRL_DM_BY_DRIVER); | ||
236 | rtlpriv->dm.inform_fw_driverctrldm = true; | ||
237 | } | ||
238 | |||
239 | rcu_read_lock(); | ||
240 | if (mac->opmode == NL80211_IFTYPE_STATION) | ||
241 | sta = get_sta(hw, mac->vif, mac->bssid); | ||
242 | if ((mac->link_state == MAC80211_LINKED) && | ||
243 | (mac->opmode == NL80211_IFTYPE_STATION)) { | ||
244 | switch (ra->pre_ratr_state) { | ||
245 | case DM_RATR_STA_HIGH: | ||
246 | high_rssi_thresh = 40; | ||
247 | middle_rssi_thresh = 30; | ||
248 | low_rssi_thresh = 20; | ||
249 | break; | ||
250 | case DM_RATR_STA_MIDDLE: | ||
251 | high_rssi_thresh = 44; | ||
252 | middle_rssi_thresh = 30; | ||
253 | low_rssi_thresh = 20; | ||
254 | break; | ||
255 | case DM_RATR_STA_LOW: | ||
256 | high_rssi_thresh = 44; | ||
257 | middle_rssi_thresh = 34; | ||
258 | low_rssi_thresh = 20; | ||
259 | break; | ||
260 | case DM_RATR_STA_ULTRALOW: | ||
261 | high_rssi_thresh = 44; | ||
262 | middle_rssi_thresh = 34; | ||
263 | low_rssi_thresh = 24; | ||
264 | break; | ||
265 | default: | ||
266 | high_rssi_thresh = 44; | ||
267 | middle_rssi_thresh = 34; | ||
268 | low_rssi_thresh = 24; | ||
269 | break; | ||
270 | } | ||
271 | |||
272 | if (rtlpriv->dm.undecorated_smoothed_pwdb > | ||
273 | (long)high_rssi_thresh) { | ||
274 | ra->ratr_state = DM_RATR_STA_HIGH; | ||
275 | rssi_level = 1; | ||
276 | } else if (rtlpriv->dm.undecorated_smoothed_pwdb > | ||
277 | (long)middle_rssi_thresh) { | ||
278 | ra->ratr_state = DM_RATR_STA_LOW; | ||
279 | rssi_level = 3; | ||
280 | } else if (rtlpriv->dm.undecorated_smoothed_pwdb > | ||
281 | (long)low_rssi_thresh) { | ||
282 | ra->ratr_state = DM_RATR_STA_LOW; | ||
283 | rssi_level = 5; | ||
284 | } else { | ||
285 | ra->ratr_state = DM_RATR_STA_ULTRALOW; | ||
286 | rssi_level = 6; | ||
287 | } | ||
288 | |||
289 | if (ra->pre_ratr_state != ra->ratr_state) { | ||
290 | RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD, ("RSSI = %ld " | ||
291 | "RSSI_LEVEL = %d PreState = %d, CurState = %d\n", | ||
292 | rtlpriv->dm.undecorated_smoothed_pwdb, | ||
293 | ra->ratr_state, | ||
294 | ra->pre_ratr_state, ra->ratr_state)); | ||
295 | |||
296 | rtlpriv->cfg->ops->update_rate_tbl(hw, sta, | ||
297 | ra->ratr_state); | ||
298 | ra->pre_ratr_state = ra->ratr_state; | ||
299 | } | ||
300 | } | ||
301 | rcu_read_unlock(); | ||
302 | } | ||
303 | |||
304 | static void _rtl92s_dm_switch_baseband_mrc(struct ieee80211_hw *hw) | ||
305 | { | ||
306 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
307 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
308 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
309 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
310 | bool current_mrc; | ||
311 | bool enable_mrc = true; | ||
312 | long tmpentry_maxpwdb = 0; | ||
313 | u8 rssi_a = 0; | ||
314 | u8 rssi_b = 0; | ||
315 | |||
316 | if (is_hal_stop(rtlhal)) | ||
317 | return; | ||
318 | |||
319 | if ((rtlphy->rf_type == RF_1T1R) || (rtlphy->rf_type == RF_2T2R)) | ||
320 | return; | ||
321 | |||
322 | rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_MRC, (u8 *)(¤t_mrc)); | ||
323 | |||
324 | if (mac->link_state >= MAC80211_LINKED) { | ||
325 | if (rtlpriv->dm.undecorated_smoothed_pwdb > tmpentry_maxpwdb) { | ||
326 | rssi_a = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_A]; | ||
327 | rssi_b = rtlpriv->stats.rx_rssi_percentage[RF90_PATH_B]; | ||
328 | } | ||
329 | } | ||
330 | |||
331 | /* MRC settings would NOT affect TP on Wireless B mode. */ | ||
332 | if (mac->mode != WIRELESS_MODE_B) { | ||
333 | if ((rssi_a == 0) && (rssi_b == 0)) { | ||
334 | enable_mrc = true; | ||
335 | } else if (rssi_b > 30) { | ||
336 | /* Turn on B-Path */ | ||
337 | enable_mrc = true; | ||
338 | } else if (rssi_b < 5) { | ||
339 | /* Turn off B-path */ | ||
340 | enable_mrc = false; | ||
341 | /* Take care of RSSI differentiation. */ | ||
342 | } else if (rssi_a > 15 && (rssi_a >= rssi_b)) { | ||
343 | if ((rssi_a - rssi_b) > 15) | ||
344 | /* Turn off B-path */ | ||
345 | enable_mrc = false; | ||
346 | else if ((rssi_a - rssi_b) < 10) | ||
347 | /* Turn on B-Path */ | ||
348 | enable_mrc = true; | ||
349 | else | ||
350 | enable_mrc = current_mrc; | ||
351 | } else { | ||
352 | /* Turn on B-Path */ | ||
353 | enable_mrc = true; | ||
354 | } | ||
355 | } | ||
356 | |||
357 | /* Update MRC settings if needed. */ | ||
358 | if (enable_mrc != current_mrc) | ||
359 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MRC, | ||
360 | (u8 *)&enable_mrc); | ||
361 | |||
362 | } | ||
363 | |||
364 | void rtl92s_dm_init_edca_turbo(struct ieee80211_hw *hw) | ||
365 | { | ||
366 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
367 | |||
368 | rtlpriv->dm.current_turbo_edca = false; | ||
369 | rtlpriv->dm.is_any_nonbepkts = false; | ||
370 | rtlpriv->dm.is_cur_rdlstate = false; | ||
371 | } | ||
372 | |||
373 | static void _rtl92s_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw) | ||
374 | { | ||
375 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
376 | struct rate_adaptive *ra = &(rtlpriv->ra); | ||
377 | |||
378 | ra->ratr_state = DM_RATR_STA_MAX; | ||
379 | ra->pre_ratr_state = DM_RATR_STA_MAX; | ||
380 | |||
381 | if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) | ||
382 | rtlpriv->dm.useramask = true; | ||
383 | else | ||
384 | rtlpriv->dm.useramask = false; | ||
385 | |||
386 | rtlpriv->dm.useramask = false; | ||
387 | rtlpriv->dm.inform_fw_driverctrldm = false; | ||
388 | } | ||
389 | |||
390 | static void _rtl92s_dm_init_txpowertracking_thermalmeter( | ||
391 | struct ieee80211_hw *hw) | ||
392 | { | ||
393 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
394 | |||
395 | rtlpriv->dm.txpower_tracking = true; | ||
396 | rtlpriv->dm.txpowercount = 0; | ||
397 | rtlpriv->dm.txpower_trackinginit = false; | ||
398 | } | ||
399 | |||
400 | static void _rtl92s_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw) | ||
401 | { | ||
402 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
403 | struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); | ||
404 | u32 ret_value; | ||
405 | |||
406 | ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD); | ||
407 | falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16); | ||
408 | |||
409 | ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD); | ||
410 | falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff); | ||
411 | falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16); | ||
412 | ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD); | ||
413 | falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff); | ||
414 | |||
415 | falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail + | ||
416 | falsealm_cnt->cnt_rate_illegal + falsealm_cnt->cnt_crc8_fail + | ||
417 | falsealm_cnt->cnt_mcs_fail; | ||
418 | |||
419 | /* read CCK false alarm */ | ||
420 | ret_value = rtl_get_bbreg(hw, 0xc64, MASKDWORD); | ||
421 | falsealm_cnt->cnt_cck_fail = (ret_value & 0xffff); | ||
422 | falsealm_cnt->cnt_all = falsealm_cnt->cnt_ofdm_fail + | ||
423 | falsealm_cnt->cnt_cck_fail; | ||
424 | } | ||
425 | |||
426 | static void rtl92s_backoff_enable_flag(struct ieee80211_hw *hw) | ||
427 | { | ||
428 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
429 | struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); | ||
430 | |||
431 | if (falsealm_cnt->cnt_all > digtable.fa_highthresh) { | ||
432 | if ((digtable.backoff_val - 6) < | ||
433 | digtable.backoffval_range_min) | ||
434 | digtable.backoff_val = digtable.backoffval_range_min; | ||
435 | else | ||
436 | digtable.backoff_val -= 6; | ||
437 | } else if (falsealm_cnt->cnt_all < digtable.fa_lowthresh) { | ||
438 | if ((digtable.backoff_val + 6) > | ||
439 | digtable.backoffval_range_max) | ||
440 | digtable.backoff_val = | ||
441 | digtable.backoffval_range_max; | ||
442 | else | ||
443 | digtable.backoff_val += 6; | ||
444 | } | ||
445 | } | ||
446 | |||
447 | static void _rtl92s_dm_initial_gain_sta_beforeconnect(struct ieee80211_hw *hw) | ||
448 | { | ||
449 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
450 | struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt); | ||
451 | static u8 initialized, force_write; | ||
452 | u8 initial_gain = 0; | ||
453 | |||
454 | if ((digtable.pre_sta_connectstate == digtable.cur_sta_connectstate) || | ||
455 | (digtable.cur_sta_connectstate == DIG_STA_BEFORE_CONNECT)) { | ||
456 | if (digtable.cur_sta_connectstate == DIG_STA_BEFORE_CONNECT) { | ||
457 | if (rtlpriv->psc.rfpwr_state != ERFON) | ||
458 | return; | ||
459 | |||
460 | if (digtable.backoff_enable_flag == true) | ||
461 | rtl92s_backoff_enable_flag(hw); | ||
462 | else | ||
463 | digtable.backoff_val = DM_DIG_BACKOFF; | ||
464 | |||
465 | if ((digtable.rssi_val + 10 - digtable.backoff_val) > | ||
466 | digtable.rx_gain_range_max) | ||
467 | digtable.cur_igvalue = | ||
468 | digtable.rx_gain_range_max; | ||
469 | else if ((digtable.rssi_val + 10 - digtable.backoff_val) | ||
470 | < digtable.rx_gain_range_min) | ||
471 | digtable.cur_igvalue = | ||
472 | digtable.rx_gain_range_min; | ||
473 | else | ||
474 | digtable.cur_igvalue = digtable.rssi_val + 10 - | ||
475 | digtable.backoff_val; | ||
476 | |||
477 | if (falsealm_cnt->cnt_all > 10000) | ||
478 | digtable.cur_igvalue = | ||
479 | (digtable.cur_igvalue > 0x33) ? | ||
480 | digtable.cur_igvalue : 0x33; | ||
481 | |||
482 | if (falsealm_cnt->cnt_all > 16000) | ||
483 | digtable.cur_igvalue = | ||
484 | digtable.rx_gain_range_max; | ||
485 | /* connected -> connected or disconnected -> disconnected */ | ||
486 | } else { | ||
487 | /* Firmware control DIG, do nothing in driver dm */ | ||
488 | return; | ||
489 | } | ||
490 | /* disconnected -> connected or connected -> | ||
491 | * disconnected or beforeconnect->(dis)connected */ | ||
492 | } else { | ||
493 | /* Enable FW DIG */ | ||
494 | digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; | ||
495 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_ENABLE); | ||
496 | |||
497 | digtable.backoff_val = DM_DIG_BACKOFF; | ||
498 | digtable.cur_igvalue = rtlpriv->phy.default_initialgain[0]; | ||
499 | digtable.pre_igvalue = 0; | ||
500 | return; | ||
501 | } | ||
502 | |||
503 | /* Forced writing to prevent from fw-dig overwriting. */ | ||
504 | if (digtable.pre_igvalue != rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, | ||
505 | MASKBYTE0)) | ||
506 | force_write = 1; | ||
507 | |||
508 | if ((digtable.pre_igvalue != digtable.cur_igvalue) || | ||
509 | !initialized || force_write) { | ||
510 | /* Disable FW DIG */ | ||
511 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_DISABLE); | ||
512 | |||
513 | initial_gain = (u8)digtable.cur_igvalue; | ||
514 | |||
515 | /* Set initial gain. */ | ||
516 | rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, initial_gain); | ||
517 | rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, initial_gain); | ||
518 | digtable.pre_igvalue = digtable.cur_igvalue; | ||
519 | initialized = 1; | ||
520 | force_write = 0; | ||
521 | } | ||
522 | } | ||
523 | |||
524 | static void _rtl92s_dm_ctrl_initgain_bytwoport(struct ieee80211_hw *hw) | ||
525 | { | ||
526 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
527 | |||
528 | if (rtlpriv->mac80211.act_scanning) | ||
529 | return; | ||
530 | |||
531 | /* Decide the current status and if modify initial gain or not */ | ||
532 | if (rtlpriv->mac80211.link_state >= MAC80211_LINKED || | ||
533 | rtlpriv->mac80211.opmode == NL80211_IFTYPE_ADHOC) | ||
534 | digtable.cur_sta_connectstate = DIG_STA_CONNECT; | ||
535 | else | ||
536 | digtable.cur_sta_connectstate = DIG_STA_DISCONNECT; | ||
537 | |||
538 | digtable.rssi_val = rtlpriv->dm.undecorated_smoothed_pwdb; | ||
539 | |||
540 | /* Change dig mode to rssi */ | ||
541 | if (digtable.cur_sta_connectstate != DIG_STA_DISCONNECT) { | ||
542 | if (digtable.dig_twoport_algorithm == | ||
543 | DIG_TWO_PORT_ALGO_FALSE_ALARM) { | ||
544 | digtable.dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI; | ||
545 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_DIG_MODE_SS); | ||
546 | } | ||
547 | } | ||
548 | |||
549 | _rtl92s_dm_false_alarm_counter_statistics(hw); | ||
550 | _rtl92s_dm_initial_gain_sta_beforeconnect(hw); | ||
551 | |||
552 | digtable.pre_sta_connectstate = digtable.cur_sta_connectstate; | ||
553 | } | ||
554 | |||
555 | static void _rtl92s_dm_ctrl_initgain_byrssi(struct ieee80211_hw *hw) | ||
556 | { | ||
557 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
558 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
559 | |||
560 | /* 2T2R TP issue */ | ||
561 | if (rtlphy->rf_type == RF_2T2R) | ||
562 | return; | ||
563 | |||
564 | if (!rtlpriv->dm.dm_initialgain_enable) | ||
565 | return; | ||
566 | |||
567 | if (digtable.dig_enable_flag == false) | ||
568 | return; | ||
569 | |||
570 | _rtl92s_dm_ctrl_initgain_bytwoport(hw); | ||
571 | } | ||
572 | |||
573 | static void _rtl92s_dm_dynamic_txpower(struct ieee80211_hw *hw) | ||
574 | { | ||
575 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
576 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
577 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
578 | long undecorated_smoothed_pwdb; | ||
579 | long txpwr_threshold_lv1, txpwr_threshold_lv2; | ||
580 | |||
581 | /* 2T2R TP issue */ | ||
582 | if (rtlphy->rf_type == RF_2T2R) | ||
583 | return; | ||
584 | |||
585 | if (!rtlpriv->dm.dynamic_txpower_enable || | ||
586 | rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) { | ||
587 | rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; | ||
588 | return; | ||
589 | } | ||
590 | |||
591 | if ((mac->link_state < MAC80211_LINKED) && | ||
592 | (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) { | ||
593 | RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE, | ||
594 | ("Not connected to any\n")); | ||
595 | |||
596 | rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; | ||
597 | |||
598 | rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL; | ||
599 | return; | ||
600 | } | ||
601 | |||
602 | if (mac->link_state >= MAC80211_LINKED) { | ||
603 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
604 | undecorated_smoothed_pwdb = | ||
605 | rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; | ||
606 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
607 | ("AP Client PWDB = 0x%lx\n", | ||
608 | undecorated_smoothed_pwdb)); | ||
609 | } else { | ||
610 | undecorated_smoothed_pwdb = | ||
611 | rtlpriv->dm.undecorated_smoothed_pwdb; | ||
612 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
613 | ("STA Default Port PWDB = 0x%lx\n", | ||
614 | undecorated_smoothed_pwdb)); | ||
615 | } | ||
616 | } else { | ||
617 | undecorated_smoothed_pwdb = | ||
618 | rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb; | ||
619 | |||
620 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
621 | ("AP Ext Port PWDB = 0x%lx\n", | ||
622 | undecorated_smoothed_pwdb)); | ||
623 | } | ||
624 | |||
625 | txpwr_threshold_lv2 = TX_POWER_NEAR_FIELD_THRESH_LVL2; | ||
626 | txpwr_threshold_lv1 = TX_POWER_NEAR_FIELD_THRESH_LVL1; | ||
627 | |||
628 | if (rtl_get_bbreg(hw, 0xc90, MASKBYTE0) == 1) | ||
629 | rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; | ||
630 | else if (undecorated_smoothed_pwdb >= txpwr_threshold_lv2) | ||
631 | rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL2; | ||
632 | else if ((undecorated_smoothed_pwdb < (txpwr_threshold_lv2 - 3)) && | ||
633 | (undecorated_smoothed_pwdb >= txpwr_threshold_lv1)) | ||
634 | rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL1; | ||
635 | else if (undecorated_smoothed_pwdb < (txpwr_threshold_lv1 - 3)) | ||
636 | rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; | ||
637 | |||
638 | if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) | ||
639 | rtl92s_phy_set_txpower(hw, rtlphy->current_channel); | ||
640 | |||
641 | rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl; | ||
642 | } | ||
643 | |||
644 | static void _rtl92s_dm_init_dig(struct ieee80211_hw *hw) | ||
645 | { | ||
646 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
647 | |||
648 | /* Disable DIG scheme now.*/ | ||
649 | digtable.dig_enable_flag = true; | ||
650 | digtable.backoff_enable_flag = true; | ||
651 | |||
652 | if ((rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER) && | ||
653 | (hal_get_firmwareversion(rtlpriv) >= 0x3c)) | ||
654 | digtable.dig_algorithm = DIG_ALGO_BY_TOW_PORT; | ||
655 | else | ||
656 | digtable.dig_algorithm = | ||
657 | DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM; | ||
658 | |||
659 | digtable.dig_twoport_algorithm = DIG_TWO_PORT_ALGO_RSSI; | ||
660 | digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX; | ||
661 | /* off=by real rssi value, on=by digtable.rssi_val for new dig */ | ||
662 | digtable.dig_dbgmode = DM_DBG_OFF; | ||
663 | digtable.dig_slgorithm_switch = 0; | ||
664 | |||
665 | /* 2007/10/04 MH Define init gain threshol. */ | ||
666 | digtable.dig_state = DM_STA_DIG_MAX; | ||
667 | digtable.dig_highpwrstate = DM_STA_DIG_MAX; | ||
668 | |||
669 | digtable.cur_sta_connectstate = DIG_STA_DISCONNECT; | ||
670 | digtable.pre_sta_connectstate = DIG_STA_DISCONNECT; | ||
671 | digtable.cur_ap_connectstate = DIG_AP_DISCONNECT; | ||
672 | digtable.pre_ap_connectstate = DIG_AP_DISCONNECT; | ||
673 | |||
674 | digtable.rssi_lowthresh = DM_DIG_THRESH_LOW; | ||
675 | digtable.rssi_highthresh = DM_DIG_THRESH_HIGH; | ||
676 | |||
677 | digtable.fa_lowthresh = DM_FALSEALARM_THRESH_LOW; | ||
678 | digtable.fa_highthresh = DM_FALSEALARM_THRESH_HIGH; | ||
679 | |||
680 | digtable.rssi_highpower_lowthresh = DM_DIG_HIGH_PWR_THRESH_LOW; | ||
681 | digtable.rssi_highpower_highthresh = DM_DIG_HIGH_PWR_THRESH_HIGH; | ||
682 | |||
683 | /* for dig debug rssi value */ | ||
684 | digtable.rssi_val = 50; | ||
685 | digtable.backoff_val = DM_DIG_BACKOFF; | ||
686 | digtable.rx_gain_range_max = DM_DIG_MAX; | ||
687 | |||
688 | digtable.rx_gain_range_min = DM_DIG_MIN; | ||
689 | |||
690 | digtable.backoffval_range_max = DM_DIG_BACKOFF_MAX; | ||
691 | digtable.backoffval_range_min = DM_DIG_BACKOFF_MIN; | ||
692 | } | ||
693 | |||
694 | static void _rtl92s_dm_init_dynamic_txpower(struct ieee80211_hw *hw) | ||
695 | { | ||
696 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
697 | |||
698 | if ((hal_get_firmwareversion(rtlpriv) >= 60) && | ||
699 | (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)) | ||
700 | rtlpriv->dm.dynamic_txpower_enable = true; | ||
701 | else | ||
702 | rtlpriv->dm.dynamic_txpower_enable = false; | ||
703 | |||
704 | rtlpriv->dm.last_dtp_lvl = TX_HIGHPWR_LEVEL_NORMAL; | ||
705 | rtlpriv->dm.dynamic_txhighpower_lvl = TX_HIGHPWR_LEVEL_NORMAL; | ||
706 | } | ||
707 | |||
708 | void rtl92s_dm_init(struct ieee80211_hw *hw) | ||
709 | { | ||
710 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
711 | |||
712 | rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER; | ||
713 | rtlpriv->dm.undecorated_smoothed_pwdb = -1; | ||
714 | |||
715 | _rtl92s_dm_init_dynamic_txpower(hw); | ||
716 | rtl92s_dm_init_edca_turbo(hw); | ||
717 | _rtl92s_dm_init_rate_adaptive_mask(hw); | ||
718 | _rtl92s_dm_init_txpowertracking_thermalmeter(hw); | ||
719 | _rtl92s_dm_init_dig(hw); | ||
720 | |||
721 | rtl_write_dword(rtlpriv, WFM5, FW_CCA_CHK_ENABLE); | ||
722 | } | ||
723 | |||
724 | void rtl92s_dm_watchdog(struct ieee80211_hw *hw) | ||
725 | { | ||
726 | _rtl92s_dm_check_edca_turbo(hw); | ||
727 | _rtl92s_dm_check_txpowertracking_thermalmeter(hw); | ||
728 | _rtl92s_dm_ctrl_initgain_byrssi(hw); | ||
729 | _rtl92s_dm_dynamic_txpower(hw); | ||
730 | _rtl92s_dm_refresh_rateadaptive_mask(hw); | ||
731 | _rtl92s_dm_switch_baseband_mrc(hw); | ||
732 | } | ||
733 | |||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/dm.h b/drivers/net/wireless/rtlwifi/rtl8192se/dm.h new file mode 100644 index 000000000000..9051a556acc4 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/dm.h | |||
@@ -0,0 +1,164 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | #ifndef __RTL_92S_DM_H__ | ||
30 | #define __RTL_92S_DM_H__ | ||
31 | |||
32 | struct dig_t { | ||
33 | u8 dig_enable_flag; | ||
34 | u8 dig_algorithm; | ||
35 | u8 dig_twoport_algorithm; | ||
36 | u8 dig_ext_port_stage; | ||
37 | u8 dig_dbgmode; | ||
38 | u8 dig_slgorithm_switch; | ||
39 | |||
40 | long rssi_lowthresh; | ||
41 | long rssi_highthresh; | ||
42 | |||
43 | u32 fa_lowthresh; | ||
44 | u32 fa_highthresh; | ||
45 | |||
46 | long rssi_highpower_lowthresh; | ||
47 | long rssi_highpower_highthresh; | ||
48 | |||
49 | u8 dig_state; | ||
50 | u8 dig_highpwrstate; | ||
51 | u8 cur_sta_connectstate; | ||
52 | u8 pre_sta_connectstate; | ||
53 | u8 cur_ap_connectstate; | ||
54 | u8 pre_ap_connectstate; | ||
55 | |||
56 | u8 cur_pd_thstate; | ||
57 | u8 pre_pd_thstate; | ||
58 | u8 cur_cs_ratiostate; | ||
59 | u8 pre_cs_ratiostate; | ||
60 | |||
61 | u32 pre_igvalue; | ||
62 | u32 cur_igvalue; | ||
63 | |||
64 | u8 backoff_enable_flag; | ||
65 | char backoff_val; | ||
66 | char backoffval_range_max; | ||
67 | char backoffval_range_min; | ||
68 | u8 rx_gain_range_max; | ||
69 | u8 rx_gain_range_min; | ||
70 | |||
71 | long rssi_val; | ||
72 | }; | ||
73 | |||
74 | enum dm_dig_alg { | ||
75 | DIG_ALGO_BY_FALSE_ALARM = 0, | ||
76 | DIG_ALGO_BY_RSSI = 1, | ||
77 | DIG_ALGO_BEFORE_CONNECT_BY_RSSI_AND_ALARM = 2, | ||
78 | DIG_ALGO_BY_TOW_PORT = 3, | ||
79 | DIG_ALGO_MAX | ||
80 | }; | ||
81 | |||
82 | enum dm_dig_two_port_alg { | ||
83 | DIG_TWO_PORT_ALGO_RSSI = 0, | ||
84 | DIG_TWO_PORT_ALGO_FALSE_ALARM = 1, | ||
85 | }; | ||
86 | |||
87 | enum dm_dig_dbg { | ||
88 | DM_DBG_OFF = 0, | ||
89 | DM_DBG_ON = 1, | ||
90 | DM_DBG_MAX | ||
91 | }; | ||
92 | |||
93 | enum dm_dig_sta { | ||
94 | DM_STA_DIG_OFF = 0, | ||
95 | DM_STA_DIG_ON, | ||
96 | DM_STA_DIG_MAX | ||
97 | }; | ||
98 | |||
99 | enum dm_dig_connect { | ||
100 | DIG_STA_DISCONNECT = 0, | ||
101 | DIG_STA_CONNECT = 1, | ||
102 | DIG_STA_BEFORE_CONNECT = 2, | ||
103 | DIG_AP_DISCONNECT = 3, | ||
104 | DIG_AP_CONNECT = 4, | ||
105 | DIG_AP_ADD_STATION = 5, | ||
106 | DIG_CONNECT_MAX | ||
107 | }; | ||
108 | |||
109 | enum dm_dig_ext_port_alg { | ||
110 | DIG_EXT_PORT_STAGE_0 = 0, | ||
111 | DIG_EXT_PORT_STAGE_1 = 1, | ||
112 | DIG_EXT_PORT_STAGE_2 = 2, | ||
113 | DIG_EXT_PORT_STAGE_3 = 3, | ||
114 | DIG_EXT_PORT_STAGE_MAX = 4, | ||
115 | }; | ||
116 | |||
117 | enum dm_ratr_sta { | ||
118 | DM_RATR_STA_HIGH = 0, | ||
119 | DM_RATR_STA_MIDDLEHIGH = 1, | ||
120 | DM_RATR_STA_MIDDLE = 2, | ||
121 | DM_RATR_STA_MIDDLELOW = 3, | ||
122 | DM_RATR_STA_LOW = 4, | ||
123 | DM_RATR_STA_ULTRALOW = 5, | ||
124 | DM_RATR_STA_MAX | ||
125 | }; | ||
126 | |||
127 | #define DM_TYPE_BYFW 0 | ||
128 | #define DM_TYPE_BYDRIVER 1 | ||
129 | |||
130 | #define TX_HIGH_PWR_LEVEL_NORMAL 0 | ||
131 | #define TX_HIGH_PWR_LEVEL_LEVEL1 1 | ||
132 | #define TX_HIGH_PWR_LEVEL_LEVEL2 2 | ||
133 | |||
134 | #define HAL_DM_DIG_DISABLE BIT(0) /* Disable Dig */ | ||
135 | #define HAL_DM_HIPWR_DISABLE BIT(1) /* Disable High Power */ | ||
136 | |||
137 | #define TX_HIGHPWR_LEVEL_NORMAL 0 | ||
138 | #define TX_HIGHPWR_LEVEL_NORMAL1 1 | ||
139 | #define TX_HIGHPWR_LEVEL_NORMAL2 2 | ||
140 | |||
141 | #define TX_POWER_NEAR_FIELD_THRESH_LVL2 74 | ||
142 | #define TX_POWER_NEAR_FIELD_THRESH_LVL1 67 | ||
143 | |||
144 | #define DM_DIG_THRESH_HIGH 40 | ||
145 | #define DM_DIG_THRESH_LOW 35 | ||
146 | #define DM_FALSEALARM_THRESH_LOW 40 | ||
147 | #define DM_FALSEALARM_THRESH_HIGH 1000 | ||
148 | #define DM_DIG_HIGH_PWR_THRESH_HIGH 75 | ||
149 | #define DM_DIG_HIGH_PWR_THRESH_LOW 70 | ||
150 | #define DM_DIG_BACKOFF 12 | ||
151 | #define DM_DIG_MAX 0x3e | ||
152 | #define DM_DIG_MIN 0x1c | ||
153 | #define DM_DIG_MIN_Netcore 0x12 | ||
154 | #define DM_DIG_BACKOFF_MAX 12 | ||
155 | #define DM_DIG_BACKOFF_MIN -4 | ||
156 | |||
157 | extern struct dig_t digtable; | ||
158 | |||
159 | void rtl92s_dm_watchdog(struct ieee80211_hw *hw); | ||
160 | void rtl92s_dm_init(struct ieee80211_hw *hw); | ||
161 | void rtl92s_dm_init_edca_turbo(struct ieee80211_hw *hw); | ||
162 | |||
163 | #endif | ||
164 | |||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c new file mode 100644 index 000000000000..3b5af0113d7f --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c | |||
@@ -0,0 +1,654 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../pci.h" | ||
32 | #include "../base.h" | ||
33 | #include "reg.h" | ||
34 | #include "def.h" | ||
35 | #include "fw.h" | ||
36 | |||
37 | static void _rtl92s_fw_set_rqpn(struct ieee80211_hw *hw) | ||
38 | { | ||
39 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
40 | |||
41 | rtl_write_dword(rtlpriv, RQPN, 0xffffffff); | ||
42 | rtl_write_dword(rtlpriv, RQPN + 4, 0xffffffff); | ||
43 | rtl_write_byte(rtlpriv, RQPN + 8, 0xff); | ||
44 | rtl_write_byte(rtlpriv, RQPN + 0xB, 0x80); | ||
45 | } | ||
46 | |||
47 | static bool _rtl92s_firmware_enable_cpu(struct ieee80211_hw *hw) | ||
48 | { | ||
49 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
50 | u32 ichecktime = 200; | ||
51 | u16 tmpu2b; | ||
52 | u8 tmpu1b, cpustatus = 0; | ||
53 | |||
54 | _rtl92s_fw_set_rqpn(hw); | ||
55 | |||
56 | /* Enable CPU. */ | ||
57 | tmpu1b = rtl_read_byte(rtlpriv, SYS_CLKR); | ||
58 | /* AFE source */ | ||
59 | rtl_write_byte(rtlpriv, SYS_CLKR, (tmpu1b | SYS_CPU_CLKSEL)); | ||
60 | |||
61 | tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); | ||
62 | rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | FEN_CPUEN)); | ||
63 | |||
64 | /* Polling IMEM Ready after CPU has refilled. */ | ||
65 | do { | ||
66 | cpustatus = rtl_read_byte(rtlpriv, TCR); | ||
67 | if (cpustatus & IMEM_RDY) { | ||
68 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
69 | ("IMEM Ready after CPU has refilled.\n")); | ||
70 | break; | ||
71 | } | ||
72 | |||
73 | udelay(100); | ||
74 | } while (ichecktime--); | ||
75 | |||
76 | if (!(cpustatus & IMEM_RDY)) | ||
77 | return false; | ||
78 | |||
79 | return true; | ||
80 | } | ||
81 | |||
82 | static enum fw_status _rtl92s_firmware_get_nextstatus( | ||
83 | enum fw_status fw_currentstatus) | ||
84 | { | ||
85 | enum fw_status next_fwstatus = 0; | ||
86 | |||
87 | switch (fw_currentstatus) { | ||
88 | case FW_STATUS_INIT: | ||
89 | next_fwstatus = FW_STATUS_LOAD_IMEM; | ||
90 | break; | ||
91 | case FW_STATUS_LOAD_IMEM: | ||
92 | next_fwstatus = FW_STATUS_LOAD_EMEM; | ||
93 | break; | ||
94 | case FW_STATUS_LOAD_EMEM: | ||
95 | next_fwstatus = FW_STATUS_LOAD_DMEM; | ||
96 | break; | ||
97 | case FW_STATUS_LOAD_DMEM: | ||
98 | next_fwstatus = FW_STATUS_READY; | ||
99 | break; | ||
100 | default: | ||
101 | break; | ||
102 | } | ||
103 | |||
104 | return next_fwstatus; | ||
105 | } | ||
106 | |||
107 | static u8 _rtl92s_firmware_header_map_rftype(struct ieee80211_hw *hw) | ||
108 | { | ||
109 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
110 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
111 | |||
112 | switch (rtlphy->rf_type) { | ||
113 | case RF_1T1R: | ||
114 | return 0x11; | ||
115 | break; | ||
116 | case RF_1T2R: | ||
117 | return 0x12; | ||
118 | break; | ||
119 | case RF_2T2R: | ||
120 | return 0x22; | ||
121 | break; | ||
122 | default: | ||
123 | RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, | ||
124 | ("Unknown RF type(%x)\n", | ||
125 | rtlphy->rf_type)); | ||
126 | break; | ||
127 | } | ||
128 | return 0x22; | ||
129 | } | ||
130 | |||
131 | static void _rtl92s_firmwareheader_priveupdate(struct ieee80211_hw *hw, | ||
132 | struct fw_priv *pfw_priv) | ||
133 | { | ||
134 | /* Update RF types for RATR settings. */ | ||
135 | pfw_priv->rf_config = _rtl92s_firmware_header_map_rftype(hw); | ||
136 | } | ||
137 | |||
138 | |||
139 | |||
140 | static bool _rtl92s_cmd_send_packet(struct ieee80211_hw *hw, | ||
141 | struct sk_buff *skb, u8 last) | ||
142 | { | ||
143 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
144 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
145 | struct rtl8192_tx_ring *ring; | ||
146 | struct rtl_tx_desc *pdesc; | ||
147 | unsigned long flags; | ||
148 | u8 idx = 0; | ||
149 | |||
150 | ring = &rtlpci->tx_ring[TXCMD_QUEUE]; | ||
151 | |||
152 | spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); | ||
153 | |||
154 | idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; | ||
155 | pdesc = &ring->desc[idx]; | ||
156 | rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); | ||
157 | __skb_queue_tail(&ring->queue, skb); | ||
158 | |||
159 | spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); | ||
160 | |||
161 | return true; | ||
162 | } | ||
163 | |||
164 | static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw, | ||
165 | u8 *code_virtual_address, u32 buffer_len) | ||
166 | { | ||
167 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
168 | struct sk_buff *skb; | ||
169 | struct rtl_tcb_desc *tcb_desc; | ||
170 | unsigned char *seg_ptr; | ||
171 | u16 frag_threshold = MAX_FIRMWARE_CODE_SIZE; | ||
172 | u16 frag_length, frag_offset = 0; | ||
173 | u16 extra_descoffset = 0; | ||
174 | u8 last_inipkt = 0; | ||
175 | |||
176 | _rtl92s_fw_set_rqpn(hw); | ||
177 | |||
178 | if (buffer_len >= MAX_FIRMWARE_CODE_SIZE) { | ||
179 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
180 | ("Size over FIRMWARE_CODE_SIZE!\n")); | ||
181 | |||
182 | return false; | ||
183 | } | ||
184 | |||
185 | extra_descoffset = 0; | ||
186 | |||
187 | do { | ||
188 | if ((buffer_len - frag_offset) > frag_threshold) { | ||
189 | frag_length = frag_threshold + extra_descoffset; | ||
190 | } else { | ||
191 | frag_length = (u16)(buffer_len - frag_offset + | ||
192 | extra_descoffset); | ||
193 | last_inipkt = 1; | ||
194 | } | ||
195 | |||
196 | /* Allocate skb buffer to contain firmware */ | ||
197 | /* info and tx descriptor info. */ | ||
198 | skb = dev_alloc_skb(frag_length); | ||
199 | skb_reserve(skb, extra_descoffset); | ||
200 | seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length - | ||
201 | extra_descoffset)); | ||
202 | memcpy(seg_ptr, code_virtual_address + frag_offset, | ||
203 | (u32)(frag_length - extra_descoffset)); | ||
204 | |||
205 | tcb_desc = (struct rtl_tcb_desc *)(skb->cb); | ||
206 | tcb_desc->queue_index = TXCMD_QUEUE; | ||
207 | tcb_desc->cmd_or_init = DESC_PACKET_TYPE_INIT; | ||
208 | tcb_desc->last_inipkt = last_inipkt; | ||
209 | |||
210 | _rtl92s_cmd_send_packet(hw, skb, last_inipkt); | ||
211 | |||
212 | frag_offset += (frag_length - extra_descoffset); | ||
213 | |||
214 | } while (frag_offset < buffer_len); | ||
215 | |||
216 | rtl_write_byte(rtlpriv, TP_POLL, TPPOLL_CQ); | ||
217 | |||
218 | return true ; | ||
219 | } | ||
220 | |||
221 | static bool _rtl92s_firmware_checkready(struct ieee80211_hw *hw, | ||
222 | u8 loadfw_status) | ||
223 | { | ||
224 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
225 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
226 | struct rt_firmware *firmware = (struct rt_firmware *)rtlhal->pfirmware; | ||
227 | u32 tmpu4b; | ||
228 | u8 cpustatus = 0; | ||
229 | short pollingcnt = 1000; | ||
230 | bool rtstatus = true; | ||
231 | |||
232 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("LoadStaus(%d)\n", | ||
233 | loadfw_status)); | ||
234 | |||
235 | firmware->fwstatus = (enum fw_status)loadfw_status; | ||
236 | |||
237 | switch (loadfw_status) { | ||
238 | case FW_STATUS_LOAD_IMEM: | ||
239 | /* Polling IMEM code done. */ | ||
240 | do { | ||
241 | cpustatus = rtl_read_byte(rtlpriv, TCR); | ||
242 | if (cpustatus & IMEM_CODE_DONE) | ||
243 | break; | ||
244 | udelay(5); | ||
245 | } while (pollingcnt--); | ||
246 | |||
247 | if (!(cpustatus & IMEM_CHK_RPT) || (pollingcnt <= 0)) { | ||
248 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
249 | ("FW_STATUS_LOAD_IMEM" | ||
250 | " FAIL CPU, Status=%x\r\n", cpustatus)); | ||
251 | goto status_check_fail; | ||
252 | } | ||
253 | break; | ||
254 | |||
255 | case FW_STATUS_LOAD_EMEM: | ||
256 | /* Check Put Code OK and Turn On CPU */ | ||
257 | /* Polling EMEM code done. */ | ||
258 | do { | ||
259 | cpustatus = rtl_read_byte(rtlpriv, TCR); | ||
260 | if (cpustatus & EMEM_CODE_DONE) | ||
261 | break; | ||
262 | udelay(5); | ||
263 | } while (pollingcnt--); | ||
264 | |||
265 | if (!(cpustatus & EMEM_CHK_RPT) || (pollingcnt <= 0)) { | ||
266 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
267 | ("FW_STATUS_LOAD_EMEM" | ||
268 | " FAIL CPU, Status=%x\r\n", cpustatus)); | ||
269 | goto status_check_fail; | ||
270 | } | ||
271 | |||
272 | /* Turn On CPU */ | ||
273 | rtstatus = _rtl92s_firmware_enable_cpu(hw); | ||
274 | if (rtstatus != true) { | ||
275 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
276 | ("Enable CPU fail!\n")); | ||
277 | goto status_check_fail; | ||
278 | } | ||
279 | break; | ||
280 | |||
281 | case FW_STATUS_LOAD_DMEM: | ||
282 | /* Polling DMEM code done */ | ||
283 | do { | ||
284 | cpustatus = rtl_read_byte(rtlpriv, TCR); | ||
285 | if (cpustatus & DMEM_CODE_DONE) | ||
286 | break; | ||
287 | udelay(5); | ||
288 | } while (pollingcnt--); | ||
289 | |||
290 | if (!(cpustatus & DMEM_CODE_DONE) || (pollingcnt <= 0)) { | ||
291 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
292 | ("Polling DMEM code done" | ||
293 | " fail ! cpustatus(%#x)\n", cpustatus)); | ||
294 | goto status_check_fail; | ||
295 | } | ||
296 | |||
297 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
298 | ("DMEM code download success," | ||
299 | " cpustatus(%#x)\n", cpustatus)); | ||
300 | |||
301 | /* Prevent Delay too much and being scheduled out */ | ||
302 | /* Polling Load Firmware ready */ | ||
303 | pollingcnt = 2000; | ||
304 | do { | ||
305 | cpustatus = rtl_read_byte(rtlpriv, TCR); | ||
306 | if (cpustatus & FWRDY) | ||
307 | break; | ||
308 | udelay(40); | ||
309 | } while (pollingcnt--); | ||
310 | |||
311 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
312 | ("Polling Load Firmware ready," | ||
313 | " cpustatus(%x)\n", cpustatus)); | ||
314 | |||
315 | if (((cpustatus & LOAD_FW_READY) != LOAD_FW_READY) || | ||
316 | (pollingcnt <= 0)) { | ||
317 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
318 | ("Polling Load Firmware" | ||
319 | " ready fail ! cpustatus(%x)\n", cpustatus)); | ||
320 | goto status_check_fail; | ||
321 | } | ||
322 | |||
323 | /* If right here, we can set TCR/RCR to desired value */ | ||
324 | /* and config MAC lookback mode to normal mode */ | ||
325 | tmpu4b = rtl_read_dword(rtlpriv, TCR); | ||
326 | rtl_write_dword(rtlpriv, TCR, (tmpu4b & (~TCR_ICV))); | ||
327 | |||
328 | tmpu4b = rtl_read_dword(rtlpriv, RCR); | ||
329 | rtl_write_dword(rtlpriv, RCR, (tmpu4b | RCR_APPFCS | | ||
330 | RCR_APP_ICV | RCR_APP_MIC)); | ||
331 | |||
332 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
333 | ("Current RCR settings(%#x)\n", tmpu4b)); | ||
334 | |||
335 | /* Set to normal mode. */ | ||
336 | rtl_write_byte(rtlpriv, LBKMD_SEL, LBK_NORMAL); | ||
337 | break; | ||
338 | |||
339 | default: | ||
340 | RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, | ||
341 | ("Unknown status check!\n")); | ||
342 | rtstatus = false; | ||
343 | break; | ||
344 | } | ||
345 | |||
346 | status_check_fail: | ||
347 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("loadfw_status(%d), " | ||
348 | "rtstatus(%x)\n", loadfw_status, rtstatus)); | ||
349 | return rtstatus; | ||
350 | } | ||
351 | |||
352 | int rtl92s_download_fw(struct ieee80211_hw *hw) | ||
353 | { | ||
354 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
355 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
356 | struct rt_firmware *firmware = NULL; | ||
357 | struct fw_hdr *pfwheader; | ||
358 | struct fw_priv *pfw_priv = NULL; | ||
359 | u8 *puc_mappedfile = NULL; | ||
360 | u32 ul_filelength = 0; | ||
361 | u32 file_length = 0; | ||
362 | u8 fwhdr_size = RT_8192S_FIRMWARE_HDR_SIZE; | ||
363 | u8 fwstatus = FW_STATUS_INIT; | ||
364 | bool rtstatus = true; | ||
365 | |||
366 | if (!rtlhal->pfirmware) | ||
367 | return 1; | ||
368 | |||
369 | firmware = (struct rt_firmware *)rtlhal->pfirmware; | ||
370 | firmware->fwstatus = FW_STATUS_INIT; | ||
371 | |||
372 | puc_mappedfile = firmware->sz_fw_tmpbuffer; | ||
373 | file_length = firmware->sz_fw_tmpbufferlen; | ||
374 | |||
375 | /* 1. Retrieve FW header. */ | ||
376 | firmware->pfwheader = (struct fw_hdr *) puc_mappedfile; | ||
377 | pfwheader = firmware->pfwheader; | ||
378 | firmware->firmwareversion = byte(pfwheader->version, 0); | ||
379 | firmware->pfwheader->fwpriv.hci_sel = 1;/* pcie */ | ||
380 | |||
381 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("signature:%x, version:" | ||
382 | "%x, size:%x," | ||
383 | "imemsize:%x, sram size:%x\n", pfwheader->signature, | ||
384 | pfwheader->version, pfwheader->dmem_size, | ||
385 | pfwheader->img_imem_size, pfwheader->img_sram_size)); | ||
386 | |||
387 | /* 2. Retrieve IMEM image. */ | ||
388 | if ((pfwheader->img_imem_size == 0) || (pfwheader->img_imem_size > | ||
389 | sizeof(firmware->fw_imem))) { | ||
390 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
391 | ("memory for data image is less than IMEM required\n")); | ||
392 | goto fail; | ||
393 | } else { | ||
394 | puc_mappedfile += fwhdr_size; | ||
395 | |||
396 | memcpy(firmware->fw_imem, puc_mappedfile, | ||
397 | pfwheader->img_imem_size); | ||
398 | firmware->fw_imem_len = pfwheader->img_imem_size; | ||
399 | } | ||
400 | |||
401 | /* 3. Retriecve EMEM image. */ | ||
402 | if (pfwheader->img_sram_size > sizeof(firmware->fw_emem)) { | ||
403 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
404 | ("memory for data image is less than EMEM required\n")); | ||
405 | goto fail; | ||
406 | } else { | ||
407 | puc_mappedfile += firmware->fw_imem_len; | ||
408 | |||
409 | memcpy(firmware->fw_emem, puc_mappedfile, | ||
410 | pfwheader->img_sram_size); | ||
411 | firmware->fw_emem_len = pfwheader->img_sram_size; | ||
412 | } | ||
413 | |||
414 | /* 4. download fw now */ | ||
415 | fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus); | ||
416 | while (fwstatus != FW_STATUS_READY) { | ||
417 | /* Image buffer redirection. */ | ||
418 | switch (fwstatus) { | ||
419 | case FW_STATUS_LOAD_IMEM: | ||
420 | puc_mappedfile = firmware->fw_imem; | ||
421 | ul_filelength = firmware->fw_imem_len; | ||
422 | break; | ||
423 | case FW_STATUS_LOAD_EMEM: | ||
424 | puc_mappedfile = firmware->fw_emem; | ||
425 | ul_filelength = firmware->fw_emem_len; | ||
426 | break; | ||
427 | case FW_STATUS_LOAD_DMEM: | ||
428 | /* Partial update the content of header private. */ | ||
429 | pfwheader = firmware->pfwheader; | ||
430 | pfw_priv = &pfwheader->fwpriv; | ||
431 | _rtl92s_firmwareheader_priveupdate(hw, pfw_priv); | ||
432 | puc_mappedfile = (u8 *)(firmware->pfwheader) + | ||
433 | RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE; | ||
434 | ul_filelength = fwhdr_size - | ||
435 | RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE; | ||
436 | break; | ||
437 | default: | ||
438 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
439 | ("Unexpected Download step!!\n")); | ||
440 | goto fail; | ||
441 | break; | ||
442 | } | ||
443 | |||
444 | /* <2> Download image file */ | ||
445 | rtstatus = _rtl92s_firmware_downloadcode(hw, puc_mappedfile, | ||
446 | ul_filelength); | ||
447 | |||
448 | if (rtstatus != true) { | ||
449 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("fail!\n")); | ||
450 | goto fail; | ||
451 | } | ||
452 | |||
453 | /* <3> Check whether load FW process is ready */ | ||
454 | rtstatus = _rtl92s_firmware_checkready(hw, fwstatus); | ||
455 | if (rtstatus != true) { | ||
456 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("fail!\n")); | ||
457 | goto fail; | ||
458 | } | ||
459 | |||
460 | fwstatus = _rtl92s_firmware_get_nextstatus(firmware->fwstatus); | ||
461 | } | ||
462 | |||
463 | return rtstatus; | ||
464 | fail: | ||
465 | return 0; | ||
466 | } | ||
467 | |||
468 | static u32 _rtl92s_fill_h2c_cmd(struct sk_buff *skb, u32 h2cbufferlen, | ||
469 | u32 cmd_num, u32 *pelement_id, u32 *pcmd_len, | ||
470 | u8 **pcmb_buffer, u8 *cmd_start_seq) | ||
471 | { | ||
472 | u32 totallen = 0, len = 0, tx_desclen = 0; | ||
473 | u32 pre_continueoffset = 0; | ||
474 | u8 *ph2c_buffer; | ||
475 | u8 i = 0; | ||
476 | |||
477 | do { | ||
478 | /* 8 - Byte aligment */ | ||
479 | len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8); | ||
480 | |||
481 | /* Buffer length is not enough */ | ||
482 | if (h2cbufferlen < totallen + len + tx_desclen) | ||
483 | break; | ||
484 | |||
485 | /* Clear content */ | ||
486 | ph2c_buffer = (u8 *)skb_put(skb, (u32)len); | ||
487 | memset((ph2c_buffer + totallen + tx_desclen), 0, len); | ||
488 | |||
489 | /* CMD len */ | ||
490 | SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), | ||
491 | 0, 16, pcmd_len[i]); | ||
492 | |||
493 | /* CMD ID */ | ||
494 | SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), | ||
495 | 16, 8, pelement_id[i]); | ||
496 | |||
497 | /* CMD Sequence */ | ||
498 | *cmd_start_seq = *cmd_start_seq % 0x80; | ||
499 | SET_BITS_TO_LE_4BYTE((ph2c_buffer + totallen + tx_desclen), | ||
500 | 24, 7, *cmd_start_seq); | ||
501 | ++*cmd_start_seq; | ||
502 | |||
503 | /* Copy memory */ | ||
504 | memcpy((ph2c_buffer + totallen + tx_desclen + | ||
505 | H2C_TX_CMD_HDR_LEN), pcmb_buffer[i], pcmd_len[i]); | ||
506 | |||
507 | /* CMD continue */ | ||
508 | /* set the continue in prevoius cmd. */ | ||
509 | if (i < cmd_num - 1) | ||
510 | SET_BITS_TO_LE_4BYTE((ph2c_buffer + pre_continueoffset), | ||
511 | 31, 1, 1); | ||
512 | |||
513 | pre_continueoffset = totallen; | ||
514 | |||
515 | totallen += len; | ||
516 | } while (++i < cmd_num); | ||
517 | |||
518 | return totallen; | ||
519 | } | ||
520 | |||
521 | static u32 _rtl92s_get_h2c_cmdlen(u32 h2cbufferlen, u32 cmd_num, u32 *pcmd_len) | ||
522 | { | ||
523 | u32 totallen = 0, len = 0, tx_desclen = 0; | ||
524 | u8 i = 0; | ||
525 | |||
526 | do { | ||
527 | /* 8 - Byte aligment */ | ||
528 | len = H2C_TX_CMD_HDR_LEN + N_BYTE_ALIGMENT(pcmd_len[i], 8); | ||
529 | |||
530 | /* Buffer length is not enough */ | ||
531 | if (h2cbufferlen < totallen + len + tx_desclen) | ||
532 | break; | ||
533 | |||
534 | totallen += len; | ||
535 | } while (++i < cmd_num); | ||
536 | |||
537 | return totallen + tx_desclen; | ||
538 | } | ||
539 | |||
540 | static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw *hw, u8 h2c_cmd, | ||
541 | u8 *pcmd_buffer) | ||
542 | { | ||
543 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
544 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
545 | struct rtl_tcb_desc *cb_desc; | ||
546 | struct sk_buff *skb; | ||
547 | u32 element_id = 0; | ||
548 | u32 cmd_len = 0; | ||
549 | u32 len; | ||
550 | |||
551 | switch (h2c_cmd) { | ||
552 | case FW_H2C_SETPWRMODE: | ||
553 | element_id = H2C_SETPWRMODE_CMD ; | ||
554 | cmd_len = sizeof(struct h2c_set_pwrmode_parm); | ||
555 | break; | ||
556 | case FW_H2C_JOINBSSRPT: | ||
557 | element_id = H2C_JOINBSSRPT_CMD; | ||
558 | cmd_len = sizeof(struct h2c_joinbss_rpt_parm); | ||
559 | break; | ||
560 | case FW_H2C_WOWLAN_UPDATE_GTK: | ||
561 | element_id = H2C_WOWLAN_UPDATE_GTK_CMD; | ||
562 | cmd_len = sizeof(struct h2c_wpa_two_way_parm); | ||
563 | break; | ||
564 | case FW_H2C_WOWLAN_UPDATE_IV: | ||
565 | element_id = H2C_WOWLAN_UPDATE_IV_CMD; | ||
566 | cmd_len = sizeof(unsigned long long); | ||
567 | break; | ||
568 | case FW_H2C_WOWLAN_OFFLOAD: | ||
569 | element_id = H2C_WOWLAN_FW_OFFLOAD; | ||
570 | cmd_len = sizeof(u8); | ||
571 | break; | ||
572 | default: | ||
573 | break; | ||
574 | } | ||
575 | |||
576 | len = _rtl92s_get_h2c_cmdlen(MAX_TRANSMIT_BUFFER_SIZE, 1, &cmd_len); | ||
577 | skb = dev_alloc_skb(len); | ||
578 | cb_desc = (struct rtl_tcb_desc *)(skb->cb); | ||
579 | cb_desc->queue_index = TXCMD_QUEUE; | ||
580 | cb_desc->cmd_or_init = DESC_PACKET_TYPE_NORMAL; | ||
581 | cb_desc->last_inipkt = false; | ||
582 | |||
583 | _rtl92s_fill_h2c_cmd(skb, MAX_TRANSMIT_BUFFER_SIZE, 1, &element_id, | ||
584 | &cmd_len, &pcmd_buffer, &rtlhal->h2c_txcmd_seq); | ||
585 | _rtl92s_cmd_send_packet(hw, skb, false); | ||
586 | rtlpriv->cfg->ops->tx_polling(hw, TXCMD_QUEUE); | ||
587 | |||
588 | return true; | ||
589 | } | ||
590 | |||
591 | void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 Mode) | ||
592 | { | ||
593 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
594 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
595 | struct h2c_set_pwrmode_parm pwrmode; | ||
596 | u16 max_wakeup_period = 0; | ||
597 | |||
598 | pwrmode.mode = Mode; | ||
599 | pwrmode.flag_low_traffic_en = 0; | ||
600 | pwrmode.flag_lpnav_en = 0; | ||
601 | pwrmode.flag_rf_low_snr_en = 0; | ||
602 | pwrmode.flag_dps_en = 0; | ||
603 | pwrmode.bcn_rx_en = 0; | ||
604 | pwrmode.bcn_to = 0; | ||
605 | SET_BITS_TO_LE_2BYTE((u8 *)(&pwrmode) + 8, 0, 16, | ||
606 | mac->vif->bss_conf.beacon_int); | ||
607 | pwrmode.app_itv = 0; | ||
608 | pwrmode.awake_bcn_itvl = ppsc->reg_max_lps_awakeintvl; | ||
609 | pwrmode.smart_ps = 1; | ||
610 | pwrmode.bcn_pass_period = 10; | ||
611 | |||
612 | /* Set beacon pass count */ | ||
613 | if (pwrmode.mode == FW_PS_MIN_MODE) | ||
614 | max_wakeup_period = mac->vif->bss_conf.beacon_int; | ||
615 | else if (pwrmode.mode == FW_PS_MAX_MODE) | ||
616 | max_wakeup_period = mac->vif->bss_conf.beacon_int * | ||
617 | mac->vif->bss_conf.dtim_period; | ||
618 | |||
619 | if (max_wakeup_period >= 500) | ||
620 | pwrmode.bcn_pass_cnt = 1; | ||
621 | else if ((max_wakeup_period >= 300) && (max_wakeup_period < 500)) | ||
622 | pwrmode.bcn_pass_cnt = 2; | ||
623 | else if ((max_wakeup_period >= 200) && (max_wakeup_period < 300)) | ||
624 | pwrmode.bcn_pass_cnt = 3; | ||
625 | else if ((max_wakeup_period >= 20) && (max_wakeup_period < 200)) | ||
626 | pwrmode.bcn_pass_cnt = 5; | ||
627 | else | ||
628 | pwrmode.bcn_pass_cnt = 1; | ||
629 | |||
630 | _rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_SETPWRMODE, (u8 *)&pwrmode); | ||
631 | |||
632 | } | ||
633 | |||
634 | void rtl92s_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, | ||
635 | u8 mstatus, u8 ps_qosinfo) | ||
636 | { | ||
637 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
638 | struct h2c_joinbss_rpt_parm joinbss_rpt; | ||
639 | |||
640 | joinbss_rpt.opmode = mstatus; | ||
641 | joinbss_rpt.ps_qos_info = ps_qosinfo; | ||
642 | joinbss_rpt.bssid[0] = mac->bssid[0]; | ||
643 | joinbss_rpt.bssid[1] = mac->bssid[1]; | ||
644 | joinbss_rpt.bssid[2] = mac->bssid[2]; | ||
645 | joinbss_rpt.bssid[3] = mac->bssid[3]; | ||
646 | joinbss_rpt.bssid[4] = mac->bssid[4]; | ||
647 | joinbss_rpt.bssid[5] = mac->bssid[5]; | ||
648 | SET_BITS_TO_LE_2BYTE((u8 *)(&joinbss_rpt) + 8, 0, 16, | ||
649 | mac->vif->bss_conf.beacon_int); | ||
650 | SET_BITS_TO_LE_2BYTE((u8 *)(&joinbss_rpt) + 10, 0, 16, mac->assoc_id); | ||
651 | |||
652 | _rtl92s_firmware_set_h2c_cmd(hw, FW_H2C_JOINBSSRPT, (u8 *)&joinbss_rpt); | ||
653 | } | ||
654 | |||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.h b/drivers/net/wireless/rtlwifi/rtl8192se/fw.h new file mode 100644 index 000000000000..74cc503efe8a --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.h | |||
@@ -0,0 +1,375 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | #ifndef __REALTEK_FIRMWARE92S_H__ | ||
30 | #define __REALTEK_FIRMWARE92S_H__ | ||
31 | |||
32 | #define RTL8190_MAX_FIRMWARE_CODE_SIZE 64000 | ||
33 | #define RTL8190_CPU_START_OFFSET 0x80 | ||
34 | /* Firmware Local buffer size. 64k */ | ||
35 | #define MAX_FIRMWARE_CODE_SIZE 0xFF00 | ||
36 | |||
37 | #define RT_8192S_FIRMWARE_HDR_SIZE 80 | ||
38 | #define RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE 32 | ||
39 | |||
40 | /* support till 64 bit bus width OS */ | ||
41 | #define MAX_DEV_ADDR_SIZE 8 | ||
42 | #define MAX_FIRMWARE_INFORMATION_SIZE 32 | ||
43 | #define MAX_802_11_HEADER_LENGTH (40 + \ | ||
44 | MAX_FIRMWARE_INFORMATION_SIZE) | ||
45 | #define ENCRYPTION_MAX_OVERHEAD 128 | ||
46 | #define MAX_FRAGMENT_COUNT 8 | ||
47 | #define MAX_TRANSMIT_BUFFER_SIZE (1600 + \ | ||
48 | (MAX_802_11_HEADER_LENGTH + \ | ||
49 | ENCRYPTION_MAX_OVERHEAD) *\ | ||
50 | MAX_FRAGMENT_COUNT) | ||
51 | |||
52 | #define H2C_TX_CMD_HDR_LEN 8 | ||
53 | |||
54 | /* The following DM control code are for Reg0x364, */ | ||
55 | #define FW_DIG_ENABLE_CTL BIT(0) | ||
56 | #define FW_HIGH_PWR_ENABLE_CTL BIT(1) | ||
57 | #define FW_SS_CTL BIT(2) | ||
58 | #define FW_RA_INIT_CTL BIT(3) | ||
59 | #define FW_RA_BG_CTL BIT(4) | ||
60 | #define FW_RA_N_CTL BIT(5) | ||
61 | #define FW_PWR_TRK_CTL BIT(6) | ||
62 | #define FW_IQK_CTL BIT(7) | ||
63 | #define FW_FA_CTL BIT(8) | ||
64 | #define FW_DRIVER_CTRL_DM_CTL BIT(9) | ||
65 | #define FW_PAPE_CTL_BY_SW_HW BIT(10) | ||
66 | #define FW_DISABLE_ALL_DM 0 | ||
67 | #define FW_PWR_TRK_PARAM_CLR 0x0000ffff | ||
68 | #define FW_RA_PARAM_CLR 0xffff0000 | ||
69 | |||
70 | enum desc_packet_type { | ||
71 | DESC_PACKET_TYPE_INIT = 0, | ||
72 | DESC_PACKET_TYPE_NORMAL = 1, | ||
73 | }; | ||
74 | |||
75 | /* 8-bytes alignment required */ | ||
76 | struct fw_priv { | ||
77 | /* --- long word 0 ---- */ | ||
78 | /* 0x12: CE product, 0x92: IT product */ | ||
79 | u8 signature_0; | ||
80 | /* 0x87: CE product, 0x81: IT product */ | ||
81 | u8 signature_1; | ||
82 | /* 0x81: PCI-AP, 01:PCIe, 02: 92S-U, | ||
83 | * 0x82: USB-AP, 0x12: 72S-U, 03:SDIO */ | ||
84 | u8 hci_sel; | ||
85 | /* the same value as reigster value */ | ||
86 | u8 chip_version; | ||
87 | /* customer ID low byte */ | ||
88 | u8 customer_id_0; | ||
89 | /* customer ID high byte */ | ||
90 | u8 customer_id_1; | ||
91 | /* 0x11: 1T1R, 0x12: 1T2R, | ||
92 | * 0x92: 1T2R turbo, 0x22: 2T2R */ | ||
93 | u8 rf_config; | ||
94 | /* 4: 4EP, 6: 6EP, 11: 11EP */ | ||
95 | u8 usb_ep_num; | ||
96 | |||
97 | /* --- long word 1 ---- */ | ||
98 | /* regulatory class bit map 0 */ | ||
99 | u8 regulatory_class_0; | ||
100 | /* regulatory class bit map 1 */ | ||
101 | u8 regulatory_class_1; | ||
102 | /* regulatory class bit map 2 */ | ||
103 | u8 regulatory_class_2; | ||
104 | /* regulatory class bit map 3 */ | ||
105 | u8 regulatory_class_3; | ||
106 | /* 0:SWSI, 1:HWSI, 2:HWPI */ | ||
107 | u8 rfintfs; | ||
108 | u8 def_nettype; | ||
109 | u8 rsvd010; | ||
110 | u8 rsvd011; | ||
111 | |||
112 | /* --- long word 2 ---- */ | ||
113 | /* 0x00: normal, 0x03: MACLBK, 0x01: PHYLBK */ | ||
114 | u8 lbk_mode; | ||
115 | /* 1: for MP use, 0: for normal | ||
116 | * driver (to be discussed) */ | ||
117 | u8 mp_mode; | ||
118 | u8 rsvd020; | ||
119 | u8 rsvd021; | ||
120 | u8 rsvd022; | ||
121 | u8 rsvd023; | ||
122 | u8 rsvd024; | ||
123 | u8 rsvd025; | ||
124 | |||
125 | /* --- long word 3 ---- */ | ||
126 | /* QoS enable */ | ||
127 | u8 qos_en; | ||
128 | /* 40MHz BW enable */ | ||
129 | /* 4181 convert AMSDU to AMPDU, 0: disable */ | ||
130 | u8 bw_40mhz_en; | ||
131 | u8 amsdu2ampdu_en; | ||
132 | /* 11n AMPDU enable */ | ||
133 | u8 ampdu_en; | ||
134 | /* FW offloads, 0: driver handles */ | ||
135 | u8 rate_control_offload; | ||
136 | /* FW offloads, 0: driver handles */ | ||
137 | u8 aggregation_offload; | ||
138 | u8 rsvd030; | ||
139 | u8 rsvd031; | ||
140 | |||
141 | /* --- long word 4 ---- */ | ||
142 | /* 1. FW offloads, 0: driver handles */ | ||
143 | u8 beacon_offload; | ||
144 | /* 2. FW offloads, 0: driver handles */ | ||
145 | u8 mlme_offload; | ||
146 | /* 3. FW offloads, 0: driver handles */ | ||
147 | u8 hwpc_offload; | ||
148 | /* 4. FW offloads, 0: driver handles */ | ||
149 | u8 tcp_checksum_offload; | ||
150 | /* 5. FW offloads, 0: driver handles */ | ||
151 | u8 tcp_offload; | ||
152 | /* 6. FW offloads, 0: driver handles */ | ||
153 | u8 ps_control_offload; | ||
154 | /* 7. FW offloads, 0: driver handles */ | ||
155 | u8 wwlan_offload; | ||
156 | u8 rsvd040; | ||
157 | |||
158 | /* --- long word 5 ---- */ | ||
159 | /* tcp tx packet length low byte */ | ||
160 | u8 tcp_tx_frame_len_L; | ||
161 | /* tcp tx packet length high byte */ | ||
162 | u8 tcp_tx_frame_len_H; | ||
163 | /* tcp rx packet length low byte */ | ||
164 | u8 tcp_rx_frame_len_L; | ||
165 | /* tcp rx packet length high byte */ | ||
166 | u8 tcp_rx_frame_len_H; | ||
167 | u8 rsvd050; | ||
168 | u8 rsvd051; | ||
169 | u8 rsvd052; | ||
170 | u8 rsvd053; | ||
171 | }; | ||
172 | |||
173 | /* 8-byte alinment required */ | ||
174 | struct fw_hdr { | ||
175 | |||
176 | /* --- LONG WORD 0 ---- */ | ||
177 | u16 signature; | ||
178 | /* 0x8000 ~ 0x8FFF for FPGA version, | ||
179 | * 0x0000 ~ 0x7FFF for ASIC version, */ | ||
180 | u16 version; | ||
181 | /* define the size of boot loader */ | ||
182 | u32 dmem_size; | ||
183 | |||
184 | |||
185 | /* --- LONG WORD 1 ---- */ | ||
186 | /* define the size of FW in IMEM */ | ||
187 | u32 img_imem_size; | ||
188 | /* define the size of FW in SRAM */ | ||
189 | u32 img_sram_size; | ||
190 | |||
191 | /* --- LONG WORD 2 ---- */ | ||
192 | /* define the size of DMEM variable */ | ||
193 | u32 fw_priv_size; | ||
194 | u32 rsvd0; | ||
195 | |||
196 | /* --- LONG WORD 3 ---- */ | ||
197 | u32 rsvd1; | ||
198 | u32 rsvd2; | ||
199 | |||
200 | struct fw_priv fwpriv; | ||
201 | |||
202 | } ; | ||
203 | |||
204 | enum fw_status { | ||
205 | FW_STATUS_INIT = 0, | ||
206 | FW_STATUS_LOAD_IMEM = 1, | ||
207 | FW_STATUS_LOAD_EMEM = 2, | ||
208 | FW_STATUS_LOAD_DMEM = 3, | ||
209 | FW_STATUS_READY = 4, | ||
210 | }; | ||
211 | |||
212 | struct rt_firmware { | ||
213 | struct fw_hdr *pfwheader; | ||
214 | enum fw_status fwstatus; | ||
215 | u16 firmwareversion; | ||
216 | u8 fw_imem[RTL8190_MAX_FIRMWARE_CODE_SIZE]; | ||
217 | u8 fw_emem[RTL8190_MAX_FIRMWARE_CODE_SIZE]; | ||
218 | u32 fw_imem_len; | ||
219 | u32 fw_emem_len; | ||
220 | u8 sz_fw_tmpbuffer[164000]; | ||
221 | u32 sz_fw_tmpbufferlen; | ||
222 | u16 cmdpacket_fragthresold; | ||
223 | }; | ||
224 | |||
225 | struct h2c_set_pwrmode_parm { | ||
226 | u8 mode; | ||
227 | u8 flag_low_traffic_en; | ||
228 | u8 flag_lpnav_en; | ||
229 | u8 flag_rf_low_snr_en; | ||
230 | /* 1: dps, 0: 32k */ | ||
231 | u8 flag_dps_en; | ||
232 | u8 bcn_rx_en; | ||
233 | u8 bcn_pass_cnt; | ||
234 | /* beacon TO (ms). ¡§=0¡¨ no limit. */ | ||
235 | u8 bcn_to; | ||
236 | u16 bcn_itv; | ||
237 | /* only for VOIP mode. */ | ||
238 | u8 app_itv; | ||
239 | u8 awake_bcn_itvl; | ||
240 | u8 smart_ps; | ||
241 | /* unit: 100 ms */ | ||
242 | u8 bcn_pass_period; | ||
243 | }; | ||
244 | |||
245 | struct h2c_joinbss_rpt_parm { | ||
246 | u8 opmode; | ||
247 | u8 ps_qos_info; | ||
248 | u8 bssid[6]; | ||
249 | u16 bcnitv; | ||
250 | u16 aid; | ||
251 | } ; | ||
252 | |||
253 | struct h2c_wpa_ptk { | ||
254 | /* EAPOL-Key Key Confirmation Key (KCK) */ | ||
255 | u8 kck[16]; | ||
256 | /* EAPOL-Key Key Encryption Key (KEK) */ | ||
257 | u8 kek[16]; | ||
258 | /* Temporal Key 1 (TK1) */ | ||
259 | u8 tk1[16]; | ||
260 | union { | ||
261 | /* Temporal Key 2 (TK2) */ | ||
262 | u8 tk2[16]; | ||
263 | struct { | ||
264 | u8 tx_mic_key[8]; | ||
265 | u8 rx_mic_key[8]; | ||
266 | } athu; | ||
267 | } u; | ||
268 | }; | ||
269 | |||
270 | struct h2c_wpa_two_way_parm { | ||
271 | /* algorithm TKIP or AES */ | ||
272 | u8 pairwise_en_alg; | ||
273 | u8 group_en_alg; | ||
274 | struct h2c_wpa_ptk wpa_ptk_value; | ||
275 | } ; | ||
276 | |||
277 | enum h2c_cmd { | ||
278 | FW_H2C_SETPWRMODE = 0, | ||
279 | FW_H2C_JOINBSSRPT = 1, | ||
280 | FW_H2C_WOWLAN_UPDATE_GTK = 2, | ||
281 | FW_H2C_WOWLAN_UPDATE_IV = 3, | ||
282 | FW_H2C_WOWLAN_OFFLOAD = 4, | ||
283 | }; | ||
284 | |||
285 | enum fw_h2c_cmd { | ||
286 | H2C_READ_MACREG_CMD, /*0*/ | ||
287 | H2C_WRITE_MACREG_CMD, | ||
288 | H2C_READBB_CMD, | ||
289 | H2C_WRITEBB_CMD, | ||
290 | H2C_READRF_CMD, | ||
291 | H2C_WRITERF_CMD, /*5*/ | ||
292 | H2C_READ_EEPROM_CMD, | ||
293 | H2C_WRITE_EEPROM_CMD, | ||
294 | H2C_READ_EFUSE_CMD, | ||
295 | H2C_WRITE_EFUSE_CMD, | ||
296 | H2C_READ_CAM_CMD, /*10*/ | ||
297 | H2C_WRITE_CAM_CMD, | ||
298 | H2C_SETBCNITV_CMD, | ||
299 | H2C_SETMBIDCFG_CMD, | ||
300 | H2C_JOINBSS_CMD, | ||
301 | H2C_DISCONNECT_CMD, /*15*/ | ||
302 | H2C_CREATEBSS_CMD, | ||
303 | H2C_SETOPMode_CMD, | ||
304 | H2C_SITESURVEY_CMD, | ||
305 | H2C_SETAUTH_CMD, | ||
306 | H2C_SETKEY_CMD, /*20*/ | ||
307 | H2C_SETSTAKEY_CMD, | ||
308 | H2C_SETASSOCSTA_CMD, | ||
309 | H2C_DELASSOCSTA_CMD, | ||
310 | H2C_SETSTAPWRSTATE_CMD, | ||
311 | H2C_SETBASICRATE_CMD, /*25*/ | ||
312 | H2C_GETBASICRATE_CMD, | ||
313 | H2C_SETDATARATE_CMD, | ||
314 | H2C_GETDATARATE_CMD, | ||
315 | H2C_SETPHYINFO_CMD, | ||
316 | H2C_GETPHYINFO_CMD, /*30*/ | ||
317 | H2C_SETPHY_CMD, | ||
318 | H2C_GETPHY_CMD, | ||
319 | H2C_READRSSI_CMD, | ||
320 | H2C_READGAIN_CMD, | ||
321 | H2C_SETATIM_CMD, /*35*/ | ||
322 | H2C_SETPWRMODE_CMD, | ||
323 | H2C_JOINBSSRPT_CMD, | ||
324 | H2C_SETRATABLE_CMD, | ||
325 | H2C_GETRATABLE_CMD, | ||
326 | H2C_GETCCXREPORT_CMD, /*40*/ | ||
327 | H2C_GETDTMREPORT_CMD, | ||
328 | H2C_GETTXRATESTATICS_CMD, | ||
329 | H2C_SETUSBSUSPEND_CMD, | ||
330 | H2C_SETH2CLBK_CMD, | ||
331 | H2C_TMP1, /*45*/ | ||
332 | H2C_WOWLAN_UPDATE_GTK_CMD, | ||
333 | H2C_WOWLAN_FW_OFFLOAD, | ||
334 | H2C_TMP2, | ||
335 | H2C_TMP3, | ||
336 | H2C_WOWLAN_UPDATE_IV_CMD, /*50*/ | ||
337 | H2C_TMP4, | ||
338 | MAX_H2CCMD /*52*/ | ||
339 | }; | ||
340 | |||
341 | /* The following macros are used for FW | ||
342 | * CMD map and parameter updated. */ | ||
343 | #define FW_CMD_IO_CLR(rtlpriv, _Bit) \ | ||
344 | do { \ | ||
345 | udelay(1000); \ | ||
346 | rtlpriv->rtlhal.fwcmd_iomap &= (~_Bit); \ | ||
347 | } while (0); | ||
348 | |||
349 | #define FW_CMD_IO_UPDATE(rtlpriv, _val) \ | ||
350 | rtlpriv->rtlhal.fwcmd_iomap = _val; | ||
351 | |||
352 | #define FW_CMD_IO_SET(rtlpriv, _val) \ | ||
353 | do { \ | ||
354 | rtl_write_word(rtlpriv, LBUS_MON_ADDR, (u16)_val); \ | ||
355 | FW_CMD_IO_UPDATE(rtlpriv, _val); \ | ||
356 | } while (0); | ||
357 | |||
358 | #define FW_CMD_PARA_SET(rtlpriv, _val) \ | ||
359 | do { \ | ||
360 | rtl_write_dword(rtlpriv, LBUS_ADDR_MASK, _val); \ | ||
361 | rtlpriv->rtlhal.fwcmd_ioparam = _val; \ | ||
362 | } while (0); | ||
363 | |||
364 | #define FW_CMD_IO_QUERY(rtlpriv) \ | ||
365 | (u16)(rtlpriv->rtlhal.fwcmd_iomap) | ||
366 | #define FW_CMD_IO_PARA_QUERY(rtlpriv) \ | ||
367 | ((u32)(rtlpriv->rtlhal.fwcmd_ioparam)) | ||
368 | |||
369 | int rtl92s_download_fw(struct ieee80211_hw *hw); | ||
370 | void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); | ||
371 | void rtl92s_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, | ||
372 | u8 mstatus, u8 ps_qosinfo); | ||
373 | |||
374 | #endif | ||
375 | |||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c new file mode 100644 index 000000000000..2e9005d0454b --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c | |||
@@ -0,0 +1,2512 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../efuse.h" | ||
32 | #include "../base.h" | ||
33 | #include "../regd.h" | ||
34 | #include "../cam.h" | ||
35 | #include "../ps.h" | ||
36 | #include "../pci.h" | ||
37 | #include "reg.h" | ||
38 | #include "def.h" | ||
39 | #include "phy.h" | ||
40 | #include "dm.h" | ||
41 | #include "fw.h" | ||
42 | #include "led.h" | ||
43 | #include "hw.h" | ||
44 | |||
45 | void rtl92se_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | ||
46 | { | ||
47 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
48 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
49 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
50 | |||
51 | switch (variable) { | ||
52 | case HW_VAR_RCR: { | ||
53 | *((u32 *) (val)) = rtlpci->receive_config; | ||
54 | break; | ||
55 | } | ||
56 | case HW_VAR_RF_STATE: { | ||
57 | *((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state; | ||
58 | break; | ||
59 | } | ||
60 | case HW_VAR_FW_PSMODE_STATUS: { | ||
61 | *((bool *) (val)) = ppsc->fw_current_inpsmode; | ||
62 | break; | ||
63 | } | ||
64 | case HW_VAR_CORRECT_TSF: { | ||
65 | u64 tsf; | ||
66 | u32 *ptsf_low = (u32 *)&tsf; | ||
67 | u32 *ptsf_high = ((u32 *)&tsf) + 1; | ||
68 | |||
69 | *ptsf_high = rtl_read_dword(rtlpriv, (TSFR + 4)); | ||
70 | *ptsf_low = rtl_read_dword(rtlpriv, TSFR); | ||
71 | |||
72 | *((u64 *) (val)) = tsf; | ||
73 | |||
74 | break; | ||
75 | } | ||
76 | case HW_VAR_MRC: { | ||
77 | *((bool *)(val)) = rtlpriv->dm.current_mrc_switch; | ||
78 | break; | ||
79 | } | ||
80 | default: { | ||
81 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
82 | ("switch case not process\n")); | ||
83 | break; | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | |||
88 | void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | ||
89 | { | ||
90 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
91 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
92 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
93 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
94 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
95 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
96 | |||
97 | switch (variable) { | ||
98 | case HW_VAR_ETHER_ADDR:{ | ||
99 | rtl_write_dword(rtlpriv, IDR0, ((u32 *)(val))[0]); | ||
100 | rtl_write_word(rtlpriv, IDR4, ((u16 *)(val + 4))[0]); | ||
101 | break; | ||
102 | } | ||
103 | case HW_VAR_BASIC_RATE:{ | ||
104 | u16 rate_cfg = ((u16 *) val)[0]; | ||
105 | u8 rate_index = 0; | ||
106 | |||
107 | if (rtlhal->version == VERSION_8192S_ACUT) | ||
108 | rate_cfg = rate_cfg & 0x150; | ||
109 | else | ||
110 | rate_cfg = rate_cfg & 0x15f; | ||
111 | |||
112 | rate_cfg |= 0x01; | ||
113 | |||
114 | rtl_write_byte(rtlpriv, RRSR, rate_cfg & 0xff); | ||
115 | rtl_write_byte(rtlpriv, RRSR + 1, | ||
116 | (rate_cfg >> 8) & 0xff); | ||
117 | |||
118 | while (rate_cfg > 0x1) { | ||
119 | rate_cfg = (rate_cfg >> 1); | ||
120 | rate_index++; | ||
121 | } | ||
122 | rtl_write_byte(rtlpriv, INIRTSMCS_SEL, rate_index); | ||
123 | |||
124 | break; | ||
125 | } | ||
126 | case HW_VAR_BSSID:{ | ||
127 | rtl_write_dword(rtlpriv, BSSIDR, ((u32 *)(val))[0]); | ||
128 | rtl_write_word(rtlpriv, BSSIDR + 4, | ||
129 | ((u16 *)(val + 4))[0]); | ||
130 | break; | ||
131 | } | ||
132 | case HW_VAR_SIFS:{ | ||
133 | rtl_write_byte(rtlpriv, SIFS_OFDM, val[0]); | ||
134 | rtl_write_byte(rtlpriv, SIFS_OFDM + 1, val[1]); | ||
135 | break; | ||
136 | } | ||
137 | case HW_VAR_SLOT_TIME:{ | ||
138 | u8 e_aci; | ||
139 | |||
140 | RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, | ||
141 | ("HW_VAR_SLOT_TIME %x\n", val[0])); | ||
142 | |||
143 | rtl_write_byte(rtlpriv, SLOT_TIME, val[0]); | ||
144 | |||
145 | for (e_aci = 0; e_aci < AC_MAX; e_aci++) { | ||
146 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
147 | HW_VAR_AC_PARAM, | ||
148 | (u8 *)(&e_aci)); | ||
149 | } | ||
150 | break; | ||
151 | } | ||
152 | case HW_VAR_ACK_PREAMBLE:{ | ||
153 | u8 reg_tmp; | ||
154 | u8 short_preamble = (bool) (*(u8 *) val); | ||
155 | reg_tmp = (mac->cur_40_prime_sc) << 5; | ||
156 | if (short_preamble) | ||
157 | reg_tmp |= 0x80; | ||
158 | |||
159 | rtl_write_byte(rtlpriv, RRSR + 2, reg_tmp); | ||
160 | break; | ||
161 | } | ||
162 | case HW_VAR_AMPDU_MIN_SPACE:{ | ||
163 | u8 min_spacing_to_set; | ||
164 | u8 sec_min_space; | ||
165 | |||
166 | min_spacing_to_set = *((u8 *)val); | ||
167 | if (min_spacing_to_set <= 7) { | ||
168 | if (rtlpriv->sec.pairwise_enc_algorithm == | ||
169 | NO_ENCRYPTION) | ||
170 | sec_min_space = 0; | ||
171 | else | ||
172 | sec_min_space = 1; | ||
173 | |||
174 | if (min_spacing_to_set < sec_min_space) | ||
175 | min_spacing_to_set = sec_min_space; | ||
176 | if (min_spacing_to_set > 5) | ||
177 | min_spacing_to_set = 5; | ||
178 | |||
179 | mac->min_space_cfg = | ||
180 | ((mac->min_space_cfg & 0xf8) | | ||
181 | min_spacing_to_set); | ||
182 | |||
183 | *val = min_spacing_to_set; | ||
184 | |||
185 | RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, | ||
186 | ("Set HW_VAR_AMPDU_MIN_SPACE: %#x\n", | ||
187 | mac->min_space_cfg)); | ||
188 | |||
189 | rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, | ||
190 | mac->min_space_cfg); | ||
191 | } | ||
192 | break; | ||
193 | } | ||
194 | case HW_VAR_SHORTGI_DENSITY:{ | ||
195 | u8 density_to_set; | ||
196 | |||
197 | density_to_set = *((u8 *) val); | ||
198 | mac->min_space_cfg = rtlpriv->rtlhal.minspace_cfg; | ||
199 | mac->min_space_cfg |= (density_to_set << 3); | ||
200 | |||
201 | RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, | ||
202 | ("Set HW_VAR_SHORTGI_DENSITY: %#x\n", | ||
203 | mac->min_space_cfg)); | ||
204 | |||
205 | rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, | ||
206 | mac->min_space_cfg); | ||
207 | |||
208 | break; | ||
209 | } | ||
210 | case HW_VAR_AMPDU_FACTOR:{ | ||
211 | u8 factor_toset; | ||
212 | u8 regtoset; | ||
213 | u8 factorlevel[18] = { | ||
214 | 2, 4, 4, 7, 7, 13, 13, | ||
215 | 13, 2, 7, 7, 13, 13, | ||
216 | 15, 15, 15, 15, 0}; | ||
217 | u8 index = 0; | ||
218 | |||
219 | factor_toset = *((u8 *) val); | ||
220 | if (factor_toset <= 3) { | ||
221 | factor_toset = (1 << (factor_toset + 2)); | ||
222 | if (factor_toset > 0xf) | ||
223 | factor_toset = 0xf; | ||
224 | |||
225 | for (index = 0; index < 17; index++) { | ||
226 | if (factorlevel[index] > factor_toset) | ||
227 | factorlevel[index] = | ||
228 | factor_toset; | ||
229 | } | ||
230 | |||
231 | for (index = 0; index < 8; index++) { | ||
232 | regtoset = ((factorlevel[index * 2]) | | ||
233 | (factorlevel[index * | ||
234 | 2 + 1] << 4)); | ||
235 | rtl_write_byte(rtlpriv, | ||
236 | AGGLEN_LMT_L + index, | ||
237 | regtoset); | ||
238 | } | ||
239 | |||
240 | regtoset = ((factorlevel[16]) | | ||
241 | (factorlevel[17] << 4)); | ||
242 | rtl_write_byte(rtlpriv, AGGLEN_LMT_H, regtoset); | ||
243 | |||
244 | RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD, | ||
245 | ("Set HW_VAR_AMPDU_FACTOR: %#x\n", | ||
246 | factor_toset)); | ||
247 | } | ||
248 | break; | ||
249 | } | ||
250 | case HW_VAR_AC_PARAM:{ | ||
251 | u8 e_aci = *((u8 *) val); | ||
252 | rtl92s_dm_init_edca_turbo(hw); | ||
253 | |||
254 | if (rtlpci->acm_method != eAcmWay2_SW) | ||
255 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
256 | HW_VAR_ACM_CTRL, | ||
257 | (u8 *)(&e_aci)); | ||
258 | break; | ||
259 | } | ||
260 | case HW_VAR_ACM_CTRL:{ | ||
261 | u8 e_aci = *((u8 *) val); | ||
262 | union aci_aifsn *p_aci_aifsn = (union aci_aifsn *)(&( | ||
263 | mac->ac[0].aifs)); | ||
264 | u8 acm = p_aci_aifsn->f.acm; | ||
265 | u8 acm_ctrl = rtl_read_byte(rtlpriv, AcmHwCtrl); | ||
266 | |||
267 | acm_ctrl = acm_ctrl | ((rtlpci->acm_method == 2) ? | ||
268 | 0x0 : 0x1); | ||
269 | |||
270 | if (acm) { | ||
271 | switch (e_aci) { | ||
272 | case AC0_BE: | ||
273 | acm_ctrl |= AcmHw_BeqEn; | ||
274 | break; | ||
275 | case AC2_VI: | ||
276 | acm_ctrl |= AcmHw_ViqEn; | ||
277 | break; | ||
278 | case AC3_VO: | ||
279 | acm_ctrl |= AcmHw_VoqEn; | ||
280 | break; | ||
281 | default: | ||
282 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
283 | ("HW_VAR_ACM_CTRL acm set " | ||
284 | "failed: eACI is %d\n", acm)); | ||
285 | break; | ||
286 | } | ||
287 | } else { | ||
288 | switch (e_aci) { | ||
289 | case AC0_BE: | ||
290 | acm_ctrl &= (~AcmHw_BeqEn); | ||
291 | break; | ||
292 | case AC2_VI: | ||
293 | acm_ctrl &= (~AcmHw_ViqEn); | ||
294 | break; | ||
295 | case AC3_VO: | ||
296 | acm_ctrl &= (~AcmHw_BeqEn); | ||
297 | break; | ||
298 | default: | ||
299 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
300 | ("switch case not process\n")); | ||
301 | break; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE, | ||
306 | ("HW_VAR_ACM_CTRL Write 0x%X\n", acm_ctrl)); | ||
307 | rtl_write_byte(rtlpriv, AcmHwCtrl, acm_ctrl); | ||
308 | break; | ||
309 | } | ||
310 | case HW_VAR_RCR:{ | ||
311 | rtl_write_dword(rtlpriv, RCR, ((u32 *) (val))[0]); | ||
312 | rtlpci->receive_config = ((u32 *) (val))[0]; | ||
313 | break; | ||
314 | } | ||
315 | case HW_VAR_RETRY_LIMIT:{ | ||
316 | u8 retry_limit = ((u8 *) (val))[0]; | ||
317 | |||
318 | rtl_write_word(rtlpriv, RETRY_LIMIT, | ||
319 | retry_limit << RETRY_LIMIT_SHORT_SHIFT | | ||
320 | retry_limit << RETRY_LIMIT_LONG_SHIFT); | ||
321 | break; | ||
322 | } | ||
323 | case HW_VAR_DUAL_TSF_RST: { | ||
324 | break; | ||
325 | } | ||
326 | case HW_VAR_EFUSE_BYTES: { | ||
327 | rtlefuse->efuse_usedbytes = *((u16 *) val); | ||
328 | break; | ||
329 | } | ||
330 | case HW_VAR_EFUSE_USAGE: { | ||
331 | rtlefuse->efuse_usedpercentage = *((u8 *) val); | ||
332 | break; | ||
333 | } | ||
334 | case HW_VAR_IO_CMD: { | ||
335 | break; | ||
336 | } | ||
337 | case HW_VAR_WPA_CONFIG: { | ||
338 | rtl_write_byte(rtlpriv, REG_SECR, *((u8 *) val)); | ||
339 | break; | ||
340 | } | ||
341 | case HW_VAR_SET_RPWM:{ | ||
342 | break; | ||
343 | } | ||
344 | case HW_VAR_H2C_FW_PWRMODE:{ | ||
345 | break; | ||
346 | } | ||
347 | case HW_VAR_FW_PSMODE_STATUS: { | ||
348 | ppsc->fw_current_inpsmode = *((bool *) val); | ||
349 | break; | ||
350 | } | ||
351 | case HW_VAR_H2C_FW_JOINBSSRPT:{ | ||
352 | break; | ||
353 | } | ||
354 | case HW_VAR_AID:{ | ||
355 | break; | ||
356 | } | ||
357 | case HW_VAR_CORRECT_TSF:{ | ||
358 | break; | ||
359 | } | ||
360 | case HW_VAR_MRC: { | ||
361 | bool bmrc_toset = *((bool *)val); | ||
362 | u8 u1bdata = 0; | ||
363 | |||
364 | if (bmrc_toset) { | ||
365 | rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, | ||
366 | MASKBYTE0, 0x33); | ||
367 | u1bdata = (u8)rtl_get_bbreg(hw, | ||
368 | ROFDM1_TRXPATHENABLE, | ||
369 | MASKBYTE0); | ||
370 | rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, | ||
371 | MASKBYTE0, | ||
372 | ((u1bdata & 0xf0) | 0x03)); | ||
373 | u1bdata = (u8)rtl_get_bbreg(hw, | ||
374 | ROFDM0_TRXPATHENABLE, | ||
375 | MASKBYTE1); | ||
376 | rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, | ||
377 | MASKBYTE1, | ||
378 | (u1bdata | 0x04)); | ||
379 | |||
380 | /* Update current settings. */ | ||
381 | rtlpriv->dm.current_mrc_switch = bmrc_toset; | ||
382 | } else { | ||
383 | rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, | ||
384 | MASKBYTE0, 0x13); | ||
385 | u1bdata = (u8)rtl_get_bbreg(hw, | ||
386 | ROFDM1_TRXPATHENABLE, | ||
387 | MASKBYTE0); | ||
388 | rtl_set_bbreg(hw, ROFDM1_TRXPATHENABLE, | ||
389 | MASKBYTE0, | ||
390 | ((u1bdata & 0xf0) | 0x01)); | ||
391 | u1bdata = (u8)rtl_get_bbreg(hw, | ||
392 | ROFDM0_TRXPATHENABLE, | ||
393 | MASKBYTE1); | ||
394 | rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, | ||
395 | MASKBYTE1, (u1bdata & 0xfb)); | ||
396 | |||
397 | /* Update current settings. */ | ||
398 | rtlpriv->dm.current_mrc_switch = bmrc_toset; | ||
399 | } | ||
400 | |||
401 | break; | ||
402 | } | ||
403 | default: | ||
404 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
405 | ("switch case not process\n")); | ||
406 | break; | ||
407 | } | ||
408 | |||
409 | } | ||
410 | |||
411 | void rtl92se_enable_hw_security_config(struct ieee80211_hw *hw) | ||
412 | { | ||
413 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
414 | u8 sec_reg_value = 0x0; | ||
415 | |||
416 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("PairwiseEncAlgorithm = %d " | ||
417 | "GroupEncAlgorithm = %d\n", | ||
418 | rtlpriv->sec.pairwise_enc_algorithm, | ||
419 | rtlpriv->sec.group_enc_algorithm)); | ||
420 | |||
421 | if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) { | ||
422 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
423 | ("not open hw encryption\n")); | ||
424 | return; | ||
425 | } | ||
426 | |||
427 | sec_reg_value = SCR_TXENCENABLE | SCR_RXENCENABLE; | ||
428 | |||
429 | if (rtlpriv->sec.use_defaultkey) { | ||
430 | sec_reg_value |= SCR_TXUSEDK; | ||
431 | sec_reg_value |= SCR_RXUSEDK; | ||
432 | } | ||
433 | |||
434 | RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, ("The SECR-value %x\n", | ||
435 | sec_reg_value)); | ||
436 | |||
437 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value); | ||
438 | |||
439 | } | ||
440 | |||
441 | static u8 _rtl92ce_halset_sysclk(struct ieee80211_hw *hw, u8 data) | ||
442 | { | ||
443 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
444 | u8 waitcount = 100; | ||
445 | bool bresult = false; | ||
446 | u8 tmpvalue; | ||
447 | |||
448 | rtl_write_byte(rtlpriv, SYS_CLKR + 1, data); | ||
449 | |||
450 | /* Wait the MAC synchronized. */ | ||
451 | udelay(400); | ||
452 | |||
453 | /* Check if it is set ready. */ | ||
454 | tmpvalue = rtl_read_byte(rtlpriv, SYS_CLKR + 1); | ||
455 | bresult = ((tmpvalue & BIT(7)) == (data & BIT(7))); | ||
456 | |||
457 | if ((data & (BIT(6) | BIT(7))) == false) { | ||
458 | waitcount = 100; | ||
459 | tmpvalue = 0; | ||
460 | |||
461 | while (1) { | ||
462 | waitcount--; | ||
463 | |||
464 | tmpvalue = rtl_read_byte(rtlpriv, SYS_CLKR + 1); | ||
465 | if ((tmpvalue & BIT(6))) | ||
466 | break; | ||
467 | |||
468 | printk(KERN_ERR "wait for BIT(6) return value %x\n", | ||
469 | tmpvalue); | ||
470 | if (waitcount == 0) | ||
471 | break; | ||
472 | |||
473 | udelay(10); | ||
474 | } | ||
475 | |||
476 | if (waitcount == 0) | ||
477 | bresult = false; | ||
478 | else | ||
479 | bresult = true; | ||
480 | } | ||
481 | |||
482 | return bresult; | ||
483 | } | ||
484 | |||
485 | void rtl8192se_gpiobit3_cfg_inputmode(struct ieee80211_hw *hw) | ||
486 | { | ||
487 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
488 | u8 u1tmp; | ||
489 | |||
490 | /* The following config GPIO function */ | ||
491 | rtl_write_byte(rtlpriv, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO)); | ||
492 | u1tmp = rtl_read_byte(rtlpriv, GPIO_IO_SEL); | ||
493 | |||
494 | /* config GPIO3 to input */ | ||
495 | u1tmp &= HAL_8192S_HW_GPIO_OFF_MASK; | ||
496 | rtl_write_byte(rtlpriv, GPIO_IO_SEL, u1tmp); | ||
497 | |||
498 | } | ||
499 | |||
500 | static u8 _rtl92se_rf_onoff_detect(struct ieee80211_hw *hw) | ||
501 | { | ||
502 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
503 | u8 u1tmp; | ||
504 | u8 retval = ERFON; | ||
505 | |||
506 | /* The following config GPIO function */ | ||
507 | rtl_write_byte(rtlpriv, MAC_PINMUX_CFG, (GPIOMUX_EN | GPIOSEL_GPIO)); | ||
508 | u1tmp = rtl_read_byte(rtlpriv, GPIO_IO_SEL); | ||
509 | |||
510 | /* config GPIO3 to input */ | ||
511 | u1tmp &= HAL_8192S_HW_GPIO_OFF_MASK; | ||
512 | rtl_write_byte(rtlpriv, GPIO_IO_SEL, u1tmp); | ||
513 | |||
514 | /* On some of the platform, driver cannot read correct | ||
515 | * value without delay between Write_GPIO_SEL and Read_GPIO_IN */ | ||
516 | mdelay(10); | ||
517 | |||
518 | /* check GPIO3 */ | ||
519 | u1tmp = rtl_read_byte(rtlpriv, GPIO_IN); | ||
520 | retval = (u1tmp & HAL_8192S_HW_GPIO_OFF_BIT) ? ERFON : ERFOFF; | ||
521 | |||
522 | return retval; | ||
523 | } | ||
524 | |||
525 | static void _rtl92se_macconfig_before_fwdownload(struct ieee80211_hw *hw) | ||
526 | { | ||
527 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
528 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
529 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
530 | |||
531 | u8 i; | ||
532 | u8 tmpu1b; | ||
533 | u16 tmpu2b; | ||
534 | u8 pollingcnt = 20; | ||
535 | |||
536 | if (rtlpci->first_init) { | ||
537 | /* Reset PCIE Digital */ | ||
538 | tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); | ||
539 | tmpu1b &= 0xFE; | ||
540 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b); | ||
541 | udelay(1); | ||
542 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b | BIT(0)); | ||
543 | } | ||
544 | |||
545 | /* Switch to SW IO control */ | ||
546 | tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); | ||
547 | if (tmpu1b & BIT(7)) { | ||
548 | tmpu1b &= ~(BIT(6) | BIT(7)); | ||
549 | |||
550 | /* Set failed, return to prevent hang. */ | ||
551 | if (!_rtl92ce_halset_sysclk(hw, tmpu1b)) | ||
552 | return; | ||
553 | } | ||
554 | |||
555 | rtl_write_byte(rtlpriv, AFE_PLL_CTRL, 0x0); | ||
556 | udelay(50); | ||
557 | rtl_write_byte(rtlpriv, LDOA15_CTRL, 0x34); | ||
558 | udelay(50); | ||
559 | |||
560 | /* Clear FW RPWM for FW control LPS.*/ | ||
561 | rtl_write_byte(rtlpriv, RPWM, 0x0); | ||
562 | |||
563 | /* Reset MAC-IO and CPU and Core Digital BIT(10)/11/15 */ | ||
564 | tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); | ||
565 | tmpu1b &= 0x73; | ||
566 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b); | ||
567 | /* wait for BIT 10/11/15 to pull high automatically!! */ | ||
568 | mdelay(1); | ||
569 | |||
570 | rtl_write_byte(rtlpriv, CMDR, 0); | ||
571 | rtl_write_byte(rtlpriv, TCR, 0); | ||
572 | |||
573 | /* Data sheet not define 0x562!!! Copy from WMAC!!!!! */ | ||
574 | tmpu1b = rtl_read_byte(rtlpriv, 0x562); | ||
575 | tmpu1b |= 0x08; | ||
576 | rtl_write_byte(rtlpriv, 0x562, tmpu1b); | ||
577 | tmpu1b &= ~(BIT(3)); | ||
578 | rtl_write_byte(rtlpriv, 0x562, tmpu1b); | ||
579 | |||
580 | /* Enable AFE clock source */ | ||
581 | tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL); | ||
582 | rtl_write_byte(rtlpriv, AFE_XTAL_CTRL, (tmpu1b | 0x01)); | ||
583 | /* Delay 1.5ms */ | ||
584 | mdelay(2); | ||
585 | tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL + 1); | ||
586 | rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, (tmpu1b & 0xfb)); | ||
587 | |||
588 | /* Enable AFE Macro Block's Bandgap */ | ||
589 | tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); | ||
590 | rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | BIT(0))); | ||
591 | mdelay(1); | ||
592 | |||
593 | /* Enable AFE Mbias */ | ||
594 | tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); | ||
595 | rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | 0x02)); | ||
596 | mdelay(1); | ||
597 | |||
598 | /* Enable LDOA15 block */ | ||
599 | tmpu1b = rtl_read_byte(rtlpriv, LDOA15_CTRL); | ||
600 | rtl_write_byte(rtlpriv, LDOA15_CTRL, (tmpu1b | BIT(0))); | ||
601 | |||
602 | /* Set Digital Vdd to Retention isolation Path. */ | ||
603 | tmpu2b = rtl_read_word(rtlpriv, REG_SYS_ISO_CTRL); | ||
604 | rtl_write_word(rtlpriv, REG_SYS_ISO_CTRL, (tmpu2b | BIT(11))); | ||
605 | |||
606 | /* For warm reboot NIC disappera bug. */ | ||
607 | tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); | ||
608 | rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(13))); | ||
609 | |||
610 | rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, 0x68); | ||
611 | |||
612 | /* Enable AFE PLL Macro Block */ | ||
613 | /* We need to delay 100u before enabling PLL. */ | ||
614 | udelay(200); | ||
615 | tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL); | ||
616 | rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | BIT(4))); | ||
617 | |||
618 | /* for divider reset */ | ||
619 | udelay(100); | ||
620 | rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | | ||
621 | BIT(4) | BIT(6))); | ||
622 | udelay(10); | ||
623 | rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | BIT(4))); | ||
624 | udelay(10); | ||
625 | |||
626 | /* Enable MAC 80MHZ clock */ | ||
627 | tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL + 1); | ||
628 | rtl_write_byte(rtlpriv, AFE_PLL_CTRL + 1, (tmpu1b | BIT(0))); | ||
629 | mdelay(1); | ||
630 | |||
631 | /* Release isolation AFE PLL & MD */ | ||
632 | rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, 0xA6); | ||
633 | |||
634 | /* Enable MAC clock */ | ||
635 | tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); | ||
636 | rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b | BIT(12) | BIT(11))); | ||
637 | |||
638 | /* Enable Core digital and enable IOREG R/W */ | ||
639 | tmpu2b = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN); | ||
640 | rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11))); | ||
641 | |||
642 | tmpu1b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); | ||
643 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, tmpu1b & ~(BIT(7))); | ||
644 | |||
645 | /* enable REG_EN */ | ||
646 | rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (tmpu2b | BIT(11) | BIT(15))); | ||
647 | |||
648 | /* Switch the control path. */ | ||
649 | tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); | ||
650 | rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b & (~BIT(2)))); | ||
651 | |||
652 | tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); | ||
653 | tmpu1b = ((tmpu1b | BIT(7)) & (~BIT(6))); | ||
654 | if (!_rtl92ce_halset_sysclk(hw, tmpu1b)) | ||
655 | return; /* Set failed, return to prevent hang. */ | ||
656 | |||
657 | rtl_write_word(rtlpriv, CMDR, 0x07FC); | ||
658 | |||
659 | /* MH We must enable the section of code to prevent load IMEM fail. */ | ||
660 | /* Load MAC register from WMAc temporarily We simulate macreg. */ | ||
661 | /* txt HW will provide MAC txt later */ | ||
662 | rtl_write_byte(rtlpriv, 0x6, 0x30); | ||
663 | rtl_write_byte(rtlpriv, 0x49, 0xf0); | ||
664 | |||
665 | rtl_write_byte(rtlpriv, 0x4b, 0x81); | ||
666 | |||
667 | rtl_write_byte(rtlpriv, 0xb5, 0x21); | ||
668 | |||
669 | rtl_write_byte(rtlpriv, 0xdc, 0xff); | ||
670 | rtl_write_byte(rtlpriv, 0xdd, 0xff); | ||
671 | rtl_write_byte(rtlpriv, 0xde, 0xff); | ||
672 | rtl_write_byte(rtlpriv, 0xdf, 0xff); | ||
673 | |||
674 | rtl_write_byte(rtlpriv, 0x11a, 0x00); | ||
675 | rtl_write_byte(rtlpriv, 0x11b, 0x00); | ||
676 | |||
677 | for (i = 0; i < 32; i++) | ||
678 | rtl_write_byte(rtlpriv, INIMCS_SEL + i, 0x1b); | ||
679 | |||
680 | rtl_write_byte(rtlpriv, 0x236, 0xff); | ||
681 | |||
682 | rtl_write_byte(rtlpriv, 0x503, 0x22); | ||
683 | |||
684 | if (ppsc->support_aspm && !ppsc->support_backdoor) | ||
685 | rtl_write_byte(rtlpriv, 0x560, 0x40); | ||
686 | else | ||
687 | rtl_write_byte(rtlpriv, 0x560, 0x00); | ||
688 | |||
689 | rtl_write_byte(rtlpriv, DBG_PORT, 0x91); | ||
690 | |||
691 | /* Set RX Desc Address */ | ||
692 | rtl_write_dword(rtlpriv, RDQDA, rtlpci->rx_ring[RX_MPDU_QUEUE].dma); | ||
693 | rtl_write_dword(rtlpriv, RCDA, rtlpci->rx_ring[RX_CMD_QUEUE].dma); | ||
694 | |||
695 | /* Set TX Desc Address */ | ||
696 | rtl_write_dword(rtlpriv, TBKDA, rtlpci->tx_ring[BK_QUEUE].dma); | ||
697 | rtl_write_dword(rtlpriv, TBEDA, rtlpci->tx_ring[BE_QUEUE].dma); | ||
698 | rtl_write_dword(rtlpriv, TVIDA, rtlpci->tx_ring[VI_QUEUE].dma); | ||
699 | rtl_write_dword(rtlpriv, TVODA, rtlpci->tx_ring[VO_QUEUE].dma); | ||
700 | rtl_write_dword(rtlpriv, TBDA, rtlpci->tx_ring[BEACON_QUEUE].dma); | ||
701 | rtl_write_dword(rtlpriv, TCDA, rtlpci->tx_ring[TXCMD_QUEUE].dma); | ||
702 | rtl_write_dword(rtlpriv, TMDA, rtlpci->tx_ring[MGNT_QUEUE].dma); | ||
703 | rtl_write_dword(rtlpriv, THPDA, rtlpci->tx_ring[HIGH_QUEUE].dma); | ||
704 | rtl_write_dword(rtlpriv, HDA, rtlpci->tx_ring[HCCA_QUEUE].dma); | ||
705 | |||
706 | rtl_write_word(rtlpriv, CMDR, 0x37FC); | ||
707 | |||
708 | /* To make sure that TxDMA can ready to download FW. */ | ||
709 | /* We should reset TxDMA if IMEM RPT was not ready. */ | ||
710 | do { | ||
711 | tmpu1b = rtl_read_byte(rtlpriv, TCR); | ||
712 | if ((tmpu1b & TXDMA_INIT_VALUE) == TXDMA_INIT_VALUE) | ||
713 | break; | ||
714 | |||
715 | udelay(5); | ||
716 | } while (pollingcnt--); | ||
717 | |||
718 | if (pollingcnt <= 0) { | ||
719 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
720 | ("Polling TXDMA_INIT_VALUE " | ||
721 | "timeout!! Current TCR(%#x)\n", tmpu1b)); | ||
722 | tmpu1b = rtl_read_byte(rtlpriv, CMDR); | ||
723 | rtl_write_byte(rtlpriv, CMDR, tmpu1b & (~TXDMA_EN)); | ||
724 | udelay(2); | ||
725 | /* Reset TxDMA */ | ||
726 | rtl_write_byte(rtlpriv, CMDR, tmpu1b | TXDMA_EN); | ||
727 | } | ||
728 | |||
729 | /* After MACIO reset,we must refresh LED state. */ | ||
730 | if ((ppsc->rfoff_reason == RF_CHANGE_BY_IPS) || | ||
731 | (ppsc->rfoff_reason == 0)) { | ||
732 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
733 | struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); | ||
734 | enum rf_pwrstate rfpwr_state_toset; | ||
735 | rfpwr_state_toset = _rtl92se_rf_onoff_detect(hw); | ||
736 | |||
737 | if (rfpwr_state_toset == ERFON) | ||
738 | rtl92se_sw_led_on(hw, pLed0); | ||
739 | } | ||
740 | } | ||
741 | |||
742 | static void _rtl92se_macconfig_after_fwdownload(struct ieee80211_hw *hw) | ||
743 | { | ||
744 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
745 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
746 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
747 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
748 | u8 i; | ||
749 | u16 tmpu2b; | ||
750 | |||
751 | /* 1. System Configure Register (Offset: 0x0000 - 0x003F) */ | ||
752 | |||
753 | /* 2. Command Control Register (Offset: 0x0040 - 0x004F) */ | ||
754 | /* Turn on 0x40 Command register */ | ||
755 | rtl_write_word(rtlpriv, CMDR, (BBRSTN | BB_GLB_RSTN | | ||
756 | SCHEDULE_EN | MACRXEN | MACTXEN | DDMA_EN | FW2HW_EN | | ||
757 | RXDMA_EN | TXDMA_EN | HCI_RXDMA_EN | HCI_TXDMA_EN)); | ||
758 | |||
759 | /* Set TCR TX DMA pre 2 FULL enable bit */ | ||
760 | rtl_write_dword(rtlpriv, TCR, rtl_read_dword(rtlpriv, TCR) | | ||
761 | TXDMAPRE2FULL); | ||
762 | |||
763 | /* Set RCR */ | ||
764 | rtl_write_dword(rtlpriv, RCR, rtlpci->receive_config); | ||
765 | |||
766 | /* 3. MACID Setting Register (Offset: 0x0050 - 0x007F) */ | ||
767 | |||
768 | /* 4. Timing Control Register (Offset: 0x0080 - 0x009F) */ | ||
769 | /* Set CCK/OFDM SIFS */ | ||
770 | /* CCK SIFS shall always be 10us. */ | ||
771 | rtl_write_word(rtlpriv, SIFS_CCK, 0x0a0a); | ||
772 | rtl_write_word(rtlpriv, SIFS_OFDM, 0x1010); | ||
773 | |||
774 | /* Set AckTimeout */ | ||
775 | rtl_write_byte(rtlpriv, ACK_TIMEOUT, 0x40); | ||
776 | |||
777 | /* Beacon related */ | ||
778 | rtl_write_word(rtlpriv, BCN_INTERVAL, 100); | ||
779 | rtl_write_word(rtlpriv, ATIMWND, 2); | ||
780 | |||
781 | /* 5. FIFO Control Register (Offset: 0x00A0 - 0x015F) */ | ||
782 | /* 5.1 Initialize Number of Reserved Pages in Firmware Queue */ | ||
783 | /* Firmware allocate now, associate with FW internal setting.!!! */ | ||
784 | |||
785 | /* 5.2 Setting TX/RX page size 0/1/2/3/4=64/128/256/512/1024 */ | ||
786 | /* 5.3 Set driver info, we only accept PHY status now. */ | ||
787 | /* 5.4 Set RXDMA arbitration to control RXDMA/MAC/FW R/W for RXFIFO */ | ||
788 | rtl_write_byte(rtlpriv, RXDMA, rtl_read_byte(rtlpriv, RXDMA) | BIT(6)); | ||
789 | |||
790 | /* 6. Adaptive Control Register (Offset: 0x0160 - 0x01CF) */ | ||
791 | /* Set RRSR to all legacy rate and HT rate | ||
792 | * CCK rate is supported by default. | ||
793 | * CCK rate will be filtered out only when associated | ||
794 | * AP does not support it. | ||
795 | * Only enable ACK rate to OFDM 24M | ||
796 | * Disable RRSR for CCK rate in A-Cut */ | ||
797 | |||
798 | if (rtlhal->version == VERSION_8192S_ACUT) | ||
799 | rtl_write_byte(rtlpriv, RRSR, 0xf0); | ||
800 | else if (rtlhal->version == VERSION_8192S_BCUT) | ||
801 | rtl_write_byte(rtlpriv, RRSR, 0xff); | ||
802 | rtl_write_byte(rtlpriv, RRSR + 1, 0x01); | ||
803 | rtl_write_byte(rtlpriv, RRSR + 2, 0x00); | ||
804 | |||
805 | /* A-Cut IC do not support CCK rate. We forbid ARFR to */ | ||
806 | /* fallback to CCK rate */ | ||
807 | for (i = 0; i < 8; i++) { | ||
808 | /*Disable RRSR for CCK rate in A-Cut */ | ||
809 | if (rtlhal->version == VERSION_8192S_ACUT) | ||
810 | rtl_write_dword(rtlpriv, ARFR0 + i * 4, 0x1f0ff0f0); | ||
811 | } | ||
812 | |||
813 | /* Different rate use different AMPDU size */ | ||
814 | /* MCS32/ MCS15_SG use max AMPDU size 15*2=30K */ | ||
815 | rtl_write_byte(rtlpriv, AGGLEN_LMT_H, 0x0f); | ||
816 | /* MCS0/1/2/3 use max AMPDU size 4*2=8K */ | ||
817 | rtl_write_word(rtlpriv, AGGLEN_LMT_L, 0x7442); | ||
818 | /* MCS4/5 use max AMPDU size 8*2=16K 6/7 use 10*2=20K */ | ||
819 | rtl_write_word(rtlpriv, AGGLEN_LMT_L + 2, 0xddd7); | ||
820 | /* MCS8/9 use max AMPDU size 8*2=16K 10/11 use 10*2=20K */ | ||
821 | rtl_write_word(rtlpriv, AGGLEN_LMT_L + 4, 0xd772); | ||
822 | /* MCS12/13/14/15 use max AMPDU size 15*2=30K */ | ||
823 | rtl_write_word(rtlpriv, AGGLEN_LMT_L + 6, 0xfffd); | ||
824 | |||
825 | /* Set Data / Response auto rate fallack retry count */ | ||
826 | rtl_write_dword(rtlpriv, DARFRC, 0x04010000); | ||
827 | rtl_write_dword(rtlpriv, DARFRC + 4, 0x09070605); | ||
828 | rtl_write_dword(rtlpriv, RARFRC, 0x04010000); | ||
829 | rtl_write_dword(rtlpriv, RARFRC + 4, 0x09070605); | ||
830 | |||
831 | /* 7. EDCA Setting Register (Offset: 0x01D0 - 0x01FF) */ | ||
832 | /* Set all rate to support SG */ | ||
833 | rtl_write_word(rtlpriv, SG_RATE, 0xFFFF); | ||
834 | |||
835 | /* 8. WMAC, BA, and CCX related Register (Offset: 0x0200 - 0x023F) */ | ||
836 | /* Set NAV protection length */ | ||
837 | rtl_write_word(rtlpriv, NAV_PROT_LEN, 0x0080); | ||
838 | /* CF-END Threshold */ | ||
839 | rtl_write_byte(rtlpriv, CFEND_TH, 0xFF); | ||
840 | /* Set AMPDU minimum space */ | ||
841 | rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, 0x07); | ||
842 | /* Set TXOP stall control for several queue/HI/BCN/MGT/ */ | ||
843 | rtl_write_byte(rtlpriv, TXOP_STALL_CTRL, 0x00); | ||
844 | |||
845 | /* 9. Security Control Register (Offset: 0x0240 - 0x025F) */ | ||
846 | /* 10. Power Save Control Register (Offset: 0x0260 - 0x02DF) */ | ||
847 | /* 11. General Purpose Register (Offset: 0x02E0 - 0x02FF) */ | ||
848 | /* 12. Host Interrupt Status Register (Offset: 0x0300 - 0x030F) */ | ||
849 | /* 13. Test Mode and Debug Control Register (Offset: 0x0310 - 0x034F) */ | ||
850 | |||
851 | /* 14. Set driver info, we only accept PHY status now. */ | ||
852 | rtl_write_byte(rtlpriv, RXDRVINFO_SZ, 4); | ||
853 | |||
854 | /* 15. For EEPROM R/W Workaround */ | ||
855 | /* 16. For EFUSE to share REG_SYS_FUNC_EN with EEPROM!!! */ | ||
856 | tmpu2b = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN); | ||
857 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, tmpu2b | BIT(13)); | ||
858 | tmpu2b = rtl_read_byte(rtlpriv, REG_SYS_ISO_CTRL); | ||
859 | rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, tmpu2b & (~BIT(8))); | ||
860 | |||
861 | /* 17. For EFUSE */ | ||
862 | /* We may R/W EFUSE in EEPROM mode */ | ||
863 | if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { | ||
864 | u8 tempval; | ||
865 | |||
866 | tempval = rtl_read_byte(rtlpriv, REG_SYS_ISO_CTRL + 1); | ||
867 | tempval &= 0xFE; | ||
868 | rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL + 1, tempval); | ||
869 | |||
870 | /* Change Program timing */ | ||
871 | rtl_write_byte(rtlpriv, REG_EFUSE_CTRL + 3, 0x72); | ||
872 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("EFUSE CONFIG OK\n")); | ||
873 | } | ||
874 | |||
875 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("OK\n")); | ||
876 | |||
877 | } | ||
878 | |||
879 | static void _rtl92se_hw_configure(struct ieee80211_hw *hw) | ||
880 | { | ||
881 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
882 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
883 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
884 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
885 | |||
886 | u8 reg_bw_opmode = 0; | ||
887 | u32 reg_ratr = 0, reg_rrsr = 0; | ||
888 | u8 regtmp = 0; | ||
889 | |||
890 | reg_bw_opmode = BW_OPMODE_20MHZ; | ||
891 | reg_ratr = RATE_ALL_CCK | RATE_ALL_OFDM_AG | RATE_ALL_OFDM_1SS | | ||
892 | RATE_ALL_OFDM_2SS; | ||
893 | reg_rrsr = RATE_ALL_CCK | RATE_ALL_OFDM_AG; | ||
894 | |||
895 | regtmp = rtl_read_byte(rtlpriv, INIRTSMCS_SEL); | ||
896 | reg_rrsr = ((reg_rrsr & 0x000fffff) << 8) | regtmp; | ||
897 | rtl_write_dword(rtlpriv, INIRTSMCS_SEL, reg_rrsr); | ||
898 | rtl_write_byte(rtlpriv, BW_OPMODE, reg_bw_opmode); | ||
899 | |||
900 | /* Set Retry Limit here */ | ||
901 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT, | ||
902 | (u8 *)(&rtlpci->shortretry_limit)); | ||
903 | |||
904 | rtl_write_byte(rtlpriv, MLT, 0x8f); | ||
905 | |||
906 | /* For Min Spacing configuration. */ | ||
907 | switch (rtlphy->rf_type) { | ||
908 | case RF_1T2R: | ||
909 | case RF_1T1R: | ||
910 | rtlhal->minspace_cfg = (MAX_MSS_DENSITY_1T << 3); | ||
911 | break; | ||
912 | case RF_2T2R: | ||
913 | case RF_2T2R_GREEN: | ||
914 | rtlhal->minspace_cfg = (MAX_MSS_DENSITY_2T << 3); | ||
915 | break; | ||
916 | } | ||
917 | rtl_write_byte(rtlpriv, AMPDU_MIN_SPACE, rtlhal->minspace_cfg); | ||
918 | } | ||
919 | |||
920 | int rtl92se_hw_init(struct ieee80211_hw *hw) | ||
921 | { | ||
922 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
923 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
924 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
925 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
926 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
927 | u8 tmp_byte = 0; | ||
928 | |||
929 | bool rtstatus = true; | ||
930 | u8 tmp_u1b; | ||
931 | int err = false; | ||
932 | u8 i; | ||
933 | int wdcapra_add[] = { | ||
934 | EDCAPARA_BE, EDCAPARA_BK, | ||
935 | EDCAPARA_VI, EDCAPARA_VO}; | ||
936 | u8 secr_value = 0x0; | ||
937 | |||
938 | rtlpci->being_init_adapter = true; | ||
939 | |||
940 | rtlpriv->intf_ops->disable_aspm(hw); | ||
941 | |||
942 | /* 1. MAC Initialize */ | ||
943 | /* Before FW download, we have to set some MAC register */ | ||
944 | _rtl92se_macconfig_before_fwdownload(hw); | ||
945 | |||
946 | rtlhal->version = (enum version_8192s)((rtl_read_dword(rtlpriv, | ||
947 | PMC_FSM) >> 16) & 0xF); | ||
948 | |||
949 | rtl8192se_gpiobit3_cfg_inputmode(hw); | ||
950 | |||
951 | /* 2. download firmware */ | ||
952 | rtstatus = rtl92s_download_fw(hw); | ||
953 | if (!rtstatus) { | ||
954 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
955 | ("Failed to download FW. " | ||
956 | "Init HW without FW now.., Please copy FW into" | ||
957 | "/lib/firmware/rtlwifi\n")); | ||
958 | rtlhal->fw_ready = false; | ||
959 | } else { | ||
960 | rtlhal->fw_ready = true; | ||
961 | } | ||
962 | |||
963 | /* After FW download, we have to reset MAC register */ | ||
964 | _rtl92se_macconfig_after_fwdownload(hw); | ||
965 | |||
966 | /*Retrieve default FW Cmd IO map. */ | ||
967 | rtlhal->fwcmd_iomap = rtl_read_word(rtlpriv, LBUS_MON_ADDR); | ||
968 | rtlhal->fwcmd_ioparam = rtl_read_dword(rtlpriv, LBUS_ADDR_MASK); | ||
969 | |||
970 | /* 3. Initialize MAC/PHY Config by MACPHY_reg.txt */ | ||
971 | if (rtl92s_phy_mac_config(hw) != true) { | ||
972 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("MAC Config failed\n")); | ||
973 | return rtstatus; | ||
974 | } | ||
975 | |||
976 | /* Make sure BB/RF write OK. We should prevent enter IPS. radio off. */ | ||
977 | /* We must set flag avoid BB/RF config period later!! */ | ||
978 | rtl_write_dword(rtlpriv, CMDR, 0x37FC); | ||
979 | |||
980 | /* 4. Initialize BB After MAC Config PHY_reg.txt, AGC_Tab.txt */ | ||
981 | if (rtl92s_phy_bb_config(hw) != true) { | ||
982 | RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, ("BB Config failed\n")); | ||
983 | return rtstatus; | ||
984 | } | ||
985 | |||
986 | /* 5. Initiailze RF RAIO_A.txt RF RAIO_B.txt */ | ||
987 | /* Before initalizing RF. We can not use FW to do RF-R/W. */ | ||
988 | |||
989 | rtlphy->rf_mode = RF_OP_BY_SW_3WIRE; | ||
990 | |||
991 | /* RF Power Save */ | ||
992 | #if 0 | ||
993 | /* H/W or S/W RF OFF before sleep. */ | ||
994 | if (rtlpriv->psc.rfoff_reason > RF_CHANGE_BY_PS) { | ||
995 | u32 rfoffreason = rtlpriv->psc.rfoff_reason; | ||
996 | |||
997 | rtlpriv->psc.rfoff_reason = RF_CHANGE_BY_INIT; | ||
998 | rtlpriv->psc.rfpwr_state = ERFON; | ||
999 | rtl_ps_set_rf_state(hw, ERFOFF, rfoffreason, true); | ||
1000 | } else { | ||
1001 | /* gpio radio on/off is out of adapter start */ | ||
1002 | if (rtlpriv->psc.hwradiooff == false) { | ||
1003 | rtlpriv->psc.rfpwr_state = ERFON; | ||
1004 | rtlpriv->psc.rfoff_reason = 0; | ||
1005 | } | ||
1006 | } | ||
1007 | #endif | ||
1008 | |||
1009 | /* Before RF-R/W we must execute the IO from Scott's suggestion. */ | ||
1010 | rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, 0xDB); | ||
1011 | if (rtlhal->version == VERSION_8192S_ACUT) | ||
1012 | rtl_write_byte(rtlpriv, SPS1_CTRL + 3, 0x07); | ||
1013 | else | ||
1014 | rtl_write_byte(rtlpriv, RF_CTRL, 0x07); | ||
1015 | |||
1016 | if (rtl92s_phy_rf_config(hw) != true) { | ||
1017 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("RF Config failed\n")); | ||
1018 | return rtstatus; | ||
1019 | } | ||
1020 | |||
1021 | /* After read predefined TXT, we must set BB/MAC/RF | ||
1022 | * register as our requirement */ | ||
1023 | |||
1024 | rtlphy->rfreg_chnlval[0] = rtl92s_phy_query_rf_reg(hw, | ||
1025 | (enum radio_path)0, | ||
1026 | RF_CHNLBW, | ||
1027 | RFREG_OFFSET_MASK); | ||
1028 | rtlphy->rfreg_chnlval[1] = rtl92s_phy_query_rf_reg(hw, | ||
1029 | (enum radio_path)1, | ||
1030 | RF_CHNLBW, | ||
1031 | RFREG_OFFSET_MASK); | ||
1032 | |||
1033 | /*---- Set CCK and OFDM Block "ON"----*/ | ||
1034 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1); | ||
1035 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1); | ||
1036 | |||
1037 | /*3 Set Hardware(Do nothing now) */ | ||
1038 | _rtl92se_hw_configure(hw); | ||
1039 | |||
1040 | /* Read EEPROM TX power index and PHY_REG_PG.txt to capture correct */ | ||
1041 | /* TX power index for different rate set. */ | ||
1042 | /* Get original hw reg values */ | ||
1043 | rtl92s_phy_get_hw_reg_originalvalue(hw); | ||
1044 | /* Write correct tx power index */ | ||
1045 | rtl92s_phy_set_txpower(hw, rtlphy->current_channel); | ||
1046 | |||
1047 | /* We must set MAC address after firmware download. */ | ||
1048 | for (i = 0; i < 6; i++) | ||
1049 | rtl_write_byte(rtlpriv, MACIDR0 + i, rtlefuse->dev_addr[i]); | ||
1050 | |||
1051 | /* EEPROM R/W workaround */ | ||
1052 | tmp_u1b = rtl_read_byte(rtlpriv, MAC_PINMUX_CFG); | ||
1053 | rtl_write_byte(rtlpriv, MAC_PINMUX_CFG, tmp_u1b & (~BIT(3))); | ||
1054 | |||
1055 | rtl_write_byte(rtlpriv, 0x4d, 0x0); | ||
1056 | |||
1057 | if (hal_get_firmwareversion(rtlpriv) >= 0x49) { | ||
1058 | tmp_byte = rtl_read_byte(rtlpriv, FW_RSVD_PG_CRTL) & (~BIT(4)); | ||
1059 | tmp_byte = tmp_byte | BIT(5); | ||
1060 | rtl_write_byte(rtlpriv, FW_RSVD_PG_CRTL, tmp_byte); | ||
1061 | rtl_write_dword(rtlpriv, TXDESC_MSK, 0xFFFFCFFF); | ||
1062 | } | ||
1063 | |||
1064 | /* We enable high power and RA related mechanism after NIC | ||
1065 | * initialized. */ | ||
1066 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_INIT); | ||
1067 | |||
1068 | /* Add to prevent ASPM bug. */ | ||
1069 | /* Always enable hst and NIC clock request. */ | ||
1070 | rtl92s_phy_switch_ephy_parameter(hw); | ||
1071 | |||
1072 | /* Security related | ||
1073 | * 1. Clear all H/W keys. | ||
1074 | * 2. Enable H/W encryption/decryption. */ | ||
1075 | rtl_cam_reset_all_entry(hw); | ||
1076 | secr_value |= SCR_TXENCENABLE; | ||
1077 | secr_value |= SCR_RXENCENABLE; | ||
1078 | secr_value |= SCR_NOSKMC; | ||
1079 | rtl_write_byte(rtlpriv, REG_SECR, secr_value); | ||
1080 | |||
1081 | for (i = 0; i < 4; i++) | ||
1082 | rtl_write_dword(rtlpriv, wdcapra_add[i], 0x5e4322); | ||
1083 | |||
1084 | if (rtlphy->rf_type == RF_1T2R) { | ||
1085 | bool mrc2set = true; | ||
1086 | /* Turn on B-Path */ | ||
1087 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_MRC, (u8 *)&mrc2set); | ||
1088 | } | ||
1089 | |||
1090 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_ON); | ||
1091 | rtl92s_dm_init(hw); | ||
1092 | rtlpci->being_init_adapter = false; | ||
1093 | |||
1094 | return err; | ||
1095 | } | ||
1096 | |||
1097 | void rtl92se_set_mac_addr(struct rtl_io *io, const u8 * addr) | ||
1098 | { | ||
1099 | } | ||
1100 | |||
1101 | void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) | ||
1102 | { | ||
1103 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1104 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1105 | u32 reg_rcr = rtlpci->receive_config; | ||
1106 | |||
1107 | if (rtlpriv->psc.rfpwr_state != ERFON) | ||
1108 | return; | ||
1109 | |||
1110 | if (check_bssid == true) { | ||
1111 | reg_rcr |= (RCR_CBSSID); | ||
1112 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); | ||
1113 | } else if (check_bssid == false) { | ||
1114 | reg_rcr &= (~RCR_CBSSID); | ||
1115 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, (u8 *)(®_rcr)); | ||
1116 | } | ||
1117 | |||
1118 | } | ||
1119 | |||
1120 | static int _rtl92se_set_media_status(struct ieee80211_hw *hw, | ||
1121 | enum nl80211_iftype type) | ||
1122 | { | ||
1123 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1124 | u8 bt_msr = rtl_read_byte(rtlpriv, MSR); | ||
1125 | enum led_ctl_mode ledaction = LED_CTL_NO_LINK; | ||
1126 | u32 temp; | ||
1127 | bt_msr &= ~MSR_LINK_MASK; | ||
1128 | |||
1129 | switch (type) { | ||
1130 | case NL80211_IFTYPE_UNSPECIFIED: | ||
1131 | bt_msr |= (MSR_LINK_NONE << MSR_LINK_SHIFT); | ||
1132 | ledaction = LED_CTL_LINK; | ||
1133 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1134 | ("Set Network type to NO LINK!\n")); | ||
1135 | break; | ||
1136 | case NL80211_IFTYPE_ADHOC: | ||
1137 | bt_msr |= (MSR_LINK_ADHOC << MSR_LINK_SHIFT); | ||
1138 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1139 | ("Set Network type to Ad Hoc!\n")); | ||
1140 | break; | ||
1141 | case NL80211_IFTYPE_STATION: | ||
1142 | bt_msr |= (MSR_LINK_MANAGED << MSR_LINK_SHIFT); | ||
1143 | ledaction = LED_CTL_LINK; | ||
1144 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1145 | ("Set Network type to STA!\n")); | ||
1146 | break; | ||
1147 | case NL80211_IFTYPE_AP: | ||
1148 | bt_msr |= (MSR_LINK_MASTER << MSR_LINK_SHIFT); | ||
1149 | RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, | ||
1150 | ("Set Network type to AP!\n")); | ||
1151 | break; | ||
1152 | default: | ||
1153 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1154 | ("Network type %d not support!\n", type)); | ||
1155 | return 1; | ||
1156 | break; | ||
1157 | |||
1158 | } | ||
1159 | |||
1160 | rtl_write_byte(rtlpriv, (MSR), bt_msr); | ||
1161 | |||
1162 | temp = rtl_read_dword(rtlpriv, TCR); | ||
1163 | rtl_write_dword(rtlpriv, TCR, temp & (~BIT(8))); | ||
1164 | rtl_write_dword(rtlpriv, TCR, temp | BIT(8)); | ||
1165 | |||
1166 | |||
1167 | return 0; | ||
1168 | } | ||
1169 | |||
1170 | /* HW_VAR_MEDIA_STATUS & HW_VAR_CECHK_BSSID */ | ||
1171 | int rtl92se_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) | ||
1172 | { | ||
1173 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1174 | |||
1175 | if (_rtl92se_set_media_status(hw, type)) | ||
1176 | return -EOPNOTSUPP; | ||
1177 | |||
1178 | if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { | ||
1179 | if (type != NL80211_IFTYPE_AP) | ||
1180 | rtl92se_set_check_bssid(hw, true); | ||
1181 | } else { | ||
1182 | rtl92se_set_check_bssid(hw, false); | ||
1183 | } | ||
1184 | |||
1185 | return 0; | ||
1186 | } | ||
1187 | |||
1188 | /* don't set REG_EDCA_BE_PARAM here because mac80211 will send pkt when scan */ | ||
1189 | void rtl92se_set_qos(struct ieee80211_hw *hw, int aci) | ||
1190 | { | ||
1191 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1192 | rtl92s_dm_init_edca_turbo(hw); | ||
1193 | |||
1194 | switch (aci) { | ||
1195 | case AC1_BK: | ||
1196 | rtl_write_dword(rtlpriv, EDCAPARA_BK, 0xa44f); | ||
1197 | break; | ||
1198 | case AC0_BE: | ||
1199 | /* rtl_write_dword(rtlpriv, EDCAPARA_BE, u4b_ac_param); */ | ||
1200 | break; | ||
1201 | case AC2_VI: | ||
1202 | rtl_write_dword(rtlpriv, EDCAPARA_VI, 0x5e4322); | ||
1203 | break; | ||
1204 | case AC3_VO: | ||
1205 | rtl_write_dword(rtlpriv, EDCAPARA_VO, 0x2f3222); | ||
1206 | break; | ||
1207 | default: | ||
1208 | RT_ASSERT(false, ("invalid aci: %d !\n", aci)); | ||
1209 | break; | ||
1210 | } | ||
1211 | } | ||
1212 | |||
1213 | void rtl92se_enable_interrupt(struct ieee80211_hw *hw) | ||
1214 | { | ||
1215 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1216 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1217 | |||
1218 | rtl_write_dword(rtlpriv, INTA_MASK, rtlpci->irq_mask[0]); | ||
1219 | /* Support Bit 32-37(Assign as Bit 0-5) interrupt setting now */ | ||
1220 | rtl_write_dword(rtlpriv, INTA_MASK + 4, rtlpci->irq_mask[1] & 0x3F); | ||
1221 | |||
1222 | rtlpci->irq_enabled = true; | ||
1223 | } | ||
1224 | |||
1225 | void rtl92se_disable_interrupt(struct ieee80211_hw *hw) | ||
1226 | { | ||
1227 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1228 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1229 | |||
1230 | rtl_write_dword(rtlpriv, INTA_MASK, 0); | ||
1231 | rtl_write_dword(rtlpriv, INTA_MASK + 4, 0); | ||
1232 | |||
1233 | rtlpci->irq_enabled = false; | ||
1234 | } | ||
1235 | |||
1236 | |||
1237 | static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data) | ||
1238 | { | ||
1239 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1240 | u8 waitcnt = 100; | ||
1241 | bool result = false; | ||
1242 | u8 tmp; | ||
1243 | |||
1244 | rtl_write_byte(rtlpriv, SYS_CLKR + 1, data); | ||
1245 | |||
1246 | /* Wait the MAC synchronized. */ | ||
1247 | udelay(400); | ||
1248 | |||
1249 | /* Check if it is set ready. */ | ||
1250 | tmp = rtl_read_byte(rtlpriv, SYS_CLKR + 1); | ||
1251 | result = ((tmp & BIT(7)) == (data & BIT(7))); | ||
1252 | |||
1253 | if ((data & (BIT(6) | BIT(7))) == false) { | ||
1254 | waitcnt = 100; | ||
1255 | tmp = 0; | ||
1256 | |||
1257 | while (1) { | ||
1258 | waitcnt--; | ||
1259 | tmp = rtl_read_byte(rtlpriv, SYS_CLKR + 1); | ||
1260 | |||
1261 | if ((tmp & BIT(6))) | ||
1262 | break; | ||
1263 | |||
1264 | printk(KERN_ERR "wait for BIT(6) return value %x\n", | ||
1265 | tmp); | ||
1266 | |||
1267 | if (waitcnt == 0) | ||
1268 | break; | ||
1269 | udelay(10); | ||
1270 | } | ||
1271 | |||
1272 | if (waitcnt == 0) | ||
1273 | result = false; | ||
1274 | else | ||
1275 | result = true; | ||
1276 | } | ||
1277 | |||
1278 | return result; | ||
1279 | } | ||
1280 | |||
1281 | static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw) | ||
1282 | { | ||
1283 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1284 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1285 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
1286 | u8 u1btmp; | ||
1287 | |||
1288 | if (rtlhal->driver_going2unload) | ||
1289 | rtl_write_byte(rtlpriv, 0x560, 0x0); | ||
1290 | |||
1291 | /* Power save for BB/RF */ | ||
1292 | u1btmp = rtl_read_byte(rtlpriv, LDOV12D_CTRL); | ||
1293 | u1btmp |= BIT(0); | ||
1294 | rtl_write_byte(rtlpriv, LDOV12D_CTRL, u1btmp); | ||
1295 | rtl_write_byte(rtlpriv, SPS1_CTRL, 0x0); | ||
1296 | rtl_write_byte(rtlpriv, TXPAUSE, 0xFF); | ||
1297 | rtl_write_word(rtlpriv, CMDR, 0x57FC); | ||
1298 | udelay(100); | ||
1299 | rtl_write_word(rtlpriv, CMDR, 0x77FC); | ||
1300 | rtl_write_byte(rtlpriv, PHY_CCA, 0x0); | ||
1301 | udelay(10); | ||
1302 | rtl_write_word(rtlpriv, CMDR, 0x37FC); | ||
1303 | udelay(10); | ||
1304 | rtl_write_word(rtlpriv, CMDR, 0x77FC); | ||
1305 | udelay(10); | ||
1306 | rtl_write_word(rtlpriv, CMDR, 0x57FC); | ||
1307 | rtl_write_word(rtlpriv, CMDR, 0x0000); | ||
1308 | |||
1309 | if (rtlhal->driver_going2unload) { | ||
1310 | u1btmp = rtl_read_byte(rtlpriv, (REG_SYS_FUNC_EN + 1)); | ||
1311 | u1btmp &= ~(BIT(0)); | ||
1312 | rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, u1btmp); | ||
1313 | } | ||
1314 | |||
1315 | u1btmp = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); | ||
1316 | |||
1317 | /* Add description. After switch control path. register | ||
1318 | * after page1 will be invisible. We can not do any IO | ||
1319 | * for register>0x40. After resume&MACIO reset, we need | ||
1320 | * to remember previous reg content. */ | ||
1321 | if (u1btmp & BIT(7)) { | ||
1322 | u1btmp &= ~(BIT(6) | BIT(7)); | ||
1323 | if (!_rtl92s_set_sysclk(hw, u1btmp)) { | ||
1324 | printk(KERN_ERR "Switch ctrl path fail\n"); | ||
1325 | return; | ||
1326 | } | ||
1327 | } | ||
1328 | |||
1329 | /* Power save for MAC */ | ||
1330 | if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS && | ||
1331 | !rtlhal->driver_going2unload) { | ||
1332 | /* enable LED function */ | ||
1333 | rtl_write_byte(rtlpriv, 0x03, 0xF9); | ||
1334 | /* SW/HW radio off or halt adapter!! For example S3/S4 */ | ||
1335 | } else { | ||
1336 | /* LED function disable. Power range is about 8mA now. */ | ||
1337 | /* if write 0xF1 disconnet_pci power | ||
1338 | * ifconfig wlan0 down power are both high 35:70 */ | ||
1339 | /* if write oxF9 disconnet_pci power | ||
1340 | * ifconfig wlan0 down power are both low 12:45*/ | ||
1341 | rtl_write_byte(rtlpriv, 0x03, 0xF9); | ||
1342 | } | ||
1343 | |||
1344 | rtl_write_byte(rtlpriv, SYS_CLKR + 1, 0x70); | ||
1345 | rtl_write_byte(rtlpriv, AFE_PLL_CTRL + 1, 0x68); | ||
1346 | rtl_write_byte(rtlpriv, AFE_PLL_CTRL, 0x00); | ||
1347 | rtl_write_byte(rtlpriv, LDOA15_CTRL, 0x34); | ||
1348 | rtl_write_byte(rtlpriv, AFE_XTAL_CTRL, 0x0E); | ||
1349 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); | ||
1350 | |||
1351 | } | ||
1352 | |||
1353 | static void _rtl92se_gen_refreshledstate(struct ieee80211_hw *hw) | ||
1354 | { | ||
1355 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1356 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1357 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
1358 | struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); | ||
1359 | |||
1360 | if (rtlpci->up_first_time == 1) | ||
1361 | return; | ||
1362 | |||
1363 | if (rtlpriv->psc.rfoff_reason == RF_CHANGE_BY_IPS) | ||
1364 | rtl92se_sw_led_on(hw, pLed0); | ||
1365 | else | ||
1366 | rtl92se_sw_led_off(hw, pLed0); | ||
1367 | } | ||
1368 | |||
1369 | |||
1370 | static void _rtl92se_power_domain_init(struct ieee80211_hw *hw) | ||
1371 | { | ||
1372 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1373 | u16 tmpu2b; | ||
1374 | u8 tmpu1b; | ||
1375 | |||
1376 | rtlpriv->psc.pwrdomain_protect = true; | ||
1377 | |||
1378 | tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); | ||
1379 | if (tmpu1b & BIT(7)) { | ||
1380 | tmpu1b &= ~(BIT(6) | BIT(7)); | ||
1381 | if (!_rtl92s_set_sysclk(hw, tmpu1b)) { | ||
1382 | rtlpriv->psc.pwrdomain_protect = false; | ||
1383 | return; | ||
1384 | } | ||
1385 | } | ||
1386 | |||
1387 | rtl_write_byte(rtlpriv, AFE_PLL_CTRL, 0x0); | ||
1388 | rtl_write_byte(rtlpriv, LDOA15_CTRL, 0x34); | ||
1389 | |||
1390 | /* Reset MAC-IO and CPU and Core Digital BIT10/11/15 */ | ||
1391 | tmpu1b = rtl_read_byte(rtlpriv, SYS_FUNC_EN + 1); | ||
1392 | |||
1393 | /* If IPS we need to turn LED on. So we not | ||
1394 | * not disable BIT 3/7 of reg3. */ | ||
1395 | if (rtlpriv->psc.rfoff_reason & (RF_CHANGE_BY_IPS | RF_CHANGE_BY_HW)) | ||
1396 | tmpu1b &= 0xFB; | ||
1397 | else | ||
1398 | tmpu1b &= 0x73; | ||
1399 | |||
1400 | rtl_write_byte(rtlpriv, SYS_FUNC_EN + 1, tmpu1b); | ||
1401 | /* wait for BIT 10/11/15 to pull high automatically!! */ | ||
1402 | mdelay(1); | ||
1403 | |||
1404 | rtl_write_byte(rtlpriv, CMDR, 0); | ||
1405 | rtl_write_byte(rtlpriv, TCR, 0); | ||
1406 | |||
1407 | /* Data sheet not define 0x562!!! Copy from WMAC!!!!! */ | ||
1408 | tmpu1b = rtl_read_byte(rtlpriv, 0x562); | ||
1409 | tmpu1b |= 0x08; | ||
1410 | rtl_write_byte(rtlpriv, 0x562, tmpu1b); | ||
1411 | tmpu1b &= ~(BIT(3)); | ||
1412 | rtl_write_byte(rtlpriv, 0x562, tmpu1b); | ||
1413 | |||
1414 | /* Enable AFE clock source */ | ||
1415 | tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL); | ||
1416 | rtl_write_byte(rtlpriv, AFE_XTAL_CTRL, (tmpu1b | 0x01)); | ||
1417 | /* Delay 1.5ms */ | ||
1418 | udelay(1500); | ||
1419 | tmpu1b = rtl_read_byte(rtlpriv, AFE_XTAL_CTRL + 1); | ||
1420 | rtl_write_byte(rtlpriv, AFE_XTAL_CTRL + 1, (tmpu1b & 0xfb)); | ||
1421 | |||
1422 | /* Enable AFE Macro Block's Bandgap */ | ||
1423 | tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); | ||
1424 | rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | BIT(0))); | ||
1425 | mdelay(1); | ||
1426 | |||
1427 | /* Enable AFE Mbias */ | ||
1428 | tmpu1b = rtl_read_byte(rtlpriv, AFE_MISC); | ||
1429 | rtl_write_byte(rtlpriv, AFE_MISC, (tmpu1b | 0x02)); | ||
1430 | mdelay(1); | ||
1431 | |||
1432 | /* Enable LDOA15 block */ | ||
1433 | tmpu1b = rtl_read_byte(rtlpriv, LDOA15_CTRL); | ||
1434 | rtl_write_byte(rtlpriv, LDOA15_CTRL, (tmpu1b | BIT(0))); | ||
1435 | |||
1436 | /* Set Digital Vdd to Retention isolation Path. */ | ||
1437 | tmpu2b = rtl_read_word(rtlpriv, SYS_ISO_CTRL); | ||
1438 | rtl_write_word(rtlpriv, SYS_ISO_CTRL, (tmpu2b | BIT(11))); | ||
1439 | |||
1440 | |||
1441 | /* For warm reboot NIC disappera bug. */ | ||
1442 | tmpu2b = rtl_read_word(rtlpriv, SYS_FUNC_EN); | ||
1443 | rtl_write_word(rtlpriv, SYS_FUNC_EN, (tmpu2b | BIT(13))); | ||
1444 | |||
1445 | rtl_write_byte(rtlpriv, SYS_ISO_CTRL + 1, 0x68); | ||
1446 | |||
1447 | /* Enable AFE PLL Macro Block */ | ||
1448 | tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL); | ||
1449 | rtl_write_byte(rtlpriv, AFE_PLL_CTRL, (tmpu1b | BIT(0) | BIT(4))); | ||
1450 | /* Enable MAC 80MHZ clock */ | ||
1451 | tmpu1b = rtl_read_byte(rtlpriv, AFE_PLL_CTRL + 1); | ||
1452 | rtl_write_byte(rtlpriv, AFE_PLL_CTRL + 1, (tmpu1b | BIT(0))); | ||
1453 | mdelay(1); | ||
1454 | |||
1455 | /* Release isolation AFE PLL & MD */ | ||
1456 | rtl_write_byte(rtlpriv, SYS_ISO_CTRL, 0xA6); | ||
1457 | |||
1458 | /* Enable MAC clock */ | ||
1459 | tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); | ||
1460 | rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b | BIT(12) | BIT(11))); | ||
1461 | |||
1462 | /* Enable Core digital and enable IOREG R/W */ | ||
1463 | tmpu2b = rtl_read_word(rtlpriv, SYS_FUNC_EN); | ||
1464 | rtl_write_word(rtlpriv, SYS_FUNC_EN, (tmpu2b | BIT(11))); | ||
1465 | /* enable REG_EN */ | ||
1466 | rtl_write_word(rtlpriv, SYS_FUNC_EN, (tmpu2b | BIT(11) | BIT(15))); | ||
1467 | |||
1468 | /* Switch the control path. */ | ||
1469 | tmpu2b = rtl_read_word(rtlpriv, SYS_CLKR); | ||
1470 | rtl_write_word(rtlpriv, SYS_CLKR, (tmpu2b & (~BIT(2)))); | ||
1471 | |||
1472 | tmpu1b = rtl_read_byte(rtlpriv, (SYS_CLKR + 1)); | ||
1473 | tmpu1b = ((tmpu1b | BIT(7)) & (~BIT(6))); | ||
1474 | if (!_rtl92s_set_sysclk(hw, tmpu1b)) { | ||
1475 | rtlpriv->psc.pwrdomain_protect = false; | ||
1476 | return; | ||
1477 | } | ||
1478 | |||
1479 | rtl_write_word(rtlpriv, CMDR, 0x37FC); | ||
1480 | |||
1481 | /* After MACIO reset,we must refresh LED state. */ | ||
1482 | _rtl92se_gen_refreshledstate(hw); | ||
1483 | |||
1484 | rtlpriv->psc.pwrdomain_protect = false; | ||
1485 | } | ||
1486 | |||
1487 | void rtl92se_card_disable(struct ieee80211_hw *hw) | ||
1488 | { | ||
1489 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1490 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1491 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1492 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
1493 | enum nl80211_iftype opmode; | ||
1494 | u8 wait = 30; | ||
1495 | |||
1496 | rtlpriv->intf_ops->enable_aspm(hw); | ||
1497 | |||
1498 | if (rtlpci->driver_is_goingto_unload || | ||
1499 | ppsc->rfoff_reason > RF_CHANGE_BY_PS) | ||
1500 | rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF); | ||
1501 | |||
1502 | /* we should chnge GPIO to input mode | ||
1503 | * this will drop away current about 25mA*/ | ||
1504 | rtl8192se_gpiobit3_cfg_inputmode(hw); | ||
1505 | |||
1506 | /* this is very important for ips power save */ | ||
1507 | while (wait-- >= 10 && rtlpriv->psc.pwrdomain_protect) { | ||
1508 | if (rtlpriv->psc.pwrdomain_protect) | ||
1509 | mdelay(20); | ||
1510 | else | ||
1511 | break; | ||
1512 | } | ||
1513 | |||
1514 | mac->link_state = MAC80211_NOLINK; | ||
1515 | opmode = NL80211_IFTYPE_UNSPECIFIED; | ||
1516 | _rtl92se_set_media_status(hw, opmode); | ||
1517 | |||
1518 | _rtl92s_phy_set_rfhalt(hw); | ||
1519 | udelay(100); | ||
1520 | } | ||
1521 | |||
1522 | void rtl92se_interrupt_recognized(struct ieee80211_hw *hw, u32 *p_inta, | ||
1523 | u32 *p_intb) | ||
1524 | { | ||
1525 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1526 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1527 | |||
1528 | *p_inta = rtl_read_dword(rtlpriv, ISR) & rtlpci->irq_mask[0]; | ||
1529 | rtl_write_dword(rtlpriv, ISR, *p_inta); | ||
1530 | |||
1531 | *p_intb = rtl_read_dword(rtlpriv, ISR + 4) & rtlpci->irq_mask[1]; | ||
1532 | rtl_write_dword(rtlpriv, ISR + 4, *p_intb); | ||
1533 | } | ||
1534 | |||
1535 | void rtl92se_set_beacon_related_registers(struct ieee80211_hw *hw) | ||
1536 | { | ||
1537 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1538 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1539 | u16 bcntime_cfg = 0; | ||
1540 | u16 bcn_cw = 6, bcn_ifs = 0xf; | ||
1541 | u16 atim_window = 2; | ||
1542 | |||
1543 | /* ATIM Window (in unit of TU). */ | ||
1544 | rtl_write_word(rtlpriv, ATIMWND, atim_window); | ||
1545 | |||
1546 | /* Beacon interval (in unit of TU). */ | ||
1547 | rtl_write_word(rtlpriv, BCN_INTERVAL, mac->beacon_interval); | ||
1548 | |||
1549 | /* DrvErlyInt (in unit of TU). (Time to send | ||
1550 | * interrupt to notify driver to change | ||
1551 | * beacon content) */ | ||
1552 | rtl_write_word(rtlpriv, BCN_DRV_EARLY_INT, 10 << 4); | ||
1553 | |||
1554 | /* BcnDMATIM(in unit of us). Indicates the | ||
1555 | * time before TBTT to perform beacon queue DMA */ | ||
1556 | rtl_write_word(rtlpriv, BCN_DMATIME, 256); | ||
1557 | |||
1558 | /* Force beacon frame transmission even | ||
1559 | * after receiving beacon frame from | ||
1560 | * other ad hoc STA */ | ||
1561 | rtl_write_byte(rtlpriv, BCN_ERR_THRESH, 100); | ||
1562 | |||
1563 | /* Beacon Time Configuration */ | ||
1564 | if (mac->opmode == NL80211_IFTYPE_ADHOC) | ||
1565 | bcntime_cfg |= (bcn_cw << BCN_TCFG_CW_SHIFT); | ||
1566 | |||
1567 | /* TODO: bcn_ifs may required to be changed on ASIC */ | ||
1568 | bcntime_cfg |= bcn_ifs << BCN_TCFG_IFS; | ||
1569 | |||
1570 | /*for beacon changed */ | ||
1571 | rtl92s_phy_set_beacon_hwreg(hw, mac->beacon_interval); | ||
1572 | } | ||
1573 | |||
1574 | void rtl92se_set_beacon_interval(struct ieee80211_hw *hw) | ||
1575 | { | ||
1576 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1577 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1578 | u16 bcn_interval = mac->beacon_interval; | ||
1579 | |||
1580 | /* Beacon interval (in unit of TU). */ | ||
1581 | rtl_write_word(rtlpriv, BCN_INTERVAL, bcn_interval); | ||
1582 | /* 2008.10.24 added by tynli for beacon changed. */ | ||
1583 | rtl92s_phy_set_beacon_hwreg(hw, bcn_interval); | ||
1584 | } | ||
1585 | |||
1586 | void rtl92se_update_interrupt_mask(struct ieee80211_hw *hw, | ||
1587 | u32 add_msr, u32 rm_msr) | ||
1588 | { | ||
1589 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1590 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
1591 | |||
1592 | RT_TRACE(rtlpriv, COMP_INTR, DBG_LOUD, | ||
1593 | ("add_msr:%x, rm_msr:%x\n", add_msr, rm_msr)); | ||
1594 | |||
1595 | if (add_msr) | ||
1596 | rtlpci->irq_mask[0] |= add_msr; | ||
1597 | |||
1598 | if (rm_msr) | ||
1599 | rtlpci->irq_mask[0] &= (~rm_msr); | ||
1600 | |||
1601 | rtl92se_disable_interrupt(hw); | ||
1602 | rtl92se_enable_interrupt(hw); | ||
1603 | } | ||
1604 | |||
1605 | static void _rtl8192se_get_IC_Inferiority(struct ieee80211_hw *hw) | ||
1606 | { | ||
1607 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1608 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1609 | u8 efuse_id; | ||
1610 | |||
1611 | rtlhal->ic_class = IC_INFERIORITY_A; | ||
1612 | |||
1613 | /* Only retrieving while using EFUSE. */ | ||
1614 | if ((rtlefuse->epromtype == EEPROM_BOOT_EFUSE) && | ||
1615 | !rtlefuse->autoload_failflag) { | ||
1616 | efuse_id = efuse_read_1byte(hw, EFUSE_IC_ID_OFFSET); | ||
1617 | |||
1618 | if (efuse_id == 0xfe) | ||
1619 | rtlhal->ic_class = IC_INFERIORITY_B; | ||
1620 | } | ||
1621 | } | ||
1622 | |||
1623 | static void _rtl92se_read_adapter_info(struct ieee80211_hw *hw) | ||
1624 | { | ||
1625 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1626 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1627 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1628 | u16 i, usvalue; | ||
1629 | u16 eeprom_id; | ||
1630 | u8 tempval; | ||
1631 | u8 hwinfo[HWSET_MAX_SIZE_92S]; | ||
1632 | u8 rf_path, index; | ||
1633 | |||
1634 | if (rtlefuse->epromtype == EEPROM_93C46) { | ||
1635 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1636 | ("RTL819X Not boot from eeprom, check it !!")); | ||
1637 | } else if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) { | ||
1638 | rtl_efuse_shadow_map_update(hw); | ||
1639 | |||
1640 | memcpy((void *)hwinfo, (void *) | ||
1641 | &rtlefuse->efuse_map[EFUSE_INIT_MAP][0], | ||
1642 | HWSET_MAX_SIZE_92S); | ||
1643 | } | ||
1644 | |||
1645 | RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_DMESG, ("MAP\n"), | ||
1646 | hwinfo, HWSET_MAX_SIZE_92S); | ||
1647 | |||
1648 | eeprom_id = *((u16 *)&hwinfo[0]); | ||
1649 | if (eeprom_id != RTL8190_EEPROM_ID) { | ||
1650 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
1651 | ("EEPROM ID(%#x) is invalid!!\n", eeprom_id)); | ||
1652 | rtlefuse->autoload_failflag = true; | ||
1653 | } else { | ||
1654 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n")); | ||
1655 | rtlefuse->autoload_failflag = false; | ||
1656 | } | ||
1657 | |||
1658 | if (rtlefuse->autoload_failflag == true) | ||
1659 | return; | ||
1660 | |||
1661 | _rtl8192se_get_IC_Inferiority(hw); | ||
1662 | |||
1663 | /* Read IC Version && Channel Plan */ | ||
1664 | /* VID, DID SE 0xA-D */ | ||
1665 | rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID]; | ||
1666 | rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID]; | ||
1667 | rtlefuse->eeprom_svid = *(u16 *)&hwinfo[EEPROM_SVID]; | ||
1668 | rtlefuse->eeprom_smid = *(u16 *)&hwinfo[EEPROM_SMID]; | ||
1669 | rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION]; | ||
1670 | |||
1671 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1672 | ("EEPROMId = 0x%4x\n", eeprom_id)); | ||
1673 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1674 | ("EEPROM VID = 0x%4x\n", rtlefuse->eeprom_vid)); | ||
1675 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1676 | ("EEPROM DID = 0x%4x\n", rtlefuse->eeprom_did)); | ||
1677 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1678 | ("EEPROM SVID = 0x%4x\n", rtlefuse->eeprom_svid)); | ||
1679 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1680 | ("EEPROM SMID = 0x%4x\n", rtlefuse->eeprom_smid)); | ||
1681 | |||
1682 | for (i = 0; i < 6; i += 2) { | ||
1683 | usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i]; | ||
1684 | *((u16 *) (&rtlefuse->dev_addr[i])) = usvalue; | ||
1685 | } | ||
1686 | |||
1687 | for (i = 0; i < 6; i++) | ||
1688 | rtl_write_byte(rtlpriv, MACIDR0 + i, rtlefuse->dev_addr[i]); | ||
1689 | |||
1690 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, | ||
1691 | (MAC_FMT "\n", MAC_ARG(rtlefuse->dev_addr))); | ||
1692 | |||
1693 | /* Get Tx Power Level by Channel */ | ||
1694 | /* Read Tx power of Channel 1 ~ 14 from EEPROM. */ | ||
1695 | /* 92S suupport RF A & B */ | ||
1696 | for (rf_path = 0; rf_path < 2; rf_path++) { | ||
1697 | for (i = 0; i < 3; i++) { | ||
1698 | /* Read CCK RF A & B Tx power */ | ||
1699 | rtlefuse->eeprom_chnlarea_txpwr_cck[rf_path][i] = | ||
1700 | hwinfo[EEPROM_TXPOWERBASE + rf_path * 3 + i]; | ||
1701 | |||
1702 | /* Read OFDM RF A & B Tx power for 1T */ | ||
1703 | rtlefuse->eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] = | ||
1704 | hwinfo[EEPROM_TXPOWERBASE + 6 + rf_path * 3 + i]; | ||
1705 | |||
1706 | /* Read OFDM RF A & B Tx power for 2T */ | ||
1707 | rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][i] | ||
1708 | = hwinfo[EEPROM_TXPOWERBASE + 12 + | ||
1709 | rf_path * 3 + i]; | ||
1710 | } | ||
1711 | } | ||
1712 | |||
1713 | for (rf_path = 0; rf_path < 2; rf_path++) | ||
1714 | for (i = 0; i < 3; i++) | ||
1715 | RTPRINT(rtlpriv, FINIT, INIT_EEPROM, | ||
1716 | ("RF(%d) EEPROM CCK Area(%d) = 0x%x\n", rf_path, | ||
1717 | i, rtlefuse->eeprom_chnlarea_txpwr_cck | ||
1718 | [rf_path][i])); | ||
1719 | for (rf_path = 0; rf_path < 2; rf_path++) | ||
1720 | for (i = 0; i < 3; i++) | ||
1721 | RTPRINT(rtlpriv, FINIT, INIT_EEPROM, | ||
1722 | ("RF(%d) EEPROM HT40 1S Area(%d) = 0x%x\n", | ||
1723 | rf_path, i, | ||
1724 | rtlefuse->eeprom_chnlarea_txpwr_ht40_1s | ||
1725 | [rf_path][i])); | ||
1726 | for (rf_path = 0; rf_path < 2; rf_path++) | ||
1727 | for (i = 0; i < 3; i++) | ||
1728 | RTPRINT(rtlpriv, FINIT, INIT_EEPROM, | ||
1729 | ("RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n", | ||
1730 | rf_path, i, | ||
1731 | rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif | ||
1732 | [rf_path][i])); | ||
1733 | |||
1734 | for (rf_path = 0; rf_path < 2; rf_path++) { | ||
1735 | |||
1736 | /* Assign dedicated channel tx power */ | ||
1737 | for (i = 0; i < 14; i++) { | ||
1738 | /* channel 1~3 use the same Tx Power Level. */ | ||
1739 | if (i < 3) | ||
1740 | index = 0; | ||
1741 | /* Channel 4-8 */ | ||
1742 | else if (i < 8) | ||
1743 | index = 1; | ||
1744 | /* Channel 9-14 */ | ||
1745 | else | ||
1746 | index = 2; | ||
1747 | |||
1748 | /* Record A & B CCK /OFDM - 1T/2T Channel area | ||
1749 | * tx power */ | ||
1750 | rtlefuse->txpwrlevel_cck[rf_path][i] = | ||
1751 | rtlefuse->eeprom_chnlarea_txpwr_cck | ||
1752 | [rf_path][index]; | ||
1753 | rtlefuse->txpwrlevel_ht40_1s[rf_path][i] = | ||
1754 | rtlefuse->eeprom_chnlarea_txpwr_ht40_1s | ||
1755 | [rf_path][index]; | ||
1756 | rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = | ||
1757 | rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif | ||
1758 | [rf_path][index]; | ||
1759 | } | ||
1760 | |||
1761 | for (i = 0; i < 14; i++) { | ||
1762 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | ||
1763 | ("RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = " | ||
1764 | "[0x%x / 0x%x / 0x%x]\n", rf_path, i, | ||
1765 | rtlefuse->txpwrlevel_cck[rf_path][i], | ||
1766 | rtlefuse->txpwrlevel_ht40_1s[rf_path][i], | ||
1767 | rtlefuse->txpwrlevel_ht40_2s[rf_path][i])); | ||
1768 | } | ||
1769 | } | ||
1770 | |||
1771 | for (rf_path = 0; rf_path < 2; rf_path++) { | ||
1772 | for (i = 0; i < 3; i++) { | ||
1773 | /* Read Power diff limit. */ | ||
1774 | rtlefuse->eeprom_pwrgroup[rf_path][i] = | ||
1775 | hwinfo[EEPROM_TXPWRGROUP + rf_path * 3 + i]; | ||
1776 | } | ||
1777 | } | ||
1778 | |||
1779 | for (rf_path = 0; rf_path < 2; rf_path++) { | ||
1780 | /* Fill Pwr group */ | ||
1781 | for (i = 0; i < 14; i++) { | ||
1782 | /* Chanel 1-3 */ | ||
1783 | if (i < 3) | ||
1784 | index = 0; | ||
1785 | /* Channel 4-8 */ | ||
1786 | else if (i < 8) | ||
1787 | index = 1; | ||
1788 | /* Channel 9-13 */ | ||
1789 | else | ||
1790 | index = 2; | ||
1791 | |||
1792 | rtlefuse->pwrgroup_ht20[rf_path][i] = | ||
1793 | (rtlefuse->eeprom_pwrgroup[rf_path][index] & | ||
1794 | 0xf); | ||
1795 | rtlefuse->pwrgroup_ht40[rf_path][i] = | ||
1796 | ((rtlefuse->eeprom_pwrgroup[rf_path][index] & | ||
1797 | 0xf0) >> 4); | ||
1798 | |||
1799 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | ||
1800 | ("RF-%d pwrgroup_ht20[%d] = 0x%x\n", | ||
1801 | rf_path, i, | ||
1802 | rtlefuse->pwrgroup_ht20[rf_path][i])); | ||
1803 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | ||
1804 | ("RF-%d pwrgroup_ht40[%d] = 0x%x\n", | ||
1805 | rf_path, i, | ||
1806 | rtlefuse->pwrgroup_ht40[rf_path][i])); | ||
1807 | } | ||
1808 | } | ||
1809 | |||
1810 | for (i = 0; i < 14; i++) { | ||
1811 | /* Read tx power difference between HT OFDM 20/40 MHZ */ | ||
1812 | /* channel 1-3 */ | ||
1813 | if (i < 3) | ||
1814 | index = 0; | ||
1815 | /* Channel 4-8 */ | ||
1816 | else if (i < 8) | ||
1817 | index = 1; | ||
1818 | /* Channel 9-14 */ | ||
1819 | else | ||
1820 | index = 2; | ||
1821 | |||
1822 | tempval = (*(u8 *)&hwinfo[EEPROM_TX_PWR_HT20_DIFF + | ||
1823 | index]) & 0xff; | ||
1824 | rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] = (tempval & 0xF); | ||
1825 | rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] = | ||
1826 | ((tempval >> 4) & 0xF); | ||
1827 | |||
1828 | /* Read OFDM<->HT tx power diff */ | ||
1829 | /* Channel 1-3 */ | ||
1830 | if (i < 3) | ||
1831 | index = 0; | ||
1832 | /* Channel 4-8 */ | ||
1833 | else if (i < 8) | ||
1834 | index = 0x11; | ||
1835 | /* Channel 9-14 */ | ||
1836 | else | ||
1837 | index = 1; | ||
1838 | |||
1839 | tempval = (*(u8 *)&hwinfo[EEPROM_TX_PWR_OFDM_DIFF + index]) | ||
1840 | & 0xff; | ||
1841 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i] = | ||
1842 | (tempval & 0xF); | ||
1843 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i] = | ||
1844 | ((tempval >> 4) & 0xF); | ||
1845 | |||
1846 | tempval = (*(u8 *)&hwinfo[TX_PWR_SAFETY_CHK]); | ||
1847 | rtlefuse->txpwr_safetyflag = (tempval & 0x01); | ||
1848 | } | ||
1849 | |||
1850 | rtlefuse->eeprom_regulatory = 0; | ||
1851 | if (rtlefuse->eeprom_version >= 2) { | ||
1852 | /* BIT(0)~2 */ | ||
1853 | if (rtlefuse->eeprom_version >= 4) | ||
1854 | rtlefuse->eeprom_regulatory = | ||
1855 | (hwinfo[EEPROM_REGULATORY] & 0x7); | ||
1856 | else /* BIT(0) */ | ||
1857 | rtlefuse->eeprom_regulatory = | ||
1858 | (hwinfo[EEPROM_REGULATORY] & 0x1); | ||
1859 | } | ||
1860 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | ||
1861 | ("eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory)); | ||
1862 | |||
1863 | for (i = 0; i < 14; i++) | ||
1864 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | ||
1865 | ("RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", i, | ||
1866 | rtlefuse->txpwr_ht20diff[RF90_PATH_A][i])); | ||
1867 | for (i = 0; i < 14; i++) | ||
1868 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | ||
1869 | ("RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", i, | ||
1870 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i])); | ||
1871 | for (i = 0; i < 14; i++) | ||
1872 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | ||
1873 | ("RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", i, | ||
1874 | rtlefuse->txpwr_ht20diff[RF90_PATH_B][i])); | ||
1875 | for (i = 0; i < 14; i++) | ||
1876 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, | ||
1877 | ("RF-B Legacy to HT40 Diff[%d] = 0x%x\n", i, | ||
1878 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i])); | ||
1879 | |||
1880 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, ("TxPwrSafetyFlag = %d\n", | ||
1881 | rtlefuse->txpwr_safetyflag)); | ||
1882 | |||
1883 | /* Read RF-indication and Tx Power gain | ||
1884 | * index diff of legacy to HT OFDM rate. */ | ||
1885 | tempval = (*(u8 *)&hwinfo[EEPROM_RFIND_POWERDIFF]) & 0xff; | ||
1886 | rtlefuse->eeprom_txpowerdiff = tempval; | ||
1887 | rtlefuse->legacy_httxpowerdiff = | ||
1888 | rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][0]; | ||
1889 | |||
1890 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, ("TxPowerDiff = %#x\n", | ||
1891 | rtlefuse->eeprom_txpowerdiff)); | ||
1892 | |||
1893 | /* Get TSSI value for each path. */ | ||
1894 | usvalue = *(u16 *)&hwinfo[EEPROM_TSSI_A]; | ||
1895 | rtlefuse->eeprom_tssi[RF90_PATH_A] = (u8)((usvalue & 0xff00) >> 8); | ||
1896 | usvalue = *(u8 *)&hwinfo[EEPROM_TSSI_B]; | ||
1897 | rtlefuse->eeprom_tssi[RF90_PATH_B] = (u8)(usvalue & 0xff); | ||
1898 | |||
1899 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, ("TSSI_A = 0x%x, TSSI_B = 0x%x\n", | ||
1900 | rtlefuse->eeprom_tssi[RF90_PATH_A], | ||
1901 | rtlefuse->eeprom_tssi[RF90_PATH_B])); | ||
1902 | |||
1903 | /* Read antenna tx power offset of B/C/D to A from EEPROM */ | ||
1904 | /* and read ThermalMeter from EEPROM */ | ||
1905 | tempval = *(u8 *)&hwinfo[EEPROM_THERMALMETER]; | ||
1906 | rtlefuse->eeprom_thermalmeter = tempval; | ||
1907 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, ("thermalmeter = 0x%x\n", | ||
1908 | rtlefuse->eeprom_thermalmeter)); | ||
1909 | |||
1910 | /* ThermalMeter, BIT(0)~3 for RFIC1, BIT(4)~7 for RFIC2 */ | ||
1911 | rtlefuse->thermalmeter[0] = (rtlefuse->eeprom_thermalmeter & 0x1f); | ||
1912 | rtlefuse->tssi_13dbm = rtlefuse->eeprom_thermalmeter * 100; | ||
1913 | |||
1914 | /* Read CrystalCap from EEPROM */ | ||
1915 | tempval = (*(u8 *)&hwinfo[EEPROM_CRYSTALCAP]) >> 4; | ||
1916 | rtlefuse->eeprom_crystalcap = tempval; | ||
1917 | /* CrystalCap, BIT(12)~15 */ | ||
1918 | rtlefuse->crystalcap = rtlefuse->eeprom_crystalcap; | ||
1919 | |||
1920 | /* Read IC Version && Channel Plan */ | ||
1921 | /* Version ID, Channel plan */ | ||
1922 | rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN]; | ||
1923 | rtlefuse->txpwr_fromeprom = true; | ||
1924 | RTPRINT(rtlpriv, FINIT, INIT_TxPower, ("EEPROM ChannelPlan = 0x%4x\n", | ||
1925 | rtlefuse->eeprom_channelplan)); | ||
1926 | |||
1927 | /* Read Customer ID or Board Type!!! */ | ||
1928 | tempval = *(u8 *)&hwinfo[EEPROM_BOARDTYPE]; | ||
1929 | /* Change RF type definition */ | ||
1930 | if (tempval == 0) | ||
1931 | rtlphy->rf_type = RF_2T2R; | ||
1932 | else if (tempval == 1) | ||
1933 | rtlphy->rf_type = RF_1T2R; | ||
1934 | else if (tempval == 2) | ||
1935 | rtlphy->rf_type = RF_1T2R; | ||
1936 | else if (tempval == 3) | ||
1937 | rtlphy->rf_type = RF_1T1R; | ||
1938 | |||
1939 | /* 1T2R but 1SS (1x1 receive combining) */ | ||
1940 | rtlefuse->b1x1_recvcombine = false; | ||
1941 | if (rtlphy->rf_type == RF_1T2R) { | ||
1942 | tempval = rtl_read_byte(rtlpriv, 0x07); | ||
1943 | if (!(tempval & BIT(0))) { | ||
1944 | rtlefuse->b1x1_recvcombine = true; | ||
1945 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1946 | ("RF_TYPE=1T2R but only 1SS\n")); | ||
1947 | } | ||
1948 | } | ||
1949 | rtlefuse->b1ss_support = rtlefuse->b1x1_recvcombine; | ||
1950 | rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMID]; | ||
1951 | |||
1952 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("EEPROM Customer ID: 0x%2x", | ||
1953 | rtlefuse->eeprom_oemid)); | ||
1954 | |||
1955 | /* set channel paln to world wide 13 */ | ||
1956 | rtlefuse->channel_plan = COUNTRY_CODE_WORLD_WIDE_13; | ||
1957 | } | ||
1958 | |||
1959 | void rtl92se_read_eeprom_info(struct ieee80211_hw *hw) | ||
1960 | { | ||
1961 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1962 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1963 | u8 tmp_u1b = 0; | ||
1964 | |||
1965 | tmp_u1b = rtl_read_byte(rtlpriv, EPROM_CMD); | ||
1966 | |||
1967 | if (tmp_u1b & BIT(4)) { | ||
1968 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from EEPROM\n")); | ||
1969 | rtlefuse->epromtype = EEPROM_93C46; | ||
1970 | } else { | ||
1971 | RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from EFUSE\n")); | ||
1972 | rtlefuse->epromtype = EEPROM_BOOT_EFUSE; | ||
1973 | } | ||
1974 | |||
1975 | if (tmp_u1b & BIT(5)) { | ||
1976 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n")); | ||
1977 | rtlefuse->autoload_failflag = false; | ||
1978 | _rtl92se_read_adapter_info(hw); | ||
1979 | } else { | ||
1980 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Autoload ERR!!\n")); | ||
1981 | rtlefuse->autoload_failflag = true; | ||
1982 | } | ||
1983 | } | ||
1984 | |||
1985 | static void rtl92se_update_hal_rate_table(struct ieee80211_hw *hw, | ||
1986 | struct ieee80211_sta *sta) | ||
1987 | { | ||
1988 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1989 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1990 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
1991 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1992 | u32 ratr_value; | ||
1993 | u8 ratr_index = 0; | ||
1994 | u8 nmode = mac->ht_enable; | ||
1995 | u8 mimo_ps = IEEE80211_SMPS_OFF; | ||
1996 | u16 shortgi_rate = 0; | ||
1997 | u32 tmp_ratr_value = 0; | ||
1998 | u8 curtxbw_40mhz = mac->bw_40; | ||
1999 | u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? | ||
2000 | 1 : 0; | ||
2001 | u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? | ||
2002 | 1 : 0; | ||
2003 | enum wireless_mode wirelessmode = mac->mode; | ||
2004 | |||
2005 | if (rtlhal->current_bandtype == BAND_ON_5G) | ||
2006 | ratr_value = sta->supp_rates[1] << 4; | ||
2007 | else | ||
2008 | ratr_value = sta->supp_rates[0]; | ||
2009 | ratr_value |= (sta->ht_cap.mcs.rx_mask[1] << 20 | | ||
2010 | sta->ht_cap.mcs.rx_mask[0] << 12); | ||
2011 | switch (wirelessmode) { | ||
2012 | case WIRELESS_MODE_B: | ||
2013 | ratr_value &= 0x0000000D; | ||
2014 | break; | ||
2015 | case WIRELESS_MODE_G: | ||
2016 | ratr_value &= 0x00000FF5; | ||
2017 | break; | ||
2018 | case WIRELESS_MODE_N_24G: | ||
2019 | case WIRELESS_MODE_N_5G: | ||
2020 | nmode = 1; | ||
2021 | if (mimo_ps == IEEE80211_SMPS_STATIC) { | ||
2022 | ratr_value &= 0x0007F005; | ||
2023 | } else { | ||
2024 | u32 ratr_mask; | ||
2025 | |||
2026 | if (get_rf_type(rtlphy) == RF_1T2R || | ||
2027 | get_rf_type(rtlphy) == RF_1T1R) { | ||
2028 | if (curtxbw_40mhz) | ||
2029 | ratr_mask = 0x000ff015; | ||
2030 | else | ||
2031 | ratr_mask = 0x000ff005; | ||
2032 | } else { | ||
2033 | if (curtxbw_40mhz) | ||
2034 | ratr_mask = 0x0f0ff015; | ||
2035 | else | ||
2036 | ratr_mask = 0x0f0ff005; | ||
2037 | } | ||
2038 | |||
2039 | ratr_value &= ratr_mask; | ||
2040 | } | ||
2041 | break; | ||
2042 | default: | ||
2043 | if (rtlphy->rf_type == RF_1T2R) | ||
2044 | ratr_value &= 0x000ff0ff; | ||
2045 | else | ||
2046 | ratr_value &= 0x0f0ff0ff; | ||
2047 | |||
2048 | break; | ||
2049 | } | ||
2050 | |||
2051 | if (rtlpriv->rtlhal.version >= VERSION_8192S_BCUT) | ||
2052 | ratr_value &= 0x0FFFFFFF; | ||
2053 | else if (rtlpriv->rtlhal.version == VERSION_8192S_ACUT) | ||
2054 | ratr_value &= 0x0FFFFFF0; | ||
2055 | |||
2056 | if (nmode && ((curtxbw_40mhz && | ||
2057 | curshortgi_40mhz) || (!curtxbw_40mhz && | ||
2058 | curshortgi_20mhz))) { | ||
2059 | |||
2060 | ratr_value |= 0x10000000; | ||
2061 | tmp_ratr_value = (ratr_value >> 12); | ||
2062 | |||
2063 | for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { | ||
2064 | if ((1 << shortgi_rate) & tmp_ratr_value) | ||
2065 | break; | ||
2066 | } | ||
2067 | |||
2068 | shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | | ||
2069 | (shortgi_rate << 4) | (shortgi_rate); | ||
2070 | |||
2071 | rtl_write_byte(rtlpriv, SG_RATE, shortgi_rate); | ||
2072 | } | ||
2073 | |||
2074 | rtl_write_dword(rtlpriv, ARFR0 + ratr_index * 4, ratr_value); | ||
2075 | if (ratr_value & 0xfffff000) | ||
2076 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_REFRESH_N); | ||
2077 | else | ||
2078 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_RA_REFRESH_BG); | ||
2079 | |||
2080 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, | ||
2081 | ("%x\n", rtl_read_dword(rtlpriv, ARFR0))); | ||
2082 | } | ||
2083 | |||
2084 | static void rtl92se_update_hal_rate_mask(struct ieee80211_hw *hw, | ||
2085 | struct ieee80211_sta *sta, | ||
2086 | u8 rssi_level) | ||
2087 | { | ||
2088 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2089 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
2090 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
2091 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
2092 | struct rtl_sta_info *sta_entry = NULL; | ||
2093 | u32 ratr_bitmap; | ||
2094 | u8 ratr_index = 0; | ||
2095 | u8 curtxbw_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) | ||
2096 | ? 1 : 0; | ||
2097 | u8 curshortgi_40mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? | ||
2098 | 1 : 0; | ||
2099 | u8 curshortgi_20mhz = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_20) ? | ||
2100 | 1 : 0; | ||
2101 | enum wireless_mode wirelessmode = 0; | ||
2102 | bool shortgi = false; | ||
2103 | u32 ratr_value = 0; | ||
2104 | u8 shortgi_rate = 0; | ||
2105 | u32 mask = 0; | ||
2106 | u32 band = 0; | ||
2107 | bool bmulticast = false; | ||
2108 | u8 macid = 0; | ||
2109 | u8 mimo_ps = IEEE80211_SMPS_OFF; | ||
2110 | |||
2111 | sta_entry = (struct rtl_sta_info *) sta->drv_priv; | ||
2112 | wirelessmode = sta_entry->wireless_mode; | ||
2113 | if (mac->opmode == NL80211_IFTYPE_STATION) | ||
2114 | curtxbw_40mhz = mac->bw_40; | ||
2115 | else if (mac->opmode == NL80211_IFTYPE_AP || | ||
2116 | mac->opmode == NL80211_IFTYPE_ADHOC) | ||
2117 | macid = sta->aid + 1; | ||
2118 | |||
2119 | if (rtlhal->current_bandtype == BAND_ON_5G) | ||
2120 | ratr_bitmap = sta->supp_rates[1] << 4; | ||
2121 | else | ||
2122 | ratr_bitmap = sta->supp_rates[0]; | ||
2123 | ratr_bitmap |= (sta->ht_cap.mcs.rx_mask[1] << 20 | | ||
2124 | sta->ht_cap.mcs.rx_mask[0] << 12); | ||
2125 | switch (wirelessmode) { | ||
2126 | case WIRELESS_MODE_B: | ||
2127 | band |= WIRELESS_11B; | ||
2128 | ratr_index = RATR_INX_WIRELESS_B; | ||
2129 | if (ratr_bitmap & 0x0000000c) | ||
2130 | ratr_bitmap &= 0x0000000d; | ||
2131 | else | ||
2132 | ratr_bitmap &= 0x0000000f; | ||
2133 | break; | ||
2134 | case WIRELESS_MODE_G: | ||
2135 | band |= (WIRELESS_11G | WIRELESS_11B); | ||
2136 | ratr_index = RATR_INX_WIRELESS_GB; | ||
2137 | |||
2138 | if (rssi_level == 1) | ||
2139 | ratr_bitmap &= 0x00000f00; | ||
2140 | else if (rssi_level == 2) | ||
2141 | ratr_bitmap &= 0x00000ff0; | ||
2142 | else | ||
2143 | ratr_bitmap &= 0x00000ff5; | ||
2144 | break; | ||
2145 | case WIRELESS_MODE_A: | ||
2146 | band |= WIRELESS_11A; | ||
2147 | ratr_index = RATR_INX_WIRELESS_A; | ||
2148 | ratr_bitmap &= 0x00000ff0; | ||
2149 | break; | ||
2150 | case WIRELESS_MODE_N_24G: | ||
2151 | case WIRELESS_MODE_N_5G: | ||
2152 | band |= (WIRELESS_11N | WIRELESS_11G | WIRELESS_11B); | ||
2153 | ratr_index = RATR_INX_WIRELESS_NGB; | ||
2154 | |||
2155 | if (mimo_ps == IEEE80211_SMPS_STATIC) { | ||
2156 | if (rssi_level == 1) | ||
2157 | ratr_bitmap &= 0x00070000; | ||
2158 | else if (rssi_level == 2) | ||
2159 | ratr_bitmap &= 0x0007f000; | ||
2160 | else | ||
2161 | ratr_bitmap &= 0x0007f005; | ||
2162 | } else { | ||
2163 | if (rtlphy->rf_type == RF_1T2R || | ||
2164 | rtlphy->rf_type == RF_1T1R) { | ||
2165 | if (rssi_level == 1) { | ||
2166 | ratr_bitmap &= 0x000f0000; | ||
2167 | } else if (rssi_level == 3) { | ||
2168 | ratr_bitmap &= 0x000fc000; | ||
2169 | } else if (rssi_level == 5) { | ||
2170 | ratr_bitmap &= 0x000ff000; | ||
2171 | } else { | ||
2172 | if (curtxbw_40mhz) | ||
2173 | ratr_bitmap &= 0x000ff015; | ||
2174 | else | ||
2175 | ratr_bitmap &= 0x000ff005; | ||
2176 | } | ||
2177 | } else { | ||
2178 | if (rssi_level == 1) { | ||
2179 | ratr_bitmap &= 0x0f8f0000; | ||
2180 | } else if (rssi_level == 3) { | ||
2181 | ratr_bitmap &= 0x0f8fc000; | ||
2182 | } else if (rssi_level == 5) { | ||
2183 | ratr_bitmap &= 0x0f8ff000; | ||
2184 | } else { | ||
2185 | if (curtxbw_40mhz) | ||
2186 | ratr_bitmap &= 0x0f8ff015; | ||
2187 | else | ||
2188 | ratr_bitmap &= 0x0f8ff005; | ||
2189 | } | ||
2190 | } | ||
2191 | } | ||
2192 | |||
2193 | if ((curtxbw_40mhz && curshortgi_40mhz) || | ||
2194 | (!curtxbw_40mhz && curshortgi_20mhz)) { | ||
2195 | if (macid == 0) | ||
2196 | shortgi = true; | ||
2197 | else if (macid == 1) | ||
2198 | shortgi = false; | ||
2199 | } | ||
2200 | break; | ||
2201 | default: | ||
2202 | band |= (WIRELESS_11N | WIRELESS_11G | WIRELESS_11B); | ||
2203 | ratr_index = RATR_INX_WIRELESS_NGB; | ||
2204 | |||
2205 | if (rtlphy->rf_type == RF_1T2R) | ||
2206 | ratr_bitmap &= 0x000ff0ff; | ||
2207 | else | ||
2208 | ratr_bitmap &= 0x0f8ff0ff; | ||
2209 | break; | ||
2210 | } | ||
2211 | |||
2212 | if (rtlpriv->rtlhal.version >= VERSION_8192S_BCUT) | ||
2213 | ratr_bitmap &= 0x0FFFFFFF; | ||
2214 | else if (rtlpriv->rtlhal.version == VERSION_8192S_ACUT) | ||
2215 | ratr_bitmap &= 0x0FFFFFF0; | ||
2216 | |||
2217 | if (shortgi) { | ||
2218 | ratr_bitmap |= 0x10000000; | ||
2219 | /* Get MAX MCS available. */ | ||
2220 | ratr_value = (ratr_bitmap >> 12); | ||
2221 | for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) { | ||
2222 | if ((1 << shortgi_rate) & ratr_value) | ||
2223 | break; | ||
2224 | } | ||
2225 | |||
2226 | shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) | | ||
2227 | (shortgi_rate << 4) | (shortgi_rate); | ||
2228 | rtl_write_byte(rtlpriv, SG_RATE, shortgi_rate); | ||
2229 | } | ||
2230 | |||
2231 | mask |= (bmulticast ? 1 : 0) << 9 | (macid & 0x1f) << 4 | (band & 0xf); | ||
2232 | |||
2233 | RT_TRACE(rtlpriv, COMP_RATR, DBG_TRACE, ("mask = %x, bitmap = %x\n", | ||
2234 | mask, ratr_bitmap)); | ||
2235 | rtl_write_dword(rtlpriv, 0x2c4, ratr_bitmap); | ||
2236 | rtl_write_dword(rtlpriv, WFM5, (FW_RA_UPDATE_MASK | (mask << 8))); | ||
2237 | |||
2238 | if (macid != 0) | ||
2239 | sta_entry->ratr_index = ratr_index; | ||
2240 | } | ||
2241 | |||
2242 | void rtl92se_update_hal_rate_tbl(struct ieee80211_hw *hw, | ||
2243 | struct ieee80211_sta *sta, u8 rssi_level) | ||
2244 | { | ||
2245 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2246 | |||
2247 | if (rtlpriv->dm.useramask) | ||
2248 | rtl92se_update_hal_rate_mask(hw, sta, rssi_level); | ||
2249 | else | ||
2250 | rtl92se_update_hal_rate_table(hw, sta); | ||
2251 | } | ||
2252 | |||
2253 | void rtl92se_update_channel_access_setting(struct ieee80211_hw *hw) | ||
2254 | { | ||
2255 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2256 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
2257 | u16 sifs_timer; | ||
2258 | |||
2259 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME, | ||
2260 | (u8 *)&mac->slot_time); | ||
2261 | sifs_timer = 0x0e0e; | ||
2262 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer); | ||
2263 | |||
2264 | } | ||
2265 | |||
2266 | /* this ifunction is for RFKILL, it's different with windows, | ||
2267 | * because UI will disable wireless when GPIO Radio Off. | ||
2268 | * And here we not check or Disable/Enable ASPM like windows*/ | ||
2269 | bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 *valid) | ||
2270 | { | ||
2271 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2272 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
2273 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
2274 | enum rf_pwrstate rfpwr_toset, cur_rfstate; | ||
2275 | unsigned long flag = 0; | ||
2276 | bool actuallyset = false; | ||
2277 | bool turnonbypowerdomain = false; | ||
2278 | |||
2279 | /* just 8191se can check gpio before firstup, 92c/92d have fixed it */ | ||
2280 | if ((rtlpci->up_first_time == 1) || (rtlpci->being_init_adapter)) | ||
2281 | return false; | ||
2282 | |||
2283 | if (ppsc->swrf_processing) | ||
2284 | return false; | ||
2285 | |||
2286 | spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); | ||
2287 | if (ppsc->rfchange_inprogress) { | ||
2288 | spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); | ||
2289 | return false; | ||
2290 | } else { | ||
2291 | ppsc->rfchange_inprogress = true; | ||
2292 | spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); | ||
2293 | } | ||
2294 | |||
2295 | cur_rfstate = ppsc->rfpwr_state; | ||
2296 | |||
2297 | /* because after _rtl92s_phy_set_rfhalt, all power | ||
2298 | * closed, so we must open some power for GPIO check, | ||
2299 | * or we will always check GPIO RFOFF here, | ||
2300 | * And we should close power after GPIO check */ | ||
2301 | if (RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { | ||
2302 | _rtl92se_power_domain_init(hw); | ||
2303 | turnonbypowerdomain = true; | ||
2304 | } | ||
2305 | |||
2306 | rfpwr_toset = _rtl92se_rf_onoff_detect(hw); | ||
2307 | |||
2308 | if ((ppsc->hwradiooff == true) && (rfpwr_toset == ERFON)) { | ||
2309 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2310 | ("RFKILL-HW Radio ON, RF ON\n")); | ||
2311 | |||
2312 | rfpwr_toset = ERFON; | ||
2313 | ppsc->hwradiooff = false; | ||
2314 | actuallyset = true; | ||
2315 | } else if ((ppsc->hwradiooff == false) && (rfpwr_toset == ERFOFF)) { | ||
2316 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
2317 | ("RFKILL-HW Radio OFF, RF OFF\n")); | ||
2318 | |||
2319 | rfpwr_toset = ERFOFF; | ||
2320 | ppsc->hwradiooff = true; | ||
2321 | actuallyset = true; | ||
2322 | } | ||
2323 | |||
2324 | if (actuallyset) { | ||
2325 | spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); | ||
2326 | ppsc->rfchange_inprogress = false; | ||
2327 | spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); | ||
2328 | |||
2329 | /* this not include ifconfig wlan0 down case */ | ||
2330 | /* } else if (rfpwr_toset == ERFOFF || cur_rfstate == ERFOFF) { */ | ||
2331 | } else { | ||
2332 | /* because power_domain_init may be happen when | ||
2333 | * _rtl92s_phy_set_rfhalt, this will open some powers | ||
2334 | * and cause current increasing about 40 mA for ips, | ||
2335 | * rfoff and ifconfig down, so we set | ||
2336 | * _rtl92s_phy_set_rfhalt again here */ | ||
2337 | if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC && | ||
2338 | turnonbypowerdomain) { | ||
2339 | _rtl92s_phy_set_rfhalt(hw); | ||
2340 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); | ||
2341 | } | ||
2342 | |||
2343 | spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag); | ||
2344 | ppsc->rfchange_inprogress = false; | ||
2345 | spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag); | ||
2346 | } | ||
2347 | |||
2348 | *valid = 1; | ||
2349 | return !ppsc->hwradiooff; | ||
2350 | |||
2351 | } | ||
2352 | |||
2353 | /* Is_wepkey just used for WEP used as group & pairwise key | ||
2354 | * if pairwise is AES ang group is WEP Is_wepkey == false.*/ | ||
2355 | void rtl92se_set_key(struct ieee80211_hw *hw, u32 key_index, u8 *p_macaddr, | ||
2356 | bool is_group, u8 enc_algo, bool is_wepkey, bool clear_all) | ||
2357 | { | ||
2358 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
2359 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
2360 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
2361 | u8 *macaddr = p_macaddr; | ||
2362 | |||
2363 | u32 entry_id = 0; | ||
2364 | bool is_pairwise = false; | ||
2365 | |||
2366 | static u8 cam_const_addr[4][6] = { | ||
2367 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
2368 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, | ||
2369 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, | ||
2370 | {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} | ||
2371 | }; | ||
2372 | static u8 cam_const_broad[] = { | ||
2373 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff | ||
2374 | }; | ||
2375 | |||
2376 | if (clear_all) { | ||
2377 | u8 idx = 0; | ||
2378 | u8 cam_offset = 0; | ||
2379 | u8 clear_number = 5; | ||
2380 | |||
2381 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("clear_all\n")); | ||
2382 | |||
2383 | for (idx = 0; idx < clear_number; idx++) { | ||
2384 | rtl_cam_mark_invalid(hw, cam_offset + idx); | ||
2385 | rtl_cam_empty_entry(hw, cam_offset + idx); | ||
2386 | |||
2387 | if (idx < 5) { | ||
2388 | memset(rtlpriv->sec.key_buf[idx], 0, | ||
2389 | MAX_KEY_LEN); | ||
2390 | rtlpriv->sec.key_len[idx] = 0; | ||
2391 | } | ||
2392 | } | ||
2393 | |||
2394 | } else { | ||
2395 | switch (enc_algo) { | ||
2396 | case WEP40_ENCRYPTION: | ||
2397 | enc_algo = CAM_WEP40; | ||
2398 | break; | ||
2399 | case WEP104_ENCRYPTION: | ||
2400 | enc_algo = CAM_WEP104; | ||
2401 | break; | ||
2402 | case TKIP_ENCRYPTION: | ||
2403 | enc_algo = CAM_TKIP; | ||
2404 | break; | ||
2405 | case AESCCMP_ENCRYPTION: | ||
2406 | enc_algo = CAM_AES; | ||
2407 | break; | ||
2408 | default: | ||
2409 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
2410 | ("switch case not process\n")); | ||
2411 | enc_algo = CAM_TKIP; | ||
2412 | break; | ||
2413 | } | ||
2414 | |||
2415 | if (is_wepkey || rtlpriv->sec.use_defaultkey) { | ||
2416 | macaddr = cam_const_addr[key_index]; | ||
2417 | entry_id = key_index; | ||
2418 | } else { | ||
2419 | if (is_group) { | ||
2420 | macaddr = cam_const_broad; | ||
2421 | entry_id = key_index; | ||
2422 | } else { | ||
2423 | if (mac->opmode == NL80211_IFTYPE_AP) { | ||
2424 | entry_id = rtl_cam_get_free_entry(hw, | ||
2425 | p_macaddr); | ||
2426 | if (entry_id >= TOTAL_CAM_ENTRY) { | ||
2427 | RT_TRACE(rtlpriv, | ||
2428 | COMP_SEC, DBG_EMERG, | ||
2429 | ("Can not find free hw" | ||
2430 | " security cam entry\n")); | ||
2431 | return; | ||
2432 | } | ||
2433 | } else { | ||
2434 | entry_id = CAM_PAIRWISE_KEY_POSITION; | ||
2435 | } | ||
2436 | |||
2437 | key_index = PAIRWISE_KEYIDX; | ||
2438 | is_pairwise = true; | ||
2439 | } | ||
2440 | } | ||
2441 | |||
2442 | if (rtlpriv->sec.key_len[key_index] == 0) { | ||
2443 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
2444 | ("delete one entry, entry_id is %d\n", | ||
2445 | entry_id)); | ||
2446 | if (mac->opmode == NL80211_IFTYPE_AP) | ||
2447 | rtl_cam_del_entry(hw, p_macaddr); | ||
2448 | rtl_cam_delete_one_entry(hw, p_macaddr, entry_id); | ||
2449 | } else { | ||
2450 | RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, | ||
2451 | ("The insert KEY length is %d\n", | ||
2452 | rtlpriv->sec.key_len[PAIRWISE_KEYIDX])); | ||
2453 | RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD, | ||
2454 | ("The insert KEY is %x %x\n", | ||
2455 | rtlpriv->sec.key_buf[0][0], | ||
2456 | rtlpriv->sec.key_buf[0][1])); | ||
2457 | |||
2458 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
2459 | ("add one entry\n")); | ||
2460 | if (is_pairwise) { | ||
2461 | RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD, | ||
2462 | "Pairwiase Key content :", | ||
2463 | rtlpriv->sec.pairwise_key, | ||
2464 | rtlpriv->sec.key_len[PAIRWISE_KEYIDX]); | ||
2465 | |||
2466 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
2467 | ("set Pairwiase key\n")); | ||
2468 | |||
2469 | rtl_cam_add_one_entry(hw, macaddr, key_index, | ||
2470 | entry_id, enc_algo, | ||
2471 | CAM_CONFIG_NO_USEDK, | ||
2472 | rtlpriv->sec.key_buf[key_index]); | ||
2473 | } else { | ||
2474 | RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, | ||
2475 | ("set group key\n")); | ||
2476 | |||
2477 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
2478 | rtl_cam_add_one_entry(hw, | ||
2479 | rtlefuse->dev_addr, | ||
2480 | PAIRWISE_KEYIDX, | ||
2481 | CAM_PAIRWISE_KEY_POSITION, | ||
2482 | enc_algo, CAM_CONFIG_NO_USEDK, | ||
2483 | rtlpriv->sec.key_buf[entry_id]); | ||
2484 | } | ||
2485 | |||
2486 | rtl_cam_add_one_entry(hw, macaddr, key_index, | ||
2487 | entry_id, enc_algo, | ||
2488 | CAM_CONFIG_NO_USEDK, | ||
2489 | rtlpriv->sec.key_buf[entry_id]); | ||
2490 | } | ||
2491 | |||
2492 | } | ||
2493 | } | ||
2494 | } | ||
2495 | |||
2496 | void rtl92se_suspend(struct ieee80211_hw *hw) | ||
2497 | { | ||
2498 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
2499 | |||
2500 | rtlpci->up_first_time = true; | ||
2501 | } | ||
2502 | |||
2503 | void rtl92se_resume(struct ieee80211_hw *hw) | ||
2504 | { | ||
2505 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
2506 | u32 val; | ||
2507 | |||
2508 | pci_read_config_dword(rtlpci->pdev, 0x40, &val); | ||
2509 | if ((val & 0x0000ff00) != 0) | ||
2510 | pci_write_config_dword(rtlpci->pdev, 0x40, | ||
2511 | val & 0xffff00ff); | ||
2512 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h new file mode 100644 index 000000000000..6160a9bfe98a --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h | |||
@@ -0,0 +1,79 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | #ifndef __REALTEK_PCI92SE_HW_H__ | ||
30 | #define __REALTEK_PCI92SE_HW_H__ | ||
31 | |||
32 | #define MSR_LINK_MANAGED 2 | ||
33 | #define MSR_LINK_NONE 0 | ||
34 | #define MSR_LINK_SHIFT 0 | ||
35 | #define MSR_LINK_ADHOC 1 | ||
36 | #define MSR_LINK_MASTER 3 | ||
37 | |||
38 | enum WIRELESS_NETWORK_TYPE { | ||
39 | WIRELESS_11B = 1, | ||
40 | WIRELESS_11G = 2, | ||
41 | WIRELESS_11A = 4, | ||
42 | WIRELESS_11N = 8 | ||
43 | }; | ||
44 | |||
45 | void rtl92se_get_hw_reg(struct ieee80211_hw *hw, | ||
46 | u8 variable, u8 *val); | ||
47 | void rtl92se_read_eeprom_info(struct ieee80211_hw *hw); | ||
48 | void rtl92se_interrupt_recognized(struct ieee80211_hw *hw, | ||
49 | u32 *inta, u32 *intb); | ||
50 | int rtl92se_hw_init(struct ieee80211_hw *hw); | ||
51 | void rtl92se_card_disable(struct ieee80211_hw *hw); | ||
52 | void rtl92se_enable_interrupt(struct ieee80211_hw *hw); | ||
53 | void rtl92se_disable_interrupt(struct ieee80211_hw *hw); | ||
54 | int rtl92se_set_network_type(struct ieee80211_hw *hw, | ||
55 | enum nl80211_iftype type); | ||
56 | void rtl92se_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); | ||
57 | void rtl92se_set_mac_addr(struct rtl_io *io, const u8 * addr); | ||
58 | void rtl92se_set_qos(struct ieee80211_hw *hw, int aci); | ||
59 | void rtl92se_set_beacon_related_registers(struct ieee80211_hw *hw); | ||
60 | void rtl92se_set_beacon_interval(struct ieee80211_hw *hw); | ||
61 | void rtl92se_update_interrupt_mask(struct ieee80211_hw *hw, | ||
62 | u32 add_msr, u32 rm_msr); | ||
63 | void rtl92se_set_hw_reg(struct ieee80211_hw *hw, u8 variable, | ||
64 | u8 *val); | ||
65 | void rtl92se_update_hal_rate_tbl(struct ieee80211_hw *hw, | ||
66 | struct ieee80211_sta *sta, u8 rssi_level); | ||
67 | void rtl92se_update_channel_access_setting(struct ieee80211_hw *hw); | ||
68 | bool rtl92se_gpio_radio_on_off_checking(struct ieee80211_hw *hw, | ||
69 | u8 *valid); | ||
70 | void rtl8192se_gpiobit3_cfg_inputmode(struct ieee80211_hw *hw); | ||
71 | void rtl92se_enable_hw_security_config(struct ieee80211_hw *hw); | ||
72 | void rtl92se_set_key(struct ieee80211_hw *hw, | ||
73 | u32 key_index, u8 *macaddr, bool is_group, | ||
74 | u8 enc_algo, bool is_wepkey, bool clear_all); | ||
75 | void rtl92se_suspend(struct ieee80211_hw *hw); | ||
76 | void rtl92se_resume(struct ieee80211_hw *hw); | ||
77 | |||
78 | #endif | ||
79 | |||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/led.c b/drivers/net/wireless/rtlwifi/rtl8192se/led.c new file mode 100644 index 000000000000..6d4f66616680 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/led.c | |||
@@ -0,0 +1,149 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../pci.h" | ||
32 | #include "reg.h" | ||
33 | #include "led.h" | ||
34 | |||
35 | static void _rtl92se_init_led(struct ieee80211_hw *hw, | ||
36 | struct rtl_led *pled, enum rtl_led_pin ledpin) | ||
37 | { | ||
38 | pled->hw = hw; | ||
39 | pled->ledpin = ledpin; | ||
40 | pled->ledon = false; | ||
41 | } | ||
42 | |||
43 | void rtl92se_init_sw_leds(struct ieee80211_hw *hw) | ||
44 | { | ||
45 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
46 | _rtl92se_init_led(hw, &(pcipriv->ledctl.sw_led0), LED_PIN_LED0); | ||
47 | _rtl92se_init_led(hw, &(pcipriv->ledctl.sw_led1), LED_PIN_LED1); | ||
48 | } | ||
49 | |||
50 | void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled) | ||
51 | { | ||
52 | u8 ledcfg; | ||
53 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
54 | |||
55 | RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, | ||
56 | ("LedAddr:%X ledpin=%d\n", LEDCFG, pled->ledpin)); | ||
57 | |||
58 | ledcfg = rtl_read_byte(rtlpriv, LEDCFG); | ||
59 | |||
60 | switch (pled->ledpin) { | ||
61 | case LED_PIN_GPIO0: | ||
62 | break; | ||
63 | case LED_PIN_LED0: | ||
64 | rtl_write_byte(rtlpriv, LEDCFG, ledcfg & 0xf0); | ||
65 | break; | ||
66 | case LED_PIN_LED1: | ||
67 | rtl_write_byte(rtlpriv, LEDCFG, ledcfg & 0x0f); | ||
68 | break; | ||
69 | default: | ||
70 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
71 | ("switch case not process\n")); | ||
72 | break; | ||
73 | } | ||
74 | pled->ledon = true; | ||
75 | } | ||
76 | |||
77 | void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled) | ||
78 | { | ||
79 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
80 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
81 | u8 ledcfg; | ||
82 | |||
83 | RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, | ||
84 | ("LedAddr:%X ledpin=%d\n", LEDCFG, pled->ledpin)); | ||
85 | |||
86 | ledcfg = rtl_read_byte(rtlpriv, LEDCFG); | ||
87 | |||
88 | switch (pled->ledpin) { | ||
89 | case LED_PIN_GPIO0: | ||
90 | break; | ||
91 | case LED_PIN_LED0: | ||
92 | ledcfg &= 0xf0; | ||
93 | if (pcipriv->ledctl.led_opendrain == true) | ||
94 | rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(1))); | ||
95 | else | ||
96 | rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3))); | ||
97 | break; | ||
98 | case LED_PIN_LED1: | ||
99 | ledcfg &= 0x0f; | ||
100 | rtl_write_byte(rtlpriv, LEDCFG, (ledcfg | BIT(3))); | ||
101 | break; | ||
102 | default: | ||
103 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
104 | ("switch case not process\n")); | ||
105 | break; | ||
106 | } | ||
107 | pled->ledon = false; | ||
108 | } | ||
109 | |||
110 | static void _rtl92se_sw_led_control(struct ieee80211_hw *hw, | ||
111 | enum led_ctl_mode ledaction) | ||
112 | { | ||
113 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
114 | struct rtl_led *pLed0 = &(pcipriv->ledctl.sw_led0); | ||
115 | switch (ledaction) { | ||
116 | case LED_CTL_POWER_ON: | ||
117 | case LED_CTL_LINK: | ||
118 | case LED_CTL_NO_LINK: | ||
119 | rtl92se_sw_led_on(hw, pLed0); | ||
120 | break; | ||
121 | case LED_CTL_POWER_OFF: | ||
122 | rtl92se_sw_led_off(hw, pLed0); | ||
123 | break; | ||
124 | default: | ||
125 | break; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | void rtl92se_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction) | ||
130 | { | ||
131 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
132 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
133 | |||
134 | if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) && | ||
135 | (ledaction == LED_CTL_TX || | ||
136 | ledaction == LED_CTL_RX || | ||
137 | ledaction == LED_CTL_SITE_SURVEY || | ||
138 | ledaction == LED_CTL_LINK || | ||
139 | ledaction == LED_CTL_NO_LINK || | ||
140 | ledaction == LED_CTL_START_TO_LINK || | ||
141 | ledaction == LED_CTL_POWER_ON)) { | ||
142 | return; | ||
143 | } | ||
144 | RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d,\n", | ||
145 | ledaction)); | ||
146 | |||
147 | _rtl92se_sw_led_control(hw, ledaction); | ||
148 | } | ||
149 | |||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/led.h b/drivers/net/wireless/rtlwifi/rtl8192se/led.h new file mode 100644 index 000000000000..8cce3870af3c --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/led.h | |||
@@ -0,0 +1,37 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | #ifndef __REALTEK_PCI92SE_LED_H__ | ||
30 | #define __REALTEK_PCI92SE_LED_H__ | ||
31 | |||
32 | void rtl92se_init_sw_leds(struct ieee80211_hw *hw); | ||
33 | void rtl92se_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled); | ||
34 | void rtl92se_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled); | ||
35 | void rtl92se_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction); | ||
36 | |||
37 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c new file mode 100644 index 000000000000..63b45e60a95e --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c | |||
@@ -0,0 +1,1740 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../pci.h" | ||
32 | #include "../ps.h" | ||
33 | #include "reg.h" | ||
34 | #include "def.h" | ||
35 | #include "phy.h" | ||
36 | #include "rf.h" | ||
37 | #include "dm.h" | ||
38 | #include "fw.h" | ||
39 | #include "hw.h" | ||
40 | #include "table.h" | ||
41 | |||
42 | static u32 _rtl92s_phy_calculate_bit_shift(u32 bitmask) | ||
43 | { | ||
44 | u32 i; | ||
45 | |||
46 | for (i = 0; i <= 31; i++) { | ||
47 | if (((bitmask >> i) & 0x1) == 1) | ||
48 | break; | ||
49 | } | ||
50 | |||
51 | return i; | ||
52 | } | ||
53 | |||
54 | u32 rtl92s_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask) | ||
55 | { | ||
56 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
57 | u32 returnvalue = 0, originalvalue, bitshift; | ||
58 | |||
59 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)\n", | ||
60 | regaddr, bitmask)); | ||
61 | |||
62 | originalvalue = rtl_read_dword(rtlpriv, regaddr); | ||
63 | bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); | ||
64 | returnvalue = (originalvalue & bitmask) >> bitshift; | ||
65 | |||
66 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, | ||
67 | ("BBR MASK=0x%x Addr[0x%x]=0x%x\n", | ||
68 | bitmask, regaddr, originalvalue)); | ||
69 | |||
70 | return returnvalue; | ||
71 | |||
72 | } | ||
73 | |||
74 | void rtl92s_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, | ||
75 | u32 data) | ||
76 | { | ||
77 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
78 | u32 originalvalue, bitshift; | ||
79 | |||
80 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)," | ||
81 | " data(%#x)\n", regaddr, bitmask, data)); | ||
82 | |||
83 | if (bitmask != MASKDWORD) { | ||
84 | originalvalue = rtl_read_dword(rtlpriv, regaddr); | ||
85 | bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); | ||
86 | data = ((originalvalue & (~bitmask)) | (data << bitshift)); | ||
87 | } | ||
88 | |||
89 | rtl_write_dword(rtlpriv, regaddr, data); | ||
90 | |||
91 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)," | ||
92 | " data(%#x)\n", regaddr, bitmask, data)); | ||
93 | |||
94 | } | ||
95 | |||
96 | static u32 _rtl92s_phy_rf_serial_read(struct ieee80211_hw *hw, | ||
97 | enum radio_path rfpath, u32 offset) | ||
98 | { | ||
99 | |||
100 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
101 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
102 | struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; | ||
103 | u32 newoffset; | ||
104 | u32 tmplong, tmplong2; | ||
105 | u8 rfpi_enable = 0; | ||
106 | u32 retvalue = 0; | ||
107 | |||
108 | offset &= 0x3f; | ||
109 | newoffset = offset; | ||
110 | |||
111 | tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD); | ||
112 | |||
113 | if (rfpath == RF90_PATH_A) | ||
114 | tmplong2 = tmplong; | ||
115 | else | ||
116 | tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD); | ||
117 | |||
118 | tmplong2 = (tmplong2 & (~BLSSI_READADDRESS)) | (newoffset << 23) | | ||
119 | BLSSI_READEDGE; | ||
120 | |||
121 | rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, | ||
122 | tmplong & (~BLSSI_READEDGE)); | ||
123 | |||
124 | mdelay(1); | ||
125 | |||
126 | rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2); | ||
127 | mdelay(1); | ||
128 | |||
129 | rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD, tmplong | | ||
130 | BLSSI_READEDGE); | ||
131 | mdelay(1); | ||
132 | |||
133 | if (rfpath == RF90_PATH_A) | ||
134 | rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1, | ||
135 | BIT(8)); | ||
136 | else if (rfpath == RF90_PATH_B) | ||
137 | rfpi_enable = (u8)rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1, | ||
138 | BIT(8)); | ||
139 | |||
140 | if (rfpi_enable) | ||
141 | retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi, | ||
142 | BLSSI_READBACK_DATA); | ||
143 | else | ||
144 | retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback, | ||
145 | BLSSI_READBACK_DATA); | ||
146 | |||
147 | retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback, | ||
148 | BLSSI_READBACK_DATA); | ||
149 | |||
150 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFR-%d Addr[0x%x]=0x%x\n", | ||
151 | rfpath, pphyreg->rflssi_readback, retvalue)); | ||
152 | |||
153 | return retvalue; | ||
154 | |||
155 | } | ||
156 | |||
157 | static void _rtl92s_phy_rf_serial_write(struct ieee80211_hw *hw, | ||
158 | enum radio_path rfpath, u32 offset, | ||
159 | u32 data) | ||
160 | { | ||
161 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
162 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
163 | struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath]; | ||
164 | u32 data_and_addr = 0; | ||
165 | u32 newoffset; | ||
166 | |||
167 | offset &= 0x3f; | ||
168 | newoffset = offset; | ||
169 | |||
170 | data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff; | ||
171 | rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr); | ||
172 | |||
173 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFW-%d Addr[0x%x]=0x%x\n", | ||
174 | rfpath, pphyreg->rf3wire_offset, data_and_addr)); | ||
175 | } | ||
176 | |||
177 | |||
178 | u32 rtl92s_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, | ||
179 | u32 regaddr, u32 bitmask) | ||
180 | { | ||
181 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
182 | u32 original_value, readback_value, bitshift; | ||
183 | unsigned long flags; | ||
184 | |||
185 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), " | ||
186 | "bitmask(%#x)\n", regaddr, rfpath, bitmask)); | ||
187 | |||
188 | spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); | ||
189 | |||
190 | original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, regaddr); | ||
191 | |||
192 | bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); | ||
193 | readback_value = (original_value & bitmask) >> bitshift; | ||
194 | |||
195 | spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); | ||
196 | |||
197 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), rfpath(%#x), " | ||
198 | "bitmask(%#x), original_value(%#x)\n", regaddr, rfpath, | ||
199 | bitmask, original_value)); | ||
200 | |||
201 | return readback_value; | ||
202 | } | ||
203 | |||
204 | void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, | ||
205 | u32 regaddr, u32 bitmask, u32 data) | ||
206 | { | ||
207 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
208 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
209 | u32 original_value, bitshift; | ||
210 | unsigned long flags; | ||
211 | |||
212 | if (!((rtlphy->rf_pathmap >> rfpath) & 0x1)) | ||
213 | return; | ||
214 | |||
215 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x)," | ||
216 | " data(%#x), rfpath(%#x)\n", regaddr, bitmask, data, rfpath)); | ||
217 | |||
218 | spin_lock_irqsave(&rtlpriv->locks.rf_lock, flags); | ||
219 | |||
220 | if (bitmask != RFREG_OFFSET_MASK) { | ||
221 | original_value = _rtl92s_phy_rf_serial_read(hw, rfpath, | ||
222 | regaddr); | ||
223 | bitshift = _rtl92s_phy_calculate_bit_shift(bitmask); | ||
224 | data = ((original_value & (~bitmask)) | (data << bitshift)); | ||
225 | } | ||
226 | |||
227 | _rtl92s_phy_rf_serial_write(hw, rfpath, regaddr, data); | ||
228 | |||
229 | spin_unlock_irqrestore(&rtlpriv->locks.rf_lock, flags); | ||
230 | |||
231 | RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x), " | ||
232 | "data(%#x), rfpath(%#x)\n", regaddr, bitmask, data, rfpath)); | ||
233 | |||
234 | } | ||
235 | |||
236 | void rtl92s_phy_scan_operation_backup(struct ieee80211_hw *hw, | ||
237 | u8 operation) | ||
238 | { | ||
239 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
240 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
241 | |||
242 | if (!is_hal_stop(rtlhal)) { | ||
243 | switch (operation) { | ||
244 | case SCAN_OPT_BACKUP: | ||
245 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_PAUSE_DM_BY_SCAN); | ||
246 | break; | ||
247 | case SCAN_OPT_RESTORE: | ||
248 | rtl92s_phy_set_fw_cmd(hw, FW_CMD_RESUME_DM_BY_SCAN); | ||
249 | break; | ||
250 | default: | ||
251 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
252 | ("Unknown operation.\n")); | ||
253 | break; | ||
254 | } | ||
255 | } | ||
256 | } | ||
257 | |||
258 | void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw, | ||
259 | enum nl80211_channel_type ch_type) | ||
260 | { | ||
261 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
262 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
263 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
264 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
265 | u8 reg_bw_opmode; | ||
266 | u8 reg_prsr_rsc; | ||
267 | |||
268 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("Switch to %s bandwidth\n", | ||
269 | rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ? | ||
270 | "20MHz" : "40MHz")); | ||
271 | |||
272 | if (rtlphy->set_bwmode_inprogress) | ||
273 | return; | ||
274 | if (is_hal_stop(rtlhal)) | ||
275 | return; | ||
276 | |||
277 | rtlphy->set_bwmode_inprogress = true; | ||
278 | |||
279 | reg_bw_opmode = rtl_read_byte(rtlpriv, BW_OPMODE); | ||
280 | reg_prsr_rsc = rtl_read_byte(rtlpriv, RRSR + 2); | ||
281 | |||
282 | switch (rtlphy->current_chan_bw) { | ||
283 | case HT_CHANNEL_WIDTH_20: | ||
284 | reg_bw_opmode |= BW_OPMODE_20MHZ; | ||
285 | rtl_write_byte(rtlpriv, BW_OPMODE, reg_bw_opmode); | ||
286 | break; | ||
287 | case HT_CHANNEL_WIDTH_20_40: | ||
288 | reg_bw_opmode &= ~BW_OPMODE_20MHZ; | ||
289 | rtl_write_byte(rtlpriv, BW_OPMODE, reg_bw_opmode); | ||
290 | break; | ||
291 | default: | ||
292 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
293 | ("unknown bandwidth: %#X\n", | ||
294 | rtlphy->current_chan_bw)); | ||
295 | break; | ||
296 | } | ||
297 | |||
298 | switch (rtlphy->current_chan_bw) { | ||
299 | case HT_CHANNEL_WIDTH_20: | ||
300 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0); | ||
301 | rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0); | ||
302 | |||
303 | if (rtlhal->version >= VERSION_8192S_BCUT) | ||
304 | rtl_write_byte(rtlpriv, RFPGA0_ANALOGPARAMETER2, 0x58); | ||
305 | break; | ||
306 | case HT_CHANNEL_WIDTH_20_40: | ||
307 | rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1); | ||
308 | rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1); | ||
309 | |||
310 | rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND, | ||
311 | (mac->cur_40_prime_sc >> 1)); | ||
312 | rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc); | ||
313 | |||
314 | if (rtlhal->version >= VERSION_8192S_BCUT) | ||
315 | rtl_write_byte(rtlpriv, RFPGA0_ANALOGPARAMETER2, 0x18); | ||
316 | break; | ||
317 | default: | ||
318 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
319 | ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw)); | ||
320 | break; | ||
321 | } | ||
322 | |||
323 | rtl92s_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw); | ||
324 | rtlphy->set_bwmode_inprogress = false; | ||
325 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); | ||
326 | } | ||
327 | |||
328 | static bool _rtl92s_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable, | ||
329 | u32 cmdtableidx, u32 cmdtablesz, enum swchnlcmd_id cmdid, | ||
330 | u32 para1, u32 para2, u32 msdelay) | ||
331 | { | ||
332 | struct swchnlcmd *pcmd; | ||
333 | |||
334 | if (cmdtable == NULL) { | ||
335 | RT_ASSERT(false, ("cmdtable cannot be NULL.\n")); | ||
336 | return false; | ||
337 | } | ||
338 | |||
339 | if (cmdtableidx >= cmdtablesz) | ||
340 | return false; | ||
341 | |||
342 | pcmd = cmdtable + cmdtableidx; | ||
343 | pcmd->cmdid = cmdid; | ||
344 | pcmd->para1 = para1; | ||
345 | pcmd->para2 = para2; | ||
346 | pcmd->msdelay = msdelay; | ||
347 | |||
348 | return true; | ||
349 | } | ||
350 | |||
351 | static bool _rtl92s_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, | ||
352 | u8 channel, u8 *stage, u8 *step, u32 *delay) | ||
353 | { | ||
354 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
355 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
356 | struct swchnlcmd precommoncmd[MAX_PRECMD_CNT]; | ||
357 | u32 precommoncmdcnt; | ||
358 | struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT]; | ||
359 | u32 postcommoncmdcnt; | ||
360 | struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT]; | ||
361 | u32 rfdependcmdcnt; | ||
362 | struct swchnlcmd *currentcmd = NULL; | ||
363 | u8 rfpath; | ||
364 | u8 num_total_rfpath = rtlphy->num_total_rfpath; | ||
365 | |||
366 | precommoncmdcnt = 0; | ||
367 | _rtl92s_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, | ||
368 | MAX_PRECMD_CNT, CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0); | ||
369 | _rtl92s_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++, | ||
370 | MAX_PRECMD_CNT, CMDID_END, 0, 0, 0); | ||
371 | |||
372 | postcommoncmdcnt = 0; | ||
373 | |||
374 | _rtl92s_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++, | ||
375 | MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0); | ||
376 | |||
377 | rfdependcmdcnt = 0; | ||
378 | |||
379 | RT_ASSERT((channel >= 1 && channel <= 14), | ||
380 | ("illegal channel for Zebra: %d\n", channel)); | ||
381 | |||
382 | _rtl92s_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, | ||
383 | MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG, | ||
384 | RF_CHNLBW, channel, 10); | ||
385 | |||
386 | _rtl92s_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++, | ||
387 | MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0, 0); | ||
388 | |||
389 | do { | ||
390 | switch (*stage) { | ||
391 | case 0: | ||
392 | currentcmd = &precommoncmd[*step]; | ||
393 | break; | ||
394 | case 1: | ||
395 | currentcmd = &rfdependcmd[*step]; | ||
396 | break; | ||
397 | case 2: | ||
398 | currentcmd = &postcommoncmd[*step]; | ||
399 | break; | ||
400 | } | ||
401 | |||
402 | if (currentcmd->cmdid == CMDID_END) { | ||
403 | if ((*stage) == 2) { | ||
404 | return true; | ||
405 | } else { | ||
406 | (*stage)++; | ||
407 | (*step) = 0; | ||
408 | continue; | ||
409 | } | ||
410 | } | ||
411 | |||
412 | switch (currentcmd->cmdid) { | ||
413 | case CMDID_SET_TXPOWEROWER_LEVEL: | ||
414 | rtl92s_phy_set_txpower(hw, channel); | ||
415 | break; | ||
416 | case CMDID_WRITEPORT_ULONG: | ||
417 | rtl_write_dword(rtlpriv, currentcmd->para1, | ||
418 | currentcmd->para2); | ||
419 | break; | ||
420 | case CMDID_WRITEPORT_USHORT: | ||
421 | rtl_write_word(rtlpriv, currentcmd->para1, | ||
422 | (u16)currentcmd->para2); | ||
423 | break; | ||
424 | case CMDID_WRITEPORT_UCHAR: | ||
425 | rtl_write_byte(rtlpriv, currentcmd->para1, | ||
426 | (u8)currentcmd->para2); | ||
427 | break; | ||
428 | case CMDID_RF_WRITEREG: | ||
429 | for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) { | ||
430 | rtlphy->rfreg_chnlval[rfpath] = | ||
431 | ((rtlphy->rfreg_chnlval[rfpath] & | ||
432 | 0xfffffc00) | currentcmd->para2); | ||
433 | rtl_set_rfreg(hw, (enum radio_path)rfpath, | ||
434 | currentcmd->para1, | ||
435 | RFREG_OFFSET_MASK, | ||
436 | rtlphy->rfreg_chnlval[rfpath]); | ||
437 | } | ||
438 | break; | ||
439 | default: | ||
440 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
441 | ("switch case not process\n")); | ||
442 | break; | ||
443 | } | ||
444 | |||
445 | break; | ||
446 | } while (true); | ||
447 | |||
448 | (*delay) = currentcmd->msdelay; | ||
449 | (*step)++; | ||
450 | return false; | ||
451 | } | ||
452 | |||
453 | u8 rtl92s_phy_sw_chnl(struct ieee80211_hw *hw) | ||
454 | { | ||
455 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
456 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
457 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
458 | u32 delay; | ||
459 | bool ret; | ||
460 | |||
461 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, | ||
462 | ("switch to channel%d\n", | ||
463 | rtlphy->current_channel)); | ||
464 | |||
465 | if (rtlphy->sw_chnl_inprogress) | ||
466 | return 0; | ||
467 | |||
468 | if (rtlphy->set_bwmode_inprogress) | ||
469 | return 0; | ||
470 | |||
471 | if (is_hal_stop(rtlhal)) | ||
472 | return 0; | ||
473 | |||
474 | rtlphy->sw_chnl_inprogress = true; | ||
475 | rtlphy->sw_chnl_stage = 0; | ||
476 | rtlphy->sw_chnl_step = 0; | ||
477 | |||
478 | do { | ||
479 | if (!rtlphy->sw_chnl_inprogress) | ||
480 | break; | ||
481 | |||
482 | ret = _rtl92s_phy_sw_chnl_step_by_step(hw, | ||
483 | rtlphy->current_channel, | ||
484 | &rtlphy->sw_chnl_stage, | ||
485 | &rtlphy->sw_chnl_step, &delay); | ||
486 | if (!ret) { | ||
487 | if (delay > 0) | ||
488 | mdelay(delay); | ||
489 | else | ||
490 | continue; | ||
491 | } else { | ||
492 | rtlphy->sw_chnl_inprogress = false; | ||
493 | } | ||
494 | break; | ||
495 | } while (true); | ||
496 | |||
497 | rtlphy->sw_chnl_inprogress = false; | ||
498 | |||
499 | RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n")); | ||
500 | |||
501 | return 1; | ||
502 | } | ||
503 | |||
504 | static void _rtl92se_phy_set_rf_sleep(struct ieee80211_hw *hw) | ||
505 | { | ||
506 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
507 | u8 u1btmp; | ||
508 | |||
509 | u1btmp = rtl_read_byte(rtlpriv, LDOV12D_CTRL); | ||
510 | u1btmp |= BIT(0); | ||
511 | |||
512 | rtl_write_byte(rtlpriv, LDOV12D_CTRL, u1btmp); | ||
513 | rtl_write_byte(rtlpriv, SPS1_CTRL, 0x0); | ||
514 | rtl_write_byte(rtlpriv, TXPAUSE, 0xFF); | ||
515 | rtl_write_word(rtlpriv, CMDR, 0x57FC); | ||
516 | udelay(100); | ||
517 | |||
518 | rtl_write_word(rtlpriv, CMDR, 0x77FC); | ||
519 | rtl_write_byte(rtlpriv, PHY_CCA, 0x0); | ||
520 | udelay(10); | ||
521 | |||
522 | rtl_write_word(rtlpriv, CMDR, 0x37FC); | ||
523 | udelay(10); | ||
524 | |||
525 | rtl_write_word(rtlpriv, CMDR, 0x77FC); | ||
526 | udelay(10); | ||
527 | |||
528 | rtl_write_word(rtlpriv, CMDR, 0x57FC); | ||
529 | |||
530 | /* we should chnge GPIO to input mode | ||
531 | * this will drop away current about 25mA*/ | ||
532 | rtl8192se_gpiobit3_cfg_inputmode(hw); | ||
533 | } | ||
534 | |||
535 | bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw, | ||
536 | enum rf_pwrstate rfpwr_state) | ||
537 | { | ||
538 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
539 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
540 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
541 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
542 | bool bresult = true; | ||
543 | u8 i, queue_id; | ||
544 | struct rtl8192_tx_ring *ring = NULL; | ||
545 | |||
546 | if (rfpwr_state == ppsc->rfpwr_state) | ||
547 | return false; | ||
548 | |||
549 | ppsc->set_rfpowerstate_inprogress = true; | ||
550 | |||
551 | switch (rfpwr_state) { | ||
552 | case ERFON:{ | ||
553 | if ((ppsc->rfpwr_state == ERFOFF) && | ||
554 | RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) { | ||
555 | |||
556 | bool rtstatus; | ||
557 | u32 InitializeCount = 0; | ||
558 | do { | ||
559 | InitializeCount++; | ||
560 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
561 | ("IPS Set eRf nic enable\n")); | ||
562 | rtstatus = rtl_ps_enable_nic(hw); | ||
563 | } while ((rtstatus != true) && | ||
564 | (InitializeCount < 10)); | ||
565 | |||
566 | RT_CLEAR_PS_LEVEL(ppsc, | ||
567 | RT_RF_OFF_LEVL_HALT_NIC); | ||
568 | } else { | ||
569 | RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, | ||
570 | ("awake, sleeped:%d ms " | ||
571 | "state_inap:%x\n", | ||
572 | jiffies_to_msecs(jiffies - | ||
573 | ppsc->last_sleep_jiffies), | ||
574 | rtlpriv->psc.state_inap)); | ||
575 | ppsc->last_awake_jiffies = jiffies; | ||
576 | rtl_write_word(rtlpriv, CMDR, 0x37FC); | ||
577 | rtl_write_byte(rtlpriv, TXPAUSE, 0x00); | ||
578 | rtl_write_byte(rtlpriv, PHY_CCA, 0x3); | ||
579 | } | ||
580 | |||
581 | if (mac->link_state == MAC80211_LINKED) | ||
582 | rtlpriv->cfg->ops->led_control(hw, | ||
583 | LED_CTL_LINK); | ||
584 | else | ||
585 | rtlpriv->cfg->ops->led_control(hw, | ||
586 | LED_CTL_NO_LINK); | ||
587 | break; | ||
588 | } | ||
589 | case ERFOFF:{ | ||
590 | if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) { | ||
591 | RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG, | ||
592 | ("IPS Set eRf nic disable\n")); | ||
593 | rtl_ps_disable_nic(hw); | ||
594 | RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC); | ||
595 | } else { | ||
596 | if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) | ||
597 | rtlpriv->cfg->ops->led_control(hw, | ||
598 | LED_CTL_NO_LINK); | ||
599 | else | ||
600 | rtlpriv->cfg->ops->led_control(hw, | ||
601 | LED_CTL_POWER_OFF); | ||
602 | } | ||
603 | break; | ||
604 | } | ||
605 | case ERFSLEEP: | ||
606 | if (ppsc->rfpwr_state == ERFOFF) | ||
607 | break; | ||
608 | |||
609 | for (queue_id = 0, i = 0; | ||
610 | queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) { | ||
611 | ring = &pcipriv->dev.tx_ring[queue_id]; | ||
612 | if (skb_queue_len(&ring->queue) == 0 || | ||
613 | queue_id == BEACON_QUEUE) { | ||
614 | queue_id++; | ||
615 | continue; | ||
616 | } else { | ||
617 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
618 | ("eRf Off/Sleep: " | ||
619 | "%d times TcbBusyQueue[%d] = " | ||
620 | "%d before doze!\n", | ||
621 | (i + 1), queue_id, | ||
622 | skb_queue_len(&ring->queue))); | ||
623 | |||
624 | udelay(10); | ||
625 | i++; | ||
626 | } | ||
627 | |||
628 | if (i >= MAX_DOZE_WAITING_TIMES_9x) { | ||
629 | RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, | ||
630 | ("\nERFOFF: %d times" | ||
631 | "TcbBusyQueue[%d] = %d !\n", | ||
632 | MAX_DOZE_WAITING_TIMES_9x, | ||
633 | queue_id, | ||
634 | skb_queue_len(&ring->queue))); | ||
635 | break; | ||
636 | } | ||
637 | } | ||
638 | |||
639 | RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, | ||
640 | ("Set ERFSLEEP awaked:%d ms\n", | ||
641 | jiffies_to_msecs(jiffies - | ||
642 | ppsc->last_awake_jiffies))); | ||
643 | |||
644 | RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG, | ||
645 | ("sleep awaked:%d ms " | ||
646 | "state_inap:%x\n", jiffies_to_msecs(jiffies - | ||
647 | ppsc->last_awake_jiffies), | ||
648 | rtlpriv->psc.state_inap)); | ||
649 | ppsc->last_sleep_jiffies = jiffies; | ||
650 | _rtl92se_phy_set_rf_sleep(hw); | ||
651 | break; | ||
652 | default: | ||
653 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
654 | ("switch case not process\n")); | ||
655 | bresult = false; | ||
656 | break; | ||
657 | } | ||
658 | |||
659 | if (bresult) | ||
660 | ppsc->rfpwr_state = rfpwr_state; | ||
661 | |||
662 | ppsc->set_rfpowerstate_inprogress = false; | ||
663 | |||
664 | return bresult; | ||
665 | } | ||
666 | |||
667 | static bool _rtl92s_phy_config_rfpa_bias_current(struct ieee80211_hw *hw, | ||
668 | enum radio_path rfpath) | ||
669 | { | ||
670 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
671 | bool rtstatus = true; | ||
672 | u32 tmpval = 0; | ||
673 | |||
674 | /* If inferiority IC, we have to increase the PA bias current */ | ||
675 | if (rtlhal->ic_class != IC_INFERIORITY_A) { | ||
676 | tmpval = rtl92s_phy_query_rf_reg(hw, rfpath, RF_IPA, 0xf); | ||
677 | rtl92s_phy_set_rf_reg(hw, rfpath, RF_IPA, 0xf, tmpval + 1); | ||
678 | } | ||
679 | |||
680 | return rtstatus; | ||
681 | } | ||
682 | |||
683 | static void _rtl92s_store_pwrindex_diffrate_offset(struct ieee80211_hw *hw, | ||
684 | u32 reg_addr, u32 bitmask, u32 data) | ||
685 | { | ||
686 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
687 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
688 | |||
689 | if (reg_addr == RTXAGC_RATE18_06) | ||
690 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] = | ||
691 | data; | ||
692 | if (reg_addr == RTXAGC_RATE54_24) | ||
693 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] = | ||
694 | data; | ||
695 | if (reg_addr == RTXAGC_CCK_MCS32) | ||
696 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] = | ||
697 | data; | ||
698 | if (reg_addr == RTXAGC_MCS03_MCS00) | ||
699 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] = | ||
700 | data; | ||
701 | if (reg_addr == RTXAGC_MCS07_MCS04) | ||
702 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] = | ||
703 | data; | ||
704 | if (reg_addr == RTXAGC_MCS11_MCS08) | ||
705 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] = | ||
706 | data; | ||
707 | if (reg_addr == RTXAGC_MCS15_MCS12) { | ||
708 | rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] = | ||
709 | data; | ||
710 | rtlphy->pwrgroup_cnt++; | ||
711 | } | ||
712 | } | ||
713 | |||
714 | static void _rtl92s_phy_init_register_definition(struct ieee80211_hw *hw) | ||
715 | { | ||
716 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
717 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
718 | |||
719 | /*RF Interface Sowrtware Control */ | ||
720 | rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW; | ||
721 | rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW; | ||
722 | rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW; | ||
723 | rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW; | ||
724 | |||
725 | /* RF Interface Readback Value */ | ||
726 | rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB; | ||
727 | rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB; | ||
728 | rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB; | ||
729 | rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB; | ||
730 | |||
731 | /* RF Interface Output (and Enable) */ | ||
732 | rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE; | ||
733 | rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE; | ||
734 | rtlphy->phyreg_def[RF90_PATH_C].rfintfo = RFPGA0_XC_RFINTERFACEOE; | ||
735 | rtlphy->phyreg_def[RF90_PATH_D].rfintfo = RFPGA0_XD_RFINTERFACEOE; | ||
736 | |||
737 | /* RF Interface (Output and) Enable */ | ||
738 | rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE; | ||
739 | rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE; | ||
740 | rtlphy->phyreg_def[RF90_PATH_C].rfintfe = RFPGA0_XC_RFINTERFACEOE; | ||
741 | rtlphy->phyreg_def[RF90_PATH_D].rfintfe = RFPGA0_XD_RFINTERFACEOE; | ||
742 | |||
743 | /* Addr of LSSI. Wirte RF register by driver */ | ||
744 | rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset = | ||
745 | RFPGA0_XA_LSSIPARAMETER; | ||
746 | rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset = | ||
747 | RFPGA0_XB_LSSIPARAMETER; | ||
748 | rtlphy->phyreg_def[RF90_PATH_C].rf3wire_offset = | ||
749 | RFPGA0_XC_LSSIPARAMETER; | ||
750 | rtlphy->phyreg_def[RF90_PATH_D].rf3wire_offset = | ||
751 | RFPGA0_XD_LSSIPARAMETER; | ||
752 | |||
753 | /* RF parameter */ | ||
754 | rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = RFPGA0_XAB_RFPARAMETER; | ||
755 | rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = RFPGA0_XAB_RFPARAMETER; | ||
756 | rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = RFPGA0_XCD_RFPARAMETER; | ||
757 | rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = RFPGA0_XCD_RFPARAMETER; | ||
758 | |||
759 | /* Tx AGC Gain Stage (same for all path. Should we remove this?) */ | ||
760 | rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE; | ||
761 | rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE; | ||
762 | rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE; | ||
763 | rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE; | ||
764 | |||
765 | /* Tranceiver A~D HSSI Parameter-1 */ | ||
766 | rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1; | ||
767 | rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1; | ||
768 | rtlphy->phyreg_def[RF90_PATH_C].rfhssi_para1 = RFPGA0_XC_HSSIPARAMETER1; | ||
769 | rtlphy->phyreg_def[RF90_PATH_D].rfhssi_para1 = RFPGA0_XD_HSSIPARAMETER1; | ||
770 | |||
771 | /* Tranceiver A~D HSSI Parameter-2 */ | ||
772 | rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2; | ||
773 | rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2; | ||
774 | rtlphy->phyreg_def[RF90_PATH_C].rfhssi_para2 = RFPGA0_XC_HSSIPARAMETER2; | ||
775 | rtlphy->phyreg_def[RF90_PATH_D].rfhssi_para2 = RFPGA0_XD_HSSIPARAMETER2; | ||
776 | |||
777 | /* RF switch Control */ | ||
778 | rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control = | ||
779 | RFPGA0_XAB_SWITCHCONTROL; | ||
780 | rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control = | ||
781 | RFPGA0_XAB_SWITCHCONTROL; | ||
782 | rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control = | ||
783 | RFPGA0_XCD_SWITCHCONTROL; | ||
784 | rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control = | ||
785 | RFPGA0_XCD_SWITCHCONTROL; | ||
786 | |||
787 | /* AGC control 1 */ | ||
788 | rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1; | ||
789 | rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1; | ||
790 | rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1; | ||
791 | rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1; | ||
792 | |||
793 | /* AGC control 2 */ | ||
794 | rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2; | ||
795 | rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2; | ||
796 | rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2; | ||
797 | rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2; | ||
798 | |||
799 | /* RX AFE control 1 */ | ||
800 | rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance = | ||
801 | ROFDM0_XARXIQIMBALANCE; | ||
802 | rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance = | ||
803 | ROFDM0_XBRXIQIMBALANCE; | ||
804 | rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance = | ||
805 | ROFDM0_XCRXIQIMBALANCE; | ||
806 | rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance = | ||
807 | ROFDM0_XDRXIQIMBALANCE; | ||
808 | |||
809 | /* RX AFE control 1 */ | ||
810 | rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE; | ||
811 | rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE; | ||
812 | rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE; | ||
813 | rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE; | ||
814 | |||
815 | /* Tx AFE control 1 */ | ||
816 | rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance = | ||
817 | ROFDM0_XATXIQIMBALANCE; | ||
818 | rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance = | ||
819 | ROFDM0_XBTXIQIMBALANCE; | ||
820 | rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance = | ||
821 | ROFDM0_XCTXIQIMBALANCE; | ||
822 | rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance = | ||
823 | ROFDM0_XDTXIQIMBALANCE; | ||
824 | |||
825 | /* Tx AFE control 2 */ | ||
826 | rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE; | ||
827 | rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE; | ||
828 | rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE; | ||
829 | rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE; | ||
830 | |||
831 | /* Tranceiver LSSI Readback */ | ||
832 | rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback = | ||
833 | RFPGA0_XA_LSSIREADBACK; | ||
834 | rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback = | ||
835 | RFPGA0_XB_LSSIREADBACK; | ||
836 | rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback = | ||
837 | RFPGA0_XC_LSSIREADBACK; | ||
838 | rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback = | ||
839 | RFPGA0_XD_LSSIREADBACK; | ||
840 | |||
841 | /* Tranceiver LSSI Readback PI mode */ | ||
842 | rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi = | ||
843 | TRANSCEIVERA_HSPI_READBACK; | ||
844 | rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi = | ||
845 | TRANSCEIVERB_HSPI_READBACK; | ||
846 | } | ||
847 | |||
848 | |||
849 | static bool _rtl92s_phy_config_bb(struct ieee80211_hw *hw, u8 configtype) | ||
850 | { | ||
851 | int i; | ||
852 | u32 *phy_reg_table; | ||
853 | u32 *agc_table; | ||
854 | u16 phy_reg_len, agc_len; | ||
855 | |||
856 | agc_len = AGCTAB_ARRAYLENGTH; | ||
857 | agc_table = rtl8192seagctab_array; | ||
858 | /* Default RF_type: 2T2R */ | ||
859 | phy_reg_len = PHY_REG_2T2RARRAYLENGTH; | ||
860 | phy_reg_table = rtl8192sephy_reg_2t2rarray; | ||
861 | |||
862 | if (configtype == BASEBAND_CONFIG_PHY_REG) { | ||
863 | for (i = 0; i < phy_reg_len; i = i + 2) { | ||
864 | if (phy_reg_table[i] == 0xfe) | ||
865 | mdelay(50); | ||
866 | else if (phy_reg_table[i] == 0xfd) | ||
867 | mdelay(5); | ||
868 | else if (phy_reg_table[i] == 0xfc) | ||
869 | mdelay(1); | ||
870 | else if (phy_reg_table[i] == 0xfb) | ||
871 | udelay(50); | ||
872 | else if (phy_reg_table[i] == 0xfa) | ||
873 | udelay(5); | ||
874 | else if (phy_reg_table[i] == 0xf9) | ||
875 | udelay(1); | ||
876 | |||
877 | /* Add delay for ECS T20 & LG malow platform, */ | ||
878 | udelay(1); | ||
879 | |||
880 | rtl92s_phy_set_bb_reg(hw, phy_reg_table[i], MASKDWORD, | ||
881 | phy_reg_table[i + 1]); | ||
882 | } | ||
883 | } else if (configtype == BASEBAND_CONFIG_AGC_TAB) { | ||
884 | for (i = 0; i < agc_len; i = i + 2) { | ||
885 | rtl92s_phy_set_bb_reg(hw, agc_table[i], MASKDWORD, | ||
886 | agc_table[i + 1]); | ||
887 | |||
888 | /* Add delay for ECS T20 & LG malow platform */ | ||
889 | udelay(1); | ||
890 | } | ||
891 | } | ||
892 | |||
893 | return true; | ||
894 | } | ||
895 | |||
896 | static bool _rtl92s_phy_set_bb_to_diff_rf(struct ieee80211_hw *hw, | ||
897 | u8 configtype) | ||
898 | { | ||
899 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
900 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
901 | u32 *phy_regarray2xtxr_table; | ||
902 | u16 phy_regarray2xtxr_len; | ||
903 | int i; | ||
904 | |||
905 | if (rtlphy->rf_type == RF_1T1R) { | ||
906 | phy_regarray2xtxr_table = rtl8192sephy_changeto_1t1rarray; | ||
907 | phy_regarray2xtxr_len = PHY_CHANGETO_1T1RARRAYLENGTH; | ||
908 | } else if (rtlphy->rf_type == RF_1T2R) { | ||
909 | phy_regarray2xtxr_table = rtl8192sephy_changeto_1t2rarray; | ||
910 | phy_regarray2xtxr_len = PHY_CHANGETO_1T2RARRAYLENGTH; | ||
911 | } else { | ||
912 | return false; | ||
913 | } | ||
914 | |||
915 | if (configtype == BASEBAND_CONFIG_PHY_REG) { | ||
916 | for (i = 0; i < phy_regarray2xtxr_len; i = i + 3) { | ||
917 | if (phy_regarray2xtxr_table[i] == 0xfe) | ||
918 | mdelay(50); | ||
919 | else if (phy_regarray2xtxr_table[i] == 0xfd) | ||
920 | mdelay(5); | ||
921 | else if (phy_regarray2xtxr_table[i] == 0xfc) | ||
922 | mdelay(1); | ||
923 | else if (phy_regarray2xtxr_table[i] == 0xfb) | ||
924 | udelay(50); | ||
925 | else if (phy_regarray2xtxr_table[i] == 0xfa) | ||
926 | udelay(5); | ||
927 | else if (phy_regarray2xtxr_table[i] == 0xf9) | ||
928 | udelay(1); | ||
929 | |||
930 | rtl92s_phy_set_bb_reg(hw, phy_regarray2xtxr_table[i], | ||
931 | phy_regarray2xtxr_table[i + 1], | ||
932 | phy_regarray2xtxr_table[i + 2]); | ||
933 | } | ||
934 | } | ||
935 | |||
936 | return true; | ||
937 | } | ||
938 | |||
939 | static bool _rtl92s_phy_config_bb_with_pg(struct ieee80211_hw *hw, | ||
940 | u8 configtype) | ||
941 | { | ||
942 | int i; | ||
943 | u32 *phy_table_pg; | ||
944 | u16 phy_pg_len; | ||
945 | |||
946 | phy_pg_len = PHY_REG_ARRAY_PGLENGTH; | ||
947 | phy_table_pg = rtl8192sephy_reg_array_pg; | ||
948 | |||
949 | if (configtype == BASEBAND_CONFIG_PHY_REG) { | ||
950 | for (i = 0; i < phy_pg_len; i = i + 3) { | ||
951 | if (phy_table_pg[i] == 0xfe) | ||
952 | mdelay(50); | ||
953 | else if (phy_table_pg[i] == 0xfd) | ||
954 | mdelay(5); | ||
955 | else if (phy_table_pg[i] == 0xfc) | ||
956 | mdelay(1); | ||
957 | else if (phy_table_pg[i] == 0xfb) | ||
958 | udelay(50); | ||
959 | else if (phy_table_pg[i] == 0xfa) | ||
960 | udelay(5); | ||
961 | else if (phy_table_pg[i] == 0xf9) | ||
962 | udelay(1); | ||
963 | |||
964 | _rtl92s_store_pwrindex_diffrate_offset(hw, | ||
965 | phy_table_pg[i], | ||
966 | phy_table_pg[i + 1], | ||
967 | phy_table_pg[i + 2]); | ||
968 | rtl92s_phy_set_bb_reg(hw, phy_table_pg[i], | ||
969 | phy_table_pg[i + 1], | ||
970 | phy_table_pg[i + 2]); | ||
971 | } | ||
972 | } | ||
973 | |||
974 | return true; | ||
975 | } | ||
976 | |||
977 | static bool _rtl92s_phy_bb_config_parafile(struct ieee80211_hw *hw) | ||
978 | { | ||
979 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
980 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
981 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
982 | bool rtstatus = true; | ||
983 | |||
984 | /* 1. Read PHY_REG.TXT BB INIT!! */ | ||
985 | /* We will separate as 1T1R/1T2R/1T2R_GREEN/2T2R */ | ||
986 | if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_2T2R || | ||
987 | rtlphy->rf_type == RF_1T1R || rtlphy->rf_type == RF_2T2R_GREEN) { | ||
988 | rtstatus = _rtl92s_phy_config_bb(hw, BASEBAND_CONFIG_PHY_REG); | ||
989 | |||
990 | if (rtlphy->rf_type != RF_2T2R && | ||
991 | rtlphy->rf_type != RF_2T2R_GREEN) | ||
992 | /* so we should reconfig BB reg with the right | ||
993 | * PHY parameters. */ | ||
994 | rtstatus = _rtl92s_phy_set_bb_to_diff_rf(hw, | ||
995 | BASEBAND_CONFIG_PHY_REG); | ||
996 | } else { | ||
997 | rtstatus = false; | ||
998 | } | ||
999 | |||
1000 | if (rtstatus != true) { | ||
1001 | RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, | ||
1002 | ("Write BB Reg Fail!!")); | ||
1003 | goto phy_BB8190_Config_ParaFile_Fail; | ||
1004 | } | ||
1005 | |||
1006 | /* 2. If EEPROM or EFUSE autoload OK, We must config by | ||
1007 | * PHY_REG_PG.txt */ | ||
1008 | if (rtlefuse->autoload_failflag == false) { | ||
1009 | rtlphy->pwrgroup_cnt = 0; | ||
1010 | |||
1011 | rtstatus = _rtl92s_phy_config_bb_with_pg(hw, | ||
1012 | BASEBAND_CONFIG_PHY_REG); | ||
1013 | } | ||
1014 | if (rtstatus != true) { | ||
1015 | RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, | ||
1016 | ("_rtl92s_phy_bb_config_parafile(): " | ||
1017 | "BB_PG Reg Fail!!")); | ||
1018 | goto phy_BB8190_Config_ParaFile_Fail; | ||
1019 | } | ||
1020 | |||
1021 | /* 3. BB AGC table Initialization */ | ||
1022 | rtstatus = _rtl92s_phy_config_bb(hw, BASEBAND_CONFIG_AGC_TAB); | ||
1023 | |||
1024 | if (rtstatus != true) { | ||
1025 | printk(KERN_ERR "_rtl92s_phy_bb_config_parafile(): " | ||
1026 | "AGC Table Fail\n"); | ||
1027 | goto phy_BB8190_Config_ParaFile_Fail; | ||
1028 | } | ||
1029 | |||
1030 | /* Check if the CCK HighPower is turned ON. */ | ||
1031 | /* This is used to calculate PWDB. */ | ||
1032 | rtlphy->cck_high_power = (bool)(rtl92s_phy_query_bb_reg(hw, | ||
1033 | RFPGA0_XA_HSSIPARAMETER2, 0x200)); | ||
1034 | |||
1035 | phy_BB8190_Config_ParaFile_Fail: | ||
1036 | return rtstatus; | ||
1037 | } | ||
1038 | |||
1039 | u8 rtl92s_phy_config_rf(struct ieee80211_hw *hw, enum radio_path rfpath) | ||
1040 | { | ||
1041 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1042 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1043 | int i; | ||
1044 | bool rtstatus = true; | ||
1045 | u32 *radio_a_table; | ||
1046 | u32 *radio_b_table; | ||
1047 | u16 radio_a_tblen, radio_b_tblen; | ||
1048 | |||
1049 | radio_a_tblen = RADIOA_1T_ARRAYLENGTH; | ||
1050 | radio_a_table = rtl8192seradioa_1t_array; | ||
1051 | |||
1052 | /* Using Green mode array table for RF_2T2R_GREEN */ | ||
1053 | if (rtlphy->rf_type == RF_2T2R_GREEN) { | ||
1054 | radio_b_table = rtl8192seradiob_gm_array; | ||
1055 | radio_b_tblen = RADIOB_GM_ARRAYLENGTH; | ||
1056 | } else { | ||
1057 | radio_b_table = rtl8192seradiob_array; | ||
1058 | radio_b_tblen = RADIOB_ARRAYLENGTH; | ||
1059 | } | ||
1060 | |||
1061 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Radio No %x\n", rfpath)); | ||
1062 | rtstatus = true; | ||
1063 | |||
1064 | switch (rfpath) { | ||
1065 | case RF90_PATH_A: | ||
1066 | for (i = 0; i < radio_a_tblen; i = i + 2) { | ||
1067 | if (radio_a_table[i] == 0xfe) | ||
1068 | /* Delay specific ms. Only RF configuration | ||
1069 | * requires delay. */ | ||
1070 | mdelay(50); | ||
1071 | else if (radio_a_table[i] == 0xfd) | ||
1072 | mdelay(5); | ||
1073 | else if (radio_a_table[i] == 0xfc) | ||
1074 | mdelay(1); | ||
1075 | else if (radio_a_table[i] == 0xfb) | ||
1076 | udelay(50); | ||
1077 | else if (radio_a_table[i] == 0xfa) | ||
1078 | udelay(5); | ||
1079 | else if (radio_a_table[i] == 0xf9) | ||
1080 | udelay(1); | ||
1081 | else | ||
1082 | rtl92s_phy_set_rf_reg(hw, rfpath, | ||
1083 | radio_a_table[i], | ||
1084 | MASK20BITS, | ||
1085 | radio_a_table[i + 1]); | ||
1086 | |||
1087 | /* Add delay for ECS T20 & LG malow platform */ | ||
1088 | udelay(1); | ||
1089 | } | ||
1090 | |||
1091 | /* PA Bias current for inferiority IC */ | ||
1092 | _rtl92s_phy_config_rfpa_bias_current(hw, rfpath); | ||
1093 | break; | ||
1094 | case RF90_PATH_B: | ||
1095 | for (i = 0; i < radio_b_tblen; i = i + 2) { | ||
1096 | if (radio_b_table[i] == 0xfe) | ||
1097 | /* Delay specific ms. Only RF configuration | ||
1098 | * requires delay.*/ | ||
1099 | mdelay(50); | ||
1100 | else if (radio_b_table[i] == 0xfd) | ||
1101 | mdelay(5); | ||
1102 | else if (radio_b_table[i] == 0xfc) | ||
1103 | mdelay(1); | ||
1104 | else if (radio_b_table[i] == 0xfb) | ||
1105 | udelay(50); | ||
1106 | else if (radio_b_table[i] == 0xfa) | ||
1107 | udelay(5); | ||
1108 | else if (radio_b_table[i] == 0xf9) | ||
1109 | udelay(1); | ||
1110 | else | ||
1111 | rtl92s_phy_set_rf_reg(hw, rfpath, | ||
1112 | radio_b_table[i], | ||
1113 | MASK20BITS, | ||
1114 | radio_b_table[i + 1]); | ||
1115 | |||
1116 | /* Add delay for ECS T20 & LG malow platform */ | ||
1117 | udelay(1); | ||
1118 | } | ||
1119 | break; | ||
1120 | case RF90_PATH_C: | ||
1121 | ; | ||
1122 | break; | ||
1123 | case RF90_PATH_D: | ||
1124 | ; | ||
1125 | break; | ||
1126 | default: | ||
1127 | break; | ||
1128 | } | ||
1129 | |||
1130 | return rtstatus; | ||
1131 | } | ||
1132 | |||
1133 | |||
1134 | bool rtl92s_phy_mac_config(struct ieee80211_hw *hw) | ||
1135 | { | ||
1136 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1137 | u32 i; | ||
1138 | u32 arraylength; | ||
1139 | u32 *ptraArray; | ||
1140 | |||
1141 | arraylength = MAC_2T_ARRAYLENGTH; | ||
1142 | ptraArray = rtl8192semac_2t_array; | ||
1143 | |||
1144 | for (i = 0; i < arraylength; i = i + 2) | ||
1145 | rtl_write_byte(rtlpriv, ptraArray[i], (u8)ptraArray[i + 1]); | ||
1146 | |||
1147 | return true; | ||
1148 | } | ||
1149 | |||
1150 | |||
1151 | bool rtl92s_phy_bb_config(struct ieee80211_hw *hw) | ||
1152 | { | ||
1153 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1154 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1155 | bool rtstatus = true; | ||
1156 | u8 pathmap, index, rf_num = 0; | ||
1157 | u8 path1, path2; | ||
1158 | |||
1159 | _rtl92s_phy_init_register_definition(hw); | ||
1160 | |||
1161 | /* Config BB and AGC */ | ||
1162 | rtstatus = _rtl92s_phy_bb_config_parafile(hw); | ||
1163 | |||
1164 | |||
1165 | /* Check BB/RF confiuration setting. */ | ||
1166 | /* We only need to configure RF which is turned on. */ | ||
1167 | path1 = (u8)(rtl92s_phy_query_bb_reg(hw, RFPGA0_TXINFO, 0xf)); | ||
1168 | mdelay(10); | ||
1169 | path2 = (u8)(rtl92s_phy_query_bb_reg(hw, ROFDM0_TRXPATHENABLE, 0xf)); | ||
1170 | pathmap = path1 | path2; | ||
1171 | |||
1172 | rtlphy->rf_pathmap = pathmap; | ||
1173 | for (index = 0; index < 4; index++) { | ||
1174 | if ((pathmap >> index) & 0x1) | ||
1175 | rf_num++; | ||
1176 | } | ||
1177 | |||
1178 | if ((rtlphy->rf_type == RF_1T1R && rf_num != 1) || | ||
1179 | (rtlphy->rf_type == RF_1T2R && rf_num != 2) || | ||
1180 | (rtlphy->rf_type == RF_2T2R && rf_num != 2) || | ||
1181 | (rtlphy->rf_type == RF_2T2R_GREEN && rf_num != 2)) { | ||
1182 | RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, | ||
1183 | ("RF_Type(%x) does not match " | ||
1184 | "RF_Num(%x)!!\n", rtlphy->rf_type, rf_num)); | ||
1185 | RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG, | ||
1186 | ("path1 0x%x, path2 0x%x, pathmap " | ||
1187 | "0x%x\n", path1, path2, pathmap)); | ||
1188 | } | ||
1189 | |||
1190 | return rtstatus; | ||
1191 | } | ||
1192 | |||
1193 | bool rtl92s_phy_rf_config(struct ieee80211_hw *hw) | ||
1194 | { | ||
1195 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1196 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1197 | |||
1198 | /* Initialize general global value */ | ||
1199 | if (rtlphy->rf_type == RF_1T1R) | ||
1200 | rtlphy->num_total_rfpath = 1; | ||
1201 | else | ||
1202 | rtlphy->num_total_rfpath = 2; | ||
1203 | |||
1204 | /* Config BB and RF */ | ||
1205 | return rtl92s_phy_rf6052_config(hw); | ||
1206 | } | ||
1207 | |||
1208 | void rtl92s_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw) | ||
1209 | { | ||
1210 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1211 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1212 | |||
1213 | /* read rx initial gain */ | ||
1214 | rtlphy->default_initialgain[0] = rtl_get_bbreg(hw, | ||
1215 | ROFDM0_XAAGCCORE1, MASKBYTE0); | ||
1216 | rtlphy->default_initialgain[1] = rtl_get_bbreg(hw, | ||
1217 | ROFDM0_XBAGCCORE1, MASKBYTE0); | ||
1218 | rtlphy->default_initialgain[2] = rtl_get_bbreg(hw, | ||
1219 | ROFDM0_XCAGCCORE1, MASKBYTE0); | ||
1220 | rtlphy->default_initialgain[3] = rtl_get_bbreg(hw, | ||
1221 | ROFDM0_XDAGCCORE1, MASKBYTE0); | ||
1222 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Default initial gain " | ||
1223 | "(c50=0x%x, c58=0x%x, c60=0x%x, c68=0x%x)\n", | ||
1224 | rtlphy->default_initialgain[0], | ||
1225 | rtlphy->default_initialgain[1], | ||
1226 | rtlphy->default_initialgain[2], | ||
1227 | rtlphy->default_initialgain[3])); | ||
1228 | |||
1229 | /* read framesync */ | ||
1230 | rtlphy->framesync = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR3, MASKBYTE0); | ||
1231 | rtlphy->framesync_c34 = rtl_get_bbreg(hw, ROFDM0_RXDETECTOR2, | ||
1232 | MASKDWORD); | ||
1233 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | ||
1234 | ("Default framesync (0x%x) = 0x%x\n", | ||
1235 | ROFDM0_RXDETECTOR3, rtlphy->framesync)); | ||
1236 | |||
1237 | } | ||
1238 | |||
1239 | static void _rtl92s_phy_get_txpower_index(struct ieee80211_hw *hw, u8 channel, | ||
1240 | u8 *cckpowerlevel, u8 *ofdmpowerLevel) | ||
1241 | { | ||
1242 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1243 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1244 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1245 | u8 index = (channel - 1); | ||
1246 | |||
1247 | /* 1. CCK */ | ||
1248 | /* RF-A */ | ||
1249 | cckpowerlevel[0] = rtlefuse->txpwrlevel_cck[0][index]; | ||
1250 | /* RF-B */ | ||
1251 | cckpowerlevel[1] = rtlefuse->txpwrlevel_cck[1][index]; | ||
1252 | |||
1253 | /* 2. OFDM for 1T or 2T */ | ||
1254 | if (rtlphy->rf_type == RF_1T2R || rtlphy->rf_type == RF_1T1R) { | ||
1255 | /* Read HT 40 OFDM TX power */ | ||
1256 | ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_1s[0][index]; | ||
1257 | ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_1s[1][index]; | ||
1258 | } else if (rtlphy->rf_type == RF_2T2R) { | ||
1259 | /* Read HT 40 OFDM TX power */ | ||
1260 | ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_2s[0][index]; | ||
1261 | ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_2s[1][index]; | ||
1262 | } | ||
1263 | } | ||
1264 | |||
1265 | static void _rtl92s_phy_ccxpower_indexcheck(struct ieee80211_hw *hw, | ||
1266 | u8 channel, u8 *cckpowerlevel, u8 *ofdmpowerlevel) | ||
1267 | { | ||
1268 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1269 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1270 | |||
1271 | rtlphy->cur_cck_txpwridx = cckpowerlevel[0]; | ||
1272 | rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0]; | ||
1273 | } | ||
1274 | |||
1275 | void rtl92s_phy_set_txpower(struct ieee80211_hw *hw, u8 channel) | ||
1276 | { | ||
1277 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1278 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1279 | /* [0]:RF-A, [1]:RF-B */ | ||
1280 | u8 cckpowerlevel[2], ofdmpowerLevel[2]; | ||
1281 | |||
1282 | if (rtlefuse->txpwr_fromeprom == false) | ||
1283 | return; | ||
1284 | |||
1285 | /* Mainly we use RF-A Tx Power to write the Tx Power registers, | ||
1286 | * but the RF-B Tx Power must be calculated by the antenna diff. | ||
1287 | * So we have to rewrite Antenna gain offset register here. | ||
1288 | * Please refer to BB register 0x80c | ||
1289 | * 1. For CCK. | ||
1290 | * 2. For OFDM 1T or 2T */ | ||
1291 | _rtl92s_phy_get_txpower_index(hw, channel, &cckpowerlevel[0], | ||
1292 | &ofdmpowerLevel[0]); | ||
1293 | |||
1294 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
1295 | ("Channel-%d, cckPowerLevel (A / B) = " | ||
1296 | "0x%x / 0x%x, ofdmPowerLevel (A / B) = 0x%x / 0x%x\n", | ||
1297 | channel, cckpowerlevel[0], cckpowerlevel[1], | ||
1298 | ofdmpowerLevel[0], ofdmpowerLevel[1])); | ||
1299 | |||
1300 | _rtl92s_phy_ccxpower_indexcheck(hw, channel, &cckpowerlevel[0], | ||
1301 | &ofdmpowerLevel[0]); | ||
1302 | |||
1303 | rtl92s_phy_rf6052_set_ccktxpower(hw, cckpowerlevel[0]); | ||
1304 | rtl92s_phy_rf6052_set_ofdmtxpower(hw, &ofdmpowerLevel[0], channel); | ||
1305 | |||
1306 | } | ||
1307 | |||
1308 | void rtl92s_phy_chk_fwcmd_iodone(struct ieee80211_hw *hw) | ||
1309 | { | ||
1310 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1311 | u16 pollingcnt = 10000; | ||
1312 | u32 tmpvalue; | ||
1313 | |||
1314 | /* Make sure that CMD IO has be accepted by FW. */ | ||
1315 | do { | ||
1316 | udelay(10); | ||
1317 | |||
1318 | tmpvalue = rtl_read_dword(rtlpriv, WFM5); | ||
1319 | if (tmpvalue == 0) | ||
1320 | break; | ||
1321 | } while (--pollingcnt); | ||
1322 | |||
1323 | if (pollingcnt == 0) | ||
1324 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Set FW Cmd fail!!\n")); | ||
1325 | } | ||
1326 | |||
1327 | |||
1328 | static void _rtl92s_phy_set_fwcmd_io(struct ieee80211_hw *hw) | ||
1329 | { | ||
1330 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1331 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1332 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
1333 | u32 input, current_aid = 0; | ||
1334 | |||
1335 | if (is_hal_stop(rtlhal)) | ||
1336 | return; | ||
1337 | |||
1338 | /* We re-map RA related CMD IO to combinational ones */ | ||
1339 | /* if FW version is v.52 or later. */ | ||
1340 | switch (rtlhal->current_fwcmd_io) { | ||
1341 | case FW_CMD_RA_REFRESH_N: | ||
1342 | rtlhal->current_fwcmd_io = FW_CMD_RA_REFRESH_N_COMB; | ||
1343 | break; | ||
1344 | case FW_CMD_RA_REFRESH_BG: | ||
1345 | rtlhal->current_fwcmd_io = FW_CMD_RA_REFRESH_BG_COMB; | ||
1346 | break; | ||
1347 | default: | ||
1348 | break; | ||
1349 | } | ||
1350 | |||
1351 | switch (rtlhal->current_fwcmd_io) { | ||
1352 | case FW_CMD_RA_RESET: | ||
1353 | RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, | ||
1354 | ("FW_CMD_RA_RESET\n")); | ||
1355 | rtl_write_dword(rtlpriv, WFM5, FW_RA_RESET); | ||
1356 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1357 | break; | ||
1358 | case FW_CMD_RA_ACTIVE: | ||
1359 | RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, | ||
1360 | ("FW_CMD_RA_ACTIVE\n")); | ||
1361 | rtl_write_dword(rtlpriv, WFM5, FW_RA_ACTIVE); | ||
1362 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1363 | break; | ||
1364 | case FW_CMD_RA_REFRESH_N: | ||
1365 | RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, | ||
1366 | ("FW_CMD_RA_REFRESH_N\n")); | ||
1367 | input = FW_RA_REFRESH; | ||
1368 | rtl_write_dword(rtlpriv, WFM5, input); | ||
1369 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1370 | rtl_write_dword(rtlpriv, WFM5, FW_RA_ENABLE_RSSI_MASK); | ||
1371 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1372 | break; | ||
1373 | case FW_CMD_RA_REFRESH_BG: | ||
1374 | RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, | ||
1375 | ("FW_CMD_RA_REFRESH_BG\n")); | ||
1376 | rtl_write_dword(rtlpriv, WFM5, FW_RA_REFRESH); | ||
1377 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1378 | rtl_write_dword(rtlpriv, WFM5, FW_RA_DISABLE_RSSI_MASK); | ||
1379 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1380 | break; | ||
1381 | case FW_CMD_RA_REFRESH_N_COMB: | ||
1382 | RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, | ||
1383 | ("FW_CMD_RA_REFRESH_N_COMB\n")); | ||
1384 | input = FW_RA_IOT_N_COMB; | ||
1385 | rtl_write_dword(rtlpriv, WFM5, input); | ||
1386 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1387 | break; | ||
1388 | case FW_CMD_RA_REFRESH_BG_COMB: | ||
1389 | RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, | ||
1390 | ("FW_CMD_RA_REFRESH_BG_COMB\n")); | ||
1391 | input = FW_RA_IOT_BG_COMB; | ||
1392 | rtl_write_dword(rtlpriv, WFM5, input); | ||
1393 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1394 | break; | ||
1395 | case FW_CMD_IQK_ENABLE: | ||
1396 | RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, | ||
1397 | ("FW_CMD_IQK_ENABLE\n")); | ||
1398 | rtl_write_dword(rtlpriv, WFM5, FW_IQK_ENABLE); | ||
1399 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1400 | break; | ||
1401 | case FW_CMD_PAUSE_DM_BY_SCAN: | ||
1402 | /* Lower initial gain */ | ||
1403 | rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, 0x17); | ||
1404 | rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, 0x17); | ||
1405 | /* CCA threshold */ | ||
1406 | rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x40); | ||
1407 | break; | ||
1408 | case FW_CMD_RESUME_DM_BY_SCAN: | ||
1409 | /* CCA threshold */ | ||
1410 | rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); | ||
1411 | rtl92s_phy_set_txpower(hw, rtlphy->current_channel); | ||
1412 | break; | ||
1413 | case FW_CMD_HIGH_PWR_DISABLE: | ||
1414 | if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) | ||
1415 | break; | ||
1416 | |||
1417 | /* Lower initial gain */ | ||
1418 | rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0, 0x17); | ||
1419 | rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0, 0x17); | ||
1420 | /* CCA threshold */ | ||
1421 | rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0x40); | ||
1422 | break; | ||
1423 | case FW_CMD_HIGH_PWR_ENABLE: | ||
1424 | if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) || | ||
1425 | (rtlpriv->dm.dynamic_txpower_enable == true)) | ||
1426 | break; | ||
1427 | |||
1428 | /* CCA threshold */ | ||
1429 | rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd); | ||
1430 | break; | ||
1431 | case FW_CMD_LPS_ENTER: | ||
1432 | RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, | ||
1433 | ("FW_CMD_LPS_ENTER\n")); | ||
1434 | current_aid = rtlpriv->mac80211.assoc_id; | ||
1435 | rtl_write_dword(rtlpriv, WFM5, (FW_LPS_ENTER | | ||
1436 | ((current_aid | 0xc000) << 8))); | ||
1437 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1438 | /* FW set TXOP disable here, so disable EDCA | ||
1439 | * turbo mode until driver leave LPS */ | ||
1440 | break; | ||
1441 | case FW_CMD_LPS_LEAVE: | ||
1442 | RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, | ||
1443 | ("FW_CMD_LPS_LEAVE\n")); | ||
1444 | rtl_write_dword(rtlpriv, WFM5, FW_LPS_LEAVE); | ||
1445 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1446 | break; | ||
1447 | case FW_CMD_ADD_A2_ENTRY: | ||
1448 | RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, | ||
1449 | ("FW_CMD_ADD_A2_ENTRY\n")); | ||
1450 | rtl_write_dword(rtlpriv, WFM5, FW_ADD_A2_ENTRY); | ||
1451 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1452 | break; | ||
1453 | case FW_CMD_CTRL_DM_BY_DRIVER: | ||
1454 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
1455 | ("FW_CMD_CTRL_DM_BY_DRIVER\n")); | ||
1456 | rtl_write_dword(rtlpriv, WFM5, FW_CTRL_DM_BY_DRIVER); | ||
1457 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1458 | break; | ||
1459 | |||
1460 | default: | ||
1461 | break; | ||
1462 | } | ||
1463 | |||
1464 | rtl92s_phy_chk_fwcmd_iodone(hw); | ||
1465 | |||
1466 | /* Clear FW CMD operation flag. */ | ||
1467 | rtlhal->set_fwcmd_inprogress = false; | ||
1468 | } | ||
1469 | |||
1470 | bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fw_cmdio) | ||
1471 | { | ||
1472 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1473 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
1474 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
1475 | u32 fw_param = FW_CMD_IO_PARA_QUERY(rtlpriv); | ||
1476 | u16 fw_cmdmap = FW_CMD_IO_QUERY(rtlpriv); | ||
1477 | bool bPostProcessing = false; | ||
1478 | |||
1479 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
1480 | ("Set FW Cmd(%#x), set_fwcmd_inprogress(%d)\n", | ||
1481 | fw_cmdio, rtlhal->set_fwcmd_inprogress)); | ||
1482 | |||
1483 | do { | ||
1484 | /* We re-map to combined FW CMD ones if firmware version */ | ||
1485 | /* is v.53 or later. */ | ||
1486 | switch (fw_cmdio) { | ||
1487 | case FW_CMD_RA_REFRESH_N: | ||
1488 | fw_cmdio = FW_CMD_RA_REFRESH_N_COMB; | ||
1489 | break; | ||
1490 | case FW_CMD_RA_REFRESH_BG: | ||
1491 | fw_cmdio = FW_CMD_RA_REFRESH_BG_COMB; | ||
1492 | break; | ||
1493 | default: | ||
1494 | break; | ||
1495 | } | ||
1496 | |||
1497 | /* If firmware version is v.62 or later, | ||
1498 | * use FW_CMD_IO_SET for FW_CMD_CTRL_DM_BY_DRIVER */ | ||
1499 | if (hal_get_firmwareversion(rtlpriv) >= 0x3E) { | ||
1500 | if (fw_cmdio == FW_CMD_CTRL_DM_BY_DRIVER) | ||
1501 | fw_cmdio = FW_CMD_CTRL_DM_BY_DRIVER_NEW; | ||
1502 | } | ||
1503 | |||
1504 | |||
1505 | /* We shall revise all FW Cmd IO into Reg0x364 | ||
1506 | * DM map table in the future. */ | ||
1507 | switch (fw_cmdio) { | ||
1508 | case FW_CMD_RA_INIT: | ||
1509 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("RA init!!\n")); | ||
1510 | fw_cmdmap |= FW_RA_INIT_CTL; | ||
1511 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | ||
1512 | /* Clear control flag to sync with FW. */ | ||
1513 | FW_CMD_IO_CLR(rtlpriv, FW_RA_INIT_CTL); | ||
1514 | break; | ||
1515 | case FW_CMD_DIG_DISABLE: | ||
1516 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
1517 | ("Set DIG disable!!\n")); | ||
1518 | fw_cmdmap &= ~FW_DIG_ENABLE_CTL; | ||
1519 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | ||
1520 | break; | ||
1521 | case FW_CMD_DIG_ENABLE: | ||
1522 | case FW_CMD_DIG_RESUME: | ||
1523 | if (!(rtlpriv->dm.dm_flag & HAL_DM_DIG_DISABLE)) { | ||
1524 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
1525 | ("Set DIG enable or resume!!\n")); | ||
1526 | fw_cmdmap |= (FW_DIG_ENABLE_CTL | FW_SS_CTL); | ||
1527 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | ||
1528 | } | ||
1529 | break; | ||
1530 | case FW_CMD_DIG_HALT: | ||
1531 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
1532 | ("Set DIG halt!!\n")); | ||
1533 | fw_cmdmap &= ~(FW_DIG_ENABLE_CTL | FW_SS_CTL); | ||
1534 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | ||
1535 | break; | ||
1536 | case FW_CMD_TXPWR_TRACK_THERMAL: { | ||
1537 | u8 thermalval = 0; | ||
1538 | fw_cmdmap |= FW_PWR_TRK_CTL; | ||
1539 | |||
1540 | /* Clear FW parameter in terms of thermal parts. */ | ||
1541 | fw_param &= FW_PWR_TRK_PARAM_CLR; | ||
1542 | |||
1543 | thermalval = rtlpriv->dm.thermalvalue; | ||
1544 | fw_param |= ((thermalval << 24) | | ||
1545 | (rtlefuse->thermalmeter[0] << 16)); | ||
1546 | |||
1547 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
1548 | ("Set TxPwr tracking!! " | ||
1549 | "FwCmdMap(%#x), FwParam(%#x)\n", | ||
1550 | fw_cmdmap, fw_param)); | ||
1551 | |||
1552 | FW_CMD_PARA_SET(rtlpriv, fw_param); | ||
1553 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | ||
1554 | |||
1555 | /* Clear control flag to sync with FW. */ | ||
1556 | FW_CMD_IO_CLR(rtlpriv, FW_PWR_TRK_CTL); | ||
1557 | } | ||
1558 | break; | ||
1559 | /* The following FW CMDs are only compatible to | ||
1560 | * v.53 or later. */ | ||
1561 | case FW_CMD_RA_REFRESH_N_COMB: | ||
1562 | fw_cmdmap |= FW_RA_N_CTL; | ||
1563 | |||
1564 | /* Clear RA BG mode control. */ | ||
1565 | fw_cmdmap &= ~(FW_RA_BG_CTL | FW_RA_INIT_CTL); | ||
1566 | |||
1567 | /* Clear FW parameter in terms of RA parts. */ | ||
1568 | fw_param &= FW_RA_PARAM_CLR; | ||
1569 | |||
1570 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
1571 | ("[FW CMD] [New Version] " | ||
1572 | "Set RA/IOT Comb in n mode!! FwCmdMap(%#x), " | ||
1573 | "FwParam(%#x)\n", fw_cmdmap, fw_param)); | ||
1574 | |||
1575 | FW_CMD_PARA_SET(rtlpriv, fw_param); | ||
1576 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | ||
1577 | |||
1578 | /* Clear control flag to sync with FW. */ | ||
1579 | FW_CMD_IO_CLR(rtlpriv, FW_RA_N_CTL); | ||
1580 | break; | ||
1581 | case FW_CMD_RA_REFRESH_BG_COMB: | ||
1582 | fw_cmdmap |= FW_RA_BG_CTL; | ||
1583 | |||
1584 | /* Clear RA n-mode control. */ | ||
1585 | fw_cmdmap &= ~(FW_RA_N_CTL | FW_RA_INIT_CTL); | ||
1586 | /* Clear FW parameter in terms of RA parts. */ | ||
1587 | fw_param &= FW_RA_PARAM_CLR; | ||
1588 | |||
1589 | FW_CMD_PARA_SET(rtlpriv, fw_param); | ||
1590 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | ||
1591 | |||
1592 | /* Clear control flag to sync with FW. */ | ||
1593 | FW_CMD_IO_CLR(rtlpriv, FW_RA_BG_CTL); | ||
1594 | break; | ||
1595 | case FW_CMD_IQK_ENABLE: | ||
1596 | fw_cmdmap |= FW_IQK_CTL; | ||
1597 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | ||
1598 | /* Clear control flag to sync with FW. */ | ||
1599 | FW_CMD_IO_CLR(rtlpriv, FW_IQK_CTL); | ||
1600 | break; | ||
1601 | /* The following FW CMD is compatible to v.62 or later. */ | ||
1602 | case FW_CMD_CTRL_DM_BY_DRIVER_NEW: | ||
1603 | fw_cmdmap |= FW_DRIVER_CTRL_DM_CTL; | ||
1604 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | ||
1605 | break; | ||
1606 | /* The followed FW Cmds needs post-processing later. */ | ||
1607 | case FW_CMD_RESUME_DM_BY_SCAN: | ||
1608 | fw_cmdmap |= (FW_DIG_ENABLE_CTL | | ||
1609 | FW_HIGH_PWR_ENABLE_CTL | | ||
1610 | FW_SS_CTL); | ||
1611 | |||
1612 | if (rtlpriv->dm.dm_flag & HAL_DM_DIG_DISABLE || | ||
1613 | !digtable.dig_enable_flag) | ||
1614 | fw_cmdmap &= ~FW_DIG_ENABLE_CTL; | ||
1615 | |||
1616 | if ((rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) || | ||
1617 | (rtlpriv->dm.dynamic_txpower_enable == true)) | ||
1618 | fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL; | ||
1619 | |||
1620 | if ((digtable.dig_ext_port_stage == | ||
1621 | DIG_EXT_PORT_STAGE_0) || | ||
1622 | (digtable.dig_ext_port_stage == | ||
1623 | DIG_EXT_PORT_STAGE_1)) | ||
1624 | fw_cmdmap &= ~FW_DIG_ENABLE_CTL; | ||
1625 | |||
1626 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | ||
1627 | bPostProcessing = true; | ||
1628 | break; | ||
1629 | case FW_CMD_PAUSE_DM_BY_SCAN: | ||
1630 | fw_cmdmap &= ~(FW_DIG_ENABLE_CTL | | ||
1631 | FW_HIGH_PWR_ENABLE_CTL | | ||
1632 | FW_SS_CTL); | ||
1633 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | ||
1634 | bPostProcessing = true; | ||
1635 | break; | ||
1636 | case FW_CMD_HIGH_PWR_DISABLE: | ||
1637 | fw_cmdmap &= ~FW_HIGH_PWR_ENABLE_CTL; | ||
1638 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | ||
1639 | bPostProcessing = true; | ||
1640 | break; | ||
1641 | case FW_CMD_HIGH_PWR_ENABLE: | ||
1642 | if (!(rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) && | ||
1643 | (rtlpriv->dm.dynamic_txpower_enable != true)) { | ||
1644 | fw_cmdmap |= (FW_HIGH_PWR_ENABLE_CTL | | ||
1645 | FW_SS_CTL); | ||
1646 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | ||
1647 | bPostProcessing = true; | ||
1648 | } | ||
1649 | break; | ||
1650 | case FW_CMD_DIG_MODE_FA: | ||
1651 | fw_cmdmap |= FW_FA_CTL; | ||
1652 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | ||
1653 | break; | ||
1654 | case FW_CMD_DIG_MODE_SS: | ||
1655 | fw_cmdmap &= ~FW_FA_CTL; | ||
1656 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | ||
1657 | break; | ||
1658 | case FW_CMD_PAPE_CONTROL: | ||
1659 | RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, | ||
1660 | ("[FW CMD] Set PAPE Control\n")); | ||
1661 | fw_cmdmap &= ~FW_PAPE_CTL_BY_SW_HW; | ||
1662 | |||
1663 | FW_CMD_IO_SET(rtlpriv, fw_cmdmap); | ||
1664 | break; | ||
1665 | default: | ||
1666 | /* Pass to original FW CMD processing callback | ||
1667 | * routine. */ | ||
1668 | bPostProcessing = true; | ||
1669 | break; | ||
1670 | } | ||
1671 | } while (false); | ||
1672 | |||
1673 | /* We shall post processing these FW CMD if | ||
1674 | * variable bPostProcessing is set. */ | ||
1675 | if (bPostProcessing && !rtlhal->set_fwcmd_inprogress) { | ||
1676 | rtlhal->set_fwcmd_inprogress = true; | ||
1677 | /* Update current FW Cmd for callback use. */ | ||
1678 | rtlhal->current_fwcmd_io = fw_cmdio; | ||
1679 | } else { | ||
1680 | return false; | ||
1681 | } | ||
1682 | |||
1683 | _rtl92s_phy_set_fwcmd_io(hw); | ||
1684 | return true; | ||
1685 | } | ||
1686 | |||
1687 | static void _rtl92s_phy_check_ephy_switchready(struct ieee80211_hw *hw) | ||
1688 | { | ||
1689 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1690 | u32 delay = 100; | ||
1691 | u8 regu1; | ||
1692 | |||
1693 | regu1 = rtl_read_byte(rtlpriv, 0x554); | ||
1694 | while ((regu1 & BIT(5)) && (delay > 0)) { | ||
1695 | regu1 = rtl_read_byte(rtlpriv, 0x554); | ||
1696 | delay--; | ||
1697 | /* We delay only 50us to prevent | ||
1698 | * being scheduled out. */ | ||
1699 | udelay(50); | ||
1700 | } | ||
1701 | } | ||
1702 | |||
1703 | void rtl92s_phy_switch_ephy_parameter(struct ieee80211_hw *hw) | ||
1704 | { | ||
1705 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1706 | struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); | ||
1707 | |||
1708 | /* The way to be capable to switch clock request | ||
1709 | * when the PG setting does not support clock request. | ||
1710 | * This is the backdoor solution to switch clock | ||
1711 | * request before ASPM or D3. */ | ||
1712 | rtl_write_dword(rtlpriv, 0x540, 0x73c11); | ||
1713 | rtl_write_dword(rtlpriv, 0x548, 0x2407c); | ||
1714 | |||
1715 | /* Switch EPHY parameter!!!! */ | ||
1716 | rtl_write_word(rtlpriv, 0x550, 0x1000); | ||
1717 | rtl_write_byte(rtlpriv, 0x554, 0x20); | ||
1718 | _rtl92s_phy_check_ephy_switchready(hw); | ||
1719 | |||
1720 | rtl_write_word(rtlpriv, 0x550, 0xa0eb); | ||
1721 | rtl_write_byte(rtlpriv, 0x554, 0x3e); | ||
1722 | _rtl92s_phy_check_ephy_switchready(hw); | ||
1723 | |||
1724 | rtl_write_word(rtlpriv, 0x550, 0xff80); | ||
1725 | rtl_write_byte(rtlpriv, 0x554, 0x39); | ||
1726 | _rtl92s_phy_check_ephy_switchready(hw); | ||
1727 | |||
1728 | /* Delay L1 enter time */ | ||
1729 | if (ppsc->support_aspm && !ppsc->support_backdoor) | ||
1730 | rtl_write_byte(rtlpriv, 0x560, 0x40); | ||
1731 | else | ||
1732 | rtl_write_byte(rtlpriv, 0x560, 0x00); | ||
1733 | |||
1734 | } | ||
1735 | |||
1736 | void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 BeaconInterval) | ||
1737 | { | ||
1738 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1739 | rtl_write_dword(rtlpriv, WFM5, 0xF1000000 | (BeaconInterval << 8)); | ||
1740 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.h b/drivers/net/wireless/rtlwifi/rtl8192se/phy.h new file mode 100644 index 000000000000..37e504af6446 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.h | |||
@@ -0,0 +1,101 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | #ifndef __RTL92S_PHY_H__ | ||
30 | #define __RTL92S_PHY_H__ | ||
31 | |||
32 | #define MAX_TXPWR_IDX_NMODE_92S 63 | ||
33 | #define MAX_DOZE_WAITING_TIMES_9x 64 | ||
34 | |||
35 | /* Channel switch:The size of | ||
36 | * command tables for switch channel */ | ||
37 | #define MAX_PRECMD_CNT 16 | ||
38 | #define MAX_RFDEPENDCMD_CNT 16 | ||
39 | #define MAX_POSTCMD_CNT 16 | ||
40 | |||
41 | #define RF90_PATH_MAX 4 | ||
42 | |||
43 | enum version_8192s { | ||
44 | VERSION_8192S_ACUT, | ||
45 | VERSION_8192S_BCUT, | ||
46 | VERSION_8192S_CCUT | ||
47 | }; | ||
48 | |||
49 | enum swchnlcmd_id { | ||
50 | CMDID_END, | ||
51 | CMDID_SET_TXPOWEROWER_LEVEL, | ||
52 | CMDID_BBREGWRITE10, | ||
53 | CMDID_WRITEPORT_ULONG, | ||
54 | CMDID_WRITEPORT_USHORT, | ||
55 | CMDID_WRITEPORT_UCHAR, | ||
56 | CMDID_RF_WRITEREG, | ||
57 | }; | ||
58 | |||
59 | struct swchnlcmd { | ||
60 | enum swchnlcmd_id cmdid; | ||
61 | u32 para1; | ||
62 | u32 para2; | ||
63 | u32 msdelay; | ||
64 | }; | ||
65 | |||
66 | enum baseband_config_type { | ||
67 | /* Radio Path A */ | ||
68 | BASEBAND_CONFIG_PHY_REG = 0, | ||
69 | /* Radio Path B */ | ||
70 | BASEBAND_CONFIG_AGC_TAB = 1, | ||
71 | }; | ||
72 | |||
73 | #define hal_get_firmwareversion(rtlpriv) \ | ||
74 | (((struct rt_firmware *)(rtlpriv->rtlhal.pfirmware))->firmwareversion) | ||
75 | |||
76 | u32 rtl92s_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask); | ||
77 | void rtl92s_phy_set_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask, | ||
78 | u32 data); | ||
79 | void rtl92s_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation); | ||
80 | u32 rtl92s_phy_query_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, | ||
81 | u32 regaddr, u32 bitmask); | ||
82 | void rtl92s_phy_set_rf_reg(struct ieee80211_hw *hw, enum radio_path rfpath, | ||
83 | u32 regaddr, u32 bitmask, u32 data); | ||
84 | void rtl92s_phy_set_bw_mode(struct ieee80211_hw *hw, | ||
85 | enum nl80211_channel_type ch_type); | ||
86 | u8 rtl92s_phy_sw_chnl(struct ieee80211_hw *hw); | ||
87 | bool rtl92s_phy_set_rf_power_state(struct ieee80211_hw *hw, | ||
88 | enum rf_pwrstate rfpower_state); | ||
89 | bool rtl92s_phy_mac_config(struct ieee80211_hw *hw); | ||
90 | void rtl92s_phy_switch_ephy_parameter(struct ieee80211_hw *hw); | ||
91 | bool rtl92s_phy_bb_config(struct ieee80211_hw *hw); | ||
92 | bool rtl92s_phy_rf_config(struct ieee80211_hw *hw); | ||
93 | void rtl92s_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw); | ||
94 | void rtl92s_phy_set_txpower(struct ieee80211_hw *hw, u8 channel); | ||
95 | bool rtl92s_phy_set_fw_cmd(struct ieee80211_hw *hw, enum fwcmd_iotype fwcmd_io); | ||
96 | void rtl92s_phy_chk_fwcmd_iodone(struct ieee80211_hw *hw); | ||
97 | void rtl92s_phy_set_beacon_hwreg(struct ieee80211_hw *hw, u16 beaconinterval); | ||
98 | u8 rtl92s_phy_config_rf(struct ieee80211_hw *hw, enum radio_path rfpath) ; | ||
99 | |||
100 | #endif | ||
101 | |||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/reg.h b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h new file mode 100644 index 000000000000..0116eaddbfac --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/reg.h | |||
@@ -0,0 +1,1188 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | #ifndef __REALTEK_92S_REG_H__ | ||
30 | #define __REALTEK_92S_REG_H__ | ||
31 | |||
32 | /* 1. System Configuration Registers */ | ||
33 | #define REG_SYS_ISO_CTRL 0x0000 | ||
34 | #define REG_SYS_FUNC_EN 0x0002 | ||
35 | #define PMC_FSM 0x0004 | ||
36 | #define SYS_CLKR 0x0008 | ||
37 | #define EPROM_CMD 0x000A | ||
38 | #define EE_VPD 0x000C | ||
39 | #define AFE_MISC 0x0010 | ||
40 | #define SPS0_CTRL 0x0011 | ||
41 | #define SPS1_CTRL 0x0018 | ||
42 | #define RF_CTRL 0x001F | ||
43 | #define LDOA15_CTRL 0x0020 | ||
44 | #define LDOV12D_CTRL 0x0021 | ||
45 | #define LDOHCI12_CTRL 0x0022 | ||
46 | #define LDO_USB_SDIO 0x0023 | ||
47 | #define LPLDO_CTRL 0x0024 | ||
48 | #define AFE_XTAL_CTRL 0x0026 | ||
49 | #define AFE_PLL_CTRL 0x0028 | ||
50 | #define REG_EFUSE_CTRL 0x0030 | ||
51 | #define REG_EFUSE_TEST 0x0034 | ||
52 | #define PWR_DATA 0x0038 | ||
53 | #define DBG_PORT 0x003A | ||
54 | #define DPS_TIMER 0x003C | ||
55 | #define RCLK_MON 0x003E | ||
56 | |||
57 | /* 2. Command Control Registers */ | ||
58 | #define CMDR 0x0040 | ||
59 | #define TXPAUSE 0x0042 | ||
60 | #define LBKMD_SEL 0x0043 | ||
61 | #define TCR 0x0044 | ||
62 | #define RCR 0x0048 | ||
63 | #define MSR 0x004C | ||
64 | #define SYSF_CFG 0x004D | ||
65 | #define RX_PKY_LIMIT 0x004E | ||
66 | #define MBIDCTRL 0x004F | ||
67 | |||
68 | /* 3. MACID Setting Registers */ | ||
69 | #define MACIDR 0x0050 | ||
70 | #define MACIDR0 0x0050 | ||
71 | #define MACIDR4 0x0054 | ||
72 | #define BSSIDR 0x0058 | ||
73 | #define HWVID 0x005E | ||
74 | #define MAR 0x0060 | ||
75 | #define MBIDCAMCONTENT 0x0068 | ||
76 | #define MBIDCAMCFG 0x0070 | ||
77 | #define BUILDTIME 0x0074 | ||
78 | #define BUILDUSER 0x0078 | ||
79 | |||
80 | #define IDR0 MACIDR0 | ||
81 | #define IDR4 MACIDR4 | ||
82 | |||
83 | /* 4. Timing Control Registers */ | ||
84 | #define TSFR 0x0080 | ||
85 | #define SLOT_TIME 0x0089 | ||
86 | #define USTIME 0x008A | ||
87 | #define SIFS_CCK 0x008C | ||
88 | #define SIFS_OFDM 0x008E | ||
89 | #define PIFS_TIME 0x0090 | ||
90 | #define ACK_TIMEOUT 0x0091 | ||
91 | #define EIFSTR 0x0092 | ||
92 | #define BCN_INTERVAL 0x0094 | ||
93 | #define ATIMWND 0x0096 | ||
94 | #define BCN_DRV_EARLY_INT 0x0098 | ||
95 | #define BCN_DMATIME 0x009A | ||
96 | #define BCN_ERR_THRESH 0x009C | ||
97 | #define MLT 0x009D | ||
98 | #define RSVD_MAC_TUNE_US 0x009E | ||
99 | |||
100 | /* 5. FIFO Control Registers */ | ||
101 | #define RQPN 0x00A0 | ||
102 | #define RQPN1 0x00A0 | ||
103 | #define RQPN2 0x00A1 | ||
104 | #define RQPN3 0x00A2 | ||
105 | #define RQPN4 0x00A3 | ||
106 | #define RQPN5 0x00A4 | ||
107 | #define RQPN6 0x00A5 | ||
108 | #define RQPN7 0x00A6 | ||
109 | #define RQPN8 0x00A7 | ||
110 | #define RQPN9 0x00A8 | ||
111 | #define RQPN10 0x00A9 | ||
112 | #define LD_RQPN 0x00AB | ||
113 | #define RXFF_BNDY 0x00AC | ||
114 | #define RXRPT_BNDY 0x00B0 | ||
115 | #define TXPKTBUF_PGBNDY 0x00B4 | ||
116 | #define PBP 0x00B5 | ||
117 | #define RXDRVINFO_SZ 0x00B6 | ||
118 | #define TXFF_STATUS 0x00B7 | ||
119 | #define RXFF_STATUS 0x00B8 | ||
120 | #define TXFF_EMPTY_TH 0x00B9 | ||
121 | #define SDIO_RX_BLKSZ 0x00BC | ||
122 | #define RXDMA 0x00BD | ||
123 | #define RXPKT_NUM 0x00BE | ||
124 | #define C2HCMD_UDT_SIZE 0x00C0 | ||
125 | #define C2HCMD_UDT_ADDR 0x00C2 | ||
126 | #define FIFOPAGE1 0x00C4 | ||
127 | #define FIFOPAGE2 0x00C8 | ||
128 | #define FIFOPAGE3 0x00CC | ||
129 | #define FIFOPAGE4 0x00D0 | ||
130 | #define FIFOPAGE5 0x00D4 | ||
131 | #define FW_RSVD_PG_CRTL 0x00D8 | ||
132 | #define RXDMA_AGG_PG_TH 0x00D9 | ||
133 | #define TXDESC_MSK 0x00DC | ||
134 | #define TXRPTFF_RDPTR 0x00E0 | ||
135 | #define TXRPTFF_WTPTR 0x00E4 | ||
136 | #define C2HFF_RDPTR 0x00E8 | ||
137 | #define C2HFF_WTPTR 0x00EC | ||
138 | #define RXFF0_RDPTR 0x00F0 | ||
139 | #define RXFF0_WTPTR 0x00F4 | ||
140 | #define RXFF1_RDPTR 0x00F8 | ||
141 | #define RXFF1_WTPTR 0x00FC | ||
142 | #define RXRPT0_RDPTR 0x0100 | ||
143 | #define RXRPT0_WTPTR 0x0104 | ||
144 | #define RXRPT1_RDPTR 0x0108 | ||
145 | #define RXRPT1_WTPTR 0x010C | ||
146 | #define RX0_UDT_SIZE 0x0110 | ||
147 | #define RX1PKTNUM 0x0114 | ||
148 | #define RXFILTERMAP 0x0116 | ||
149 | #define RXFILTERMAP_GP1 0x0118 | ||
150 | #define RXFILTERMAP_GP2 0x011A | ||
151 | #define RXFILTERMAP_GP3 0x011C | ||
152 | #define BCNQ_CTRL 0x0120 | ||
153 | #define MGTQ_CTRL 0x0124 | ||
154 | #define HIQ_CTRL 0x0128 | ||
155 | #define VOTID7_CTRL 0x012c | ||
156 | #define VOTID6_CTRL 0x0130 | ||
157 | #define VITID5_CTRL 0x0134 | ||
158 | #define VITID4_CTRL 0x0138 | ||
159 | #define BETID3_CTRL 0x013c | ||
160 | #define BETID0_CTRL 0x0140 | ||
161 | #define BKTID2_CTRL 0x0144 | ||
162 | #define BKTID1_CTRL 0x0148 | ||
163 | #define CMDQ_CTRL 0x014c | ||
164 | #define TXPKT_NUM_CTRL 0x0150 | ||
165 | #define TXQ_PGADD 0x0152 | ||
166 | #define TXFF_PG_NUM 0x0154 | ||
167 | #define TRXDMA_STATUS 0x0156 | ||
168 | |||
169 | /* 6. Adaptive Control Registers */ | ||
170 | #define INIMCS_SEL 0x0160 | ||
171 | #define TX_RATE_REG INIMCS_SEL | ||
172 | #define INIRTSMCS_SEL 0x0180 | ||
173 | #define RRSR 0x0181 | ||
174 | #define ARFR0 0x0184 | ||
175 | #define ARFR1 0x0188 | ||
176 | #define ARFR2 0x018C | ||
177 | #define ARFR3 0x0190 | ||
178 | #define ARFR4 0x0194 | ||
179 | #define ARFR5 0x0198 | ||
180 | #define ARFR6 0x019C | ||
181 | #define ARFR7 0x01A0 | ||
182 | #define AGGLEN_LMT_H 0x01A7 | ||
183 | #define AGGLEN_LMT_L 0x01A8 | ||
184 | #define DARFRC 0x01B0 | ||
185 | #define RARFRC 0x01B8 | ||
186 | #define MCS_TXAGC 0x01C0 | ||
187 | #define CCK_TXAGC 0x01C8 | ||
188 | |||
189 | /* 7. EDCA Setting Registers */ | ||
190 | #define EDCAPARA_VO 0x01D0 | ||
191 | #define EDCAPARA_VI 0x01D4 | ||
192 | #define EDCAPARA_BE 0x01D8 | ||
193 | #define EDCAPARA_BK 0x01DC | ||
194 | #define BCNTCFG 0x01E0 | ||
195 | #define CWRR 0x01E2 | ||
196 | #define ACMAVG 0x01E4 | ||
197 | #define AcmHwCtrl 0x01E7 | ||
198 | #define VO_ADMTM 0x01E8 | ||
199 | #define VI_ADMTM 0x01EC | ||
200 | #define BE_ADMTM 0x01F0 | ||
201 | #define RETRY_LIMIT 0x01F4 | ||
202 | #define SG_RATE 0x01F6 | ||
203 | |||
204 | /* 8. WMAC, BA and CCX related Register. */ | ||
205 | #define NAV_CTRL 0x0200 | ||
206 | #define BW_OPMODE 0x0203 | ||
207 | #define BACAMCMD 0x0204 | ||
208 | #define BACAMCONTENT 0x0208 | ||
209 | |||
210 | /* the 0x2xx register WMAC definition */ | ||
211 | #define LBDLY 0x0210 | ||
212 | #define FWDLY 0x0211 | ||
213 | #define HWPC_RX_CTRL 0x0218 | ||
214 | #define MQIR 0x0220 | ||
215 | #define MAIR 0x0222 | ||
216 | #define MSIR 0x0224 | ||
217 | #define CLM_RESULT 0x0227 | ||
218 | #define NHM_RPI_CNT 0x0228 | ||
219 | #define RXERR_RPT 0x0230 | ||
220 | #define NAV_PROT_LEN 0x0234 | ||
221 | #define CFEND_TH 0x0236 | ||
222 | #define AMPDU_MIN_SPACE 0x0237 | ||
223 | #define TXOP_STALL_CTRL 0x0238 | ||
224 | |||
225 | /* 9. Security Control Registers */ | ||
226 | #define REG_RWCAM 0x0240 | ||
227 | #define REG_WCAMI 0x0244 | ||
228 | #define REG_RCAMO 0x0248 | ||
229 | #define REG_CAMDBG 0x024C | ||
230 | #define REG_SECR 0x0250 | ||
231 | |||
232 | /* 10. Power Save Control Registers */ | ||
233 | #define WOW_CTRL 0x0260 | ||
234 | #define PSSTATUS 0x0261 | ||
235 | #define PSSWITCH 0x0262 | ||
236 | #define MIMOPS_WAIT_PERIOD 0x0263 | ||
237 | #define LPNAV_CTRL 0x0264 | ||
238 | #define WFM0 0x0270 | ||
239 | #define WFM1 0x0280 | ||
240 | #define WFM2 0x0290 | ||
241 | #define WFM3 0x02A0 | ||
242 | #define WFM4 0x02B0 | ||
243 | #define WFM5 0x02C0 | ||
244 | #define WFCRC 0x02D0 | ||
245 | #define FW_RPT_REG 0x02c4 | ||
246 | |||
247 | /* 11. General Purpose Registers */ | ||
248 | #define PSTIME 0x02E0 | ||
249 | #define TIMER0 0x02E4 | ||
250 | #define TIMER1 0x02E8 | ||
251 | #define GPIO_CTRL 0x02EC | ||
252 | #define GPIO_IN 0x02EC | ||
253 | #define GPIO_OUT 0x02ED | ||
254 | #define GPIO_IO_SEL 0x02EE | ||
255 | #define GPIO_MOD 0x02EF | ||
256 | #define GPIO_INTCTRL 0x02F0 | ||
257 | #define MAC_PINMUX_CFG 0x02F1 | ||
258 | #define LEDCFG 0x02F2 | ||
259 | #define PHY_REG 0x02F3 | ||
260 | #define PHY_REG_DATA 0x02F4 | ||
261 | #define REG_EFUSE_CLK 0x02F8 | ||
262 | |||
263 | /* 12. Host Interrupt Status Registers */ | ||
264 | #define INTA_MASK 0x0300 | ||
265 | #define ISR 0x0308 | ||
266 | |||
267 | /* 13. Test Mode and Debug Control Registers */ | ||
268 | #define DBG_PORT_SWITCH 0x003A | ||
269 | #define BIST 0x0310 | ||
270 | #define DBS 0x0314 | ||
271 | #define CPUINST 0x0318 | ||
272 | #define CPUCAUSE 0x031C | ||
273 | #define LBUS_ERR_ADDR 0x0320 | ||
274 | #define LBUS_ERR_CMD 0x0324 | ||
275 | #define LBUS_ERR_DATA_L 0x0328 | ||
276 | #define LBUS_ERR_DATA_H 0x032C | ||
277 | #define LX_EXCEPTION_ADDR 0x0330 | ||
278 | #define WDG_CTRL 0x0334 | ||
279 | #define INTMTU 0x0338 | ||
280 | #define INTM 0x033A | ||
281 | #define FDLOCKTURN0 0x033C | ||
282 | #define FDLOCKTURN1 0x033D | ||
283 | #define TRXPKTBUF_DBG_DATA 0x0340 | ||
284 | #define TRXPKTBUF_DBG_CTRL 0x0348 | ||
285 | #define DPLL 0x034A | ||
286 | #define CBUS_ERR_ADDR 0x0350 | ||
287 | #define CBUS_ERR_CMD 0x0354 | ||
288 | #define CBUS_ERR_DATA_L 0x0358 | ||
289 | #define CBUS_ERR_DATA_H 0x035C | ||
290 | #define USB_SIE_INTF_ADDR 0x0360 | ||
291 | #define USB_SIE_INTF_WD 0x0361 | ||
292 | #define USB_SIE_INTF_RD 0x0362 | ||
293 | #define USB_SIE_INTF_CTRL 0x0363 | ||
294 | #define LBUS_MON_ADDR 0x0364 | ||
295 | #define LBUS_ADDR_MASK 0x0368 | ||
296 | |||
297 | /* Boundary is 0x37F */ | ||
298 | |||
299 | /* 14. PCIE config register */ | ||
300 | #define TP_POLL 0x0500 | ||
301 | #define PM_CTRL 0x0502 | ||
302 | #define PCIF 0x0503 | ||
303 | |||
304 | #define THPDA 0x0514 | ||
305 | #define TMDA 0x0518 | ||
306 | #define TCDA 0x051C | ||
307 | #define HDA 0x0520 | ||
308 | #define TVODA 0x0524 | ||
309 | #define TVIDA 0x0528 | ||
310 | #define TBEDA 0x052C | ||
311 | #define TBKDA 0x0530 | ||
312 | #define TBDA 0x0534 | ||
313 | #define RCDA 0x0538 | ||
314 | #define RDQDA 0x053C | ||
315 | #define DBI_WDATA 0x0540 | ||
316 | #define DBI_RDATA 0x0544 | ||
317 | #define DBI_CTRL 0x0548 | ||
318 | #define MDIO_DATA 0x0550 | ||
319 | #define MDIO_CTRL 0x0554 | ||
320 | #define PCI_RPWM 0x0561 | ||
321 | #define PCI_CPWM 0x0563 | ||
322 | |||
323 | /* Config register (Offset 0x800-) */ | ||
324 | #define PHY_CCA 0x803 | ||
325 | |||
326 | /* Min Spacing related settings. */ | ||
327 | #define MAX_MSS_DENSITY_2T 0x13 | ||
328 | #define MAX_MSS_DENSITY_1T 0x0A | ||
329 | |||
330 | /* Rx DMA Control related settings */ | ||
331 | #define RXDMA_AGG_EN BIT(7) | ||
332 | |||
333 | #define RPWM PCI_RPWM | ||
334 | |||
335 | /* Regsiter Bit and Content definition */ | ||
336 | |||
337 | #define ISO_MD2PP BIT(0) | ||
338 | #define ISO_PA2PCIE BIT(3) | ||
339 | #define ISO_PLL2MD BIT(4) | ||
340 | #define ISO_PWC_DV2RP BIT(11) | ||
341 | #define ISO_PWC_RV2RP BIT(12) | ||
342 | |||
343 | |||
344 | #define FEN_MREGEN BIT(15) | ||
345 | #define FEN_DCORE BIT(11) | ||
346 | #define FEN_CPUEN BIT(10) | ||
347 | |||
348 | #define PAD_HWPD_IDN BIT(22) | ||
349 | |||
350 | #define SYS_CLKSEL_80M BIT(0) | ||
351 | #define SYS_PS_CLKSEL BIT(1) | ||
352 | #define SYS_CPU_CLKSEL BIT(2) | ||
353 | #define SYS_MAC_CLK_EN BIT(11) | ||
354 | #define SYS_SWHW_SEL BIT(14) | ||
355 | #define SYS_FWHW_SEL BIT(15) | ||
356 | |||
357 | #define CmdEEPROM_En BIT(5) | ||
358 | #define CmdEERPOMSEL BIT(4) | ||
359 | #define Cmd9346CR_9356SEL BIT(4) | ||
360 | |||
361 | #define AFE_MBEN BIT(1) | ||
362 | #define AFE_BGEN BIT(0) | ||
363 | |||
364 | #define SPS1_SWEN BIT(1) | ||
365 | #define SPS1_LDEN BIT(0) | ||
366 | |||
367 | #define RF_EN BIT(0) | ||
368 | #define RF_RSTB BIT(1) | ||
369 | #define RF_SDMRSTB BIT(2) | ||
370 | |||
371 | #define LDA15_EN BIT(0) | ||
372 | |||
373 | #define LDV12_EN BIT(0) | ||
374 | #define LDV12_SDBY BIT(1) | ||
375 | |||
376 | #define XTAL_GATE_AFE BIT(10) | ||
377 | |||
378 | #define APLL_EN BIT(0) | ||
379 | |||
380 | #define AFR_CardBEn BIT(0) | ||
381 | #define AFR_CLKRUN_SEL BIT(1) | ||
382 | #define AFR_FuncRegEn BIT(2) | ||
383 | |||
384 | #define APSDOFF_STATUS BIT(15) | ||
385 | #define APSDOFF BIT(14) | ||
386 | #define BBRSTN BIT(13) | ||
387 | #define BB_GLB_RSTN BIT(12) | ||
388 | #define SCHEDULE_EN BIT(10) | ||
389 | #define MACRXEN BIT(9) | ||
390 | #define MACTXEN BIT(8) | ||
391 | #define DDMA_EN BIT(7) | ||
392 | #define FW2HW_EN BIT(6) | ||
393 | #define RXDMA_EN BIT(5) | ||
394 | #define TXDMA_EN BIT(4) | ||
395 | #define HCI_RXDMA_EN BIT(3) | ||
396 | #define HCI_TXDMA_EN BIT(2) | ||
397 | |||
398 | #define StopHCCA BIT(6) | ||
399 | #define StopHigh BIT(5) | ||
400 | #define StopMgt BIT(4) | ||
401 | #define StopVO BIT(3) | ||
402 | #define StopVI BIT(2) | ||
403 | #define StopBE BIT(1) | ||
404 | #define StopBK BIT(0) | ||
405 | |||
406 | #define LBK_NORMAL 0x00 | ||
407 | #define LBK_MAC_LB (BIT(0) | BIT(1) | BIT(3)) | ||
408 | #define LBK_MAC_DLB (BIT(0) | BIT(1)) | ||
409 | #define LBK_DMA_LB (BIT(0) | BIT(1) | BIT(2)) | ||
410 | |||
411 | #define TCP_OFDL_EN BIT(25) | ||
412 | #define HWPC_TX_EN BIT(24) | ||
413 | #define TXDMAPRE2FULL BIT(23) | ||
414 | #define DISCW BIT(20) | ||
415 | #define TCRICV BIT(19) | ||
416 | #define CfendForm BIT(17) | ||
417 | #define TCRCRC BIT(16) | ||
418 | #define FAKE_IMEM_EN BIT(15) | ||
419 | #define TSFRST BIT(9) | ||
420 | #define TSFEN BIT(8) | ||
421 | #define FWALLRDY (BIT(0) | BIT(1) | BIT(2) | \ | ||
422 | BIT(3) | BIT(4) | BIT(5) | \ | ||
423 | BIT(6) | BIT(7)) | ||
424 | #define FWRDY BIT(7) | ||
425 | #define BASECHG BIT(6) | ||
426 | #define IMEM BIT(5) | ||
427 | #define DMEM_CODE_DONE BIT(4) | ||
428 | #define EXT_IMEM_CHK_RPT BIT(3) | ||
429 | #define EXT_IMEM_CODE_DONE BIT(2) | ||
430 | #define IMEM_CHK_RPT BIT(1) | ||
431 | #define IMEM_CODE_DONE BIT(0) | ||
432 | #define IMEM_CODE_DONE BIT(0) | ||
433 | #define IMEM_CHK_RPT BIT(1) | ||
434 | #define EMEM_CODE_DONE BIT(2) | ||
435 | #define EMEM_CHK_RPT BIT(3) | ||
436 | #define DMEM_CODE_DONE BIT(4) | ||
437 | #define IMEM_RDY BIT(5) | ||
438 | #define BASECHG BIT(6) | ||
439 | #define FWRDY BIT(7) | ||
440 | #define LOAD_FW_READY (IMEM_CODE_DONE | \ | ||
441 | IMEM_CHK_RPT | \ | ||
442 | EMEM_CODE_DONE | \ | ||
443 | EMEM_CHK_RPT | \ | ||
444 | DMEM_CODE_DONE | \ | ||
445 | IMEM_RDY | \ | ||
446 | BASECHG | \ | ||
447 | FWRDY) | ||
448 | #define TCR_TSFEN BIT(8) | ||
449 | #define TCR_TSFRST BIT(9) | ||
450 | #define TCR_FAKE_IMEM_EN BIT(15) | ||
451 | #define TCR_CRC BIT(16) | ||
452 | #define TCR_ICV BIT(19) | ||
453 | #define TCR_DISCW BIT(20) | ||
454 | #define TCR_HWPC_TX_EN BIT(24) | ||
455 | #define TCR_TCP_OFDL_EN BIT(25) | ||
456 | #define TXDMA_INIT_VALUE (IMEM_CHK_RPT | \ | ||
457 | EXT_IMEM_CHK_RPT) | ||
458 | |||
459 | #define RCR_APPFCS BIT(31) | ||
460 | #define RCR_DIS_ENC_2BYTE BIT(30) | ||
461 | #define RCR_DIS_AES_2BYTE BIT(29) | ||
462 | #define RCR_HTC_LOC_CTRL BIT(28) | ||
463 | #define RCR_ENMBID BIT(27) | ||
464 | #define RCR_RX_TCPOFDL_EN BIT(26) | ||
465 | #define RCR_APP_PHYST_RXFF BIT(25) | ||
466 | #define RCR_APP_PHYST_STAFF BIT(24) | ||
467 | #define RCR_CBSSID BIT(23) | ||
468 | #define RCR_APWRMGT BIT(22) | ||
469 | #define RCR_ADD3 BIT(21) | ||
470 | #define RCR_AMF BIT(20) | ||
471 | #define RCR_ACF BIT(19) | ||
472 | #define RCR_ADF BIT(18) | ||
473 | #define RCR_APP_MIC BIT(17) | ||
474 | #define RCR_APP_ICV BIT(16) | ||
475 | #define RCR_RXFTH BIT(13) | ||
476 | #define RCR_AICV BIT(12) | ||
477 | #define RCR_RXDESC_LK_EN BIT(11) | ||
478 | #define RCR_APP_BA_SSN BIT(6) | ||
479 | #define RCR_ACRC32 BIT(5) | ||
480 | #define RCR_RXSHFT_EN BIT(4) | ||
481 | #define RCR_AB BIT(3) | ||
482 | #define RCR_AM BIT(2) | ||
483 | #define RCR_APM BIT(1) | ||
484 | #define RCR_AAP BIT(0) | ||
485 | #define RCR_MXDMA_OFFSET 8 | ||
486 | #define RCR_FIFO_OFFSET 13 | ||
487 | |||
488 | |||
489 | #define MSR_LINK_MASK ((1 << 0) | (1 << 1)) | ||
490 | #define MSR_LINK_MANAGED 2 | ||
491 | #define MSR_LINK_NONE 0 | ||
492 | #define MSR_LINK_SHIFT 0 | ||
493 | #define MSR_LINK_ADHOC 1 | ||
494 | #define MSR_LINK_MASTER 3 | ||
495 | #define MSR_NOLINK 0x00 | ||
496 | #define MSR_ADHOC 0x01 | ||
497 | #define MSR_INFRA 0x02 | ||
498 | #define MSR_AP 0x03 | ||
499 | |||
500 | #define ENUART BIT(7) | ||
501 | #define ENJTAG BIT(3) | ||
502 | #define BTMODE (BIT(2) | BIT(1)) | ||
503 | #define ENBT BIT(0) | ||
504 | |||
505 | #define ENMBID BIT(7) | ||
506 | #define BCNUM (BIT(6) | BIT(5) | BIT(4)) | ||
507 | |||
508 | #define USTIME_EDCA 0xFF00 | ||
509 | #define USTIME_TSF 0x00FF | ||
510 | |||
511 | #define SIFS_TRX 0xFF00 | ||
512 | #define SIFS_CTX 0x00FF | ||
513 | |||
514 | #define ENSWBCN BIT(15) | ||
515 | #define DRVERLY_TU 0x0FF0 | ||
516 | #define DRVERLY_US 0x000F | ||
517 | #define BCN_TCFG_CW_SHIFT 8 | ||
518 | #define BCN_TCFG_IFS 0 | ||
519 | |||
520 | #define RRSR_RSC_OFFSET 21 | ||
521 | #define RRSR_SHORT_OFFSET 23 | ||
522 | #define RRSR_RSC_BW_40M 0x600000 | ||
523 | #define RRSR_RSC_UPSUBCHNL 0x400000 | ||
524 | #define RRSR_RSC_LOWSUBCHNL 0x200000 | ||
525 | #define RRSR_SHORT 0x800000 | ||
526 | #define RRSR_1M BIT(0) | ||
527 | #define RRSR_2M BIT(1) | ||
528 | #define RRSR_5_5M BIT(2) | ||
529 | #define RRSR_11M BIT(3) | ||
530 | #define RRSR_6M BIT(4) | ||
531 | #define RRSR_9M BIT(5) | ||
532 | #define RRSR_12M BIT(6) | ||
533 | #define RRSR_18M BIT(7) | ||
534 | #define RRSR_24M BIT(8) | ||
535 | #define RRSR_36M BIT(9) | ||
536 | #define RRSR_48M BIT(10) | ||
537 | #define RRSR_54M BIT(11) | ||
538 | #define RRSR_MCS0 BIT(12) | ||
539 | #define RRSR_MCS1 BIT(13) | ||
540 | #define RRSR_MCS2 BIT(14) | ||
541 | #define RRSR_MCS3 BIT(15) | ||
542 | #define RRSR_MCS4 BIT(16) | ||
543 | #define RRSR_MCS5 BIT(17) | ||
544 | #define RRSR_MCS6 BIT(18) | ||
545 | #define RRSR_MCS7 BIT(19) | ||
546 | #define BRSR_AckShortPmb BIT(23) | ||
547 | |||
548 | #define RATR_1M 0x00000001 | ||
549 | #define RATR_2M 0x00000002 | ||
550 | #define RATR_55M 0x00000004 | ||
551 | #define RATR_11M 0x00000008 | ||
552 | #define RATR_6M 0x00000010 | ||
553 | #define RATR_9M 0x00000020 | ||
554 | #define RATR_12M 0x00000040 | ||
555 | #define RATR_18M 0x00000080 | ||
556 | #define RATR_24M 0x00000100 | ||
557 | #define RATR_36M 0x00000200 | ||
558 | #define RATR_48M 0x00000400 | ||
559 | #define RATR_54M 0x00000800 | ||
560 | #define RATR_MCS0 0x00001000 | ||
561 | #define RATR_MCS1 0x00002000 | ||
562 | #define RATR_MCS2 0x00004000 | ||
563 | #define RATR_MCS3 0x00008000 | ||
564 | #define RATR_MCS4 0x00010000 | ||
565 | #define RATR_MCS5 0x00020000 | ||
566 | #define RATR_MCS6 0x00040000 | ||
567 | #define RATR_MCS7 0x00080000 | ||
568 | #define RATR_MCS8 0x00100000 | ||
569 | #define RATR_MCS9 0x00200000 | ||
570 | #define RATR_MCS10 0x00400000 | ||
571 | #define RATR_MCS11 0x00800000 | ||
572 | #define RATR_MCS12 0x01000000 | ||
573 | #define RATR_MCS13 0x02000000 | ||
574 | #define RATR_MCS14 0x04000000 | ||
575 | #define RATR_MCS15 0x08000000 | ||
576 | |||
577 | #define RATE_ALL_CCK (RATR_1M | RATR_2M | \ | ||
578 | RATR_55M | RATR_11M) | ||
579 | #define RATE_ALL_OFDM_AG (RATR_6M | RATR_9M | \ | ||
580 | RATR_12M | RATR_18M | \ | ||
581 | RATR_24M | RATR_36M | \ | ||
582 | RATR_48M | RATR_54M) | ||
583 | #define RATE_ALL_OFDM_1SS (RATR_MCS0 | RATR_MCS1 | \ | ||
584 | RATR_MCS2 | RATR_MCS3 | \ | ||
585 | RATR_MCS4 | RATR_MCS5 | \ | ||
586 | RATR_MCS6 | RATR_MCS7) | ||
587 | #define RATE_ALL_OFDM_2SS (RATR_MCS8 | RATR_MCS9 | \ | ||
588 | RATR_MCS10 | RATR_MCS11 | \ | ||
589 | RATR_MCS12 | RATR_MCS13 | \ | ||
590 | RATR_MCS14 | RATR_MCS15) | ||
591 | |||
592 | #define AC_PARAM_TXOP_LIMIT_OFFSET 16 | ||
593 | #define AC_PARAM_ECW_MAX_OFFSET 12 | ||
594 | #define AC_PARAM_ECW_MIN_OFFSET 8 | ||
595 | #define AC_PARAM_AIFS_OFFSET 0 | ||
596 | |||
597 | #define AcmHw_HwEn BIT(0) | ||
598 | #define AcmHw_BeqEn BIT(1) | ||
599 | #define AcmHw_ViqEn BIT(2) | ||
600 | #define AcmHw_VoqEn BIT(3) | ||
601 | #define AcmHw_BeqStatus BIT(4) | ||
602 | #define AcmHw_ViqStatus BIT(5) | ||
603 | #define AcmHw_VoqStatus BIT(6) | ||
604 | |||
605 | #define RETRY_LIMIT_SHORT_SHIFT 8 | ||
606 | #define RETRY_LIMIT_LONG_SHIFT 0 | ||
607 | |||
608 | #define NAV_UPPER_EN BIT(16) | ||
609 | #define NAV_UPPER 0xFF00 | ||
610 | #define NAV_RTSRST 0xFF | ||
611 | |||
612 | #define BW_OPMODE_20MHZ BIT(2) | ||
613 | #define BW_OPMODE_5G BIT(1) | ||
614 | #define BW_OPMODE_11J BIT(0) | ||
615 | |||
616 | #define RXERR_RPT_RST BIT(27) | ||
617 | #define RXERR_OFDM_PPDU 0 | ||
618 | #define RXERR_OFDM_FALSE_ALARM 1 | ||
619 | #define RXERR_OFDM_MPDU_OK 2 | ||
620 | #define RXERR_OFDM_MPDU_FAIL 3 | ||
621 | #define RXERR_CCK_PPDU 4 | ||
622 | #define RXERR_CCK_FALSE_ALARM 5 | ||
623 | #define RXERR_CCK_MPDU_OK 6 | ||
624 | #define RXERR_CCK_MPDU_FAIL 7 | ||
625 | #define RXERR_HT_PPDU 8 | ||
626 | #define RXERR_HT_FALSE_ALARM 9 | ||
627 | #define RXERR_HT_MPDU_TOTAL 10 | ||
628 | #define RXERR_HT_MPDU_OK 11 | ||
629 | #define RXERR_HT_MPDU_FAIL 12 | ||
630 | #define RXERR_RX_FULL_DROP 15 | ||
631 | |||
632 | #define SCR_TXUSEDK BIT(0) | ||
633 | #define SCR_RXUSEDK BIT(1) | ||
634 | #define SCR_TXENCENABLE BIT(2) | ||
635 | #define SCR_RXENCENABLE BIT(3) | ||
636 | #define SCR_SKBYA2 BIT(4) | ||
637 | #define SCR_NOSKMC BIT(5) | ||
638 | |||
639 | #define CAM_VALID BIT(15) | ||
640 | #define CAM_NOTVALID 0x0000 | ||
641 | #define CAM_USEDK BIT(5) | ||
642 | |||
643 | #define CAM_NONE 0x0 | ||
644 | #define CAM_WEP40 0x01 | ||
645 | #define CAM_TKIP 0x02 | ||
646 | #define CAM_AES 0x04 | ||
647 | #define CAM_WEP104 0x05 | ||
648 | |||
649 | #define TOTAL_CAM_ENTRY 32 | ||
650 | #define HALF_CAM_ENTRY 16 | ||
651 | |||
652 | #define CAM_WRITE BIT(16) | ||
653 | #define CAM_READ 0x00000000 | ||
654 | #define CAM_POLLINIG BIT(31) | ||
655 | |||
656 | #define WOW_PMEN BIT(0) | ||
657 | #define WOW_WOMEN BIT(1) | ||
658 | #define WOW_MAGIC BIT(2) | ||
659 | #define WOW_UWF BIT(3) | ||
660 | |||
661 | #define GPIOMUX_EN BIT(3) | ||
662 | #define GPIOSEL_GPIO 0 | ||
663 | #define GPIOSEL_PHYDBG 1 | ||
664 | #define GPIOSEL_BT 2 | ||
665 | #define GPIOSEL_WLANDBG 3 | ||
666 | #define GPIOSEL_GPIO_MASK (~(BIT(0)|BIT(1))) | ||
667 | |||
668 | #define HST_RDBUSY BIT(0) | ||
669 | #define CPU_WTBUSY BIT(1) | ||
670 | |||
671 | #define IMR8190_DISABLED 0x0 | ||
672 | #define IMR_CPUERR BIT(5) | ||
673 | #define IMR_ATIMEND BIT(4) | ||
674 | #define IMR_TBDOK BIT(3) | ||
675 | #define IMR_TBDER BIT(2) | ||
676 | #define IMR_BCNDMAINT8 BIT(1) | ||
677 | #define IMR_BCNDMAINT7 BIT(0) | ||
678 | #define IMR_BCNDMAINT6 BIT(31) | ||
679 | #define IMR_BCNDMAINT5 BIT(30) | ||
680 | #define IMR_BCNDMAINT4 BIT(29) | ||
681 | #define IMR_BCNDMAINT3 BIT(28) | ||
682 | #define IMR_BCNDMAINT2 BIT(27) | ||
683 | #define IMR_BCNDMAINT1 BIT(26) | ||
684 | #define IMR_BCNDOK8 BIT(25) | ||
685 | #define IMR_BCNDOK7 BIT(24) | ||
686 | #define IMR_BCNDOK6 BIT(23) | ||
687 | #define IMR_BCNDOK5 BIT(22) | ||
688 | #define IMR_BCNDOK4 BIT(21) | ||
689 | #define IMR_BCNDOK3 BIT(20) | ||
690 | #define IMR_BCNDOK2 BIT(19) | ||
691 | #define IMR_BCNDOK1 BIT(18) | ||
692 | #define IMR_TIMEOUT2 BIT(17) | ||
693 | #define IMR_TIMEOUT1 BIT(16) | ||
694 | #define IMR_TXFOVW BIT(15) | ||
695 | #define IMR_PSTIMEOUT BIT(14) | ||
696 | #define IMR_BCNINT BIT(13) | ||
697 | #define IMR_RXFOVW BIT(12) | ||
698 | #define IMR_RDU BIT(11) | ||
699 | #define IMR_RXCMDOK BIT(10) | ||
700 | #define IMR_BDOK BIT(9) | ||
701 | #define IMR_HIGHDOK BIT(8) | ||
702 | #define IMR_COMDOK BIT(7) | ||
703 | #define IMR_MGNTDOK BIT(6) | ||
704 | #define IMR_HCCADOK BIT(5) | ||
705 | #define IMR_BKDOK BIT(4) | ||
706 | #define IMR_BEDOK BIT(3) | ||
707 | #define IMR_VIDOK BIT(2) | ||
708 | #define IMR_VODOK BIT(1) | ||
709 | #define IMR_ROK BIT(0) | ||
710 | |||
711 | #define TPPOLL_BKQ BIT(0) | ||
712 | #define TPPOLL_BEQ BIT(1) | ||
713 | #define TPPOLL_VIQ BIT(2) | ||
714 | #define TPPOLL_VOQ BIT(3) | ||
715 | #define TPPOLL_BQ BIT(4) | ||
716 | #define TPPOLL_CQ BIT(5) | ||
717 | #define TPPOLL_MQ BIT(6) | ||
718 | #define TPPOLL_HQ BIT(7) | ||
719 | #define TPPOLL_HCCAQ BIT(8) | ||
720 | #define TPPOLL_STOPBK BIT(9) | ||
721 | #define TPPOLL_STOPBE BIT(10) | ||
722 | #define TPPOLL_STOPVI BIT(11) | ||
723 | #define TPPOLL_STOPVO BIT(12) | ||
724 | #define TPPOLL_STOPMGT BIT(13) | ||
725 | #define TPPOLL_STOPHIGH BIT(14) | ||
726 | #define TPPOLL_STOPHCCA BIT(15) | ||
727 | #define TPPOLL_SHIFT 8 | ||
728 | |||
729 | #define CCX_CMD_CLM_ENABLE BIT(0) | ||
730 | #define CCX_CMD_NHM_ENABLE BIT(1) | ||
731 | #define CCX_CMD_FUNCTION_ENABLE BIT(8) | ||
732 | #define CCX_CMD_IGNORE_CCA BIT(9) | ||
733 | #define CCX_CMD_IGNORE_TXON BIT(10) | ||
734 | #define CCX_CLM_RESULT_READY BIT(16) | ||
735 | #define CCX_NHM_RESULT_READY BIT(16) | ||
736 | #define CCX_CMD_RESET 0x0 | ||
737 | |||
738 | |||
739 | #define HWSET_MAX_SIZE_92S 128 | ||
740 | #define EFUSE_MAX_SECTION 16 | ||
741 | #define EFUSE_REAL_CONTENT_LEN 512 | ||
742 | |||
743 | #define RTL8190_EEPROM_ID 0x8129 | ||
744 | #define EEPROM_HPON 0x02 | ||
745 | #define EEPROM_CLK 0x06 | ||
746 | #define EEPROM_TESTR 0x08 | ||
747 | |||
748 | #define EEPROM_VID 0x0A | ||
749 | #define EEPROM_DID 0x0C | ||
750 | #define EEPROM_SVID 0x0E | ||
751 | #define EEPROM_SMID 0x10 | ||
752 | |||
753 | #define EEPROM_MAC_ADDR 0x12 | ||
754 | #define EEPROM_NODE_ADDRESS_BYTE_0 0x12 | ||
755 | |||
756 | #define EEPROM_PWDIFF 0x54 | ||
757 | |||
758 | #define EEPROM_TXPOWERBASE 0x50 | ||
759 | #define EEPROM_TX_PWR_INDEX_RANGE 28 | ||
760 | |||
761 | #define EEPROM_TX_PWR_HT20_DIFF 0x62 | ||
762 | #define DEFAULT_HT20_TXPWR_DIFF 2 | ||
763 | #define EEPROM_TX_PWR_OFDM_DIFF 0x65 | ||
764 | |||
765 | #define EEPROM_TXPWRGROUP 0x67 | ||
766 | #define EEPROM_REGULATORY 0x6D | ||
767 | |||
768 | #define TX_PWR_SAFETY_CHK 0x6D | ||
769 | #define EEPROM_TXPWINDEX_CCK_24G 0x5D | ||
770 | #define EEPROM_TXPWINDEX_OFDM_24G 0x6B | ||
771 | #define EEPROM_HT2T_CH1_A 0x6c | ||
772 | #define EEPROM_HT2T_CH7_A 0x6d | ||
773 | #define EEPROM_HT2T_CH13_A 0x6e | ||
774 | #define EEPROM_HT2T_CH1_B 0x6f | ||
775 | #define EEPROM_HT2T_CH7_B 0x70 | ||
776 | #define EEPROM_HT2T_CH13_B 0x71 | ||
777 | |||
778 | #define EEPROM_TSSI_A 0x74 | ||
779 | #define EEPROM_TSSI_B 0x75 | ||
780 | |||
781 | #define EEPROM_RFIND_POWERDIFF 0x76 | ||
782 | #define EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF 0x3 | ||
783 | |||
784 | #define EEPROM_THERMALMETER 0x77 | ||
785 | #define EEPROM_BLUETOOTH_COEXIST 0x78 | ||
786 | #define EEPROM_BLUETOOTH_TYPE 0x4f | ||
787 | |||
788 | #define EEPROM_OPTIONAL 0x78 | ||
789 | #define EEPROM_WOWLAN 0x78 | ||
790 | |||
791 | #define EEPROM_CRYSTALCAP 0x79 | ||
792 | #define EEPROM_CHANNELPLAN 0x7B | ||
793 | #define EEPROM_VERSION 0x7C | ||
794 | #define EEPROM_CUSTOMID 0x7A | ||
795 | #define EEPROM_BOARDTYPE 0x7E | ||
796 | |||
797 | #define EEPROM_CHANNEL_PLAN_FCC 0x0 | ||
798 | #define EEPROM_CHANNEL_PLAN_IC 0x1 | ||
799 | #define EEPROM_CHANNEL_PLAN_ETSI 0x2 | ||
800 | #define EEPROM_CHANNEL_PLAN_SPAIN 0x3 | ||
801 | #define EEPROM_CHANNEL_PLAN_FRANCE 0x4 | ||
802 | #define EEPROM_CHANNEL_PLAN_MKK 0x5 | ||
803 | #define EEPROM_CHANNEL_PLAN_MKK1 0x6 | ||
804 | #define EEPROM_CHANNEL_PLAN_ISRAEL 0x7 | ||
805 | #define EEPROM_CHANNEL_PLAN_TELEC 0x8 | ||
806 | #define EEPROM_CHANNEL_PLAN_GLOBAL_DOMAIN 0x9 | ||
807 | #define EEPROM_CHANNEL_PLAN_WORLD_WIDE_13 0xA | ||
808 | #define EEPROM_CHANNEL_PLAN_NCC 0xB | ||
809 | #define EEPROM_CHANNEL_PLAN_BY_HW_MASK 0x80 | ||
810 | |||
811 | #define FW_DIG_DISABLE 0xfd00cc00 | ||
812 | #define FW_DIG_ENABLE 0xfd000000 | ||
813 | #define FW_DIG_HALT 0xfd000001 | ||
814 | #define FW_DIG_RESUME 0xfd000002 | ||
815 | #define FW_HIGH_PWR_DISABLE 0xfd000008 | ||
816 | #define FW_HIGH_PWR_ENABLE 0xfd000009 | ||
817 | #define FW_ADD_A2_ENTRY 0xfd000016 | ||
818 | #define FW_TXPWR_TRACK_ENABLE 0xfd000017 | ||
819 | #define FW_TXPWR_TRACK_DISABLE 0xfd000018 | ||
820 | #define FW_TXPWR_TRACK_THERMAL 0xfd000019 | ||
821 | #define FW_TXANT_SWITCH_ENABLE 0xfd000023 | ||
822 | #define FW_TXANT_SWITCH_DISABLE 0xfd000024 | ||
823 | #define FW_RA_INIT 0xfd000026 | ||
824 | #define FW_CTRL_DM_BY_DRIVER 0Xfd00002a | ||
825 | #define FW_RA_IOT_BG_COMB 0xfd000030 | ||
826 | #define FW_RA_IOT_N_COMB 0xfd000031 | ||
827 | #define FW_RA_REFRESH 0xfd0000a0 | ||
828 | #define FW_RA_UPDATE_MASK 0xfd0000a2 | ||
829 | #define FW_RA_DISABLE 0xfd0000a4 | ||
830 | #define FW_RA_ACTIVE 0xfd0000a6 | ||
831 | #define FW_RA_DISABLE_RSSI_MASK 0xfd0000ac | ||
832 | #define FW_RA_ENABLE_RSSI_MASK 0xfd0000ad | ||
833 | #define FW_RA_RESET 0xfd0000af | ||
834 | #define FW_DM_DISABLE 0xfd00aa00 | ||
835 | #define FW_IQK_ENABLE 0xf0000020 | ||
836 | #define FW_IQK_SUCCESS 0x0000dddd | ||
837 | #define FW_IQK_FAIL 0x0000ffff | ||
838 | #define FW_OP_FAILURE 0xffffffff | ||
839 | #define FW_TX_FEEDBACK_NONE 0xfb000000 | ||
840 | #define FW_TX_FEEDBACK_DTM_ENABLE (FW_TX_FEEDBACK_NONE | 0x1) | ||
841 | #define FW_TX_FEEDBACK_CCX_ENABL (FW_TX_FEEDBACK_NONE | 0x2) | ||
842 | #define FW_BB_RESET_ENABLE 0xff00000d | ||
843 | #define FW_BB_RESET_DISABLE 0xff00000e | ||
844 | #define FW_CCA_CHK_ENABLE 0xff000011 | ||
845 | #define FW_CCK_RESET_CNT 0xff000013 | ||
846 | #define FW_LPS_ENTER 0xfe000010 | ||
847 | #define FW_LPS_LEAVE 0xfe000011 | ||
848 | #define FW_INDIRECT_READ 0xf2000000 | ||
849 | #define FW_INDIRECT_WRITE 0xf2000001 | ||
850 | #define FW_CHAN_SET 0xf3000001 | ||
851 | |||
852 | #define RFPC 0x5F | ||
853 | #define RCR_9356SEL BIT(6) | ||
854 | #define TCR_LRL_OFFSET 0 | ||
855 | #define TCR_SRL_OFFSET 8 | ||
856 | #define TCR_MXDMA_OFFSET 21 | ||
857 | #define TCR_SAT BIT(24) | ||
858 | #define RCR_MXDMA_OFFSET 8 | ||
859 | #define RCR_FIFO_OFFSET 13 | ||
860 | #define RCR_OnlyErlPkt BIT(31) | ||
861 | #define CWR 0xDC | ||
862 | #define RETRYCTR 0xDE | ||
863 | |||
864 | #define CPU_GEN_SYSTEM_RESET 0x00000001 | ||
865 | |||
866 | #define CCX_COMMAND_REG 0x890 | ||
867 | #define CLM_PERIOD_REG 0x894 | ||
868 | #define NHM_PERIOD_REG 0x896 | ||
869 | |||
870 | #define NHM_THRESHOLD0 0x898 | ||
871 | #define NHM_THRESHOLD1 0x899 | ||
872 | #define NHM_THRESHOLD2 0x89A | ||
873 | #define NHM_THRESHOLD3 0x89B | ||
874 | #define NHM_THRESHOLD4 0x89C | ||
875 | #define NHM_THRESHOLD5 0x89D | ||
876 | #define NHM_THRESHOLD6 0x89E | ||
877 | #define CLM_RESULT_REG 0x8D0 | ||
878 | #define NHM_RESULT_REG 0x8D4 | ||
879 | #define NHM_RPI_COUNTER0 0x8D8 | ||
880 | #define NHM_RPI_COUNTER1 0x8D9 | ||
881 | #define NHM_RPI_COUNTER2 0x8DA | ||
882 | #define NHM_RPI_COUNTER3 0x8DB | ||
883 | #define NHM_RPI_COUNTER4 0x8DC | ||
884 | #define NHM_RPI_COUNTER5 0x8DD | ||
885 | #define NHM_RPI_COUNTER6 0x8DE | ||
886 | #define NHM_RPI_COUNTER7 0x8DF | ||
887 | |||
888 | #define HAL_8192S_HW_GPIO_OFF_BIT BIT(3) | ||
889 | #define HAL_8192S_HW_GPIO_OFF_MASK 0xF7 | ||
890 | #define HAL_8192S_HW_GPIO_WPS_BIT BIT(4) | ||
891 | |||
892 | #define RPMAC_RESET 0x100 | ||
893 | #define RPMAC_TXSTART 0x104 | ||
894 | #define RPMAC_TXLEGACYSIG 0x108 | ||
895 | #define RPMAC_TXHTSIG1 0x10c | ||
896 | #define RPMAC_TXHTSIG2 0x110 | ||
897 | #define RPMAC_PHYDEBUG 0x114 | ||
898 | #define RPMAC_TXPACKETNNM 0x118 | ||
899 | #define RPMAC_TXIDLE 0x11c | ||
900 | #define RPMAC_TXMACHEADER0 0x120 | ||
901 | #define RPMAC_TXMACHEADER1 0x124 | ||
902 | #define RPMAC_TXMACHEADER2 0x128 | ||
903 | #define RPMAC_TXMACHEADER3 0x12c | ||
904 | #define RPMAC_TXMACHEADER4 0x130 | ||
905 | #define RPMAC_TXMACHEADER5 0x134 | ||
906 | #define RPMAC_TXDATATYPE 0x138 | ||
907 | #define RPMAC_TXRANDOMSEED 0x13c | ||
908 | #define RPMAC_CCKPLCPPREAMBLE 0x140 | ||
909 | #define RPMAC_CCKPLCPHEADER 0x144 | ||
910 | #define RPMAC_CCKCRC16 0x148 | ||
911 | #define RPMAC_OFDMRXCRC32OK 0x170 | ||
912 | #define RPMAC_OFDMRXCRC32ER 0x174 | ||
913 | #define RPMAC_OFDMRXPARITYER 0x178 | ||
914 | #define RPMAC_OFDMRXCRC8ER 0x17c | ||
915 | #define RPMAC_CCKCRXRC16ER 0x180 | ||
916 | #define RPMAC_CCKCRXRC32ER 0x184 | ||
917 | #define RPMAC_CCKCRXRC32OK 0x188 | ||
918 | #define RPMAC_TXSTATUS 0x18c | ||
919 | |||
920 | #define RF_BB_CMD_ADDR 0x02c0 | ||
921 | #define RF_BB_CMD_DATA 0x02c4 | ||
922 | |||
923 | #define RFPGA0_RFMOD 0x800 | ||
924 | |||
925 | #define RFPGA0_TXINFO 0x804 | ||
926 | #define RFPGA0_PSDFUNCTION 0x808 | ||
927 | |||
928 | #define RFPGA0_TXGAINSTAGE 0x80c | ||
929 | |||
930 | #define RFPGA0_RFTIMING1 0x810 | ||
931 | #define RFPGA0_RFTIMING2 0x814 | ||
932 | #define RFPGA0_XA_HSSIPARAMETER1 0x820 | ||
933 | #define RFPGA0_XA_HSSIPARAMETER2 0x824 | ||
934 | #define RFPGA0_XB_HSSIPARAMETER1 0x828 | ||
935 | #define RFPGA0_XB_HSSIPARAMETER2 0x82c | ||
936 | #define RFPGA0_XC_HSSIPARAMETER1 0x830 | ||
937 | #define RFPGA0_XC_HSSIPARAMETER2 0x834 | ||
938 | #define RFPGA0_XD_HSSIPARAMETER1 0x838 | ||
939 | #define RFPGA0_XD_HSSIPARAMETER2 0x83c | ||
940 | #define RFPGA0_XA_LSSIPARAMETER 0x840 | ||
941 | #define RFPGA0_XB_LSSIPARAMETER 0x844 | ||
942 | #define RFPGA0_XC_LSSIPARAMETER 0x848 | ||
943 | #define RFPGA0_XD_LSSIPARAMETER 0x84c | ||
944 | |||
945 | #define RFPGA0_RFWAKEUP_PARAMETER 0x850 | ||
946 | #define RFPGA0_RFSLEEPUP_PARAMETER 0x854 | ||
947 | |||
948 | #define RFPGA0_XAB_SWITCHCONTROL 0x858 | ||
949 | #define RFPGA0_XCD_SWITCHCONTROL 0x85c | ||
950 | |||
951 | #define RFPGA0_XA_RFINTERFACEOE 0x860 | ||
952 | #define RFPGA0_XB_RFINTERFACEOE 0x864 | ||
953 | #define RFPGA0_XC_RFINTERFACEOE 0x868 | ||
954 | #define RFPGA0_XD_RFINTERFACEOE 0x86c | ||
955 | |||
956 | #define RFPGA0_XAB_RFINTERFACESW 0x870 | ||
957 | #define RFPGA0_XCD_RFINTERFACESW 0x874 | ||
958 | |||
959 | #define RFPGA0_XAB_RFPARAMETER 0x878 | ||
960 | #define RFPGA0_XCD_RFPARAMETER 0x87c | ||
961 | |||
962 | #define RFPGA0_ANALOGPARAMETER1 0x880 | ||
963 | #define RFPGA0_ANALOGPARAMETER2 0x884 | ||
964 | #define RFPGA0_ANALOGPARAMETER3 0x888 | ||
965 | #define RFPGA0_ANALOGPARAMETER4 0x88c | ||
966 | |||
967 | #define RFPGA0_XA_LSSIREADBACK 0x8a0 | ||
968 | #define RFPGA0_XB_LSSIREADBACK 0x8a4 | ||
969 | #define RFPGA0_XC_LSSIREADBACK 0x8a8 | ||
970 | #define RFPGA0_XD_LSSIREADBACK 0x8ac | ||
971 | |||
972 | #define RFPGA0_PSDREPORT 0x8b4 | ||
973 | #define TRANSCEIVERA_HSPI_READBACK 0x8b8 | ||
974 | #define TRANSCEIVERB_HSPI_READBACK 0x8bc | ||
975 | #define RFPGA0_XAB_RFINTERFACERB 0x8e0 | ||
976 | #define RFPGA0_XCD_RFINTERFACERB 0x8e4 | ||
977 | #define RFPGA1_RFMOD 0x900 | ||
978 | |||
979 | #define RFPGA1_TXBLOCK 0x904 | ||
980 | #define RFPGA1_DEBUGSELECT 0x908 | ||
981 | #define RFPGA1_TXINFO 0x90c | ||
982 | |||
983 | #define RCCK0_SYSTEM 0xa00 | ||
984 | |||
985 | #define RCCK0_AFESETTING 0xa04 | ||
986 | #define RCCK0_CCA 0xa08 | ||
987 | |||
988 | #define RCCK0_RXAGC1 0xa0c | ||
989 | #define RCCK0_RXAGC2 0xa10 | ||
990 | |||
991 | #define RCCK0_RXHP 0xa14 | ||
992 | |||
993 | #define RCCK0_DSPPARAMETER1 0xa18 | ||
994 | #define RCCK0_DSPPARAMETER2 0xa1c | ||
995 | |||
996 | #define RCCK0_TXFILTER1 0xa20 | ||
997 | #define RCCK0_TXFILTER2 0xa24 | ||
998 | #define RCCK0_DEBUGPORT 0xa28 | ||
999 | #define RCCK0_FALSEALARMREPORT 0xa2c | ||
1000 | #define RCCK0_TRSSIREPORT 0xa50 | ||
1001 | #define RCCK0_RXREPORT 0xa54 | ||
1002 | #define RCCK0_FACOUNTERLOWER 0xa5c | ||
1003 | #define RCCK0_FACOUNTERUPPER 0xa58 | ||
1004 | |||
1005 | #define ROFDM0_LSTF 0xc00 | ||
1006 | |||
1007 | #define ROFDM0_TRXPATHENABLE 0xc04 | ||
1008 | #define ROFDM0_TRMUXPAR 0xc08 | ||
1009 | #define ROFDM0_TRSWISOLATION 0xc0c | ||
1010 | |||
1011 | #define ROFDM0_XARXAFE 0xc10 | ||
1012 | #define ROFDM0_XARXIQIMBALANCE 0xc14 | ||
1013 | #define ROFDM0_XBRXAFE 0xc18 | ||
1014 | #define ROFDM0_XBRXIQIMBALANCE 0xc1c | ||
1015 | #define ROFDM0_XCRXAFE 0xc20 | ||
1016 | #define ROFDM0_XCRXIQIMBALANCE 0xc24 | ||
1017 | #define ROFDM0_XDRXAFE 0xc28 | ||
1018 | #define ROFDM0_XDRXIQIMBALANCE 0xc2c | ||
1019 | |||
1020 | #define ROFDM0_RXDETECTOR1 0xc30 | ||
1021 | #define ROFDM0_RXDETECTOR2 0xc34 | ||
1022 | #define ROFDM0_RXDETECTOR3 0xc38 | ||
1023 | #define ROFDM0_RXDETECTOR4 0xc3c | ||
1024 | |||
1025 | #define ROFDM0_RXDSP 0xc40 | ||
1026 | #define ROFDM0_CFO_AND_DAGC 0xc44 | ||
1027 | #define ROFDM0_CCADROP_THRESHOLD 0xc48 | ||
1028 | #define ROFDM0_ECCA_THRESHOLD 0xc4c | ||
1029 | |||
1030 | #define ROFDM0_XAAGCCORE1 0xc50 | ||
1031 | #define ROFDM0_XAAGCCORE2 0xc54 | ||
1032 | #define ROFDM0_XBAGCCORE1 0xc58 | ||
1033 | #define ROFDM0_XBAGCCORE2 0xc5c | ||
1034 | #define ROFDM0_XCAGCCORE1 0xc60 | ||
1035 | #define ROFDM0_XCAGCCORE2 0xc64 | ||
1036 | #define ROFDM0_XDAGCCORE1 0xc68 | ||
1037 | #define ROFDM0_XDAGCCORE2 0xc6c | ||
1038 | |||
1039 | #define ROFDM0_AGCPARAMETER1 0xc70 | ||
1040 | #define ROFDM0_AGCPARAMETER2 0xc74 | ||
1041 | #define ROFDM0_AGCRSSITABLE 0xc78 | ||
1042 | #define ROFDM0_HTSTFAGC 0xc7c | ||
1043 | |||
1044 | #define ROFDM0_XATXIQIMBALANCE 0xc80 | ||
1045 | #define ROFDM0_XATXAFE 0xc84 | ||
1046 | #define ROFDM0_XBTXIQIMBALANCE 0xc88 | ||
1047 | #define ROFDM0_XBTXAFE 0xc8c | ||
1048 | #define ROFDM0_XCTXIQIMBALANCE 0xc90 | ||
1049 | #define ROFDM0_XCTXAFE 0xc94 | ||
1050 | #define ROFDM0_XDTXIQIMBALANCE 0xc98 | ||
1051 | #define ROFDM0_XDTXAFE 0xc9c | ||
1052 | |||
1053 | #define ROFDM0_RXHP_PARAMETER 0xce0 | ||
1054 | #define ROFDM0_TXPSEUDO_NOISE_WGT 0xce4 | ||
1055 | #define ROFDM0_FRAME_SYNC 0xcf0 | ||
1056 | #define ROFDM0_DFSREPORT 0xcf4 | ||
1057 | #define ROFDM0_TXCOEFF1 0xca4 | ||
1058 | #define ROFDM0_TXCOEFF2 0xca8 | ||
1059 | #define ROFDM0_TXCOEFF3 0xcac | ||
1060 | #define ROFDM0_TXCOEFF4 0xcb0 | ||
1061 | #define ROFDM0_TXCOEFF5 0xcb4 | ||
1062 | #define ROFDM0_TXCOEFF6 0xcb8 | ||
1063 | |||
1064 | |||
1065 | #define ROFDM1_LSTF 0xd00 | ||
1066 | #define ROFDM1_TRXPATHENABLE 0xd04 | ||
1067 | |||
1068 | #define ROFDM1_CFO 0xd08 | ||
1069 | #define ROFDM1_CSI1 0xd10 | ||
1070 | #define ROFDM1_SBD 0xd14 | ||
1071 | #define ROFDM1_CSI2 0xd18 | ||
1072 | #define ROFDM1_CFOTRACKING 0xd2c | ||
1073 | #define ROFDM1_TRXMESAURE1 0xd34 | ||
1074 | #define ROFDM1_INTF_DET 0xd3c | ||
1075 | #define ROFDM1_PSEUDO_NOISESTATEAB 0xd50 | ||
1076 | #define ROFDM1_PSEUDO_NOISESTATECD 0xd54 | ||
1077 | #define ROFDM1_RX_PSEUDO_NOISE_WGT 0xd58 | ||
1078 | |||
1079 | #define ROFDM_PHYCOUNTER1 0xda0 | ||
1080 | #define ROFDM_PHYCOUNTER2 0xda4 | ||
1081 | #define ROFDM_PHYCOUNTER3 0xda8 | ||
1082 | |||
1083 | #define ROFDM_SHORT_CFOAB 0xdac | ||
1084 | #define ROFDM_SHORT_CFOCD 0xdb0 | ||
1085 | #define ROFDM_LONG_CFOAB 0xdb4 | ||
1086 | #define ROFDM_LONG_CFOCD 0xdb8 | ||
1087 | #define ROFDM_TAIL_CFOAB 0xdbc | ||
1088 | #define ROFDM_TAIL_CFOCD 0xdc0 | ||
1089 | #define ROFDM_PW_MEASURE1 0xdc4 | ||
1090 | #define ROFDM_PW_MEASURE2 0xdc8 | ||
1091 | #define ROFDM_BW_REPORT 0xdcc | ||
1092 | #define ROFDM_AGC_REPORT 0xdd0 | ||
1093 | #define ROFDM_RXSNR 0xdd4 | ||
1094 | #define ROFDM_RXEVMCSI 0xdd8 | ||
1095 | #define ROFDM_SIG_REPORT 0xddc | ||
1096 | |||
1097 | |||
1098 | #define RTXAGC_RATE18_06 0xe00 | ||
1099 | #define RTXAGC_RATE54_24 0xe04 | ||
1100 | #define RTXAGC_CCK_MCS32 0xe08 | ||
1101 | #define RTXAGC_MCS03_MCS00 0xe10 | ||
1102 | #define RTXAGC_MCS07_MCS04 0xe14 | ||
1103 | #define RTXAGC_MCS11_MCS08 0xe18 | ||
1104 | #define RTXAGC_MCS15_MCS12 0xe1c | ||
1105 | |||
1106 | |||
1107 | #define RF_AC 0x00 | ||
1108 | #define RF_IQADJ_G1 0x01 | ||
1109 | #define RF_IQADJ_G2 0x02 | ||
1110 | #define RF_POW_TRSW 0x05 | ||
1111 | #define RF_GAIN_RX 0x06 | ||
1112 | #define RF_GAIN_TX 0x07 | ||
1113 | #define RF_TXM_IDAC 0x08 | ||
1114 | #define RF_BS_IQGEN 0x0F | ||
1115 | |||
1116 | #define RF_MODE1 0x10 | ||
1117 | #define RF_MODE2 0x11 | ||
1118 | #define RF_RX_AGC_HP 0x12 | ||
1119 | #define RF_TX_AGC 0x13 | ||
1120 | #define RF_BIAS 0x14 | ||
1121 | #define RF_IPA 0x15 | ||
1122 | #define RF_POW_ABILITY 0x17 | ||
1123 | #define RF_MODE_AG 0x18 | ||
1124 | #define RF_CHANNEL 0x18 | ||
1125 | #define RF_CHNLBW 0x18 | ||
1126 | #define RF_TOP 0x19 | ||
1127 | #define RF_RX_G1 0x1A | ||
1128 | #define RF_RX_G2 0x1B | ||
1129 | #define RF_RX_BB2 0x1C | ||
1130 | #define RF_RX_BB1 0x1D | ||
1131 | #define RF_RCK1 0x1E | ||
1132 | #define RF_RCK2 0x1F | ||
1133 | |||
1134 | #define RF_TX_G1 0x20 | ||
1135 | #define RF_TX_G2 0x21 | ||
1136 | #define RF_TX_G3 0x22 | ||
1137 | #define RF_TX_BB1 0x23 | ||
1138 | #define RF_T_METER 0x24 | ||
1139 | #define RF_SYN_G1 0x25 | ||
1140 | #define RF_SYN_G2 0x26 | ||
1141 | #define RF_SYN_G3 0x27 | ||
1142 | #define RF_SYN_G4 0x28 | ||
1143 | #define RF_SYN_G5 0x29 | ||
1144 | #define RF_SYN_G6 0x2A | ||
1145 | #define RF_SYN_G7 0x2B | ||
1146 | #define RF_SYN_G8 0x2C | ||
1147 | |||
1148 | #define RF_RCK_OS 0x30 | ||
1149 | #define RF_TXPA_G1 0x31 | ||
1150 | #define RF_TXPA_G2 0x32 | ||
1151 | #define RF_TXPA_G3 0x33 | ||
1152 | |||
1153 | #define BRFMOD 0x1 | ||
1154 | #define BCCKEN 0x1000000 | ||
1155 | #define BOFDMEN 0x2000000 | ||
1156 | |||
1157 | #define BXBTXAGC 0xf00 | ||
1158 | #define BXCTXAGC 0xf000 | ||
1159 | #define BXDTXAGC 0xf0000 | ||
1160 | |||
1161 | #define B3WIRE_DATALENGTH 0x800 | ||
1162 | #define B3WIRE_ADDRESSLENGTH 0x400 | ||
1163 | |||
1164 | #define BRFSI_RFENV 0x10 | ||
1165 | |||
1166 | #define BLSSI_READADDRESS 0x7f800000 | ||
1167 | #define BLSSI_READEDGE 0x80000000 | ||
1168 | #define BLSSI_READBACK_DATA 0xfffff | ||
1169 | |||
1170 | #define BADCLKPHASE 0x4000000 | ||
1171 | |||
1172 | #define BCCK_SIDEBAND 0x10 | ||
1173 | |||
1174 | #define BTX_AGCRATECCK 0x7f00 | ||
1175 | |||
1176 | #define MASKBYTE0 0xff | ||
1177 | #define MASKBYTE1 0xff00 | ||
1178 | #define MASKBYTE2 0xff0000 | ||
1179 | #define MASKBYTE3 0xff000000 | ||
1180 | #define MASKHWORD 0xffff0000 | ||
1181 | #define MASKLWORD 0x0000ffff | ||
1182 | #define MASKDWORD 0xffffffff | ||
1183 | |||
1184 | #define MAKS12BITS 0xfffff | ||
1185 | #define MASK20BITS 0xfffff | ||
1186 | #define RFREG_OFFSET_MASK 0xfffff | ||
1187 | |||
1188 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c new file mode 100644 index 000000000000..1d3a48330399 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c | |||
@@ -0,0 +1,546 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "reg.h" | ||
32 | #include "def.h" | ||
33 | #include "phy.h" | ||
34 | #include "rf.h" | ||
35 | #include "dm.h" | ||
36 | |||
37 | |||
38 | static void _rtl92s_get_powerbase(struct ieee80211_hw *hw, u8 *p_pwrlevel, | ||
39 | u8 chnl, u32 *ofdmbase, u32 *mcsbase, | ||
40 | u8 *p_final_pwridx) | ||
41 | { | ||
42 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
43 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
44 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
45 | u32 pwrbase0, pwrbase1; | ||
46 | u8 legacy_pwrdiff = 0, ht20_pwrdiff = 0; | ||
47 | u8 i, pwrlevel[4]; | ||
48 | |||
49 | for (i = 0; i < 2; i++) | ||
50 | pwrlevel[i] = p_pwrlevel[i]; | ||
51 | |||
52 | /* We only care about the path A for legacy. */ | ||
53 | if (rtlefuse->eeprom_version < 2) { | ||
54 | pwrbase0 = pwrlevel[0] + (rtlefuse->legacy_httxpowerdiff & 0xf); | ||
55 | } else if (rtlefuse->eeprom_version >= 2) { | ||
56 | legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff | ||
57 | [RF90_PATH_A][chnl - 1]; | ||
58 | |||
59 | /* For legacy OFDM, tx pwr always > HT OFDM pwr. | ||
60 | * We do not care Path B | ||
61 | * legacy OFDM pwr diff. NO BB register | ||
62 | * to notify HW. */ | ||
63 | pwrbase0 = pwrlevel[0] + legacy_pwrdiff; | ||
64 | } | ||
65 | |||
66 | pwrbase0 = (pwrbase0 << 24) | (pwrbase0 << 16) | (pwrbase0 << 8) | | ||
67 | pwrbase0; | ||
68 | *ofdmbase = pwrbase0; | ||
69 | |||
70 | /* MCS rates */ | ||
71 | if (rtlefuse->eeprom_version >= 2) { | ||
72 | /* Check HT20 to HT40 diff */ | ||
73 | if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) { | ||
74 | for (i = 0; i < 2; i++) { | ||
75 | /* rf-A, rf-B */ | ||
76 | /* HT 20<->40 pwr diff */ | ||
77 | ht20_pwrdiff = rtlefuse->txpwr_ht20diff | ||
78 | [i][chnl - 1]; | ||
79 | |||
80 | if (ht20_pwrdiff < 8) /* 0~+7 */ | ||
81 | pwrlevel[i] += ht20_pwrdiff; | ||
82 | else /* index8-15=-8~-1 */ | ||
83 | pwrlevel[i] -= (16 - ht20_pwrdiff); | ||
84 | } | ||
85 | } | ||
86 | } | ||
87 | |||
88 | /* use index of rf-A */ | ||
89 | pwrbase1 = pwrlevel[0]; | ||
90 | pwrbase1 = (pwrbase1 << 24) | (pwrbase1 << 16) | (pwrbase1 << 8) | | ||
91 | pwrbase1; | ||
92 | *mcsbase = pwrbase1; | ||
93 | |||
94 | /* The following is for Antenna | ||
95 | * diff from Ant-B to Ant-A */ | ||
96 | p_final_pwridx[0] = pwrlevel[0]; | ||
97 | p_final_pwridx[1] = pwrlevel[1]; | ||
98 | |||
99 | switch (rtlefuse->eeprom_regulatory) { | ||
100 | case 3: | ||
101 | /* The following is for calculation | ||
102 | * of the power diff for Ant-B to Ant-A. */ | ||
103 | if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { | ||
104 | p_final_pwridx[0] += rtlefuse->pwrgroup_ht40 | ||
105 | [RF90_PATH_A][ | ||
106 | chnl - 1]; | ||
107 | p_final_pwridx[1] += rtlefuse->pwrgroup_ht40 | ||
108 | [RF90_PATH_B][ | ||
109 | chnl - 1]; | ||
110 | } else { | ||
111 | p_final_pwridx[0] += rtlefuse->pwrgroup_ht20 | ||
112 | [RF90_PATH_A][ | ||
113 | chnl - 1]; | ||
114 | p_final_pwridx[1] += rtlefuse->pwrgroup_ht20 | ||
115 | [RF90_PATH_B][ | ||
116 | chnl - 1]; | ||
117 | } | ||
118 | break; | ||
119 | default: | ||
120 | break; | ||
121 | } | ||
122 | |||
123 | if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { | ||
124 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("40MHz finalpwr_idx " | ||
125 | "(A / B) = 0x%x / 0x%x\n", p_final_pwridx[0], | ||
126 | p_final_pwridx[1])); | ||
127 | } else { | ||
128 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("20MHz finalpwr_idx " | ||
129 | "(A / B) = 0x%x / 0x%x\n", p_final_pwridx[0], | ||
130 | p_final_pwridx[1])); | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static void _rtl92s_set_antennadiff(struct ieee80211_hw *hw, | ||
135 | u8 *p_final_pwridx) | ||
136 | { | ||
137 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
138 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
139 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
140 | char ant_pwr_diff = 0; | ||
141 | u32 u4reg_val = 0; | ||
142 | |||
143 | if (rtlphy->rf_type == RF_2T2R) { | ||
144 | ant_pwr_diff = p_final_pwridx[1] - p_final_pwridx[0]; | ||
145 | |||
146 | /* range is from 7~-8, | ||
147 | * index = 0x0~0xf */ | ||
148 | if (ant_pwr_diff > 7) | ||
149 | ant_pwr_diff = 7; | ||
150 | if (ant_pwr_diff < -8) | ||
151 | ant_pwr_diff = -8; | ||
152 | |||
153 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
154 | ("Antenna Diff from RF-B " | ||
155 | "to RF-A = %d (0x%x)\n", ant_pwr_diff, | ||
156 | ant_pwr_diff & 0xf)); | ||
157 | |||
158 | ant_pwr_diff &= 0xf; | ||
159 | } | ||
160 | |||
161 | /* Antenna TX power difference */ | ||
162 | rtlefuse->antenna_txpwdiff[2] = 0;/* RF-D, don't care */ | ||
163 | rtlefuse->antenna_txpwdiff[1] = 0;/* RF-C, don't care */ | ||
164 | rtlefuse->antenna_txpwdiff[0] = (u8)(ant_pwr_diff); /* RF-B */ | ||
165 | |||
166 | u4reg_val = rtlefuse->antenna_txpwdiff[2] << 8 | | ||
167 | rtlefuse->antenna_txpwdiff[1] << 4 | | ||
168 | rtlefuse->antenna_txpwdiff[0]; | ||
169 | |||
170 | rtl_set_bbreg(hw, RFPGA0_TXGAINSTAGE, (BXBTXAGC | BXCTXAGC | BXDTXAGC), | ||
171 | u4reg_val); | ||
172 | |||
173 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
174 | ("Write BCD-Diff(0x%x) = 0x%x\n", | ||
175 | RFPGA0_TXGAINSTAGE, u4reg_val)); | ||
176 | } | ||
177 | |||
178 | static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw, | ||
179 | u8 chnl, u8 index, | ||
180 | u32 pwrbase0, | ||
181 | u32 pwrbase1, | ||
182 | u32 *p_outwrite_val) | ||
183 | { | ||
184 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
185 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
186 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
187 | u8 i, chnlgroup, pwrdiff_limit[4]; | ||
188 | u32 writeval, customer_limit; | ||
189 | |||
190 | /* Index 0 & 1= legacy OFDM, 2-5=HT_MCS rate */ | ||
191 | switch (rtlefuse->eeprom_regulatory) { | ||
192 | case 0: | ||
193 | /* Realtek better performance increase power diff | ||
194 | * defined by Realtek for large power */ | ||
195 | chnlgroup = 0; | ||
196 | |||
197 | writeval = rtlphy->mcs_txpwrlevel_origoffset | ||
198 | [chnlgroup][index] + | ||
199 | ((index < 2) ? pwrbase0 : pwrbase1); | ||
200 | |||
201 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
202 | ("RTK better performance, " | ||
203 | "writeval = 0x%x\n", writeval)); | ||
204 | break; | ||
205 | case 1: | ||
206 | /* Realtek regulatory increase power diff defined | ||
207 | * by Realtek for regulatory */ | ||
208 | if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { | ||
209 | writeval = ((index < 2) ? pwrbase0 : pwrbase1); | ||
210 | |||
211 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
212 | ("Realtek regulatory, " | ||
213 | "40MHz, writeval = 0x%x\n", writeval)); | ||
214 | } else { | ||
215 | if (rtlphy->pwrgroup_cnt == 1) | ||
216 | chnlgroup = 0; | ||
217 | |||
218 | if (rtlphy->pwrgroup_cnt >= 3) { | ||
219 | if (chnl <= 3) | ||
220 | chnlgroup = 0; | ||
221 | else if (chnl >= 4 && chnl <= 8) | ||
222 | chnlgroup = 1; | ||
223 | else if (chnl > 8) | ||
224 | chnlgroup = 2; | ||
225 | if (rtlphy->pwrgroup_cnt == 4) | ||
226 | chnlgroup++; | ||
227 | } | ||
228 | |||
229 | writeval = rtlphy->mcs_txpwrlevel_origoffset | ||
230 | [chnlgroup][index] | ||
231 | + ((index < 2) ? | ||
232 | pwrbase0 : pwrbase1); | ||
233 | |||
234 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
235 | ("Realtek regulatory, " | ||
236 | "20MHz, writeval = 0x%x\n", writeval)); | ||
237 | } | ||
238 | break; | ||
239 | case 2: | ||
240 | /* Better regulatory don't increase any power diff */ | ||
241 | writeval = ((index < 2) ? pwrbase0 : pwrbase1); | ||
242 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
243 | ("Better regulatory, " | ||
244 | "writeval = 0x%x\n", writeval)); | ||
245 | break; | ||
246 | case 3: | ||
247 | /* Customer defined power diff. increase power diff | ||
248 | defined by customer. */ | ||
249 | chnlgroup = 0; | ||
250 | |||
251 | if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40) { | ||
252 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
253 | ("customer's limit, 40MHz = 0x%x\n", | ||
254 | rtlefuse->pwrgroup_ht40 | ||
255 | [RF90_PATH_A][chnl - 1])); | ||
256 | } else { | ||
257 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
258 | ("customer's limit, 20MHz = 0x%x\n", | ||
259 | rtlefuse->pwrgroup_ht20 | ||
260 | [RF90_PATH_A][chnl - 1])); | ||
261 | } | ||
262 | |||
263 | for (i = 0; i < 4; i++) { | ||
264 | pwrdiff_limit[i] = | ||
265 | (u8)((rtlphy->mcs_txpwrlevel_origoffset | ||
266 | [chnlgroup][index] & (0x7f << (i * 8))) | ||
267 | >> (i * 8)); | ||
268 | |||
269 | if (rtlphy->current_chan_bw == | ||
270 | HT_CHANNEL_WIDTH_20_40) { | ||
271 | if (pwrdiff_limit[i] > | ||
272 | rtlefuse->pwrgroup_ht40 | ||
273 | [RF90_PATH_A][chnl - 1]) { | ||
274 | pwrdiff_limit[i] = | ||
275 | rtlefuse->pwrgroup_ht20 | ||
276 | [RF90_PATH_A][chnl - 1]; | ||
277 | } | ||
278 | } else { | ||
279 | if (pwrdiff_limit[i] > | ||
280 | rtlefuse->pwrgroup_ht20 | ||
281 | [RF90_PATH_A][chnl - 1]) { | ||
282 | pwrdiff_limit[i] = | ||
283 | rtlefuse->pwrgroup_ht20 | ||
284 | [RF90_PATH_A][chnl - 1]; | ||
285 | } | ||
286 | } | ||
287 | } | ||
288 | |||
289 | customer_limit = (pwrdiff_limit[3] << 24) | | ||
290 | (pwrdiff_limit[2] << 16) | | ||
291 | (pwrdiff_limit[1] << 8) | | ||
292 | (pwrdiff_limit[0]); | ||
293 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
294 | ("Customer's limit = 0x%x\n", | ||
295 | customer_limit)); | ||
296 | |||
297 | writeval = customer_limit + ((index < 2) ? | ||
298 | pwrbase0 : pwrbase1); | ||
299 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
300 | ("Customer, writeval = " | ||
301 | "0x%x\n", writeval)); | ||
302 | break; | ||
303 | default: | ||
304 | chnlgroup = 0; | ||
305 | writeval = rtlphy->mcs_txpwrlevel_origoffset[chnlgroup][index] + | ||
306 | ((index < 2) ? pwrbase0 : pwrbase1); | ||
307 | RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, | ||
308 | ("RTK better performance, " | ||
309 | "writeval = 0x%x\n", writeval)); | ||
310 | break; | ||
311 | } | ||
312 | |||
313 | if (rtlpriv->dm.dynamic_txhighpower_lvl == TX_HIGH_PWR_LEVEL_LEVEL1) | ||
314 | writeval = 0x10101010; | ||
315 | else if (rtlpriv->dm.dynamic_txhighpower_lvl == | ||
316 | TX_HIGH_PWR_LEVEL_LEVEL2) | ||
317 | writeval = 0x0; | ||
318 | |||
319 | *p_outwrite_val = writeval; | ||
320 | |||
321 | } | ||
322 | |||
323 | static void _rtl92s_write_ofdm_powerreg(struct ieee80211_hw *hw, | ||
324 | u8 index, u32 val) | ||
325 | { | ||
326 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
327 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
328 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
329 | u16 regoffset[6] = {0xe00, 0xe04, 0xe10, 0xe14, 0xe18, 0xe1c}; | ||
330 | u8 i, rfa_pwr[4]; | ||
331 | u8 rfa_lower_bound = 0, rfa_upper_bound = 0, rf_pwr_diff = 0; | ||
332 | u32 writeval = val; | ||
333 | |||
334 | /* If path A and Path B coexist, we must limit Path A tx power. | ||
335 | * Protect Path B pwr over or under flow. We need to calculate | ||
336 | * upper and lower bound of path A tx power. */ | ||
337 | if (rtlphy->rf_type == RF_2T2R) { | ||
338 | rf_pwr_diff = rtlefuse->antenna_txpwdiff[0]; | ||
339 | |||
340 | /* Diff=-8~-1 */ | ||
341 | if (rf_pwr_diff >= 8) { | ||
342 | /* Prevent underflow!! */ | ||
343 | rfa_lower_bound = 0x10 - rf_pwr_diff; | ||
344 | /* if (rf_pwr_diff >= 0) Diff = 0-7 */ | ||
345 | } else { | ||
346 | rfa_upper_bound = RF6052_MAX_TX_PWR - rf_pwr_diff; | ||
347 | } | ||
348 | } | ||
349 | |||
350 | for (i = 0; i < 4; i++) { | ||
351 | rfa_pwr[i] = (u8)((writeval & (0x7f << (i * 8))) >> (i * 8)); | ||
352 | if (rfa_pwr[i] > RF6052_MAX_TX_PWR) | ||
353 | rfa_pwr[i] = RF6052_MAX_TX_PWR; | ||
354 | |||
355 | /* If path A and Path B coexist, we must limit Path A tx power. | ||
356 | * Protect Path B pwr over or under flow. We need to calculate | ||
357 | * upper and lower bound of path A tx power. */ | ||
358 | if (rtlphy->rf_type == RF_2T2R) { | ||
359 | /* Diff=-8~-1 */ | ||
360 | if (rf_pwr_diff >= 8) { | ||
361 | /* Prevent underflow!! */ | ||
362 | if (rfa_pwr[i] < rfa_lower_bound) | ||
363 | rfa_pwr[i] = rfa_lower_bound; | ||
364 | /* Diff = 0-7 */ | ||
365 | } else if (rf_pwr_diff >= 1) { | ||
366 | /* Prevent overflow */ | ||
367 | if (rfa_pwr[i] > rfa_upper_bound) | ||
368 | rfa_pwr[i] = rfa_upper_bound; | ||
369 | } | ||
370 | } | ||
371 | |||
372 | } | ||
373 | |||
374 | writeval = (rfa_pwr[3] << 24) | (rfa_pwr[2] << 16) | (rfa_pwr[1] << 8) | | ||
375 | rfa_pwr[0]; | ||
376 | |||
377 | rtl_set_bbreg(hw, regoffset[index], 0x7f7f7f7f, writeval); | ||
378 | } | ||
379 | |||
380 | void rtl92s_phy_rf6052_set_ofdmtxpower(struct ieee80211_hw *hw, | ||
381 | u8 *p_pwrlevel, u8 chnl) | ||
382 | { | ||
383 | u32 writeval, pwrbase0, pwrbase1; | ||
384 | u8 index = 0; | ||
385 | u8 finalpwr_idx[4]; | ||
386 | |||
387 | _rtl92s_get_powerbase(hw, p_pwrlevel, chnl, &pwrbase0, &pwrbase1, | ||
388 | &finalpwr_idx[0]); | ||
389 | _rtl92s_set_antennadiff(hw, &finalpwr_idx[0]); | ||
390 | |||
391 | for (index = 0; index < 6; index++) { | ||
392 | _rtl92s_get_txpower_writeval_byregulatory(hw, chnl, index, | ||
393 | pwrbase0, pwrbase1, &writeval); | ||
394 | |||
395 | _rtl92s_write_ofdm_powerreg(hw, index, writeval); | ||
396 | } | ||
397 | } | ||
398 | |||
399 | void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, u8 pwrlevel) | ||
400 | { | ||
401 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
402 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
403 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
404 | u32 txagc = 0; | ||
405 | bool dont_inc_cck_or_turboscanoff = false; | ||
406 | |||
407 | if (((rtlefuse->eeprom_version >= 2) && | ||
408 | (rtlefuse->txpwr_safetyflag == 1)) || | ||
409 | ((rtlefuse->eeprom_version >= 2) && | ||
410 | (rtlefuse->eeprom_regulatory != 0))) | ||
411 | dont_inc_cck_or_turboscanoff = true; | ||
412 | |||
413 | if (mac->act_scanning == true) { | ||
414 | txagc = 0x3f; | ||
415 | if (dont_inc_cck_or_turboscanoff) | ||
416 | txagc = pwrlevel; | ||
417 | } else { | ||
418 | txagc = pwrlevel; | ||
419 | |||
420 | if (rtlpriv->dm.dynamic_txhighpower_lvl == | ||
421 | TX_HIGH_PWR_LEVEL_LEVEL1) | ||
422 | txagc = 0x10; | ||
423 | else if (rtlpriv->dm.dynamic_txhighpower_lvl == | ||
424 | TX_HIGH_PWR_LEVEL_LEVEL2) | ||
425 | txagc = 0x0; | ||
426 | } | ||
427 | |||
428 | if (txagc > RF6052_MAX_TX_PWR) | ||
429 | txagc = RF6052_MAX_TX_PWR; | ||
430 | |||
431 | rtl_set_bbreg(hw, RTXAGC_CCK_MCS32, BTX_AGCRATECCK, txagc); | ||
432 | |||
433 | } | ||
434 | |||
435 | bool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw) | ||
436 | { | ||
437 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
438 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
439 | u32 u4reg_val = 0; | ||
440 | u8 rfpath; | ||
441 | bool rtstatus = true; | ||
442 | struct bb_reg_def *pphyreg; | ||
443 | |||
444 | /* Initialize RF */ | ||
445 | for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) { | ||
446 | |||
447 | pphyreg = &rtlphy->phyreg_def[rfpath]; | ||
448 | |||
449 | /* Store original RFENV control type */ | ||
450 | switch (rfpath) { | ||
451 | case RF90_PATH_A: | ||
452 | case RF90_PATH_C: | ||
453 | u4reg_val = rtl92s_phy_query_bb_reg(hw, | ||
454 | pphyreg->rfintfs, | ||
455 | BRFSI_RFENV); | ||
456 | break; | ||
457 | case RF90_PATH_B: | ||
458 | case RF90_PATH_D: | ||
459 | u4reg_val = rtl92s_phy_query_bb_reg(hw, | ||
460 | pphyreg->rfintfs, | ||
461 | BRFSI_RFENV << 16); | ||
462 | break; | ||
463 | } | ||
464 | |||
465 | /* Set RF_ENV enable */ | ||
466 | rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfe, | ||
467 | BRFSI_RFENV << 16, 0x1); | ||
468 | |||
469 | /* Set RF_ENV output high */ | ||
470 | rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1); | ||
471 | |||
472 | /* Set bit number of Address and Data for RF register */ | ||
473 | rtl92s_phy_set_bb_reg(hw, pphyreg->rfhssi_para2, | ||
474 | B3WIRE_ADDRESSLENGTH, 0x0); | ||
475 | rtl92s_phy_set_bb_reg(hw, pphyreg->rfhssi_para2, | ||
476 | B3WIRE_DATALENGTH, 0x0); | ||
477 | |||
478 | /* Initialize RF fom connfiguration file */ | ||
479 | switch (rfpath) { | ||
480 | case RF90_PATH_A: | ||
481 | rtstatus = rtl92s_phy_config_rf(hw, | ||
482 | (enum radio_path)rfpath); | ||
483 | break; | ||
484 | case RF90_PATH_B: | ||
485 | rtstatus = rtl92s_phy_config_rf(hw, | ||
486 | (enum radio_path)rfpath); | ||
487 | break; | ||
488 | case RF90_PATH_C: | ||
489 | break; | ||
490 | case RF90_PATH_D: | ||
491 | break; | ||
492 | } | ||
493 | |||
494 | /* Restore RFENV control type */ | ||
495 | switch (rfpath) { | ||
496 | case RF90_PATH_A: | ||
497 | case RF90_PATH_C: | ||
498 | rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfs, BRFSI_RFENV, | ||
499 | u4reg_val); | ||
500 | break; | ||
501 | case RF90_PATH_B: | ||
502 | case RF90_PATH_D: | ||
503 | rtl92s_phy_set_bb_reg(hw, pphyreg->rfintfs, | ||
504 | BRFSI_RFENV << 16, | ||
505 | u4reg_val); | ||
506 | break; | ||
507 | } | ||
508 | |||
509 | if (rtstatus != true) { | ||
510 | printk(KERN_ERR "Radio[%d] Fail!!", rfpath); | ||
511 | goto fail; | ||
512 | } | ||
513 | |||
514 | } | ||
515 | |||
516 | return rtstatus; | ||
517 | |||
518 | fail: | ||
519 | return rtstatus; | ||
520 | } | ||
521 | |||
522 | void rtl92s_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth) | ||
523 | { | ||
524 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
525 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
526 | |||
527 | switch (bandwidth) { | ||
528 | case HT_CHANNEL_WIDTH_20: | ||
529 | rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & | ||
530 | 0xfffff3ff) | 0x0400); | ||
531 | rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, | ||
532 | rtlphy->rfreg_chnlval[0]); | ||
533 | break; | ||
534 | case HT_CHANNEL_WIDTH_20_40: | ||
535 | rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] & | ||
536 | 0xfffff3ff)); | ||
537 | rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK, | ||
538 | rtlphy->rfreg_chnlval[0]); | ||
539 | break; | ||
540 | default: | ||
541 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
542 | ("unknown bandwidth: %#X\n", | ||
543 | bandwidth)); | ||
544 | break; | ||
545 | } | ||
546 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.h b/drivers/net/wireless/rtlwifi/rtl8192se/rf.h new file mode 100644 index 000000000000..3843baa1a874 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/rf.h | |||
@@ -0,0 +1,43 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | #ifndef __INC_RTL92S_RF_H | ||
30 | #define __INC_RTL92S_RF_H | ||
31 | |||
32 | #define RF6052_MAX_TX_PWR 0x3F | ||
33 | |||
34 | void rtl92s_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, | ||
35 | u8 bandwidth); | ||
36 | bool rtl92s_phy_rf6052_config(struct ieee80211_hw *hw) ; | ||
37 | void rtl92s_phy_rf6052_set_ccktxpower(struct ieee80211_hw *hw, | ||
38 | u8 powerlevel); | ||
39 | void rtl92s_phy_rf6052_set_ofdmtxpower(struct ieee80211_hw *hw, | ||
40 | u8 *p_pwrlevel, u8 chnl); | ||
41 | |||
42 | #endif | ||
43 | |||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c new file mode 100644 index 000000000000..1c6cb1d7d660 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c | |||
@@ -0,0 +1,423 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include <linux/vmalloc.h> | ||
31 | |||
32 | #include "../wifi.h" | ||
33 | #include "../core.h" | ||
34 | #include "../pci.h" | ||
35 | #include "reg.h" | ||
36 | #include "def.h" | ||
37 | #include "phy.h" | ||
38 | #include "dm.h" | ||
39 | #include "fw.h" | ||
40 | #include "hw.h" | ||
41 | #include "sw.h" | ||
42 | #include "trx.h" | ||
43 | #include "led.h" | ||
44 | |||
45 | static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw) | ||
46 | { | ||
47 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
48 | |||
49 | /*close ASPM for AMD defaultly */ | ||
50 | rtlpci->const_amdpci_aspm = 0; | ||
51 | |||
52 | /* | ||
53 | * ASPM PS mode. | ||
54 | * 0 - Disable ASPM, | ||
55 | * 1 - Enable ASPM without Clock Req, | ||
56 | * 2 - Enable ASPM with Clock Req, | ||
57 | * 3 - Alwyas Enable ASPM with Clock Req, | ||
58 | * 4 - Always Enable ASPM without Clock Req. | ||
59 | * set defult to RTL8192CE:3 RTL8192E:2 | ||
60 | * */ | ||
61 | rtlpci->const_pci_aspm = 2; | ||
62 | |||
63 | /*Setting for PCI-E device */ | ||
64 | rtlpci->const_devicepci_aspm_setting = 0x03; | ||
65 | |||
66 | /*Setting for PCI-E bridge */ | ||
67 | rtlpci->const_hostpci_aspm_setting = 0x02; | ||
68 | |||
69 | /* | ||
70 | * In Hw/Sw Radio Off situation. | ||
71 | * 0 - Default, | ||
72 | * 1 - From ASPM setting without low Mac Pwr, | ||
73 | * 2 - From ASPM setting with low Mac Pwr, | ||
74 | * 3 - Bus D3 | ||
75 | * set default to RTL8192CE:0 RTL8192SE:2 | ||
76 | */ | ||
77 | rtlpci->const_hwsw_rfoff_d3 = 2; | ||
78 | |||
79 | /* | ||
80 | * This setting works for those device with | ||
81 | * backdoor ASPM setting such as EPHY setting. | ||
82 | * 0 - Not support ASPM, | ||
83 | * 1 - Support ASPM, | ||
84 | * 2 - According to chipset. | ||
85 | */ | ||
86 | rtlpci->const_support_pciaspm = 2; | ||
87 | } | ||
88 | |||
89 | static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) | ||
90 | { | ||
91 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
92 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
93 | const struct firmware *firmware; | ||
94 | struct rt_firmware *pfirmware = NULL; | ||
95 | int err = 0; | ||
96 | u16 earlyrxthreshold = 7; | ||
97 | |||
98 | rtlpriv->dm.dm_initialgain_enable = 1; | ||
99 | rtlpriv->dm.dm_flag = 0; | ||
100 | rtlpriv->dm.disable_framebursting = 0; | ||
101 | rtlpriv->dm.thermalvalue = 0; | ||
102 | rtlpriv->dm.useramask = true; | ||
103 | |||
104 | /* compatible 5G band 91se just 2.4G band & smsp */ | ||
105 | rtlpriv->rtlhal.current_bandtype = BAND_ON_2_4G; | ||
106 | rtlpriv->rtlhal.bandset = BAND_ON_2_4G; | ||
107 | rtlpriv->rtlhal.macphymode = SINGLEMAC_SINGLEPHY; | ||
108 | |||
109 | rtlpci->transmit_config = 0; | ||
110 | |||
111 | rtlpci->receive_config = | ||
112 | RCR_APPFCS | | ||
113 | RCR_APWRMGT | | ||
114 | /*RCR_ADD3 |*/ | ||
115 | RCR_AMF | | ||
116 | RCR_ADF | | ||
117 | RCR_APP_MIC | | ||
118 | RCR_APP_ICV | | ||
119 | RCR_AICV | | ||
120 | /* Accept ICV error, CRC32 Error */ | ||
121 | RCR_ACRC32 | | ||
122 | RCR_AB | | ||
123 | /* Accept Broadcast, Multicast */ | ||
124 | RCR_AM | | ||
125 | /* Accept Physical match */ | ||
126 | RCR_APM | | ||
127 | /* Accept Destination Address packets */ | ||
128 | /*RCR_AAP |*/ | ||
129 | RCR_APP_PHYST_STAFF | | ||
130 | /* Accept PHY status */ | ||
131 | RCR_APP_PHYST_RXFF | | ||
132 | (earlyrxthreshold << RCR_FIFO_OFFSET); | ||
133 | |||
134 | rtlpci->irq_mask[0] = (u32) | ||
135 | (IMR_ROK | | ||
136 | IMR_VODOK | | ||
137 | IMR_VIDOK | | ||
138 | IMR_BEDOK | | ||
139 | IMR_BKDOK | | ||
140 | IMR_HCCADOK | | ||
141 | IMR_MGNTDOK | | ||
142 | IMR_COMDOK | | ||
143 | IMR_HIGHDOK | | ||
144 | IMR_BDOK | | ||
145 | IMR_RXCMDOK | | ||
146 | /*IMR_TIMEOUT0 |*/ | ||
147 | IMR_RDU | | ||
148 | IMR_RXFOVW | | ||
149 | IMR_BCNINT | ||
150 | /*| IMR_TXFOVW*/ | ||
151 | /*| IMR_TBDOK | | ||
152 | IMR_TBDER*/); | ||
153 | |||
154 | rtlpci->irq_mask[1] = (u32) 0; | ||
155 | |||
156 | rtlpci->shortretry_limit = 0x30; | ||
157 | rtlpci->longretry_limit = 0x30; | ||
158 | |||
159 | rtlpci->first_init = true; | ||
160 | |||
161 | /* for LPS & IPS */ | ||
162 | rtlpriv->psc.inactiveps = rtlpriv->cfg->mod_params->inactiveps; | ||
163 | rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps; | ||
164 | rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps; | ||
165 | rtlpriv->psc.reg_fwctrl_lps = 3; | ||
166 | rtlpriv->psc.reg_max_lps_awakeintvl = 5; | ||
167 | /* for ASPM, you can close aspm through | ||
168 | * set const_support_pciaspm = 0 */ | ||
169 | rtl92s_init_aspm_vars(hw); | ||
170 | |||
171 | if (rtlpriv->psc.reg_fwctrl_lps == 1) | ||
172 | rtlpriv->psc.fwctrl_psmode = FW_PS_MIN_MODE; | ||
173 | else if (rtlpriv->psc.reg_fwctrl_lps == 2) | ||
174 | rtlpriv->psc.fwctrl_psmode = FW_PS_MAX_MODE; | ||
175 | else if (rtlpriv->psc.reg_fwctrl_lps == 3) | ||
176 | rtlpriv->psc.fwctrl_psmode = FW_PS_DTIM_MODE; | ||
177 | |||
178 | /* for firmware buf */ | ||
179 | rtlpriv->rtlhal.pfirmware = vzalloc(sizeof(struct rt_firmware)); | ||
180 | if (!rtlpriv->rtlhal.pfirmware) { | ||
181 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
182 | ("Can't alloc buffer for fw.\n")); | ||
183 | return 1; | ||
184 | } | ||
185 | |||
186 | printk(KERN_INFO "rtl8192se: Driver for Realtek RTL8192SE/RTL8191SE\n" | ||
187 | " Loading firmware %s\n", rtlpriv->cfg->fw_name); | ||
188 | /* request fw */ | ||
189 | err = request_firmware(&firmware, rtlpriv->cfg->fw_name, | ||
190 | rtlpriv->io.dev); | ||
191 | if (err) { | ||
192 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
193 | ("Failed to request firmware!\n")); | ||
194 | return 1; | ||
195 | } | ||
196 | if (firmware->size > sizeof(struct rt_firmware)) { | ||
197 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
198 | ("Firmware is too big!\n")); | ||
199 | release_firmware(firmware); | ||
200 | return 1; | ||
201 | } | ||
202 | |||
203 | pfirmware = (struct rt_firmware *)rtlpriv->rtlhal.pfirmware; | ||
204 | memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size); | ||
205 | pfirmware->sz_fw_tmpbufferlen = firmware->size; | ||
206 | release_firmware(firmware); | ||
207 | |||
208 | return err; | ||
209 | } | ||
210 | |||
211 | static void rtl92s_deinit_sw_vars(struct ieee80211_hw *hw) | ||
212 | { | ||
213 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
214 | |||
215 | if (rtlpriv->rtlhal.pfirmware) { | ||
216 | vfree(rtlpriv->rtlhal.pfirmware); | ||
217 | rtlpriv->rtlhal.pfirmware = NULL; | ||
218 | } | ||
219 | } | ||
220 | |||
221 | static struct rtl_hal_ops rtl8192se_hal_ops = { | ||
222 | .init_sw_vars = rtl92s_init_sw_vars, | ||
223 | .deinit_sw_vars = rtl92s_deinit_sw_vars, | ||
224 | .read_eeprom_info = rtl92se_read_eeprom_info, | ||
225 | .interrupt_recognized = rtl92se_interrupt_recognized, | ||
226 | .hw_init = rtl92se_hw_init, | ||
227 | .hw_disable = rtl92se_card_disable, | ||
228 | .hw_suspend = rtl92se_suspend, | ||
229 | .hw_resume = rtl92se_resume, | ||
230 | .enable_interrupt = rtl92se_enable_interrupt, | ||
231 | .disable_interrupt = rtl92se_disable_interrupt, | ||
232 | .set_network_type = rtl92se_set_network_type, | ||
233 | .set_chk_bssid = rtl92se_set_check_bssid, | ||
234 | .set_qos = rtl92se_set_qos, | ||
235 | .set_bcn_reg = rtl92se_set_beacon_related_registers, | ||
236 | .set_bcn_intv = rtl92se_set_beacon_interval, | ||
237 | .update_interrupt_mask = rtl92se_update_interrupt_mask, | ||
238 | .get_hw_reg = rtl92se_get_hw_reg, | ||
239 | .set_hw_reg = rtl92se_set_hw_reg, | ||
240 | .update_rate_tbl = rtl92se_update_hal_rate_tbl, | ||
241 | .fill_tx_desc = rtl92se_tx_fill_desc, | ||
242 | .fill_tx_cmddesc = rtl92se_tx_fill_cmddesc, | ||
243 | .query_rx_desc = rtl92se_rx_query_desc, | ||
244 | .set_channel_access = rtl92se_update_channel_access_setting, | ||
245 | .radio_onoff_checking = rtl92se_gpio_radio_on_off_checking, | ||
246 | .set_bw_mode = rtl92s_phy_set_bw_mode, | ||
247 | .switch_channel = rtl92s_phy_sw_chnl, | ||
248 | .dm_watchdog = rtl92s_dm_watchdog, | ||
249 | .scan_operation_backup = rtl92s_phy_scan_operation_backup, | ||
250 | .set_rf_power_state = rtl92s_phy_set_rf_power_state, | ||
251 | .led_control = rtl92se_led_control, | ||
252 | .set_desc = rtl92se_set_desc, | ||
253 | .get_desc = rtl92se_get_desc, | ||
254 | .tx_polling = rtl92se_tx_polling, | ||
255 | .enable_hw_sec = rtl92se_enable_hw_security_config, | ||
256 | .set_key = rtl92se_set_key, | ||
257 | .init_sw_leds = rtl92se_init_sw_leds, | ||
258 | .get_bbreg = rtl92s_phy_query_bb_reg, | ||
259 | .set_bbreg = rtl92s_phy_set_bb_reg, | ||
260 | .get_rfreg = rtl92s_phy_query_rf_reg, | ||
261 | .set_rfreg = rtl92s_phy_set_rf_reg, | ||
262 | }; | ||
263 | |||
264 | static struct rtl_mod_params rtl92se_mod_params = { | ||
265 | .sw_crypto = false, | ||
266 | .inactiveps = true, | ||
267 | .swctrl_lps = true, | ||
268 | .fwctrl_lps = false, | ||
269 | }; | ||
270 | |||
271 | /* Because memory R/W bursting will cause system hang/crash | ||
272 | * for 92se, so we don't read back after every write action */ | ||
273 | static struct rtl_hal_cfg rtl92se_hal_cfg = { | ||
274 | .bar_id = 1, | ||
275 | .write_readback = false, | ||
276 | .name = "rtl92s_pci", | ||
277 | .fw_name = "rtlwifi/rtl8192sefw.bin", | ||
278 | .ops = &rtl8192se_hal_ops, | ||
279 | .mod_params = &rtl92se_mod_params, | ||
280 | |||
281 | .maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL, | ||
282 | .maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN, | ||
283 | .maps[SYS_CLK] = SYS_CLKR, | ||
284 | .maps[MAC_RCR_AM] = RCR_AM, | ||
285 | .maps[MAC_RCR_AB] = RCR_AB, | ||
286 | .maps[MAC_RCR_ACRC32] = RCR_ACRC32, | ||
287 | .maps[MAC_RCR_ACF] = RCR_ACF, | ||
288 | .maps[MAC_RCR_AAP] = RCR_AAP, | ||
289 | |||
290 | .maps[EFUSE_TEST] = REG_EFUSE_TEST, | ||
291 | .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, | ||
292 | .maps[EFUSE_CLK] = REG_EFUSE_CLK, | ||
293 | .maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL, | ||
294 | .maps[EFUSE_PWC_EV12V] = 0, /* nouse for 8192se */ | ||
295 | .maps[EFUSE_FEN_ELDR] = 0, /* nouse for 8192se */ | ||
296 | .maps[EFUSE_LOADER_CLK_EN] = 0,/* nouse for 8192se */ | ||
297 | .maps[EFUSE_ANA8M] = EFUSE_ANA8M, | ||
298 | .maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE_92S, | ||
299 | .maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION, | ||
300 | .maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN, | ||
301 | |||
302 | .maps[RWCAM] = REG_RWCAM, | ||
303 | .maps[WCAMI] = REG_WCAMI, | ||
304 | .maps[RCAMO] = REG_RCAMO, | ||
305 | .maps[CAMDBG] = REG_CAMDBG, | ||
306 | .maps[SECR] = REG_SECR, | ||
307 | .maps[SEC_CAM_NONE] = CAM_NONE, | ||
308 | .maps[SEC_CAM_WEP40] = CAM_WEP40, | ||
309 | .maps[SEC_CAM_TKIP] = CAM_TKIP, | ||
310 | .maps[SEC_CAM_AES] = CAM_AES, | ||
311 | .maps[SEC_CAM_WEP104] = CAM_WEP104, | ||
312 | |||
313 | .maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6, | ||
314 | .maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5, | ||
315 | .maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4, | ||
316 | .maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3, | ||
317 | .maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2, | ||
318 | .maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1, | ||
319 | .maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8, | ||
320 | .maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7, | ||
321 | .maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6, | ||
322 | .maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5, | ||
323 | .maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4, | ||
324 | .maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3, | ||
325 | .maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2, | ||
326 | .maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1, | ||
327 | .maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2, | ||
328 | .maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1, | ||
329 | |||
330 | .maps[RTL_IMR_TXFOVW] = IMR_TXFOVW, | ||
331 | .maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT, | ||
332 | .maps[RTL_IMR_BcnInt] = IMR_BCNINT, | ||
333 | .maps[RTL_IMR_RXFOVW] = IMR_RXFOVW, | ||
334 | .maps[RTL_IMR_RDU] = IMR_RDU, | ||
335 | .maps[RTL_IMR_ATIMEND] = IMR_ATIMEND, | ||
336 | .maps[RTL_IMR_BDOK] = IMR_BDOK, | ||
337 | .maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK, | ||
338 | .maps[RTL_IMR_TBDER] = IMR_TBDER, | ||
339 | .maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK, | ||
340 | .maps[RTL_IMR_COMDOK] = IMR_COMDOK, | ||
341 | .maps[RTL_IMR_TBDOK] = IMR_TBDOK, | ||
342 | .maps[RTL_IMR_BKDOK] = IMR_BKDOK, | ||
343 | .maps[RTL_IMR_BEDOK] = IMR_BEDOK, | ||
344 | .maps[RTL_IMR_VIDOK] = IMR_VIDOK, | ||
345 | .maps[RTL_IMR_VODOK] = IMR_VODOK, | ||
346 | .maps[RTL_IMR_ROK] = IMR_ROK, | ||
347 | .maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER), | ||
348 | |||
349 | .maps[RTL_RC_CCK_RATE1M] = DESC92S_RATE1M, | ||
350 | .maps[RTL_RC_CCK_RATE2M] = DESC92S_RATE2M, | ||
351 | .maps[RTL_RC_CCK_RATE5_5M] = DESC92S_RATE5_5M, | ||
352 | .maps[RTL_RC_CCK_RATE11M] = DESC92S_RATE11M, | ||
353 | .maps[RTL_RC_OFDM_RATE6M] = DESC92S_RATE6M, | ||
354 | .maps[RTL_RC_OFDM_RATE9M] = DESC92S_RATE9M, | ||
355 | .maps[RTL_RC_OFDM_RATE12M] = DESC92S_RATE12M, | ||
356 | .maps[RTL_RC_OFDM_RATE18M] = DESC92S_RATE18M, | ||
357 | .maps[RTL_RC_OFDM_RATE24M] = DESC92S_RATE24M, | ||
358 | .maps[RTL_RC_OFDM_RATE36M] = DESC92S_RATE36M, | ||
359 | .maps[RTL_RC_OFDM_RATE48M] = DESC92S_RATE48M, | ||
360 | .maps[RTL_RC_OFDM_RATE54M] = DESC92S_RATE54M, | ||
361 | |||
362 | .maps[RTL_RC_HT_RATEMCS7] = DESC92S_RATEMCS7, | ||
363 | .maps[RTL_RC_HT_RATEMCS15] = DESC92S_RATEMCS15, | ||
364 | }; | ||
365 | |||
366 | static struct pci_device_id rtl92se_pci_ids[] __devinitdata = { | ||
367 | {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8192, rtl92se_hal_cfg)}, | ||
368 | {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8171, rtl92se_hal_cfg)}, | ||
369 | {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8172, rtl92se_hal_cfg)}, | ||
370 | {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8173, rtl92se_hal_cfg)}, | ||
371 | {RTL_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8174, rtl92se_hal_cfg)}, | ||
372 | {}, | ||
373 | }; | ||
374 | |||
375 | MODULE_DEVICE_TABLE(pci, rtl92se_pci_ids); | ||
376 | |||
377 | MODULE_AUTHOR("lizhaoming <chaoming_li@realsil.com.cn>"); | ||
378 | MODULE_AUTHOR("Realtek WlanFAE <wlanfae@realtek.com>"); | ||
379 | MODULE_LICENSE("GPL"); | ||
380 | MODULE_DESCRIPTION("Realtek 8192S/8191S 802.11n PCI wireless"); | ||
381 | MODULE_FIRMWARE("rtlwifi/rtl8192sefw.bin"); | ||
382 | |||
383 | module_param_named(swenc, rtl92se_mod_params.sw_crypto, bool, 0444); | ||
384 | module_param_named(ips, rtl92se_mod_params.inactiveps, bool, 0444); | ||
385 | module_param_named(swlps, rtl92se_mod_params.swctrl_lps, bool, 0444); | ||
386 | module_param_named(fwlps, rtl92se_mod_params.fwctrl_lps, bool, 0444); | ||
387 | MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n"); | ||
388 | MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n"); | ||
389 | MODULE_PARM_DESC(swlps, "using linked sw control power save (default 1 is " | ||
390 | "open)\n"); | ||
391 | |||
392 | |||
393 | static struct pci_driver rtl92se_driver = { | ||
394 | .name = KBUILD_MODNAME, | ||
395 | .id_table = rtl92se_pci_ids, | ||
396 | .probe = rtl_pci_probe, | ||
397 | .remove = rtl_pci_disconnect, | ||
398 | |||
399 | #ifdef CONFIG_PM | ||
400 | .suspend = rtl_pci_suspend, | ||
401 | .resume = rtl_pci_resume, | ||
402 | #endif | ||
403 | |||
404 | }; | ||
405 | |||
406 | static int __init rtl92se_module_init(void) | ||
407 | { | ||
408 | int ret = 0; | ||
409 | |||
410 | ret = pci_register_driver(&rtl92se_driver); | ||
411 | if (ret) | ||
412 | RT_ASSERT(false, (": No device found\n")); | ||
413 | |||
414 | return ret; | ||
415 | } | ||
416 | |||
417 | static void __exit rtl92se_module_exit(void) | ||
418 | { | ||
419 | pci_unregister_driver(&rtl92se_driver); | ||
420 | } | ||
421 | |||
422 | module_init(rtl92se_module_init); | ||
423 | module_exit(rtl92se_module_exit); | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.h b/drivers/net/wireless/rtlwifi/rtl8192se/sw.h new file mode 100644 index 000000000000..fc4eb285a0ac --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.h | |||
@@ -0,0 +1,36 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | *****************************************************************************/ | ||
27 | #ifndef __REALTEK_PCI92SE_SW_H__ | ||
28 | #define __REALTEK_PCI92SE_SW_H__ | ||
29 | |||
30 | #define EFUSE_MAX_SECTION 16 | ||
31 | |||
32 | int rtl92se_init_sw(struct ieee80211_hw *hw); | ||
33 | void rtl92se_deinit_sw(struct ieee80211_hw *hw); | ||
34 | void rtl92se_init_var_map(struct ieee80211_hw *hw); | ||
35 | |||
36 | #endif | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/table.c b/drivers/net/wireless/rtlwifi/rtl8192se/table.c new file mode 100644 index 000000000000..154185b3969d --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/table.c | |||
@@ -0,0 +1,634 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | * Created on 2010/ 5/18, 1:41 | ||
29 | *****************************************************************************/ | ||
30 | |||
31 | #include "table.h" | ||
32 | |||
33 | u32 rtl8192sephy_reg_2t2rarray[PHY_REG_2T2RARRAYLENGTH] = { | ||
34 | 0x01c, 0x07000000, | ||
35 | 0x800, 0x00040000, | ||
36 | 0x804, 0x00008003, | ||
37 | 0x808, 0x0000fc00, | ||
38 | 0x80c, 0x0000000a, | ||
39 | 0x810, 0x10005088, | ||
40 | 0x814, 0x020c3d10, | ||
41 | 0x818, 0x00200185, | ||
42 | 0x81c, 0x00000000, | ||
43 | 0x820, 0x01000000, | ||
44 | 0x824, 0x00390004, | ||
45 | 0x828, 0x01000000, | ||
46 | 0x82c, 0x00390004, | ||
47 | 0x830, 0x00000004, | ||
48 | 0x834, 0x00690200, | ||
49 | 0x838, 0x00000004, | ||
50 | 0x83c, 0x00690200, | ||
51 | 0x840, 0x00010000, | ||
52 | 0x844, 0x00010000, | ||
53 | 0x848, 0x00000000, | ||
54 | 0x84c, 0x00000000, | ||
55 | 0x850, 0x00000000, | ||
56 | 0x854, 0x00000000, | ||
57 | 0x858, 0x48484848, | ||
58 | 0x85c, 0x65a965a9, | ||
59 | 0x860, 0x0f7f0130, | ||
60 | 0x864, 0x0f7f0130, | ||
61 | 0x868, 0x0f7f0130, | ||
62 | 0x86c, 0x0f7f0130, | ||
63 | 0x870, 0x03000700, | ||
64 | 0x874, 0x03000300, | ||
65 | 0x878, 0x00020002, | ||
66 | 0x87c, 0x004f0201, | ||
67 | 0x880, 0xa8300ac1, | ||
68 | 0x884, 0x00000058, | ||
69 | 0x888, 0x00000008, | ||
70 | 0x88c, 0x00000004, | ||
71 | 0x890, 0x00000000, | ||
72 | 0x894, 0xfffffffe, | ||
73 | 0x898, 0x40302010, | ||
74 | 0x89c, 0x00706050, | ||
75 | 0x8b0, 0x00000000, | ||
76 | 0x8e0, 0x00000000, | ||
77 | 0x8e4, 0x00000000, | ||
78 | 0xe00, 0x30333333, | ||
79 | 0xe04, 0x2a2d2e2f, | ||
80 | 0xe08, 0x00003232, | ||
81 | 0xe10, 0x30333333, | ||
82 | 0xe14, 0x2a2d2e2f, | ||
83 | 0xe18, 0x30333333, | ||
84 | 0xe1c, 0x2a2d2e2f, | ||
85 | 0xe30, 0x01007c00, | ||
86 | 0xe34, 0x01004800, | ||
87 | 0xe38, 0x1000dc1f, | ||
88 | 0xe3c, 0x10008c1f, | ||
89 | 0xe40, 0x021400a0, | ||
90 | 0xe44, 0x281600a0, | ||
91 | 0xe48, 0xf8000001, | ||
92 | 0xe4c, 0x00002910, | ||
93 | 0xe50, 0x01007c00, | ||
94 | 0xe54, 0x01004800, | ||
95 | 0xe58, 0x1000dc1f, | ||
96 | 0xe5c, 0x10008c1f, | ||
97 | 0xe60, 0x021400a0, | ||
98 | 0xe64, 0x281600a0, | ||
99 | 0xe6c, 0x00002910, | ||
100 | 0xe70, 0x31ed92fb, | ||
101 | 0xe74, 0x361536fb, | ||
102 | 0xe78, 0x361536fb, | ||
103 | 0xe7c, 0x361536fb, | ||
104 | 0xe80, 0x361536fb, | ||
105 | 0xe84, 0x000d92fb, | ||
106 | 0xe88, 0x000d92fb, | ||
107 | 0xe8c, 0x31ed92fb, | ||
108 | 0xed0, 0x31ed92fb, | ||
109 | 0xed4, 0x31ed92fb, | ||
110 | 0xed8, 0x000d92fb, | ||
111 | 0xedc, 0x000d92fb, | ||
112 | 0xee0, 0x000d92fb, | ||
113 | 0xee4, 0x015e5448, | ||
114 | 0xee8, 0x21555448, | ||
115 | 0x900, 0x00000000, | ||
116 | 0x904, 0x00000023, | ||
117 | 0x908, 0x00000000, | ||
118 | 0x90c, 0x01121313, | ||
119 | 0xa00, 0x00d047c8, | ||
120 | 0xa04, 0x80ff0008, | ||
121 | 0xa08, 0x8ccd8300, | ||
122 | 0xa0c, 0x2e62120f, | ||
123 | 0xa10, 0x9500bb78, | ||
124 | 0xa14, 0x11144028, | ||
125 | 0xa18, 0x00881117, | ||
126 | 0xa1c, 0x89140f00, | ||
127 | 0xa20, 0x1a1b0000, | ||
128 | 0xa24, 0x090e1317, | ||
129 | 0xa28, 0x00000204, | ||
130 | 0xa2c, 0x10d30000, | ||
131 | 0xc00, 0x40071d40, | ||
132 | 0xc04, 0x00a05633, | ||
133 | 0xc08, 0x000000e4, | ||
134 | 0xc0c, 0x6c6c6c6c, | ||
135 | 0xc10, 0x08800000, | ||
136 | 0xc14, 0x40000100, | ||
137 | 0xc18, 0x08000000, | ||
138 | 0xc1c, 0x40000100, | ||
139 | 0xc20, 0x08000000, | ||
140 | 0xc24, 0x40000100, | ||
141 | 0xc28, 0x08000000, | ||
142 | 0xc2c, 0x40000100, | ||
143 | 0xc30, 0x6de9ac44, | ||
144 | 0xc34, 0x469652cf, | ||
145 | 0xc38, 0x49795994, | ||
146 | 0xc3c, 0x0a979764, | ||
147 | 0xc40, 0x1f7c403f, | ||
148 | 0xc44, 0x000100b7, | ||
149 | 0xc48, 0xec020000, | ||
150 | 0xc4c, 0x007f037f, | ||
151 | 0xc50, 0x69543420, | ||
152 | 0xc54, 0x433c0094, | ||
153 | 0xc58, 0x69543420, | ||
154 | 0xc5c, 0x433c0094, | ||
155 | 0xc60, 0x69543420, | ||
156 | 0xc64, 0x433c0094, | ||
157 | 0xc68, 0x69543420, | ||
158 | 0xc6c, 0x433c0094, | ||
159 | 0xc70, 0x2c7f000d, | ||
160 | 0xc74, 0x0186155b, | ||
161 | 0xc78, 0x0000001f, | ||
162 | 0xc7c, 0x00b91612, | ||
163 | 0xc80, 0x40000100, | ||
164 | 0xc84, 0x20f60000, | ||
165 | 0xc88, 0x20000080, | ||
166 | 0xc8c, 0x20200000, | ||
167 | 0xc90, 0x40000100, | ||
168 | 0xc94, 0x00000000, | ||
169 | 0xc98, 0x40000100, | ||
170 | 0xc9c, 0x00000000, | ||
171 | 0xca0, 0x00492492, | ||
172 | 0xca4, 0x00000000, | ||
173 | 0xca8, 0x00000000, | ||
174 | 0xcac, 0x00000000, | ||
175 | 0xcb0, 0x00000000, | ||
176 | 0xcb4, 0x00000000, | ||
177 | 0xcb8, 0x00000000, | ||
178 | 0xcbc, 0x28000000, | ||
179 | 0xcc0, 0x00000000, | ||
180 | 0xcc4, 0x00000000, | ||
181 | 0xcc8, 0x00000000, | ||
182 | 0xccc, 0x00000000, | ||
183 | 0xcd0, 0x00000000, | ||
184 | 0xcd4, 0x00000000, | ||
185 | 0xcd8, 0x64b22427, | ||
186 | 0xcdc, 0x00766932, | ||
187 | 0xce0, 0x00222222, | ||
188 | 0xce4, 0x00000000, | ||
189 | 0xce8, 0x37644302, | ||
190 | 0xcec, 0x2f97d40c, | ||
191 | 0xd00, 0x00000750, | ||
192 | 0xd04, 0x00000403, | ||
193 | 0xd08, 0x0000907f, | ||
194 | 0xd0c, 0x00000001, | ||
195 | 0xd10, 0xa0633333, | ||
196 | 0xd14, 0x33333c63, | ||
197 | 0xd18, 0x6a8f5b6b, | ||
198 | 0xd1c, 0x00000000, | ||
199 | 0xd20, 0x00000000, | ||
200 | 0xd24, 0x00000000, | ||
201 | 0xd28, 0x00000000, | ||
202 | 0xd2c, 0xcc979975, | ||
203 | 0xd30, 0x00000000, | ||
204 | 0xd34, 0x00000000, | ||
205 | 0xd38, 0x00000000, | ||
206 | 0xd3c, 0x00027293, | ||
207 | 0xd40, 0x00000000, | ||
208 | 0xd44, 0x00000000, | ||
209 | 0xd48, 0x00000000, | ||
210 | 0xd50, 0x6437140a, | ||
211 | 0xd54, 0x024dbd02, | ||
212 | 0xd58, 0x00000000, | ||
213 | 0xd5c, 0x30032064, | ||
214 | 0xd60, 0x4653de68, | ||
215 | 0xd64, 0x00518a3c, | ||
216 | 0xd68, 0x00002101, | ||
217 | 0xf14, 0x00000003, | ||
218 | 0xf4c, 0x00000000, | ||
219 | 0xf00, 0x00000300, | ||
220 | }; | ||
221 | |||
222 | u32 rtl8192sephy_changeto_1t1rarray[PHY_CHANGETO_1T1RARRAYLENGTH] = { | ||
223 | 0x844, 0xffffffff, 0x00010000, | ||
224 | 0x804, 0x0000000f, 0x00000001, | ||
225 | 0x824, 0x00f0000f, 0x00300004, | ||
226 | 0x82c, 0x00f0000f, 0x00100002, | ||
227 | 0x870, 0x04000000, 0x00000001, | ||
228 | 0x864, 0x00000400, 0x00000000, | ||
229 | 0x878, 0x000f000f, 0x00000002, | ||
230 | 0xe74, 0x0f000000, 0x00000002, | ||
231 | 0xe78, 0x0f000000, 0x00000002, | ||
232 | 0xe7c, 0x0f000000, 0x00000002, | ||
233 | 0xe80, 0x0f000000, 0x00000002, | ||
234 | 0x90c, 0x000000ff, 0x00000011, | ||
235 | 0xc04, 0x000000ff, 0x00000011, | ||
236 | 0xd04, 0x0000000f, 0x00000001, | ||
237 | 0x1f4, 0xffff0000, 0x00007777, | ||
238 | 0x234, 0xf8000000, 0x0000000a, | ||
239 | }; | ||
240 | |||
241 | u32 rtl8192sephy_changeto_1t2rarray[PHY_CHANGETO_1T2RARRAYLENGTH] = { | ||
242 | 0x804, 0x0000000f, 0x00000003, | ||
243 | 0x824, 0x00f0000f, 0x00300004, | ||
244 | 0x82c, 0x00f0000f, 0x00300002, | ||
245 | 0x870, 0x04000000, 0x00000001, | ||
246 | 0x864, 0x00000400, 0x00000000, | ||
247 | 0x878, 0x000f000f, 0x00000002, | ||
248 | 0xe74, 0x0f000000, 0x00000002, | ||
249 | 0xe78, 0x0f000000, 0x00000002, | ||
250 | 0xe7c, 0x0f000000, 0x00000002, | ||
251 | 0xe80, 0x0f000000, 0x00000002, | ||
252 | 0x90c, 0x000000ff, 0x00000011, | ||
253 | 0xc04, 0x000000ff, 0x00000033, | ||
254 | 0xd04, 0x0000000f, 0x00000003, | ||
255 | 0x1f4, 0xffff0000, 0x00007777, | ||
256 | 0x234, 0xf8000000, 0x0000000a, | ||
257 | }; | ||
258 | |||
259 | u32 rtl8192sephy_reg_array_pg[PHY_REG_ARRAY_PGLENGTH] = { | ||
260 | 0xe00, 0xffffffff, 0x06090909, | ||
261 | 0xe04, 0xffffffff, 0x00030406, | ||
262 | 0xe08, 0x0000ff00, 0x00000000, | ||
263 | 0xe10, 0xffffffff, 0x0a0c0d0e, | ||
264 | 0xe14, 0xffffffff, 0x04070809, | ||
265 | 0xe18, 0xffffffff, 0x0a0c0d0e, | ||
266 | 0xe1c, 0xffffffff, 0x04070809, | ||
267 | 0xe00, 0xffffffff, 0x04040404, | ||
268 | 0xe04, 0xffffffff, 0x00020204, | ||
269 | 0xe08, 0x0000ff00, 0x00000000, | ||
270 | 0xe10, 0xffffffff, 0x02040404, | ||
271 | 0xe14, 0xffffffff, 0x00000002, | ||
272 | 0xe18, 0xffffffff, 0x02040404, | ||
273 | 0xe1c, 0xffffffff, 0x00000002, | ||
274 | 0xe00, 0xffffffff, 0x04040404, | ||
275 | 0xe04, 0xffffffff, 0x00020204, | ||
276 | 0xe08, 0x0000ff00, 0x00000000, | ||
277 | 0xe10, 0xffffffff, 0x02040404, | ||
278 | 0xe14, 0xffffffff, 0x00000002, | ||
279 | 0xe18, 0xffffffff, 0x02040404, | ||
280 | 0xe1c, 0xffffffff, 0x00000002, | ||
281 | 0xe00, 0xffffffff, 0x02020202, | ||
282 | 0xe04, 0xffffffff, 0x00020202, | ||
283 | 0xe08, 0x0000ff00, 0x00000000, | ||
284 | 0xe10, 0xffffffff, 0x02020202, | ||
285 | 0xe14, 0xffffffff, 0x00000002, | ||
286 | 0xe18, 0xffffffff, 0x02020202, | ||
287 | 0xe1c, 0xffffffff, 0x00000002, | ||
288 | }; | ||
289 | |||
290 | u32 rtl8192seradioa_1t_array[RADIOA_1T_ARRAYLENGTH] = { | ||
291 | 0x000, 0x00030159, | ||
292 | 0x001, 0x00030250, | ||
293 | 0x002, 0x00010000, | ||
294 | 0x010, 0x0008000f, | ||
295 | 0x011, 0x000231fc, | ||
296 | 0x010, 0x000c000f, | ||
297 | 0x011, 0x0003f9f8, | ||
298 | 0x010, 0x0002000f, | ||
299 | 0x011, 0x00020101, | ||
300 | 0x014, 0x0001093e, | ||
301 | 0x014, 0x0009093e, | ||
302 | 0x015, 0x0000f8f4, | ||
303 | 0x017, 0x000f6500, | ||
304 | 0x01a, 0x00013056, | ||
305 | 0x01b, 0x00060000, | ||
306 | 0x01c, 0x00000300, | ||
307 | 0x01e, 0x00031059, | ||
308 | 0x021, 0x00054000, | ||
309 | 0x022, 0x0000083c, | ||
310 | 0x023, 0x00001558, | ||
311 | 0x024, 0x00000060, | ||
312 | 0x025, 0x00022583, | ||
313 | 0x026, 0x0000f200, | ||
314 | 0x027, 0x000eacf1, | ||
315 | 0x028, 0x0009bd54, | ||
316 | 0x029, 0x00004582, | ||
317 | 0x02a, 0x00000001, | ||
318 | 0x02b, 0x00021334, | ||
319 | 0x02a, 0x00000000, | ||
320 | 0x02b, 0x0000000a, | ||
321 | 0x02a, 0x00000001, | ||
322 | 0x02b, 0x00000808, | ||
323 | 0x02b, 0x00053333, | ||
324 | 0x02c, 0x0000000c, | ||
325 | 0x02a, 0x00000002, | ||
326 | 0x02b, 0x00000808, | ||
327 | 0x02b, 0x0005b333, | ||
328 | 0x02c, 0x0000000d, | ||
329 | 0x02a, 0x00000003, | ||
330 | 0x02b, 0x00000808, | ||
331 | 0x02b, 0x00063333, | ||
332 | 0x02c, 0x0000000d, | ||
333 | 0x02a, 0x00000004, | ||
334 | 0x02b, 0x00000808, | ||
335 | 0x02b, 0x0006b333, | ||
336 | 0x02c, 0x0000000d, | ||
337 | 0x02a, 0x00000005, | ||
338 | 0x02b, 0x00000709, | ||
339 | 0x02b, 0x00053333, | ||
340 | 0x02c, 0x0000000d, | ||
341 | 0x02a, 0x00000006, | ||
342 | 0x02b, 0x00000709, | ||
343 | 0x02b, 0x0005b333, | ||
344 | 0x02c, 0x0000000d, | ||
345 | 0x02a, 0x00000007, | ||
346 | 0x02b, 0x00000709, | ||
347 | 0x02b, 0x00063333, | ||
348 | 0x02c, 0x0000000d, | ||
349 | 0x02a, 0x00000008, | ||
350 | 0x02b, 0x00000709, | ||
351 | 0x02b, 0x0006b333, | ||
352 | 0x02c, 0x0000000d, | ||
353 | 0x02a, 0x00000009, | ||
354 | 0x02b, 0x0000060a, | ||
355 | 0x02b, 0x00053333, | ||
356 | 0x02c, 0x0000000d, | ||
357 | 0x02a, 0x0000000a, | ||
358 | 0x02b, 0x0000060a, | ||
359 | 0x02b, 0x0005b333, | ||
360 | 0x02c, 0x0000000d, | ||
361 | 0x02a, 0x0000000b, | ||
362 | 0x02b, 0x0000060a, | ||
363 | 0x02b, 0x00063333, | ||
364 | 0x02c, 0x0000000d, | ||
365 | 0x02a, 0x0000000c, | ||
366 | 0x02b, 0x0000060a, | ||
367 | 0x02b, 0x0006b333, | ||
368 | 0x02c, 0x0000000d, | ||
369 | 0x02a, 0x0000000d, | ||
370 | 0x02b, 0x0000050b, | ||
371 | 0x02b, 0x00053333, | ||
372 | 0x02c, 0x0000000d, | ||
373 | 0x02a, 0x0000000e, | ||
374 | 0x02b, 0x0000050b, | ||
375 | 0x02b, 0x00066623, | ||
376 | 0x02c, 0x0000001a, | ||
377 | 0x02a, 0x000e4000, | ||
378 | 0x030, 0x00020000, | ||
379 | 0x031, 0x000b9631, | ||
380 | 0x032, 0x0000130d, | ||
381 | 0x033, 0x00000187, | ||
382 | 0x013, 0x00019e6c, | ||
383 | 0x013, 0x00015e94, | ||
384 | 0x000, 0x00010159, | ||
385 | 0x018, 0x0000f401, | ||
386 | 0x0fe, 0x00000000, | ||
387 | 0x01e, 0x0003105b, | ||
388 | 0x0fe, 0x00000000, | ||
389 | 0x000, 0x00030159, | ||
390 | 0x010, 0x0004000f, | ||
391 | 0x011, 0x000203f9, | ||
392 | }; | ||
393 | |||
394 | u32 rtl8192seradiob_array[RADIOB_ARRAYLENGTH] = { | ||
395 | 0x000, 0x00030159, | ||
396 | 0x001, 0x00001041, | ||
397 | 0x002, 0x00011000, | ||
398 | 0x005, 0x00080fc0, | ||
399 | 0x007, 0x000fc803, | ||
400 | 0x013, 0x00017cb0, | ||
401 | 0x013, 0x00011cc0, | ||
402 | 0x013, 0x0000dc60, | ||
403 | 0x013, 0x00008c60, | ||
404 | 0x013, 0x00004450, | ||
405 | 0x013, 0x00000020, | ||
406 | }; | ||
407 | |||
408 | u32 rtl8192seradiob_gm_array[RADIOB_GM_ARRAYLENGTH] = { | ||
409 | 0x000, 0x00030159, | ||
410 | 0x001, 0x00001041, | ||
411 | 0x002, 0x00011000, | ||
412 | 0x005, 0x00080fc0, | ||
413 | 0x007, 0x000fc803, | ||
414 | }; | ||
415 | |||
416 | u32 rtl8192semac_2t_array[MAC_2T_ARRAYLENGTH] = { | ||
417 | 0x020, 0x00000035, | ||
418 | 0x048, 0x0000000e, | ||
419 | 0x049, 0x000000f0, | ||
420 | 0x04a, 0x00000077, | ||
421 | 0x04b, 0x00000083, | ||
422 | 0x0b5, 0x00000021, | ||
423 | 0x0dc, 0x000000ff, | ||
424 | 0x0dd, 0x000000ff, | ||
425 | 0x0de, 0x000000ff, | ||
426 | 0x0df, 0x000000ff, | ||
427 | 0x116, 0x00000000, | ||
428 | 0x117, 0x00000000, | ||
429 | 0x118, 0x00000000, | ||
430 | 0x119, 0x00000000, | ||
431 | 0x11a, 0x00000000, | ||
432 | 0x11b, 0x00000000, | ||
433 | 0x11c, 0x00000000, | ||
434 | 0x11d, 0x00000000, | ||
435 | 0x160, 0x0000000b, | ||
436 | 0x161, 0x0000000b, | ||
437 | 0x162, 0x0000000b, | ||
438 | 0x163, 0x0000000b, | ||
439 | 0x164, 0x0000000b, | ||
440 | 0x165, 0x0000000b, | ||
441 | 0x166, 0x0000000b, | ||
442 | 0x167, 0x0000000b, | ||
443 | 0x168, 0x0000000b, | ||
444 | 0x169, 0x0000000b, | ||
445 | 0x16a, 0x0000000b, | ||
446 | 0x16b, 0x0000000b, | ||
447 | 0x16c, 0x0000000b, | ||
448 | 0x16d, 0x0000000b, | ||
449 | 0x16e, 0x0000000b, | ||
450 | 0x16f, 0x0000000b, | ||
451 | 0x170, 0x0000000b, | ||
452 | 0x171, 0x0000000b, | ||
453 | 0x172, 0x0000000b, | ||
454 | 0x173, 0x0000000b, | ||
455 | 0x174, 0x0000000b, | ||
456 | 0x175, 0x0000000b, | ||
457 | 0x176, 0x0000000b, | ||
458 | 0x177, 0x0000000b, | ||
459 | 0x178, 0x0000000b, | ||
460 | 0x179, 0x0000000b, | ||
461 | 0x17a, 0x0000000b, | ||
462 | 0x17b, 0x0000000b, | ||
463 | 0x17c, 0x0000000b, | ||
464 | 0x17d, 0x0000000b, | ||
465 | 0x17e, 0x0000000b, | ||
466 | 0x17f, 0x0000000b, | ||
467 | 0x236, 0x0000000c, | ||
468 | 0x503, 0x00000022, | ||
469 | 0x560, 0x00000000, | ||
470 | }; | ||
471 | |||
472 | u32 rtl8192seagctab_array[AGCTAB_ARRAYLENGTH] = { | ||
473 | 0xc78, 0x7f000001, | ||
474 | 0xc78, 0x7f010001, | ||
475 | 0xc78, 0x7e020001, | ||
476 | 0xc78, 0x7d030001, | ||
477 | 0xc78, 0x7c040001, | ||
478 | 0xc78, 0x7b050001, | ||
479 | 0xc78, 0x7a060001, | ||
480 | 0xc78, 0x79070001, | ||
481 | 0xc78, 0x78080001, | ||
482 | 0xc78, 0x77090001, | ||
483 | 0xc78, 0x760a0001, | ||
484 | 0xc78, 0x750b0001, | ||
485 | 0xc78, 0x740c0001, | ||
486 | 0xc78, 0x730d0001, | ||
487 | 0xc78, 0x720e0001, | ||
488 | 0xc78, 0x710f0001, | ||
489 | 0xc78, 0x70100001, | ||
490 | 0xc78, 0x6f110001, | ||
491 | 0xc78, 0x6f120001, | ||
492 | 0xc78, 0x6e130001, | ||
493 | 0xc78, 0x6d140001, | ||
494 | 0xc78, 0x6d150001, | ||
495 | 0xc78, 0x6c160001, | ||
496 | 0xc78, 0x6b170001, | ||
497 | 0xc78, 0x6a180001, | ||
498 | 0xc78, 0x6a190001, | ||
499 | 0xc78, 0x691a0001, | ||
500 | 0xc78, 0x681b0001, | ||
501 | 0xc78, 0x671c0001, | ||
502 | 0xc78, 0x661d0001, | ||
503 | 0xc78, 0x651e0001, | ||
504 | 0xc78, 0x641f0001, | ||
505 | 0xc78, 0x63200001, | ||
506 | 0xc78, 0x4c210001, | ||
507 | 0xc78, 0x4b220001, | ||
508 | 0xc78, 0x4a230001, | ||
509 | 0xc78, 0x49240001, | ||
510 | 0xc78, 0x48250001, | ||
511 | 0xc78, 0x47260001, | ||
512 | 0xc78, 0x46270001, | ||
513 | 0xc78, 0x45280001, | ||
514 | 0xc78, 0x44290001, | ||
515 | 0xc78, 0x2c2a0001, | ||
516 | 0xc78, 0x2b2b0001, | ||
517 | 0xc78, 0x2a2c0001, | ||
518 | 0xc78, 0x292d0001, | ||
519 | 0xc78, 0x282e0001, | ||
520 | 0xc78, 0x272f0001, | ||
521 | 0xc78, 0x26300001, | ||
522 | 0xc78, 0x25310001, | ||
523 | 0xc78, 0x24320001, | ||
524 | 0xc78, 0x23330001, | ||
525 | 0xc78, 0x22340001, | ||
526 | 0xc78, 0x09350001, | ||
527 | 0xc78, 0x08360001, | ||
528 | 0xc78, 0x07370001, | ||
529 | 0xc78, 0x06380001, | ||
530 | 0xc78, 0x05390001, | ||
531 | 0xc78, 0x043a0001, | ||
532 | 0xc78, 0x033b0001, | ||
533 | 0xc78, 0x023c0001, | ||
534 | 0xc78, 0x013d0001, | ||
535 | 0xc78, 0x003e0001, | ||
536 | 0xc78, 0x003f0001, | ||
537 | 0xc78, 0x7f400001, | ||
538 | 0xc78, 0x7f410001, | ||
539 | 0xc78, 0x7e420001, | ||
540 | 0xc78, 0x7d430001, | ||
541 | 0xc78, 0x7c440001, | ||
542 | 0xc78, 0x7b450001, | ||
543 | 0xc78, 0x7a460001, | ||
544 | 0xc78, 0x79470001, | ||
545 | 0xc78, 0x78480001, | ||
546 | 0xc78, 0x77490001, | ||
547 | 0xc78, 0x764a0001, | ||
548 | 0xc78, 0x754b0001, | ||
549 | 0xc78, 0x744c0001, | ||
550 | 0xc78, 0x734d0001, | ||
551 | 0xc78, 0x724e0001, | ||
552 | 0xc78, 0x714f0001, | ||
553 | 0xc78, 0x70500001, | ||
554 | 0xc78, 0x6f510001, | ||
555 | 0xc78, 0x6f520001, | ||
556 | 0xc78, 0x6e530001, | ||
557 | 0xc78, 0x6d540001, | ||
558 | 0xc78, 0x6d550001, | ||
559 | 0xc78, 0x6c560001, | ||
560 | 0xc78, 0x6b570001, | ||
561 | 0xc78, 0x6a580001, | ||
562 | 0xc78, 0x6a590001, | ||
563 | 0xc78, 0x695a0001, | ||
564 | 0xc78, 0x685b0001, | ||
565 | 0xc78, 0x675c0001, | ||
566 | 0xc78, 0x665d0001, | ||
567 | 0xc78, 0x655e0001, | ||
568 | 0xc78, 0x645f0001, | ||
569 | 0xc78, 0x63600001, | ||
570 | 0xc78, 0x4c610001, | ||
571 | 0xc78, 0x4b620001, | ||
572 | 0xc78, 0x4a630001, | ||
573 | 0xc78, 0x49640001, | ||
574 | 0xc78, 0x48650001, | ||
575 | 0xc78, 0x47660001, | ||
576 | 0xc78, 0x46670001, | ||
577 | 0xc78, 0x45680001, | ||
578 | 0xc78, 0x44690001, | ||
579 | 0xc78, 0x2c6a0001, | ||
580 | 0xc78, 0x2b6b0001, | ||
581 | 0xc78, 0x2a6c0001, | ||
582 | 0xc78, 0x296d0001, | ||
583 | 0xc78, 0x286e0001, | ||
584 | 0xc78, 0x276f0001, | ||
585 | 0xc78, 0x26700001, | ||
586 | 0xc78, 0x25710001, | ||
587 | 0xc78, 0x24720001, | ||
588 | 0xc78, 0x23730001, | ||
589 | 0xc78, 0x22740001, | ||
590 | 0xc78, 0x09750001, | ||
591 | 0xc78, 0x08760001, | ||
592 | 0xc78, 0x07770001, | ||
593 | 0xc78, 0x06780001, | ||
594 | 0xc78, 0x05790001, | ||
595 | 0xc78, 0x047a0001, | ||
596 | 0xc78, 0x037b0001, | ||
597 | 0xc78, 0x027c0001, | ||
598 | 0xc78, 0x017d0001, | ||
599 | 0xc78, 0x007e0001, | ||
600 | 0xc78, 0x007f0001, | ||
601 | 0xc78, 0x3000001e, | ||
602 | 0xc78, 0x3001001e, | ||
603 | 0xc78, 0x3002001e, | ||
604 | 0xc78, 0x3003001e, | ||
605 | 0xc78, 0x3004001e, | ||
606 | 0xc78, 0x3405001e, | ||
607 | 0xc78, 0x3806001e, | ||
608 | 0xc78, 0x3e07001e, | ||
609 | 0xc78, 0x3e08001e, | ||
610 | 0xc78, 0x4409001e, | ||
611 | 0xc78, 0x460a001e, | ||
612 | 0xc78, 0x480b001e, | ||
613 | 0xc78, 0x480c001e, | ||
614 | 0xc78, 0x4e0d001e, | ||
615 | 0xc78, 0x560e001e, | ||
616 | 0xc78, 0x5a0f001e, | ||
617 | 0xc78, 0x5e10001e, | ||
618 | 0xc78, 0x6211001e, | ||
619 | 0xc78, 0x6c12001e, | ||
620 | 0xc78, 0x7213001e, | ||
621 | 0xc78, 0x7214001e, | ||
622 | 0xc78, 0x7215001e, | ||
623 | 0xc78, 0x7216001e, | ||
624 | 0xc78, 0x7217001e, | ||
625 | 0xc78, 0x7218001e, | ||
626 | 0xc78, 0x7219001e, | ||
627 | 0xc78, 0x721a001e, | ||
628 | 0xc78, 0x721b001e, | ||
629 | 0xc78, 0x721c001e, | ||
630 | 0xc78, 0x721d001e, | ||
631 | 0xc78, 0x721e001e, | ||
632 | 0xc78, 0x721f001e, | ||
633 | }; | ||
634 | |||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/table.h b/drivers/net/wireless/rtlwifi/rtl8192se/table.h new file mode 100644 index 000000000000..b4ed6d951ebb --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/table.h | |||
@@ -0,0 +1,49 @@ | |||
1 | /****************************************************************************** | ||
2 | * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. | ||
3 | * | ||
4 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
5 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
6 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
7 | * more details. | ||
8 | * | ||
9 | * You should have received a copy of the GNU General Public License along with | ||
10 | * this program; if not, write to the Free Software Foundation, Inc., | ||
11 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
12 | * | ||
13 | * The full GNU General Public License is included in this distribution in the | ||
14 | * file called LICENSE. | ||
15 | * | ||
16 | * Contact Information: | ||
17 | * wlanfae <wlanfae@realtek.com> | ||
18 | * | ||
19 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
20 | * | ||
21 | ******************************************************************************/ | ||
22 | #ifndef __INC_HAL8192SE_FW_IMG_H | ||
23 | #define __INC_HAL8192SE_FW_IMG_H | ||
24 | |||
25 | #include <linux/types.h> | ||
26 | |||
27 | /*Created on 2010/ 4/12, 5:56*/ | ||
28 | |||
29 | #define PHY_REG_2T2RARRAYLENGTH 372 | ||
30 | extern u32 rtl8192sephy_reg_2t2rarray[PHY_REG_2T2RARRAYLENGTH]; | ||
31 | #define PHY_CHANGETO_1T1RARRAYLENGTH 48 | ||
32 | extern u32 rtl8192sephy_changeto_1t1rarray[PHY_CHANGETO_1T1RARRAYLENGTH]; | ||
33 | #define PHY_CHANGETO_1T2RARRAYLENGTH 45 | ||
34 | extern u32 rtl8192sephy_changeto_1t2rarray[PHY_CHANGETO_1T2RARRAYLENGTH]; | ||
35 | #define PHY_REG_ARRAY_PGLENGTH 84 | ||
36 | extern u32 rtl8192sephy_reg_array_pg[PHY_REG_ARRAY_PGLENGTH]; | ||
37 | #define RADIOA_1T_ARRAYLENGTH 202 | ||
38 | extern u32 rtl8192seradioa_1t_array[RADIOA_1T_ARRAYLENGTH]; | ||
39 | #define RADIOB_ARRAYLENGTH 22 | ||
40 | extern u32 rtl8192seradiob_array[RADIOB_ARRAYLENGTH]; | ||
41 | #define RADIOB_GM_ARRAYLENGTH 10 | ||
42 | extern u32 rtl8192seradiob_gm_array[RADIOB_GM_ARRAYLENGTH]; | ||
43 | #define MAC_2T_ARRAYLENGTH 106 | ||
44 | extern u32 rtl8192semac_2t_array[MAC_2T_ARRAYLENGTH]; | ||
45 | #define AGCTAB_ARRAYLENGTH 320 | ||
46 | extern u32 rtl8192seagctab_array[AGCTAB_ARRAYLENGTH]; | ||
47 | |||
48 | #endif | ||
49 | |||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c new file mode 100644 index 000000000000..5cf442373d46 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c | |||
@@ -0,0 +1,976 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | |||
30 | #include "../wifi.h" | ||
31 | #include "../pci.h" | ||
32 | #include "../base.h" | ||
33 | #include "reg.h" | ||
34 | #include "def.h" | ||
35 | #include "phy.h" | ||
36 | #include "fw.h" | ||
37 | #include "trx.h" | ||
38 | #include "led.h" | ||
39 | |||
40 | static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue) | ||
41 | { | ||
42 | __le16 fc = rtl_get_fc(skb); | ||
43 | |||
44 | if (unlikely(ieee80211_is_beacon(fc))) | ||
45 | return QSLT_BEACON; | ||
46 | if (ieee80211_is_mgmt(fc)) | ||
47 | return QSLT_MGNT; | ||
48 | if (ieee80211_is_nullfunc(fc)) | ||
49 | return QSLT_HIGH; | ||
50 | |||
51 | return skb->priority; | ||
52 | } | ||
53 | |||
54 | static int _rtl92se_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu) | ||
55 | { | ||
56 | int rate_idx = 0; | ||
57 | |||
58 | if (first_ampdu) { | ||
59 | if (false == isht) { | ||
60 | switch (desc_rate) { | ||
61 | case DESC92S_RATE1M: | ||
62 | rate_idx = 0; | ||
63 | break; | ||
64 | case DESC92S_RATE2M: | ||
65 | rate_idx = 1; | ||
66 | break; | ||
67 | case DESC92S_RATE5_5M: | ||
68 | rate_idx = 2; | ||
69 | break; | ||
70 | case DESC92S_RATE11M: | ||
71 | rate_idx = 3; | ||
72 | break; | ||
73 | case DESC92S_RATE6M: | ||
74 | rate_idx = 4; | ||
75 | break; | ||
76 | case DESC92S_RATE9M: | ||
77 | rate_idx = 5; | ||
78 | break; | ||
79 | case DESC92S_RATE12M: | ||
80 | rate_idx = 6; | ||
81 | break; | ||
82 | case DESC92S_RATE18M: | ||
83 | rate_idx = 7; | ||
84 | break; | ||
85 | case DESC92S_RATE24M: | ||
86 | rate_idx = 8; | ||
87 | break; | ||
88 | case DESC92S_RATE36M: | ||
89 | rate_idx = 9; | ||
90 | break; | ||
91 | case DESC92S_RATE48M: | ||
92 | rate_idx = 10; | ||
93 | break; | ||
94 | case DESC92S_RATE54M: | ||
95 | rate_idx = 11; | ||
96 | break; | ||
97 | default: | ||
98 | rate_idx = 0; | ||
99 | break; | ||
100 | } | ||
101 | } else { | ||
102 | rate_idx = 11; | ||
103 | } | ||
104 | |||
105 | return rate_idx; | ||
106 | } | ||
107 | |||
108 | switch (desc_rate) { | ||
109 | case DESC92S_RATE1M: | ||
110 | rate_idx = 0; | ||
111 | break; | ||
112 | case DESC92S_RATE2M: | ||
113 | rate_idx = 1; | ||
114 | break; | ||
115 | case DESC92S_RATE5_5M: | ||
116 | rate_idx = 2; | ||
117 | break; | ||
118 | case DESC92S_RATE11M: | ||
119 | rate_idx = 3; | ||
120 | break; | ||
121 | case DESC92S_RATE6M: | ||
122 | rate_idx = 4; | ||
123 | break; | ||
124 | case DESC92S_RATE9M: | ||
125 | rate_idx = 5; | ||
126 | break; | ||
127 | case DESC92S_RATE12M: | ||
128 | rate_idx = 6; | ||
129 | break; | ||
130 | case DESC92S_RATE18M: | ||
131 | rate_idx = 7; | ||
132 | break; | ||
133 | case DESC92S_RATE24M: | ||
134 | rate_idx = 8; | ||
135 | break; | ||
136 | case DESC92S_RATE36M: | ||
137 | rate_idx = 9; | ||
138 | break; | ||
139 | case DESC92S_RATE48M: | ||
140 | rate_idx = 10; | ||
141 | break; | ||
142 | case DESC92S_RATE54M: | ||
143 | rate_idx = 11; | ||
144 | break; | ||
145 | default: | ||
146 | rate_idx = 11; | ||
147 | break; | ||
148 | } | ||
149 | return rate_idx; | ||
150 | } | ||
151 | |||
152 | static u8 _rtl92s_query_rxpwrpercentage(char antpower) | ||
153 | { | ||
154 | if ((antpower <= -100) || (antpower >= 20)) | ||
155 | return 0; | ||
156 | else if (antpower >= 0) | ||
157 | return 100; | ||
158 | else | ||
159 | return 100 + antpower; | ||
160 | } | ||
161 | |||
162 | static u8 _rtl92s_evm_db_to_percentage(char value) | ||
163 | { | ||
164 | char ret_val; | ||
165 | ret_val = value; | ||
166 | |||
167 | if (ret_val >= 0) | ||
168 | ret_val = 0; | ||
169 | |||
170 | if (ret_val <= -33) | ||
171 | ret_val = -33; | ||
172 | |||
173 | ret_val = 0 - ret_val; | ||
174 | ret_val *= 3; | ||
175 | |||
176 | if (ret_val == 99) | ||
177 | ret_val = 100; | ||
178 | |||
179 | return ret_val; | ||
180 | } | ||
181 | |||
182 | static long _rtl92se_translate_todbm(struct ieee80211_hw *hw, | ||
183 | u8 signal_strength_index) | ||
184 | { | ||
185 | long signal_power; | ||
186 | |||
187 | signal_power = (long)((signal_strength_index + 1) >> 1); | ||
188 | signal_power -= 95; | ||
189 | return signal_power; | ||
190 | } | ||
191 | |||
192 | static long _rtl92se_signal_scale_mapping(struct ieee80211_hw *hw, | ||
193 | long currsig) | ||
194 | { | ||
195 | long retsig = 0; | ||
196 | |||
197 | /* Step 1. Scale mapping. */ | ||
198 | if (currsig > 47) | ||
199 | retsig = 100; | ||
200 | else if (currsig > 14 && currsig <= 47) | ||
201 | retsig = 100 - ((47 - currsig) * 3) / 2; | ||
202 | else if (currsig > 2 && currsig <= 14) | ||
203 | retsig = 48 - ((14 - currsig) * 15) / 7; | ||
204 | else if (currsig >= 0) | ||
205 | retsig = currsig * 9 + 1; | ||
206 | |||
207 | return retsig; | ||
208 | } | ||
209 | |||
210 | |||
211 | static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw, | ||
212 | struct rtl_stats *pstats, u8 *pdesc, | ||
213 | struct rx_fwinfo *p_drvinfo, | ||
214 | bool packet_match_bssid, | ||
215 | bool packet_toself, | ||
216 | bool packet_beacon) | ||
217 | { | ||
218 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
219 | struct phy_sts_cck_8192s_t *cck_buf; | ||
220 | s8 rx_pwr_all = 0, rx_pwr[4]; | ||
221 | u8 rf_rx_num = 0, evm, pwdb_all; | ||
222 | u8 i, max_spatial_stream; | ||
223 | u32 rssi, total_rssi = 0; | ||
224 | bool in_powersavemode = false; | ||
225 | bool is_cck_rate; | ||
226 | |||
227 | is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc); | ||
228 | pstats->packet_matchbssid = packet_match_bssid; | ||
229 | pstats->packet_toself = packet_toself; | ||
230 | pstats->is_cck = is_cck_rate; | ||
231 | pstats->packet_beacon = packet_beacon; | ||
232 | pstats->is_cck = is_cck_rate; | ||
233 | pstats->rx_mimo_signalquality[0] = -1; | ||
234 | pstats->rx_mimo_signalquality[1] = -1; | ||
235 | |||
236 | if (is_cck_rate) { | ||
237 | u8 report, cck_highpwr; | ||
238 | cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo; | ||
239 | |||
240 | if (!in_powersavemode) | ||
241 | cck_highpwr = (u8) rtl_get_bbreg(hw, | ||
242 | RFPGA0_XA_HSSIPARAMETER2, | ||
243 | 0x200); | ||
244 | else | ||
245 | cck_highpwr = false; | ||
246 | |||
247 | if (!cck_highpwr) { | ||
248 | u8 cck_agc_rpt = cck_buf->cck_agc_rpt; | ||
249 | report = cck_buf->cck_agc_rpt & 0xc0; | ||
250 | report = report >> 6; | ||
251 | switch (report) { | ||
252 | case 0x3: | ||
253 | rx_pwr_all = -40 - (cck_agc_rpt & 0x3e); | ||
254 | break; | ||
255 | case 0x2: | ||
256 | rx_pwr_all = -20 - (cck_agc_rpt & 0x3e); | ||
257 | break; | ||
258 | case 0x1: | ||
259 | rx_pwr_all = -2 - (cck_agc_rpt & 0x3e); | ||
260 | break; | ||
261 | case 0x0: | ||
262 | rx_pwr_all = 14 - (cck_agc_rpt & 0x3e); | ||
263 | break; | ||
264 | } | ||
265 | } else { | ||
266 | u8 cck_agc_rpt = cck_buf->cck_agc_rpt; | ||
267 | report = p_drvinfo->cfosho[0] & 0x60; | ||
268 | report = report >> 5; | ||
269 | switch (report) { | ||
270 | case 0x3: | ||
271 | rx_pwr_all = -40 - ((cck_agc_rpt & 0x1f) << 1); | ||
272 | break; | ||
273 | case 0x2: | ||
274 | rx_pwr_all = -20 - ((cck_agc_rpt & 0x1f) << 1); | ||
275 | break; | ||
276 | case 0x1: | ||
277 | rx_pwr_all = -2 - ((cck_agc_rpt & 0x1f) << 1); | ||
278 | break; | ||
279 | case 0x0: | ||
280 | rx_pwr_all = 14 - ((cck_agc_rpt & 0x1f) << 1); | ||
281 | break; | ||
282 | } | ||
283 | } | ||
284 | |||
285 | pwdb_all = _rtl92s_query_rxpwrpercentage(rx_pwr_all); | ||
286 | |||
287 | /* CCK gain is smaller than OFDM/MCS gain, */ | ||
288 | /* so we add gain diff by experiences, the val is 6 */ | ||
289 | pwdb_all += 6; | ||
290 | if (pwdb_all > 100) | ||
291 | pwdb_all = 100; | ||
292 | /* modify the offset to make the same gain index with OFDM. */ | ||
293 | if (pwdb_all > 34 && pwdb_all <= 42) | ||
294 | pwdb_all -= 2; | ||
295 | else if (pwdb_all > 26 && pwdb_all <= 34) | ||
296 | pwdb_all -= 6; | ||
297 | else if (pwdb_all > 14 && pwdb_all <= 26) | ||
298 | pwdb_all -= 8; | ||
299 | else if (pwdb_all > 4 && pwdb_all <= 14) | ||
300 | pwdb_all -= 4; | ||
301 | |||
302 | pstats->rx_pwdb_all = pwdb_all; | ||
303 | pstats->recvsignalpower = rx_pwr_all; | ||
304 | |||
305 | if (packet_match_bssid) { | ||
306 | u8 sq; | ||
307 | if (pstats->rx_pwdb_all > 40) { | ||
308 | sq = 100; | ||
309 | } else { | ||
310 | sq = cck_buf->sq_rpt; | ||
311 | if (sq > 64) | ||
312 | sq = 0; | ||
313 | else if (sq < 20) | ||
314 | sq = 100; | ||
315 | else | ||
316 | sq = ((64 - sq) * 100) / 44; | ||
317 | } | ||
318 | |||
319 | pstats->signalquality = sq; | ||
320 | pstats->rx_mimo_signalquality[0] = sq; | ||
321 | pstats->rx_mimo_signalquality[1] = -1; | ||
322 | } | ||
323 | } else { | ||
324 | rtlpriv->dm.rfpath_rxenable[0] = | ||
325 | rtlpriv->dm.rfpath_rxenable[1] = true; | ||
326 | for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) { | ||
327 | if (rtlpriv->dm.rfpath_rxenable[i]) | ||
328 | rf_rx_num++; | ||
329 | |||
330 | rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & | ||
331 | 0x3f) * 2) - 110; | ||
332 | rssi = _rtl92s_query_rxpwrpercentage(rx_pwr[i]); | ||
333 | total_rssi += rssi; | ||
334 | rtlpriv->stats.rx_snr_db[i] = | ||
335 | (long)(p_drvinfo->rxsnr[i] / 2); | ||
336 | |||
337 | if (packet_match_bssid) | ||
338 | pstats->rx_mimo_signalstrength[i] = (u8) rssi; | ||
339 | } | ||
340 | |||
341 | rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110; | ||
342 | pwdb_all = _rtl92s_query_rxpwrpercentage(rx_pwr_all); | ||
343 | pstats->rx_pwdb_all = pwdb_all; | ||
344 | pstats->rxpower = rx_pwr_all; | ||
345 | pstats->recvsignalpower = rx_pwr_all; | ||
346 | |||
347 | if (GET_RX_STATUS_DESC_RX_HT(pdesc) && | ||
348 | GET_RX_STATUS_DESC_RX_MCS(pdesc) >= DESC92S_RATEMCS8 && | ||
349 | GET_RX_STATUS_DESC_RX_MCS(pdesc) <= DESC92S_RATEMCS15) | ||
350 | max_spatial_stream = 2; | ||
351 | else | ||
352 | max_spatial_stream = 1; | ||
353 | |||
354 | for (i = 0; i < max_spatial_stream; i++) { | ||
355 | evm = _rtl92s_evm_db_to_percentage(p_drvinfo->rxevm[i]); | ||
356 | |||
357 | if (packet_match_bssid) { | ||
358 | if (i == 0) | ||
359 | pstats->signalquality = (u8)(evm & | ||
360 | 0xff); | ||
361 | pstats->rx_mimo_signalquality[i] = | ||
362 | (u8) (evm & 0xff); | ||
363 | } | ||
364 | } | ||
365 | } | ||
366 | |||
367 | if (is_cck_rate) | ||
368 | pstats->signalstrength = (u8)(_rtl92se_signal_scale_mapping(hw, | ||
369 | pwdb_all)); | ||
370 | else if (rf_rx_num != 0) | ||
371 | pstats->signalstrength = (u8) (_rtl92se_signal_scale_mapping(hw, | ||
372 | total_rssi /= rf_rx_num)); | ||
373 | } | ||
374 | |||
375 | static void _rtl92se_process_ui_rssi(struct ieee80211_hw *hw, | ||
376 | struct rtl_stats *pstats) | ||
377 | { | ||
378 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
379 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | ||
380 | u8 rfpath; | ||
381 | u32 last_rssi, tmpval; | ||
382 | |||
383 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
384 | rtlpriv->stats.rssi_calculate_cnt++; | ||
385 | |||
386 | if (rtlpriv->stats.ui_rssi.total_num++ >= | ||
387 | PHY_RSSI_SLID_WIN_MAX) { | ||
388 | rtlpriv->stats.ui_rssi.total_num = | ||
389 | PHY_RSSI_SLID_WIN_MAX; | ||
390 | last_rssi = rtlpriv->stats.ui_rssi.elements[ | ||
391 | rtlpriv->stats.ui_rssi.index]; | ||
392 | rtlpriv->stats.ui_rssi.total_val -= last_rssi; | ||
393 | } | ||
394 | |||
395 | rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength; | ||
396 | rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.index++] | ||
397 | = pstats->signalstrength; | ||
398 | |||
399 | if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX) | ||
400 | rtlpriv->stats.ui_rssi.index = 0; | ||
401 | |||
402 | tmpval = rtlpriv->stats.ui_rssi.total_val / | ||
403 | rtlpriv->stats.ui_rssi.total_num; | ||
404 | rtlpriv->stats.signal_strength = _rtl92se_translate_todbm(hw, | ||
405 | (u8) tmpval); | ||
406 | pstats->rssi = rtlpriv->stats.signal_strength; | ||
407 | } | ||
408 | |||
409 | if (!pstats->is_cck && pstats->packet_toself) { | ||
410 | for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath; | ||
411 | rfpath++) { | ||
412 | if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) { | ||
413 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
414 | pstats->rx_mimo_signalstrength[rfpath]; | ||
415 | |||
416 | } | ||
417 | |||
418 | if (pstats->rx_mimo_signalstrength[rfpath] > | ||
419 | rtlpriv->stats.rx_rssi_percentage[rfpath]) { | ||
420 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
421 | ((rtlpriv->stats.rx_rssi_percentage[rfpath] | ||
422 | * (RX_SMOOTH_FACTOR - 1)) + | ||
423 | (pstats->rx_mimo_signalstrength[rfpath])) / | ||
424 | (RX_SMOOTH_FACTOR); | ||
425 | |||
426 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
427 | rtlpriv->stats.rx_rssi_percentage[rfpath] | ||
428 | + 1; | ||
429 | } else { | ||
430 | rtlpriv->stats.rx_rssi_percentage[rfpath] = | ||
431 | ((rtlpriv->stats.rx_rssi_percentage[rfpath] | ||
432 | * (RX_SMOOTH_FACTOR - 1)) + | ||
433 | (pstats->rx_mimo_signalstrength[rfpath])) / | ||
434 | (RX_SMOOTH_FACTOR); | ||
435 | } | ||
436 | |||
437 | } | ||
438 | } | ||
439 | } | ||
440 | |||
441 | static void _rtl92se_update_rxsignalstatistics(struct ieee80211_hw *hw, | ||
442 | struct rtl_stats *pstats) | ||
443 | { | ||
444 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
445 | int weighting = 0; | ||
446 | |||
447 | if (rtlpriv->stats.recv_signal_power == 0) | ||
448 | rtlpriv->stats.recv_signal_power = pstats->recvsignalpower; | ||
449 | |||
450 | if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power) | ||
451 | weighting = 5; | ||
452 | else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power) | ||
453 | weighting = (-5); | ||
454 | |||
455 | rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power * 5 | ||
456 | + pstats->recvsignalpower + | ||
457 | weighting) / 6; | ||
458 | } | ||
459 | |||
460 | static void _rtl92se_process_pwdb(struct ieee80211_hw *hw, | ||
461 | struct rtl_stats *pstats) | ||
462 | { | ||
463 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
464 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
465 | long undec_sm_pwdb = 0; | ||
466 | |||
467 | if (mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
468 | return; | ||
469 | } else { | ||
470 | undec_sm_pwdb = | ||
471 | rtlpriv->dm.undecorated_smoothed_pwdb; | ||
472 | } | ||
473 | |||
474 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
475 | if (undec_sm_pwdb < 0) | ||
476 | undec_sm_pwdb = pstats->rx_pwdb_all; | ||
477 | |||
478 | if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) { | ||
479 | undec_sm_pwdb = | ||
480 | (((undec_sm_pwdb) * | ||
481 | (RX_SMOOTH_FACTOR - 1)) + | ||
482 | (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR); | ||
483 | |||
484 | undec_sm_pwdb = undec_sm_pwdb + 1; | ||
485 | } else { | ||
486 | undec_sm_pwdb = (((undec_sm_pwdb) * | ||
487 | (RX_SMOOTH_FACTOR - 1)) + (pstats->rx_pwdb_all)) / | ||
488 | (RX_SMOOTH_FACTOR); | ||
489 | } | ||
490 | |||
491 | rtlpriv->dm.undecorated_smoothed_pwdb = undec_sm_pwdb; | ||
492 | _rtl92se_update_rxsignalstatistics(hw, pstats); | ||
493 | } | ||
494 | } | ||
495 | |||
496 | static void rtl_92s_process_streams(struct ieee80211_hw *hw, | ||
497 | struct rtl_stats *pstats) | ||
498 | { | ||
499 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
500 | u32 stream; | ||
501 | |||
502 | for (stream = 0; stream < 2; stream++) { | ||
503 | if (pstats->rx_mimo_signalquality[stream] != -1) { | ||
504 | if (rtlpriv->stats.rx_evm_percentage[stream] == 0) { | ||
505 | rtlpriv->stats.rx_evm_percentage[stream] = | ||
506 | pstats->rx_mimo_signalquality[stream]; | ||
507 | } | ||
508 | |||
509 | rtlpriv->stats.rx_evm_percentage[stream] = | ||
510 | ((rtlpriv->stats.rx_evm_percentage[stream] * | ||
511 | (RX_SMOOTH_FACTOR - 1)) + | ||
512 | (pstats->rx_mimo_signalquality[stream] * | ||
513 | 1)) / (RX_SMOOTH_FACTOR); | ||
514 | } | ||
515 | } | ||
516 | } | ||
517 | |||
518 | static void _rtl92se_process_ui_link_quality(struct ieee80211_hw *hw, | ||
519 | struct rtl_stats *pstats) | ||
520 | { | ||
521 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
522 | u32 last_evm = 0, tmpval; | ||
523 | |||
524 | if (pstats->signalquality != 0) { | ||
525 | if (pstats->packet_toself || pstats->packet_beacon) { | ||
526 | |||
527 | if (rtlpriv->stats.ui_link_quality.total_num++ >= | ||
528 | PHY_LINKQUALITY_SLID_WIN_MAX) { | ||
529 | rtlpriv->stats.ui_link_quality.total_num = | ||
530 | PHY_LINKQUALITY_SLID_WIN_MAX; | ||
531 | last_evm = | ||
532 | rtlpriv->stats.ui_link_quality.elements[ | ||
533 | rtlpriv->stats.ui_link_quality.index]; | ||
534 | rtlpriv->stats.ui_link_quality.total_val -= | ||
535 | last_evm; | ||
536 | } | ||
537 | |||
538 | rtlpriv->stats.ui_link_quality.total_val += | ||
539 | pstats->signalquality; | ||
540 | rtlpriv->stats.ui_link_quality.elements[ | ||
541 | rtlpriv->stats.ui_link_quality.index++] = | ||
542 | pstats->signalquality; | ||
543 | |||
544 | if (rtlpriv->stats.ui_link_quality.index >= | ||
545 | PHY_LINKQUALITY_SLID_WIN_MAX) | ||
546 | rtlpriv->stats.ui_link_quality.index = 0; | ||
547 | |||
548 | tmpval = rtlpriv->stats.ui_link_quality.total_val / | ||
549 | rtlpriv->stats.ui_link_quality.total_num; | ||
550 | rtlpriv->stats.signal_quality = tmpval; | ||
551 | |||
552 | rtlpriv->stats.last_sigstrength_inpercent = tmpval; | ||
553 | |||
554 | rtl_92s_process_streams(hw, pstats); | ||
555 | |||
556 | } | ||
557 | } | ||
558 | } | ||
559 | |||
560 | static void _rtl92se_process_phyinfo(struct ieee80211_hw *hw, | ||
561 | u8 *buffer, | ||
562 | struct rtl_stats *pcurrent_stats) | ||
563 | { | ||
564 | |||
565 | if (!pcurrent_stats->packet_matchbssid && | ||
566 | !pcurrent_stats->packet_beacon) | ||
567 | return; | ||
568 | |||
569 | _rtl92se_process_ui_rssi(hw, pcurrent_stats); | ||
570 | _rtl92se_process_pwdb(hw, pcurrent_stats); | ||
571 | _rtl92se_process_ui_link_quality(hw, pcurrent_stats); | ||
572 | } | ||
573 | |||
574 | static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw, | ||
575 | struct sk_buff *skb, struct rtl_stats *pstats, | ||
576 | u8 *pdesc, struct rx_fwinfo *p_drvinfo) | ||
577 | { | ||
578 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
579 | struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw)); | ||
580 | |||
581 | struct ieee80211_hdr *hdr; | ||
582 | u8 *tmp_buf; | ||
583 | u8 *praddr; | ||
584 | u8 *psaddr; | ||
585 | __le16 fc; | ||
586 | u16 type, cfc; | ||
587 | bool packet_matchbssid, packet_toself, packet_beacon; | ||
588 | |||
589 | tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift; | ||
590 | |||
591 | hdr = (struct ieee80211_hdr *)tmp_buf; | ||
592 | fc = hdr->frame_control; | ||
593 | cfc = le16_to_cpu(fc); | ||
594 | type = WLAN_FC_GET_TYPE(fc); | ||
595 | praddr = hdr->addr1; | ||
596 | psaddr = hdr->addr2; | ||
597 | |||
598 | packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) && | ||
599 | (!compare_ether_addr(mac->bssid, (cfc & IEEE80211_FCTL_TODS) ? | ||
600 | hdr->addr1 : (cfc & IEEE80211_FCTL_FROMDS) ? | ||
601 | hdr->addr2 : hdr->addr3)) && (!pstats->hwerror) && | ||
602 | (!pstats->crc) && (!pstats->icv)); | ||
603 | |||
604 | packet_toself = packet_matchbssid && | ||
605 | (!compare_ether_addr(praddr, rtlefuse->dev_addr)); | ||
606 | |||
607 | if (ieee80211_is_beacon(fc)) | ||
608 | packet_beacon = true; | ||
609 | |||
610 | _rtl92se_query_rxphystatus(hw, pstats, pdesc, p_drvinfo, | ||
611 | packet_matchbssid, packet_toself, packet_beacon); | ||
612 | _rtl92se_process_phyinfo(hw, tmp_buf, pstats); | ||
613 | } | ||
614 | |||
615 | bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, | ||
616 | struct ieee80211_rx_status *rx_status, u8 *pdesc, | ||
617 | struct sk_buff *skb) | ||
618 | { | ||
619 | struct rx_fwinfo *p_drvinfo; | ||
620 | u32 phystatus = (u32)GET_RX_STATUS_DESC_PHY_STATUS(pdesc); | ||
621 | |||
622 | stats->length = (u16)GET_RX_STATUS_DESC_PKT_LEN(pdesc); | ||
623 | stats->rx_drvinfo_size = (u8)GET_RX_STATUS_DESC_DRVINFO_SIZE(pdesc) * 8; | ||
624 | stats->rx_bufshift = (u8)(GET_RX_STATUS_DESC_SHIFT(pdesc) & 0x03); | ||
625 | stats->icv = (u16)GET_RX_STATUS_DESC_ICV(pdesc); | ||
626 | stats->crc = (u16)GET_RX_STATUS_DESC_CRC32(pdesc); | ||
627 | stats->hwerror = (u16)(stats->crc | stats->icv); | ||
628 | stats->decrypted = !GET_RX_STATUS_DESC_SWDEC(pdesc); | ||
629 | |||
630 | stats->rate = (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc); | ||
631 | stats->shortpreamble = (u16)GET_RX_STATUS_DESC_SPLCP(pdesc); | ||
632 | stats->isampdu = (bool)(GET_RX_STATUS_DESC_PAGGR(pdesc) == 1); | ||
633 | stats->timestamp_low = GET_RX_STATUS_DESC_TSFL(pdesc); | ||
634 | stats->rx_is40Mhzpacket = (bool)GET_RX_STATUS_DESC_BW(pdesc); | ||
635 | |||
636 | if (stats->hwerror) | ||
637 | return false; | ||
638 | |||
639 | rx_status->freq = hw->conf.channel->center_freq; | ||
640 | rx_status->band = hw->conf.channel->band; | ||
641 | |||
642 | if (GET_RX_STATUS_DESC_CRC32(pdesc)) | ||
643 | rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; | ||
644 | |||
645 | if (!GET_RX_STATUS_DESC_SWDEC(pdesc)) | ||
646 | rx_status->flag |= RX_FLAG_DECRYPTED; | ||
647 | |||
648 | if (GET_RX_STATUS_DESC_BW(pdesc)) | ||
649 | rx_status->flag |= RX_FLAG_40MHZ; | ||
650 | |||
651 | if (GET_RX_STATUS_DESC_RX_HT(pdesc)) | ||
652 | rx_status->flag |= RX_FLAG_HT; | ||
653 | |||
654 | rx_status->flag |= RX_FLAG_MACTIME_MPDU; | ||
655 | |||
656 | if (stats->decrypted) | ||
657 | rx_status->flag |= RX_FLAG_DECRYPTED; | ||
658 | |||
659 | rx_status->rate_idx = _rtl92se_rate_mapping((bool) | ||
660 | GET_RX_STATUS_DESC_RX_HT(pdesc), | ||
661 | (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc), | ||
662 | (bool)GET_RX_STATUS_DESC_PAGGR(pdesc)); | ||
663 | |||
664 | |||
665 | rx_status->mactime = GET_RX_STATUS_DESC_TSFL(pdesc); | ||
666 | if (phystatus == true) { | ||
667 | p_drvinfo = (struct rx_fwinfo *)(skb->data + | ||
668 | stats->rx_bufshift); | ||
669 | _rtl92se_translate_rx_signal_stuff(hw, skb, stats, pdesc, | ||
670 | p_drvinfo); | ||
671 | } | ||
672 | |||
673 | /*rx_status->qual = stats->signal; */ | ||
674 | rx_status->signal = stats->rssi + 10; | ||
675 | /*rx_status->noise = -stats->noise; */ | ||
676 | |||
677 | return true; | ||
678 | } | ||
679 | |||
680 | void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, | ||
681 | struct ieee80211_hdr *hdr, u8 *pdesc_tx, | ||
682 | struct ieee80211_tx_info *info, struct sk_buff *skb, | ||
683 | u8 hw_queue, struct rtl_tcb_desc *ptcb_desc) | ||
684 | { | ||
685 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
686 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | ||
687 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
688 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
689 | struct ieee80211_sta *sta = info->control.sta; | ||
690 | u8 *pdesc = (u8 *) pdesc_tx; | ||
691 | u16 seq_number; | ||
692 | __le16 fc = hdr->frame_control; | ||
693 | u8 reserved_macid = 0; | ||
694 | u8 fw_qsel = _rtl92se_map_hwqueue_to_fwqueue(skb, hw_queue); | ||
695 | bool firstseg = (!(hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG))); | ||
696 | bool lastseg = (!(hdr->frame_control & | ||
697 | cpu_to_le16(IEEE80211_FCTL_MOREFRAGS))); | ||
698 | dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, | ||
699 | PCI_DMA_TODEVICE); | ||
700 | u8 bw_40 = 0; | ||
701 | |||
702 | if (mac->opmode == NL80211_IFTYPE_STATION) { | ||
703 | bw_40 = mac->bw_40; | ||
704 | } else if (mac->opmode == NL80211_IFTYPE_AP || | ||
705 | mac->opmode == NL80211_IFTYPE_ADHOC) { | ||
706 | if (sta) | ||
707 | bw_40 = sta->ht_cap.cap & | ||
708 | IEEE80211_HT_CAP_SUP_WIDTH_20_40; | ||
709 | } | ||
710 | |||
711 | seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4; | ||
712 | |||
713 | rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc); | ||
714 | |||
715 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE_RTL8192S); | ||
716 | |||
717 | if (firstseg) { | ||
718 | if (rtlpriv->dm.useramask) { | ||
719 | /* set txdesc macId */ | ||
720 | if (ptcb_desc->mac_id < 32) { | ||
721 | SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id); | ||
722 | reserved_macid |= ptcb_desc->mac_id; | ||
723 | } | ||
724 | } | ||
725 | SET_TX_DESC_RSVD_MACID(pdesc, reserved_macid); | ||
726 | |||
727 | SET_TX_DESC_TXHT(pdesc, ((ptcb_desc->hw_rate >= | ||
728 | DESC92S_RATEMCS0) ? 1 : 0)); | ||
729 | |||
730 | if (rtlhal->version == VERSION_8192S_ACUT) { | ||
731 | if (ptcb_desc->hw_rate == DESC92S_RATE1M || | ||
732 | ptcb_desc->hw_rate == DESC92S_RATE2M || | ||
733 | ptcb_desc->hw_rate == DESC92S_RATE5_5M || | ||
734 | ptcb_desc->hw_rate == DESC92S_RATE11M) { | ||
735 | ptcb_desc->hw_rate = DESC92S_RATE12M; | ||
736 | } | ||
737 | } | ||
738 | |||
739 | SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate); | ||
740 | |||
741 | if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble) | ||
742 | SET_TX_DESC_TX_SHORT(pdesc, 0); | ||
743 | |||
744 | /* Aggregation related */ | ||
745 | if (info->flags & IEEE80211_TX_CTL_AMPDU) | ||
746 | SET_TX_DESC_AGG_ENABLE(pdesc, 1); | ||
747 | |||
748 | /* For AMPDU, we must insert SSN into TX_DESC */ | ||
749 | SET_TX_DESC_SEQ(pdesc, seq_number); | ||
750 | |||
751 | /* Protection mode related */ | ||
752 | /* For 92S, if RTS/CTS are set, HW will execute RTS. */ | ||
753 | /* We choose only one protection mode to execute */ | ||
754 | SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable && | ||
755 | !ptcb_desc->cts_enable) ? 1 : 0)); | ||
756 | SET_TX_DESC_CTS_ENABLE(pdesc, ((ptcb_desc->cts_enable) ? | ||
757 | 1 : 0)); | ||
758 | SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0)); | ||
759 | |||
760 | SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate); | ||
761 | SET_TX_DESC_RTS_BANDWIDTH(pdesc, 0); | ||
762 | SET_TX_DESC_RTS_SUB_CARRIER(pdesc, ptcb_desc->rts_sc); | ||
763 | SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <= | ||
764 | DESC92S_RATE54M) ? | ||
765 | (ptcb_desc->rts_use_shortpreamble ? 1 : 0) | ||
766 | : (ptcb_desc->rts_use_shortgi ? 1 : 0))); | ||
767 | |||
768 | |||
769 | /* Set Bandwidth and sub-channel settings. */ | ||
770 | if (bw_40) { | ||
771 | if (ptcb_desc->packet_bw) { | ||
772 | SET_TX_DESC_TX_BANDWIDTH(pdesc, 1); | ||
773 | /* use duplicated mode */ | ||
774 | SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); | ||
775 | } else { | ||
776 | SET_TX_DESC_TX_BANDWIDTH(pdesc, 0); | ||
777 | SET_TX_DESC_TX_SUB_CARRIER(pdesc, | ||
778 | mac->cur_40_prime_sc); | ||
779 | } | ||
780 | } else { | ||
781 | SET_TX_DESC_TX_BANDWIDTH(pdesc, 0); | ||
782 | SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0); | ||
783 | } | ||
784 | |||
785 | /* 3 Fill necessary field in First Descriptor */ | ||
786 | /*DWORD 0*/ | ||
787 | SET_TX_DESC_LINIP(pdesc, 0); | ||
788 | SET_TX_DESC_OFFSET(pdesc, 32); | ||
789 | SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len); | ||
790 | |||
791 | /*DWORD 1*/ | ||
792 | SET_TX_DESC_RA_BRSR_ID(pdesc, ptcb_desc->ratr_index); | ||
793 | |||
794 | /* Fill security related */ | ||
795 | if (info->control.hw_key) { | ||
796 | struct ieee80211_key_conf *keyconf; | ||
797 | |||
798 | keyconf = info->control.hw_key; | ||
799 | switch (keyconf->cipher) { | ||
800 | case WLAN_CIPHER_SUITE_WEP40: | ||
801 | case WLAN_CIPHER_SUITE_WEP104: | ||
802 | SET_TX_DESC_SEC_TYPE(pdesc, 0x1); | ||
803 | break; | ||
804 | case WLAN_CIPHER_SUITE_TKIP: | ||
805 | SET_TX_DESC_SEC_TYPE(pdesc, 0x2); | ||
806 | break; | ||
807 | case WLAN_CIPHER_SUITE_CCMP: | ||
808 | SET_TX_DESC_SEC_TYPE(pdesc, 0x3); | ||
809 | break; | ||
810 | default: | ||
811 | SET_TX_DESC_SEC_TYPE(pdesc, 0x0); | ||
812 | break; | ||
813 | |||
814 | } | ||
815 | } | ||
816 | |||
817 | /* Set Packet ID */ | ||
818 | SET_TX_DESC_PACKET_ID(pdesc, 0); | ||
819 | |||
820 | /* We will assign magement queue to BK. */ | ||
821 | SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel); | ||
822 | |||
823 | /* Alwasy enable all rate fallback range */ | ||
824 | SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F); | ||
825 | |||
826 | /* Fix: I don't kown why hw use 6.5M to tx when set it */ | ||
827 | SET_TX_DESC_USER_RATE(pdesc, | ||
828 | ptcb_desc->use_driver_rate ? 1 : 0); | ||
829 | |||
830 | /* Set NON_QOS bit. */ | ||
831 | if (!ieee80211_is_data_qos(fc)) | ||
832 | SET_TX_DESC_NON_QOS(pdesc, 1); | ||
833 | |||
834 | } | ||
835 | |||
836 | /* Fill fields that are required to be initialized | ||
837 | * in all of the descriptors */ | ||
838 | /*DWORD 0 */ | ||
839 | SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0)); | ||
840 | SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0)); | ||
841 | |||
842 | /* DWORD 7 */ | ||
843 | SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len); | ||
844 | |||
845 | /* DOWRD 8 */ | ||
846 | SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); | ||
847 | |||
848 | RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, ("\n")); | ||
849 | } | ||
850 | |||
851 | void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, | ||
852 | bool firstseg, bool lastseg, struct sk_buff *skb) | ||
853 | { | ||
854 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
855 | struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); | ||
856 | struct rtl_tcb_desc *tcb_desc = (struct rtl_tcb_desc *)(skb->cb); | ||
857 | |||
858 | dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len, | ||
859 | PCI_DMA_TODEVICE); | ||
860 | |||
861 | /* Clear all status */ | ||
862 | CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_CMDDESC_SIZE_RTL8192S); | ||
863 | |||
864 | /* This bit indicate this packet is used for FW download. */ | ||
865 | if (tcb_desc->cmd_or_init == DESC_PACKET_TYPE_INIT) { | ||
866 | /* For firmware downlaod we only need to set LINIP */ | ||
867 | SET_TX_DESC_LINIP(pdesc, tcb_desc->last_inipkt); | ||
868 | |||
869 | /* 92SE must set as 1 for firmware download HW DMA error */ | ||
870 | SET_TX_DESC_FIRST_SEG(pdesc, 1); | ||
871 | SET_TX_DESC_LAST_SEG(pdesc, 1); | ||
872 | |||
873 | /* 92SE need not to set TX packet size when firmware download */ | ||
874 | SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len)); | ||
875 | SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); | ||
876 | SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); | ||
877 | |||
878 | SET_TX_DESC_OWN(pdesc, 1); | ||
879 | } else { /* H2C Command Desc format (Host TXCMD) */ | ||
880 | /* 92SE must set as 1 for firmware download HW DMA error */ | ||
881 | SET_TX_DESC_FIRST_SEG(pdesc, 1); | ||
882 | SET_TX_DESC_LAST_SEG(pdesc, 1); | ||
883 | |||
884 | SET_TX_DESC_OFFSET(pdesc, 0x20); | ||
885 | |||
886 | /* Buffer size + command header */ | ||
887 | SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len)); | ||
888 | /* Fixed queue of H2C command */ | ||
889 | SET_TX_DESC_QUEUE_SEL(pdesc, 0x13); | ||
890 | |||
891 | SET_BITS_TO_LE_4BYTE(skb->data, 24, 7, rtlhal->h2c_txcmd_seq); | ||
892 | |||
893 | SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len)); | ||
894 | SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping)); | ||
895 | |||
896 | SET_TX_DESC_OWN(pdesc, 1); | ||
897 | |||
898 | } | ||
899 | } | ||
900 | |||
901 | void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val) | ||
902 | { | ||
903 | if (istx == true) { | ||
904 | switch (desc_name) { | ||
905 | case HW_DESC_OWN: | ||
906 | SET_TX_DESC_OWN(pdesc, 1); | ||
907 | break; | ||
908 | case HW_DESC_TX_NEXTDESC_ADDR: | ||
909 | SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val); | ||
910 | break; | ||
911 | default: | ||
912 | RT_ASSERT(false, ("ERR txdesc :%d not process\n", | ||
913 | desc_name)); | ||
914 | break; | ||
915 | } | ||
916 | } else { | ||
917 | switch (desc_name) { | ||
918 | case HW_DESC_RXOWN: | ||
919 | SET_RX_STATUS_DESC_OWN(pdesc, 1); | ||
920 | break; | ||
921 | case HW_DESC_RXBUFF_ADDR: | ||
922 | SET_RX_STATUS__DESC_BUFF_ADDR(pdesc, *(u32 *) val); | ||
923 | break; | ||
924 | case HW_DESC_RXPKT_LEN: | ||
925 | SET_RX_STATUS_DESC_PKT_LEN(pdesc, *(u32 *) val); | ||
926 | break; | ||
927 | case HW_DESC_RXERO: | ||
928 | SET_RX_STATUS_DESC_EOR(pdesc, 1); | ||
929 | break; | ||
930 | default: | ||
931 | RT_ASSERT(false, ("ERR rxdesc :%d not process\n", | ||
932 | desc_name)); | ||
933 | break; | ||
934 | } | ||
935 | } | ||
936 | } | ||
937 | |||
938 | u32 rtl92se_get_desc(u8 *desc, bool istx, u8 desc_name) | ||
939 | { | ||
940 | u32 ret = 0; | ||
941 | |||
942 | if (istx == true) { | ||
943 | switch (desc_name) { | ||
944 | case HW_DESC_OWN: | ||
945 | ret = GET_TX_DESC_OWN(desc); | ||
946 | break; | ||
947 | case HW_DESC_TXBUFF_ADDR: | ||
948 | ret = GET_TX_DESC_TX_BUFFER_ADDRESS(desc); | ||
949 | break; | ||
950 | default: | ||
951 | RT_ASSERT(false, ("ERR txdesc :%d not process\n", | ||
952 | desc_name)); | ||
953 | break; | ||
954 | } | ||
955 | } else { | ||
956 | switch (desc_name) { | ||
957 | case HW_DESC_OWN: | ||
958 | ret = GET_RX_STATUS_DESC_OWN(desc); | ||
959 | break; | ||
960 | case HW_DESC_RXPKT_LEN: | ||
961 | ret = GET_RX_STATUS_DESC_PKT_LEN(desc); | ||
962 | break; | ||
963 | default: | ||
964 | RT_ASSERT(false, ("ERR rxdesc :%d not process\n", | ||
965 | desc_name)); | ||
966 | break; | ||
967 | } | ||
968 | } | ||
969 | return ret; | ||
970 | } | ||
971 | |||
972 | void rtl92se_tx_polling(struct ieee80211_hw *hw, u8 hw_queue) | ||
973 | { | ||
974 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
975 | rtl_write_word(rtlpriv, TP_POLL, BIT(0) << (hw_queue)); | ||
976 | } | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.h b/drivers/net/wireless/rtlwifi/rtl8192se/trx.h new file mode 100644 index 000000000000..05862c51b861 --- /dev/null +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Copyright(c) 2009-2010 Realtek Corporation. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of version 2 of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | ||
17 | * | ||
18 | * The full GNU General Public License is included in this distribution in the | ||
19 | * file called LICENSE. | ||
20 | * | ||
21 | * Contact Information: | ||
22 | * wlanfae <wlanfae@realtek.com> | ||
23 | * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, | ||
24 | * Hsinchu 300, Taiwan. | ||
25 | * | ||
26 | * Larry Finger <Larry.Finger@lwfinger.net> | ||
27 | * | ||
28 | *****************************************************************************/ | ||
29 | #ifndef __REALTEK_PCI92SE_TRX_H__ | ||
30 | #define __REALTEK_PCI92SE_TRX_H__ | ||
31 | |||
32 | void rtl92se_tx_fill_desc(struct ieee80211_hw *hw, struct ieee80211_hdr *hdr, | ||
33 | u8 *pdesc, struct ieee80211_tx_info *info, | ||
34 | struct sk_buff *skb, u8 hw_queue, | ||
35 | struct rtl_tcb_desc *ptcb_desc); | ||
36 | void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc, bool firstseg, | ||
37 | bool lastseg, struct sk_buff *skb); | ||
38 | bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, | ||
39 | struct ieee80211_rx_status *rx_status, u8 *pdesc, | ||
40 | struct sk_buff *skb); | ||
41 | void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val); | ||
42 | u32 rtl92se_get_desc(u8 *pdesc, bool istx, u8 desc_name); | ||
43 | void rtl92se_tx_polling(struct ieee80211_hw *hw, u8 hw_queue); | ||
44 | |||
45 | #endif | ||
diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c index a5c9c0aff83f..c6ee530e5bf7 100644 --- a/drivers/net/wireless/wl12xx/acx.c +++ b/drivers/net/wireless/wl12xx/acx.c | |||
@@ -325,12 +325,19 @@ out: | |||
325 | return ret; | 325 | return ret; |
326 | } | 326 | } |
327 | 327 | ||
328 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold) | 328 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold) |
329 | { | 329 | { |
330 | struct acx_rts_threshold *rts; | 330 | struct acx_rts_threshold *rts; |
331 | int ret; | 331 | int ret; |
332 | 332 | ||
333 | wl1271_debug(DEBUG_ACX, "acx rts threshold"); | 333 | /* |
334 | * If the RTS threshold is not configured or out of range, use the | ||
335 | * default value. | ||
336 | */ | ||
337 | if (rts_threshold > IEEE80211_MAX_RTS_THRESHOLD) | ||
338 | rts_threshold = wl->conf.rx.rts_threshold; | ||
339 | |||
340 | wl1271_debug(DEBUG_ACX, "acx rts threshold: %d", rts_threshold); | ||
334 | 341 | ||
335 | rts = kzalloc(sizeof(*rts), GFP_KERNEL); | 342 | rts = kzalloc(sizeof(*rts), GFP_KERNEL); |
336 | if (!rts) { | 343 | if (!rts) { |
@@ -338,7 +345,7 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold) | |||
338 | goto out; | 345 | goto out; |
339 | } | 346 | } |
340 | 347 | ||
341 | rts->threshold = cpu_to_le16(rts_threshold); | 348 | rts->threshold = cpu_to_le16((u16)rts_threshold); |
342 | 349 | ||
343 | ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); | 350 | ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); |
344 | if (ret < 0) { | 351 | if (ret < 0) { |
@@ -540,13 +547,13 @@ out: | |||
540 | return ret; | 547 | return ret; |
541 | } | 548 | } |
542 | 549 | ||
543 | int wl1271_acx_sg_cfg(struct wl1271 *wl) | 550 | int wl1271_acx_sta_sg_cfg(struct wl1271 *wl) |
544 | { | 551 | { |
545 | struct acx_bt_wlan_coex_param *param; | 552 | struct acx_sta_bt_wlan_coex_param *param; |
546 | struct conf_sg_settings *c = &wl->conf.sg; | 553 | struct conf_sg_settings *c = &wl->conf.sg; |
547 | int i, ret; | 554 | int i, ret; |
548 | 555 | ||
549 | wl1271_debug(DEBUG_ACX, "acx sg cfg"); | 556 | wl1271_debug(DEBUG_ACX, "acx sg sta cfg"); |
550 | 557 | ||
551 | param = kzalloc(sizeof(*param), GFP_KERNEL); | 558 | param = kzalloc(sizeof(*param), GFP_KERNEL); |
552 | if (!param) { | 559 | if (!param) { |
@@ -555,8 +562,38 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl) | |||
555 | } | 562 | } |
556 | 563 | ||
557 | /* BT-WLAN coext parameters */ | 564 | /* BT-WLAN coext parameters */ |
558 | for (i = 0; i < CONF_SG_PARAMS_MAX; i++) | 565 | for (i = 0; i < CONF_SG_STA_PARAMS_MAX; i++) |
559 | param->params[i] = cpu_to_le32(c->params[i]); | 566 | param->params[i] = cpu_to_le32(c->sta_params[i]); |
567 | param->param_idx = CONF_SG_PARAMS_ALL; | ||
568 | |||
569 | ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); | ||
570 | if (ret < 0) { | ||
571 | wl1271_warning("failed to set sg config: %d", ret); | ||
572 | goto out; | ||
573 | } | ||
574 | |||
575 | out: | ||
576 | kfree(param); | ||
577 | return ret; | ||
578 | } | ||
579 | |||
580 | int wl1271_acx_ap_sg_cfg(struct wl1271 *wl) | ||
581 | { | ||
582 | struct acx_ap_bt_wlan_coex_param *param; | ||
583 | struct conf_sg_settings *c = &wl->conf.sg; | ||
584 | int i, ret; | ||
585 | |||
586 | wl1271_debug(DEBUG_ACX, "acx sg ap cfg"); | ||
587 | |||
588 | param = kzalloc(sizeof(*param), GFP_KERNEL); | ||
589 | if (!param) { | ||
590 | ret = -ENOMEM; | ||
591 | goto out; | ||
592 | } | ||
593 | |||
594 | /* BT-WLAN coext parameters */ | ||
595 | for (i = 0; i < CONF_SG_AP_PARAMS_MAX; i++) | ||
596 | param->params[i] = cpu_to_le32(c->ap_params[i]); | ||
560 | param->param_idx = CONF_SG_PARAMS_ALL; | 597 | param->param_idx = CONF_SG_PARAMS_ALL; |
561 | 598 | ||
562 | ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); | 599 | ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); |
@@ -804,7 +841,8 @@ int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c, | |||
804 | struct acx_ap_rate_policy *acx; | 841 | struct acx_ap_rate_policy *acx; |
805 | int ret = 0; | 842 | int ret = 0; |
806 | 843 | ||
807 | wl1271_debug(DEBUG_ACX, "acx ap rate policy"); | 844 | wl1271_debug(DEBUG_ACX, "acx ap rate policy %d rates 0x%x", |
845 | idx, c->enabled_rates); | ||
808 | 846 | ||
809 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 847 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
810 | if (!acx) { | 848 | if (!acx) { |
@@ -898,12 +936,19 @@ out: | |||
898 | return ret; | 936 | return ret; |
899 | } | 937 | } |
900 | 938 | ||
901 | int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold) | 939 | int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold) |
902 | { | 940 | { |
903 | struct acx_frag_threshold *acx; | 941 | struct acx_frag_threshold *acx; |
904 | int ret = 0; | 942 | int ret = 0; |
905 | 943 | ||
906 | wl1271_debug(DEBUG_ACX, "acx frag threshold"); | 944 | /* |
945 | * If the fragmentation is not configured or out of range, use the | ||
946 | * default value. | ||
947 | */ | ||
948 | if (frag_threshold > IEEE80211_MAX_FRAG_THRESHOLD) | ||
949 | frag_threshold = wl->conf.tx.frag_threshold; | ||
950 | |||
951 | wl1271_debug(DEBUG_ACX, "acx frag threshold: %d", frag_threshold); | ||
907 | 952 | ||
908 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 953 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
909 | 954 | ||
@@ -912,7 +957,7 @@ int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold) | |||
912 | goto out; | 957 | goto out; |
913 | } | 958 | } |
914 | 959 | ||
915 | acx->frag_threshold = cpu_to_le16(frag_threshold); | 960 | acx->frag_threshold = cpu_to_le16((u16)frag_threshold); |
916 | ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx)); | 961 | ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx)); |
917 | if (ret < 0) { | 962 | if (ret < 0) { |
918 | wl1271_warning("Setting of frag threshold failed: %d", ret); | 963 | wl1271_warning("Setting of frag threshold failed: %d", ret); |
@@ -954,6 +999,7 @@ out: | |||
954 | int wl1271_acx_ap_mem_cfg(struct wl1271 *wl) | 999 | int wl1271_acx_ap_mem_cfg(struct wl1271 *wl) |
955 | { | 1000 | { |
956 | struct wl1271_acx_ap_config_memory *mem_conf; | 1001 | struct wl1271_acx_ap_config_memory *mem_conf; |
1002 | struct conf_memory_settings *mem; | ||
957 | int ret; | 1003 | int ret; |
958 | 1004 | ||
959 | wl1271_debug(DEBUG_ACX, "wl1271 mem cfg"); | 1005 | wl1271_debug(DEBUG_ACX, "wl1271 mem cfg"); |
@@ -964,14 +1010,21 @@ int wl1271_acx_ap_mem_cfg(struct wl1271 *wl) | |||
964 | goto out; | 1010 | goto out; |
965 | } | 1011 | } |
966 | 1012 | ||
1013 | if (wl->chip.id == CHIP_ID_1283_PG20) | ||
1014 | /* | ||
1015 | * FIXME: The 128x AP FW does not yet support dynamic memory. | ||
1016 | * Use the base memory configuration for 128x for now. This | ||
1017 | * should be fine tuned in the future. | ||
1018 | */ | ||
1019 | mem = &wl->conf.mem_wl128x; | ||
1020 | else | ||
1021 | mem = &wl->conf.mem_wl127x; | ||
1022 | |||
967 | /* memory config */ | 1023 | /* memory config */ |
968 | /* FIXME: for now we always use mem_wl127x for AP, because it | 1024 | mem_conf->num_stations = mem->num_stations; |
969 | * doesn't support dynamic memory and we don't have the | 1025 | mem_conf->rx_mem_block_num = mem->rx_block_num; |
970 | * optimal values for wl128x without dynamic memory yet */ | 1026 | mem_conf->tx_min_mem_block_num = mem->tx_min_block_num; |
971 | mem_conf->num_stations = wl->conf.mem_wl127x.num_stations; | 1027 | mem_conf->num_ssid_profiles = mem->ssid_profiles; |
972 | mem_conf->rx_mem_block_num = wl->conf.mem_wl127x.rx_block_num; | ||
973 | mem_conf->tx_min_mem_block_num = wl->conf.mem_wl127x.tx_min_block_num; | ||
974 | mem_conf->num_ssid_profiles = wl->conf.mem_wl127x.ssid_profiles; | ||
975 | mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); | 1028 | mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS); |
976 | 1029 | ||
977 | ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, | 1030 | ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, |
@@ -1524,46 +1577,22 @@ out: | |||
1524 | return ret; | 1577 | return ret; |
1525 | } | 1578 | } |
1526 | 1579 | ||
1527 | int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl) | 1580 | int wl1271_acx_max_tx_retry(struct wl1271 *wl) |
1528 | { | 1581 | { |
1529 | struct wl1271_acx_ap_max_tx_retry *acx = NULL; | 1582 | struct wl1271_acx_max_tx_retry *acx = NULL; |
1530 | int ret; | 1583 | int ret; |
1531 | 1584 | ||
1532 | wl1271_debug(DEBUG_ACX, "acx ap max tx retry"); | 1585 | wl1271_debug(DEBUG_ACX, "acx max tx retry"); |
1533 | 1586 | ||
1534 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | 1587 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); |
1535 | if (!acx) | 1588 | if (!acx) |
1536 | return -ENOMEM; | 1589 | return -ENOMEM; |
1537 | 1590 | ||
1538 | acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries); | 1591 | acx->max_tx_retry = cpu_to_le16(wl->conf.tx.ap_max_tx_retries); |
1539 | 1592 | ||
1540 | ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx)); | 1593 | ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx)); |
1541 | if (ret < 0) { | 1594 | if (ret < 0) { |
1542 | wl1271_warning("acx ap max tx retry failed: %d", ret); | 1595 | wl1271_warning("acx max tx retry failed: %d", ret); |
1543 | goto out; | ||
1544 | } | ||
1545 | |||
1546 | out: | ||
1547 | kfree(acx); | ||
1548 | return ret; | ||
1549 | } | ||
1550 | |||
1551 | int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl) | ||
1552 | { | ||
1553 | struct wl1271_acx_sta_max_tx_retry *acx = NULL; | ||
1554 | int ret; | ||
1555 | |||
1556 | wl1271_debug(DEBUG_ACX, "acx sta max tx retry"); | ||
1557 | |||
1558 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1559 | if (!acx) | ||
1560 | return -ENOMEM; | ||
1561 | |||
1562 | acx->max_tx_retry = wl->conf.tx.max_tx_retries; | ||
1563 | |||
1564 | ret = wl1271_cmd_configure(wl, ACX_CONS_TX_FAILURE, acx, sizeof(*acx)); | ||
1565 | if (ret < 0) { | ||
1566 | wl1271_warning("acx sta max tx retry failed: %d", ret); | ||
1567 | goto out; | 1596 | goto out; |
1568 | } | 1597 | } |
1569 | 1598 | ||
@@ -1626,3 +1655,68 @@ out: | |||
1626 | kfree(acx); | 1655 | kfree(acx); |
1627 | return ret; | 1656 | return ret; |
1628 | } | 1657 | } |
1658 | |||
1659 | int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable) | ||
1660 | { | ||
1661 | struct acx_ap_beacon_filter *acx = NULL; | ||
1662 | int ret; | ||
1663 | |||
1664 | wl1271_debug(DEBUG_ACX, "acx set ap beacon filter: %d", enable); | ||
1665 | |||
1666 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1667 | if (!acx) | ||
1668 | return -ENOMEM; | ||
1669 | |||
1670 | acx->enable = enable ? 1 : 0; | ||
1671 | |||
1672 | ret = wl1271_cmd_configure(wl, ACX_AP_BEACON_FILTER_OPT, | ||
1673 | acx, sizeof(*acx)); | ||
1674 | if (ret < 0) { | ||
1675 | wl1271_warning("acx set ap beacon filter failed: %d", ret); | ||
1676 | goto out; | ||
1677 | } | ||
1678 | |||
1679 | out: | ||
1680 | kfree(acx); | ||
1681 | return ret; | ||
1682 | } | ||
1683 | |||
1684 | int wl1271_acx_fm_coex(struct wl1271 *wl) | ||
1685 | { | ||
1686 | struct wl1271_acx_fm_coex *acx; | ||
1687 | int ret; | ||
1688 | |||
1689 | wl1271_debug(DEBUG_ACX, "acx fm coex setting"); | ||
1690 | |||
1691 | acx = kzalloc(sizeof(*acx), GFP_KERNEL); | ||
1692 | if (!acx) { | ||
1693 | ret = -ENOMEM; | ||
1694 | goto out; | ||
1695 | } | ||
1696 | |||
1697 | acx->enable = wl->conf.fm_coex.enable; | ||
1698 | acx->swallow_period = wl->conf.fm_coex.swallow_period; | ||
1699 | acx->n_divider_fref_set_1 = wl->conf.fm_coex.n_divider_fref_set_1; | ||
1700 | acx->n_divider_fref_set_2 = wl->conf.fm_coex.n_divider_fref_set_2; | ||
1701 | acx->m_divider_fref_set_1 = | ||
1702 | cpu_to_le16(wl->conf.fm_coex.m_divider_fref_set_1); | ||
1703 | acx->m_divider_fref_set_2 = | ||
1704 | cpu_to_le16(wl->conf.fm_coex.m_divider_fref_set_2); | ||
1705 | acx->coex_pll_stabilization_time = | ||
1706 | cpu_to_le32(wl->conf.fm_coex.coex_pll_stabilization_time); | ||
1707 | acx->ldo_stabilization_time = | ||
1708 | cpu_to_le16(wl->conf.fm_coex.ldo_stabilization_time); | ||
1709 | acx->fm_disturbed_band_margin = | ||
1710 | wl->conf.fm_coex.fm_disturbed_band_margin; | ||
1711 | acx->swallow_clk_diff = wl->conf.fm_coex.swallow_clk_diff; | ||
1712 | |||
1713 | ret = wl1271_cmd_configure(wl, ACX_FM_COEX_CFG, acx, sizeof(*acx)); | ||
1714 | if (ret < 0) { | ||
1715 | wl1271_warning("acx fm coex setting failed: %d", ret); | ||
1716 | goto out; | ||
1717 | } | ||
1718 | |||
1719 | out: | ||
1720 | kfree(acx); | ||
1721 | return ret; | ||
1722 | } | ||
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h index 942908cd53a3..9a895e3cc613 100644 --- a/drivers/net/wireless/wl12xx/acx.h +++ b/drivers/net/wireless/wl12xx/acx.h | |||
@@ -303,7 +303,6 @@ struct acx_beacon_filter_option { | |||
303 | struct acx_header header; | 303 | struct acx_header header; |
304 | 304 | ||
305 | u8 enable; | 305 | u8 enable; |
306 | |||
307 | /* | 306 | /* |
308 | * The number of beacons without the unicast TIM | 307 | * The number of beacons without the unicast TIM |
309 | * bit set that the firmware buffers before | 308 | * bit set that the firmware buffers before |
@@ -370,14 +369,23 @@ struct acx_bt_wlan_coex { | |||
370 | u8 pad[3]; | 369 | u8 pad[3]; |
371 | } __packed; | 370 | } __packed; |
372 | 371 | ||
373 | struct acx_bt_wlan_coex_param { | 372 | struct acx_sta_bt_wlan_coex_param { |
374 | struct acx_header header; | 373 | struct acx_header header; |
375 | 374 | ||
376 | __le32 params[CONF_SG_PARAMS_MAX]; | 375 | __le32 params[CONF_SG_STA_PARAMS_MAX]; |
377 | u8 param_idx; | 376 | u8 param_idx; |
378 | u8 padding[3]; | 377 | u8 padding[3]; |
379 | } __packed; | 378 | } __packed; |
380 | 379 | ||
380 | struct acx_ap_bt_wlan_coex_param { | ||
381 | struct acx_header header; | ||
382 | |||
383 | __le32 params[CONF_SG_AP_PARAMS_MAX]; | ||
384 | u8 param_idx; | ||
385 | u8 padding[3]; | ||
386 | } __packed; | ||
387 | |||
388 | |||
381 | struct acx_dco_itrim_params { | 389 | struct acx_dco_itrim_params { |
382 | struct acx_header header; | 390 | struct acx_header header; |
383 | 391 | ||
@@ -1145,7 +1153,7 @@ struct wl1271_acx_fw_tsf_information { | |||
1145 | u8 padding[3]; | 1153 | u8 padding[3]; |
1146 | } __packed; | 1154 | } __packed; |
1147 | 1155 | ||
1148 | struct wl1271_acx_ap_max_tx_retry { | 1156 | struct wl1271_acx_max_tx_retry { |
1149 | struct acx_header header; | 1157 | struct acx_header header; |
1150 | 1158 | ||
1151 | /* | 1159 | /* |
@@ -1156,13 +1164,6 @@ struct wl1271_acx_ap_max_tx_retry { | |||
1156 | u8 padding_1[2]; | 1164 | u8 padding_1[2]; |
1157 | } __packed; | 1165 | } __packed; |
1158 | 1166 | ||
1159 | struct wl1271_acx_sta_max_tx_retry { | ||
1160 | struct acx_header header; | ||
1161 | |||
1162 | u8 max_tx_retry; | ||
1163 | u8 padding_1[3]; | ||
1164 | } __packed; | ||
1165 | |||
1166 | struct wl1271_acx_config_ps { | 1167 | struct wl1271_acx_config_ps { |
1167 | struct acx_header header; | 1168 | struct acx_header header; |
1168 | 1169 | ||
@@ -1179,6 +1180,72 @@ struct wl1271_acx_inconnection_sta { | |||
1179 | u8 padding1[2]; | 1180 | u8 padding1[2]; |
1180 | } __packed; | 1181 | } __packed; |
1181 | 1182 | ||
1183 | struct acx_ap_beacon_filter { | ||
1184 | struct acx_header header; | ||
1185 | |||
1186 | u8 enable; | ||
1187 | u8 pad[3]; | ||
1188 | } __packed; | ||
1189 | |||
1190 | /* | ||
1191 | * ACX_FM_COEX_CFG | ||
1192 | * set the FM co-existence parameters. | ||
1193 | */ | ||
1194 | struct wl1271_acx_fm_coex { | ||
1195 | struct acx_header header; | ||
1196 | /* enable(1) / disable(0) the FM Coex feature */ | ||
1197 | u8 enable; | ||
1198 | /* | ||
1199 | * Swallow period used in COEX PLL swallowing mechanism. | ||
1200 | * 0xFF = use FW default | ||
1201 | */ | ||
1202 | u8 swallow_period; | ||
1203 | /* | ||
1204 | * The N divider used in COEX PLL swallowing mechanism for Fref of | ||
1205 | * 38.4/19.2 Mhz. 0xFF = use FW default | ||
1206 | */ | ||
1207 | u8 n_divider_fref_set_1; | ||
1208 | /* | ||
1209 | * The N divider used in COEX PLL swallowing mechanism for Fref of | ||
1210 | * 26/52 Mhz. 0xFF = use FW default | ||
1211 | */ | ||
1212 | u8 n_divider_fref_set_2; | ||
1213 | /* | ||
1214 | * The M divider used in COEX PLL swallowing mechanism for Fref of | ||
1215 | * 38.4/19.2 Mhz. 0xFFFF = use FW default | ||
1216 | */ | ||
1217 | __le16 m_divider_fref_set_1; | ||
1218 | /* | ||
1219 | * The M divider used in COEX PLL swallowing mechanism for Fref of | ||
1220 | * 26/52 Mhz. 0xFFFF = use FW default | ||
1221 | */ | ||
1222 | __le16 m_divider_fref_set_2; | ||
1223 | /* | ||
1224 | * The time duration in uSec required for COEX PLL to stabilize. | ||
1225 | * 0xFFFFFFFF = use FW default | ||
1226 | */ | ||
1227 | __le32 coex_pll_stabilization_time; | ||
1228 | /* | ||
1229 | * The time duration in uSec required for LDO to stabilize. | ||
1230 | * 0xFFFFFFFF = use FW default | ||
1231 | */ | ||
1232 | __le16 ldo_stabilization_time; | ||
1233 | /* | ||
1234 | * The disturbed frequency band margin around the disturbed frequency | ||
1235 | * center (single sided). | ||
1236 | * For example, if 2 is configured, the following channels will be | ||
1237 | * considered disturbed channel: | ||
1238 | * 80 +- 0.1 MHz, 91 +- 0.1 MHz, 98 +- 0.1 MHz, 102 +- 0.1 MH | ||
1239 | * 0xFF = use FW default | ||
1240 | */ | ||
1241 | u8 fm_disturbed_band_margin; | ||
1242 | /* | ||
1243 | * The swallow clock difference of the swallowing mechanism. | ||
1244 | * 0xFF = use FW default | ||
1245 | */ | ||
1246 | u8 swallow_clk_diff; | ||
1247 | } __packed; | ||
1248 | |||
1182 | enum { | 1249 | enum { |
1183 | ACX_WAKE_UP_CONDITIONS = 0x0002, | 1250 | ACX_WAKE_UP_CONDITIONS = 0x0002, |
1184 | ACX_MEM_CFG = 0x0003, | 1251 | ACX_MEM_CFG = 0x0003, |
@@ -1197,6 +1264,7 @@ enum { | |||
1197 | ACX_TID_CFG = 0x001A, | 1264 | ACX_TID_CFG = 0x001A, |
1198 | ACX_PS_RX_STREAMING = 0x001B, | 1265 | ACX_PS_RX_STREAMING = 0x001B, |
1199 | ACX_BEACON_FILTER_OPT = 0x001F, | 1266 | ACX_BEACON_FILTER_OPT = 0x001F, |
1267 | ACX_AP_BEACON_FILTER_OPT = 0x0020, | ||
1200 | ACX_NOISE_HIST = 0x0021, | 1268 | ACX_NOISE_HIST = 0x0021, |
1201 | ACX_HDK_VERSION = 0x0022, /* ??? */ | 1269 | ACX_HDK_VERSION = 0x0022, /* ??? */ |
1202 | ACX_PD_THRESHOLD = 0x0023, | 1270 | ACX_PD_THRESHOLD = 0x0023, |
@@ -1208,6 +1276,7 @@ enum { | |||
1208 | ACX_BCN_DTIM_OPTIONS = 0x0031, | 1276 | ACX_BCN_DTIM_OPTIONS = 0x0031, |
1209 | ACX_SG_ENABLE = 0x0032, | 1277 | ACX_SG_ENABLE = 0x0032, |
1210 | ACX_SG_CFG = 0x0033, | 1278 | ACX_SG_CFG = 0x0033, |
1279 | ACX_FM_COEX_CFG = 0x0034, | ||
1211 | ACX_BEACON_FILTER_TABLE = 0x0038, | 1280 | ACX_BEACON_FILTER_TABLE = 0x0038, |
1212 | ACX_ARP_IP_FILTER = 0x0039, | 1281 | ACX_ARP_IP_FILTER = 0x0039, |
1213 | ACX_ROAMING_STATISTICS_TBL = 0x003B, | 1282 | ACX_ROAMING_STATISTICS_TBL = 0x003B, |
@@ -1264,13 +1333,14 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time); | |||
1264 | int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, | 1333 | int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable, |
1265 | void *mc_list, u32 mc_list_len); | 1334 | void *mc_list, u32 mc_list_len); |
1266 | int wl1271_acx_service_period_timeout(struct wl1271 *wl); | 1335 | int wl1271_acx_service_period_timeout(struct wl1271 *wl); |
1267 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); | 1336 | int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold); |
1268 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl); | 1337 | int wl1271_acx_dco_itrim_params(struct wl1271 *wl); |
1269 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); | 1338 | int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter); |
1270 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); | 1339 | int wl1271_acx_beacon_filter_table(struct wl1271 *wl); |
1271 | int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable); | 1340 | int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable); |
1272 | int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); | 1341 | int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable); |
1273 | int wl1271_acx_sg_cfg(struct wl1271 *wl); | 1342 | int wl1271_acx_sta_sg_cfg(struct wl1271 *wl); |
1343 | int wl1271_acx_ap_sg_cfg(struct wl1271 *wl); | ||
1274 | int wl1271_acx_cca_threshold(struct wl1271 *wl); | 1344 | int wl1271_acx_cca_threshold(struct wl1271 *wl); |
1275 | int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); | 1345 | int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); |
1276 | int wl1271_acx_aid(struct wl1271 *wl, u16 aid); | 1346 | int wl1271_acx_aid(struct wl1271 *wl, u16 aid); |
@@ -1287,7 +1357,7 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max, | |||
1287 | int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, | 1357 | int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type, |
1288 | u8 tsid, u8 ps_scheme, u8 ack_policy, | 1358 | u8 tsid, u8 ps_scheme, u8 ack_policy, |
1289 | u32 apsd_conf0, u32 apsd_conf1); | 1359 | u32 apsd_conf0, u32 apsd_conf1); |
1290 | int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold); | 1360 | int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold); |
1291 | int wl1271_acx_tx_config_options(struct wl1271 *wl); | 1361 | int wl1271_acx_tx_config_options(struct wl1271 *wl); |
1292 | int wl1271_acx_ap_mem_cfg(struct wl1271 *wl); | 1362 | int wl1271_acx_ap_mem_cfg(struct wl1271 *wl); |
1293 | int wl1271_acx_sta_mem_cfg(struct wl1271 *wl); | 1363 | int wl1271_acx_sta_mem_cfg(struct wl1271 *wl); |
@@ -1314,9 +1384,10 @@ int wl1271_acx_set_ba_session(struct wl1271 *wl, | |||
1314 | int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, | 1384 | int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn, |
1315 | bool enable); | 1385 | bool enable); |
1316 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); | 1386 | int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime); |
1317 | int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl); | 1387 | int wl1271_acx_max_tx_retry(struct wl1271 *wl); |
1318 | int wl1271_acx_sta_max_tx_retry(struct wl1271 *wl); | ||
1319 | int wl1271_acx_config_ps(struct wl1271 *wl); | 1388 | int wl1271_acx_config_ps(struct wl1271 *wl); |
1320 | int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); | 1389 | int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr); |
1390 | int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable); | ||
1391 | int wl1271_acx_fm_coex(struct wl1271 *wl); | ||
1321 | 1392 | ||
1322 | #endif /* __WL1271_ACX_H__ */ | 1393 | #endif /* __WL1271_ACX_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c index d263ebb6f974..b07f8b7e5f11 100644 --- a/drivers/net/wireless/wl12xx/boot.c +++ b/drivers/net/wireless/wl12xx/boot.c | |||
@@ -479,11 +479,11 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl) | |||
479 | RSSI_SNR_TRIGGER_0_EVENT_ID | | 479 | RSSI_SNR_TRIGGER_0_EVENT_ID | |
480 | PSPOLL_DELIVERY_FAILURE_EVENT_ID | | 480 | PSPOLL_DELIVERY_FAILURE_EVENT_ID | |
481 | SOFT_GEMINI_SENSE_EVENT_ID | | 481 | SOFT_GEMINI_SENSE_EVENT_ID | |
482 | MAX_TX_RETRY_EVENT_ID; | 482 | PERIODIC_SCAN_REPORT_EVENT_ID | |
483 | PERIODIC_SCAN_COMPLETE_EVENT_ID; | ||
483 | 484 | ||
484 | if (wl->bss_type == BSS_TYPE_AP_BSS) | 485 | if (wl->bss_type == BSS_TYPE_AP_BSS) |
485 | wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID | | 486 | wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID; |
486 | INACTIVE_STA_EVENT_ID; | ||
487 | else | 487 | else |
488 | wl->event_mask |= DUMMY_PACKET_EVENT_ID; | 488 | wl->event_mask |= DUMMY_PACKET_EVENT_ID; |
489 | 489 | ||
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c index 69d24f35cd9a..42935ac72663 100644 --- a/drivers/net/wireless/wl12xx/cmd.c +++ b/drivers/net/wireless/wl12xx/cmd.c | |||
@@ -76,7 +76,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
76 | if (time_after(jiffies, timeout)) { | 76 | if (time_after(jiffies, timeout)) { |
77 | wl1271_error("command complete timeout"); | 77 | wl1271_error("command complete timeout"); |
78 | ret = -ETIMEDOUT; | 78 | ret = -ETIMEDOUT; |
79 | goto out; | 79 | goto fail; |
80 | } | 80 | } |
81 | 81 | ||
82 | poll_count++; | 82 | poll_count++; |
@@ -96,14 +96,17 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
96 | status = le16_to_cpu(cmd->status); | 96 | status = le16_to_cpu(cmd->status); |
97 | if (status != CMD_STATUS_SUCCESS) { | 97 | if (status != CMD_STATUS_SUCCESS) { |
98 | wl1271_error("command execute failure %d", status); | 98 | wl1271_error("command execute failure %d", status); |
99 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
100 | ret = -EIO; | 99 | ret = -EIO; |
100 | goto fail; | ||
101 | } | 101 | } |
102 | 102 | ||
103 | wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, | 103 | wl1271_write32(wl, ACX_REG_INTERRUPT_ACK, |
104 | WL1271_ACX_INTR_CMD_COMPLETE); | 104 | WL1271_ACX_INTR_CMD_COMPLETE); |
105 | return 0; | ||
105 | 106 | ||
106 | out: | 107 | fail: |
108 | WARN_ON(1); | ||
109 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
107 | return ret; | 110 | return ret; |
108 | } | 111 | } |
109 | 112 | ||
@@ -129,6 +132,9 @@ int wl1271_cmd_general_parms(struct wl1271 *wl) | |||
129 | if (gp->tx_bip_fem_auto_detect) | 132 | if (gp->tx_bip_fem_auto_detect) |
130 | answer = true; | 133 | answer = true; |
131 | 134 | ||
135 | /* Override the REF CLK from the NVS with the one from platform data */ | ||
136 | gen_parms->general_params.ref_clock = wl->ref_clock; | ||
137 | |||
132 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); | 138 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); |
133 | if (ret < 0) { | 139 | if (ret < 0) { |
134 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); | 140 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); |
@@ -168,6 +174,10 @@ int wl128x_cmd_general_parms(struct wl1271 *wl) | |||
168 | if (gp->tx_bip_fem_auto_detect) | 174 | if (gp->tx_bip_fem_auto_detect) |
169 | answer = true; | 175 | answer = true; |
170 | 176 | ||
177 | /* Replace REF and TCXO CLKs with the ones from platform data */ | ||
178 | gen_parms->general_params.ref_clock = wl->ref_clock; | ||
179 | gen_parms->general_params.tcxo_ref_clock = wl->tcxo_clock; | ||
180 | |||
171 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); | 181 | ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), answer); |
172 | if (ret < 0) { | 182 | if (ret < 0) { |
173 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); | 183 | wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); |
@@ -1070,7 +1080,7 @@ int wl1271_cmd_start_bss(struct wl1271 *wl) | |||
1070 | 1080 | ||
1071 | memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN); | 1081 | memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN); |
1072 | 1082 | ||
1073 | cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period); | 1083 | cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC); |
1074 | cmd->bss_index = WL1271_AP_BSS_INDEX; | 1084 | cmd->bss_index = WL1271_AP_BSS_INDEX; |
1075 | cmd->global_hlid = WL1271_AP_GLOBAL_HLID; | 1085 | cmd->global_hlid = WL1271_AP_GLOBAL_HLID; |
1076 | cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID; | 1086 | cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID; |
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h index e3de91528de8..1ab6c86aac40 100644 --- a/drivers/net/wireless/wl12xx/conf.h +++ b/drivers/net/wireless/wl12xx/conf.h | |||
@@ -396,12 +396,43 @@ enum { | |||
396 | CONF_SG_TEMP_PARAM_3, | 396 | CONF_SG_TEMP_PARAM_3, |
397 | CONF_SG_TEMP_PARAM_4, | 397 | CONF_SG_TEMP_PARAM_4, |
398 | CONF_SG_TEMP_PARAM_5, | 398 | CONF_SG_TEMP_PARAM_5, |
399 | CONF_SG_PARAMS_MAX, | 399 | |
400 | /* | ||
401 | * AP beacon miss | ||
402 | * | ||
403 | * Range: 0 - 255 | ||
404 | */ | ||
405 | CONF_SG_AP_BEACON_MISS_TX, | ||
406 | |||
407 | /* | ||
408 | * AP RX window length | ||
409 | * | ||
410 | * Range: 0 - 50 | ||
411 | */ | ||
412 | CONF_SG_RX_WINDOW_LENGTH, | ||
413 | |||
414 | /* | ||
415 | * AP connection protection time | ||
416 | * | ||
417 | * Range: 0 - 5000 | ||
418 | */ | ||
419 | CONF_SG_AP_CONNECTION_PROTECTION_TIME, | ||
420 | |||
421 | CONF_SG_TEMP_PARAM_6, | ||
422 | CONF_SG_TEMP_PARAM_7, | ||
423 | CONF_SG_TEMP_PARAM_8, | ||
424 | CONF_SG_TEMP_PARAM_9, | ||
425 | CONF_SG_TEMP_PARAM_10, | ||
426 | |||
427 | CONF_SG_STA_PARAMS_MAX = CONF_SG_TEMP_PARAM_5 + 1, | ||
428 | CONF_SG_AP_PARAMS_MAX = CONF_SG_TEMP_PARAM_10 + 1, | ||
429 | |||
400 | CONF_SG_PARAMS_ALL = 0xff | 430 | CONF_SG_PARAMS_ALL = 0xff |
401 | }; | 431 | }; |
402 | 432 | ||
403 | struct conf_sg_settings { | 433 | struct conf_sg_settings { |
404 | u32 params[CONF_SG_PARAMS_MAX]; | 434 | u32 sta_params[CONF_SG_STA_PARAMS_MAX]; |
435 | u32 ap_params[CONF_SG_AP_PARAMS_MAX]; | ||
405 | u8 state; | 436 | u8 state; |
406 | }; | 437 | }; |
407 | 438 | ||
@@ -509,6 +540,12 @@ struct conf_rx_settings { | |||
509 | CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ | 540 | CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ |
510 | CONF_HW_BIT_RATE_54MBPS) | 541 | CONF_HW_BIT_RATE_54MBPS) |
511 | 542 | ||
543 | #define CONF_TX_OFDM_RATES (CONF_HW_BIT_RATE_6MBPS | \ | ||
544 | CONF_HW_BIT_RATE_12MBPS | CONF_HW_BIT_RATE_24MBPS | \ | ||
545 | CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS | \ | ||
546 | CONF_HW_BIT_RATE_54MBPS) | ||
547 | |||
548 | |||
512 | /* | 549 | /* |
513 | * Default rates for management traffic when operating in AP mode. This | 550 | * Default rates for management traffic when operating in AP mode. This |
514 | * should be configured according to the basic rate set of the AP | 551 | * should be configured according to the basic rate set of the AP |
@@ -516,6 +553,13 @@ struct conf_rx_settings { | |||
516 | #define CONF_TX_AP_DEFAULT_MGMT_RATES (CONF_HW_BIT_RATE_1MBPS | \ | 553 | #define CONF_TX_AP_DEFAULT_MGMT_RATES (CONF_HW_BIT_RATE_1MBPS | \ |
517 | CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS) | 554 | CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS) |
518 | 555 | ||
556 | /* | ||
557 | * Default rates for working as IBSS. use 11b rates | ||
558 | */ | ||
559 | #define CONF_TX_IBSS_DEFAULT_RATES (CONF_HW_BIT_RATE_1MBPS | \ | ||
560 | CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \ | ||
561 | CONF_HW_BIT_RATE_11MBPS); | ||
562 | |||
519 | struct conf_tx_rate_class { | 563 | struct conf_tx_rate_class { |
520 | 564 | ||
521 | /* | 565 | /* |
@@ -667,34 +711,10 @@ struct conf_tx_settings { | |||
667 | struct conf_tx_ac_category ac_conf[CONF_TX_MAX_AC_COUNT]; | 711 | struct conf_tx_ac_category ac_conf[CONF_TX_MAX_AC_COUNT]; |
668 | 712 | ||
669 | /* | 713 | /* |
670 | * Configuration for rate classes in AP-mode. These rate classes | 714 | * AP-mode - allow this number of TX retries to a station before an |
671 | * are for the AC TX queues | ||
672 | */ | ||
673 | struct conf_tx_rate_class ap_rc_conf[CONF_TX_MAX_AC_COUNT]; | ||
674 | |||
675 | /* | ||
676 | * Management TX rate class for AP-mode. | ||
677 | */ | ||
678 | struct conf_tx_rate_class ap_mgmt_conf; | ||
679 | |||
680 | /* | ||
681 | * Broadcast TX rate class for AP-mode. | ||
682 | */ | ||
683 | struct conf_tx_rate_class ap_bcst_conf; | ||
684 | |||
685 | /* | ||
686 | * Allow this number of TX retries to a connected station/AP before an | ||
687 | * event is triggered from FW. | 715 | * event is triggered from FW. |
688 | * In AP-mode the hlids of unreachable stations are given in the | ||
689 | * "sta_tx_retry_exceeded" member in the event mailbox. | ||
690 | */ | ||
691 | u8 max_tx_retries; | ||
692 | |||
693 | /* | ||
694 | * AP-mode - after this number of seconds a connected station is | ||
695 | * considered inactive. | ||
696 | */ | 716 | */ |
697 | u16 ap_aging_period; | 717 | u16 ap_max_tx_retries; |
698 | 718 | ||
699 | /* | 719 | /* |
700 | * Configuration for TID parameters. | 720 | * Configuration for TID parameters. |
@@ -1127,6 +1147,26 @@ struct conf_scan_settings { | |||
1127 | 1147 | ||
1128 | }; | 1148 | }; |
1129 | 1149 | ||
1150 | struct conf_sched_scan_settings { | ||
1151 | /* minimum time to wait on the channel for active scans (in TUs) */ | ||
1152 | u16 min_dwell_time_active; | ||
1153 | |||
1154 | /* maximum time to wait on the channel for active scans (in TUs) */ | ||
1155 | u16 max_dwell_time_active; | ||
1156 | |||
1157 | /* time to wait on the channel for passive scans (in TUs) */ | ||
1158 | u32 dwell_time_passive; | ||
1159 | |||
1160 | /* number of probe requests to send on each channel in active scans */ | ||
1161 | u8 num_probe_reqs; | ||
1162 | |||
1163 | /* RSSI threshold to be used for filtering */ | ||
1164 | s8 rssi_threshold; | ||
1165 | |||
1166 | /* SNR threshold to be used for filtering */ | ||
1167 | s8 snr_threshold; | ||
1168 | }; | ||
1169 | |||
1130 | /* these are number of channels on the band divided by two, rounded up */ | 1170 | /* these are number of channels on the band divided by two, rounded up */ |
1131 | #define CONF_TX_PWR_COMPENSATION_LEN_2 7 | 1171 | #define CONF_TX_PWR_COMPENSATION_LEN_2 7 |
1132 | #define CONF_TX_PWR_COMPENSATION_LEN_5 18 | 1172 | #define CONF_TX_PWR_COMPENSATION_LEN_5 18 |
@@ -1192,6 +1232,19 @@ struct conf_memory_settings { | |||
1192 | u8 tx_min; | 1232 | u8 tx_min; |
1193 | }; | 1233 | }; |
1194 | 1234 | ||
1235 | struct conf_fm_coex { | ||
1236 | u8 enable; | ||
1237 | u8 swallow_period; | ||
1238 | u8 n_divider_fref_set_1; | ||
1239 | u8 n_divider_fref_set_2; | ||
1240 | u16 m_divider_fref_set_1; | ||
1241 | u16 m_divider_fref_set_2; | ||
1242 | u32 coex_pll_stabilization_time; | ||
1243 | u16 ldo_stabilization_time; | ||
1244 | u8 fm_disturbed_band_margin; | ||
1245 | u8 swallow_clk_diff; | ||
1246 | }; | ||
1247 | |||
1195 | struct conf_drv_settings { | 1248 | struct conf_drv_settings { |
1196 | struct conf_sg_settings sg; | 1249 | struct conf_sg_settings sg; |
1197 | struct conf_rx_settings rx; | 1250 | struct conf_rx_settings rx; |
@@ -1201,10 +1254,12 @@ struct conf_drv_settings { | |||
1201 | struct conf_pm_config_settings pm_config; | 1254 | struct conf_pm_config_settings pm_config; |
1202 | struct conf_roam_trigger_settings roam_trigger; | 1255 | struct conf_roam_trigger_settings roam_trigger; |
1203 | struct conf_scan_settings scan; | 1256 | struct conf_scan_settings scan; |
1257 | struct conf_sched_scan_settings sched_scan; | ||
1204 | struct conf_rf_settings rf; | 1258 | struct conf_rf_settings rf; |
1205 | struct conf_ht_setting ht; | 1259 | struct conf_ht_setting ht; |
1206 | struct conf_memory_settings mem_wl127x; | 1260 | struct conf_memory_settings mem_wl127x; |
1207 | struct conf_memory_settings mem_wl128x; | 1261 | struct conf_memory_settings mem_wl128x; |
1262 | struct conf_fm_coex fm_coex; | ||
1208 | u8 hci_io_ds; | 1263 | u8 hci_io_ds; |
1209 | }; | 1264 | }; |
1210 | 1265 | ||
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c index 70ab1986788e..f1f8df9b6cd7 100644 --- a/drivers/net/wireless/wl12xx/debugfs.c +++ b/drivers/net/wireless/wl12xx/debugfs.c | |||
@@ -291,6 +291,242 @@ static const struct file_operations gpio_power_ops = { | |||
291 | .llseek = default_llseek, | 291 | .llseek = default_llseek, |
292 | }; | 292 | }; |
293 | 293 | ||
294 | static ssize_t start_recovery_write(struct file *file, | ||
295 | const char __user *user_buf, | ||
296 | size_t count, loff_t *ppos) | ||
297 | { | ||
298 | struct wl1271 *wl = file->private_data; | ||
299 | |||
300 | mutex_lock(&wl->mutex); | ||
301 | ieee80211_queue_work(wl->hw, &wl->recovery_work); | ||
302 | mutex_unlock(&wl->mutex); | ||
303 | |||
304 | return count; | ||
305 | } | ||
306 | |||
307 | static const struct file_operations start_recovery_ops = { | ||
308 | .write = start_recovery_write, | ||
309 | .open = wl1271_open_file_generic, | ||
310 | .llseek = default_llseek, | ||
311 | }; | ||
312 | |||
313 | static ssize_t driver_state_read(struct file *file, char __user *user_buf, | ||
314 | size_t count, loff_t *ppos) | ||
315 | { | ||
316 | struct wl1271 *wl = file->private_data; | ||
317 | int res = 0; | ||
318 | char buf[1024]; | ||
319 | |||
320 | mutex_lock(&wl->mutex); | ||
321 | |||
322 | #define DRIVER_STATE_PRINT(x, fmt) \ | ||
323 | (res += scnprintf(buf + res, sizeof(buf) - res,\ | ||
324 | #x " = " fmt "\n", wl->x)) | ||
325 | |||
326 | #define DRIVER_STATE_PRINT_LONG(x) DRIVER_STATE_PRINT(x, "%ld") | ||
327 | #define DRIVER_STATE_PRINT_INT(x) DRIVER_STATE_PRINT(x, "%d") | ||
328 | #define DRIVER_STATE_PRINT_STR(x) DRIVER_STATE_PRINT(x, "%s") | ||
329 | #define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx") | ||
330 | #define DRIVER_STATE_PRINT_HEX(x) DRIVER_STATE_PRINT(x, "0x%x") | ||
331 | |||
332 | DRIVER_STATE_PRINT_INT(tx_blocks_available); | ||
333 | DRIVER_STATE_PRINT_INT(tx_allocated_blocks); | ||
334 | DRIVER_STATE_PRINT_INT(tx_frames_cnt); | ||
335 | DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]); | ||
336 | DRIVER_STATE_PRINT_INT(tx_queue_count); | ||
337 | DRIVER_STATE_PRINT_INT(tx_packets_count); | ||
338 | DRIVER_STATE_PRINT_INT(tx_results_count); | ||
339 | DRIVER_STATE_PRINT_LHEX(flags); | ||
340 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[0]); | ||
341 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[1]); | ||
342 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[2]); | ||
343 | DRIVER_STATE_PRINT_INT(tx_blocks_freed[3]); | ||
344 | DRIVER_STATE_PRINT_INT(tx_security_last_seq); | ||
345 | DRIVER_STATE_PRINT_INT(rx_counter); | ||
346 | DRIVER_STATE_PRINT_INT(session_counter); | ||
347 | DRIVER_STATE_PRINT_INT(state); | ||
348 | DRIVER_STATE_PRINT_INT(bss_type); | ||
349 | DRIVER_STATE_PRINT_INT(channel); | ||
350 | DRIVER_STATE_PRINT_HEX(rate_set); | ||
351 | DRIVER_STATE_PRINT_HEX(basic_rate_set); | ||
352 | DRIVER_STATE_PRINT_HEX(basic_rate); | ||
353 | DRIVER_STATE_PRINT_INT(band); | ||
354 | DRIVER_STATE_PRINT_INT(beacon_int); | ||
355 | DRIVER_STATE_PRINT_INT(psm_entry_retry); | ||
356 | DRIVER_STATE_PRINT_INT(ps_poll_failures); | ||
357 | DRIVER_STATE_PRINT_HEX(filters); | ||
358 | DRIVER_STATE_PRINT_HEX(rx_config); | ||
359 | DRIVER_STATE_PRINT_HEX(rx_filter); | ||
360 | DRIVER_STATE_PRINT_INT(power_level); | ||
361 | DRIVER_STATE_PRINT_INT(rssi_thold); | ||
362 | DRIVER_STATE_PRINT_INT(last_rssi_event); | ||
363 | DRIVER_STATE_PRINT_INT(sg_enabled); | ||
364 | DRIVER_STATE_PRINT_INT(enable_11a); | ||
365 | DRIVER_STATE_PRINT_INT(noise); | ||
366 | DRIVER_STATE_PRINT_LHEX(ap_hlid_map[0]); | ||
367 | DRIVER_STATE_PRINT_INT(last_tx_hlid); | ||
368 | DRIVER_STATE_PRINT_INT(ba_support); | ||
369 | DRIVER_STATE_PRINT_HEX(ba_rx_bitmap); | ||
370 | DRIVER_STATE_PRINT_HEX(ap_fw_ps_map); | ||
371 | DRIVER_STATE_PRINT_LHEX(ap_ps_map); | ||
372 | DRIVER_STATE_PRINT_HEX(quirks); | ||
373 | DRIVER_STATE_PRINT_HEX(irq); | ||
374 | DRIVER_STATE_PRINT_HEX(ref_clock); | ||
375 | DRIVER_STATE_PRINT_HEX(tcxo_clock); | ||
376 | DRIVER_STATE_PRINT_HEX(hw_pg_ver); | ||
377 | DRIVER_STATE_PRINT_HEX(platform_quirks); | ||
378 | DRIVER_STATE_PRINT_HEX(chip.id); | ||
379 | DRIVER_STATE_PRINT_STR(chip.fw_ver_str); | ||
380 | DRIVER_STATE_PRINT_INT(sched_scanning); | ||
381 | |||
382 | #undef DRIVER_STATE_PRINT_INT | ||
383 | #undef DRIVER_STATE_PRINT_LONG | ||
384 | #undef DRIVER_STATE_PRINT_HEX | ||
385 | #undef DRIVER_STATE_PRINT_LHEX | ||
386 | #undef DRIVER_STATE_PRINT_STR | ||
387 | #undef DRIVER_STATE_PRINT | ||
388 | |||
389 | mutex_unlock(&wl->mutex); | ||
390 | |||
391 | return simple_read_from_buffer(user_buf, count, ppos, buf, res); | ||
392 | } | ||
393 | |||
394 | static const struct file_operations driver_state_ops = { | ||
395 | .read = driver_state_read, | ||
396 | .open = wl1271_open_file_generic, | ||
397 | .llseek = default_llseek, | ||
398 | }; | ||
399 | |||
400 | static ssize_t dtim_interval_read(struct file *file, char __user *user_buf, | ||
401 | size_t count, loff_t *ppos) | ||
402 | { | ||
403 | struct wl1271 *wl = file->private_data; | ||
404 | u8 value; | ||
405 | |||
406 | if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_DTIM || | ||
407 | wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_DTIM) | ||
408 | value = wl->conf.conn.listen_interval; | ||
409 | else | ||
410 | value = 0; | ||
411 | |||
412 | return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value); | ||
413 | } | ||
414 | |||
415 | static ssize_t dtim_interval_write(struct file *file, | ||
416 | const char __user *user_buf, | ||
417 | size_t count, loff_t *ppos) | ||
418 | { | ||
419 | struct wl1271 *wl = file->private_data; | ||
420 | char buf[10]; | ||
421 | size_t len; | ||
422 | unsigned long value; | ||
423 | int ret; | ||
424 | |||
425 | len = min(count, sizeof(buf) - 1); | ||
426 | if (copy_from_user(buf, user_buf, len)) | ||
427 | return -EFAULT; | ||
428 | buf[len] = '\0'; | ||
429 | |||
430 | ret = kstrtoul(buf, 0, &value); | ||
431 | if (ret < 0) { | ||
432 | wl1271_warning("illegal value for dtim_interval"); | ||
433 | return -EINVAL; | ||
434 | } | ||
435 | |||
436 | if (value < 1 || value > 10) { | ||
437 | wl1271_warning("dtim value is not in valid range"); | ||
438 | return -ERANGE; | ||
439 | } | ||
440 | |||
441 | mutex_lock(&wl->mutex); | ||
442 | |||
443 | wl->conf.conn.listen_interval = value; | ||
444 | /* for some reason there are different event types for 1 and >1 */ | ||
445 | if (value == 1) | ||
446 | wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_DTIM; | ||
447 | else | ||
448 | wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_DTIM; | ||
449 | |||
450 | /* | ||
451 | * we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only | ||
452 | * take effect on the next time we enter psm. | ||
453 | */ | ||
454 | mutex_unlock(&wl->mutex); | ||
455 | return count; | ||
456 | } | ||
457 | |||
458 | static const struct file_operations dtim_interval_ops = { | ||
459 | .read = dtim_interval_read, | ||
460 | .write = dtim_interval_write, | ||
461 | .open = wl1271_open_file_generic, | ||
462 | .llseek = default_llseek, | ||
463 | }; | ||
464 | |||
465 | static ssize_t beacon_interval_read(struct file *file, char __user *user_buf, | ||
466 | size_t count, loff_t *ppos) | ||
467 | { | ||
468 | struct wl1271 *wl = file->private_data; | ||
469 | u8 value; | ||
470 | |||
471 | if (wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_BEACON || | ||
472 | wl->conf.conn.wake_up_event == CONF_WAKE_UP_EVENT_N_BEACONS) | ||
473 | value = wl->conf.conn.listen_interval; | ||
474 | else | ||
475 | value = 0; | ||
476 | |||
477 | return wl1271_format_buffer(user_buf, count, ppos, "%d\n", value); | ||
478 | } | ||
479 | |||
480 | static ssize_t beacon_interval_write(struct file *file, | ||
481 | const char __user *user_buf, | ||
482 | size_t count, loff_t *ppos) | ||
483 | { | ||
484 | struct wl1271 *wl = file->private_data; | ||
485 | char buf[10]; | ||
486 | size_t len; | ||
487 | unsigned long value; | ||
488 | int ret; | ||
489 | |||
490 | len = min(count, sizeof(buf) - 1); | ||
491 | if (copy_from_user(buf, user_buf, len)) | ||
492 | return -EFAULT; | ||
493 | buf[len] = '\0'; | ||
494 | |||
495 | ret = kstrtoul(buf, 0, &value); | ||
496 | if (ret < 0) { | ||
497 | wl1271_warning("illegal value for beacon_interval"); | ||
498 | return -EINVAL; | ||
499 | } | ||
500 | |||
501 | if (value < 1 || value > 255) { | ||
502 | wl1271_warning("beacon interval value is not in valid range"); | ||
503 | return -ERANGE; | ||
504 | } | ||
505 | |||
506 | mutex_lock(&wl->mutex); | ||
507 | |||
508 | wl->conf.conn.listen_interval = value; | ||
509 | /* for some reason there are different event types for 1 and >1 */ | ||
510 | if (value == 1) | ||
511 | wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_BEACON; | ||
512 | else | ||
513 | wl->conf.conn.wake_up_event = CONF_WAKE_UP_EVENT_N_BEACONS; | ||
514 | |||
515 | /* | ||
516 | * we don't reconfigure ACX_WAKE_UP_CONDITIONS now, so it will only | ||
517 | * take effect on the next time we enter psm. | ||
518 | */ | ||
519 | mutex_unlock(&wl->mutex); | ||
520 | return count; | ||
521 | } | ||
522 | |||
523 | static const struct file_operations beacon_interval_ops = { | ||
524 | .read = beacon_interval_read, | ||
525 | .write = beacon_interval_write, | ||
526 | .open = wl1271_open_file_generic, | ||
527 | .llseek = default_llseek, | ||
528 | }; | ||
529 | |||
294 | static int wl1271_debugfs_add_files(struct wl1271 *wl, | 530 | static int wl1271_debugfs_add_files(struct wl1271 *wl, |
295 | struct dentry *rootdir) | 531 | struct dentry *rootdir) |
296 | { | 532 | { |
@@ -399,6 +635,10 @@ static int wl1271_debugfs_add_files(struct wl1271 *wl, | |||
399 | DEBUGFS_ADD(excessive_retries, rootdir); | 635 | DEBUGFS_ADD(excessive_retries, rootdir); |
400 | 636 | ||
401 | DEBUGFS_ADD(gpio_power, rootdir); | 637 | DEBUGFS_ADD(gpio_power, rootdir); |
638 | DEBUGFS_ADD(start_recovery, rootdir); | ||
639 | DEBUGFS_ADD(driver_state, rootdir); | ||
640 | DEBUGFS_ADD(dtim_interval, rootdir); | ||
641 | DEBUGFS_ADD(beacon_interval, rootdir); | ||
402 | 642 | ||
403 | return 0; | 643 | return 0; |
404 | 644 | ||
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c index d7be3aec6fc3..c3c554cd6580 100644 --- a/drivers/net/wireless/wl12xx/event.c +++ b/drivers/net/wireless/wl12xx/event.c | |||
@@ -135,6 +135,13 @@ static int wl1271_event_ps_report(struct wl1271 *wl, | |||
135 | 135 | ||
136 | /* enable beacon early termination */ | 136 | /* enable beacon early termination */ |
137 | ret = wl1271_acx_bet_enable(wl, true); | 137 | ret = wl1271_acx_bet_enable(wl, true); |
138 | if (ret < 0) | ||
139 | break; | ||
140 | |||
141 | if (wl->ps_compl) { | ||
142 | complete(wl->ps_compl); | ||
143 | wl->ps_compl = NULL; | ||
144 | } | ||
138 | break; | 145 | break; |
139 | default: | 146 | default: |
140 | break; | 147 | break; |
@@ -174,8 +181,6 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
174 | u32 vector; | 181 | u32 vector; |
175 | bool beacon_loss = false; | 182 | bool beacon_loss = false; |
176 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); | 183 | bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS); |
177 | bool disconnect_sta = false; | ||
178 | unsigned long sta_bitmap = 0; | ||
179 | 184 | ||
180 | wl1271_event_mbox_dump(mbox); | 185 | wl1271_event_mbox_dump(mbox); |
181 | 186 | ||
@@ -190,6 +195,22 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
190 | wl1271_scan_stm(wl); | 195 | wl1271_scan_stm(wl); |
191 | } | 196 | } |
192 | 197 | ||
198 | if (vector & PERIODIC_SCAN_REPORT_EVENT_ID) { | ||
199 | wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_REPORT_EVENT " | ||
200 | "(status 0x%0x)", mbox->scheduled_scan_status); | ||
201 | |||
202 | wl1271_scan_sched_scan_results(wl); | ||
203 | } | ||
204 | |||
205 | if (vector & PERIODIC_SCAN_COMPLETE_EVENT_ID) { | ||
206 | wl1271_debug(DEBUG_EVENT, "PERIODIC_SCAN_COMPLETE_EVENT " | ||
207 | "(status 0x%0x)", mbox->scheduled_scan_status); | ||
208 | if (wl->sched_scanning) { | ||
209 | wl1271_scan_sched_scan_stop(wl); | ||
210 | ieee80211_sched_scan_stopped(wl->hw); | ||
211 | } | ||
212 | } | ||
213 | |||
193 | /* disable dynamic PS when requested by the firmware */ | 214 | /* disable dynamic PS when requested by the firmware */ |
194 | if (vector & SOFT_GEMINI_SENSE_EVENT_ID && | 215 | if (vector & SOFT_GEMINI_SENSE_EVENT_ID && |
195 | wl->bss_type == BSS_TYPE_STA_BSS) { | 216 | wl->bss_type == BSS_TYPE_STA_BSS) { |
@@ -237,54 +258,9 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) | |||
237 | wl1271_tx_dummy_packet(wl); | 258 | wl1271_tx_dummy_packet(wl); |
238 | } | 259 | } |
239 | 260 | ||
240 | /* | ||
241 | * "TX retries exceeded" has a different meaning according to mode. | ||
242 | * In AP mode the offending station is disconnected. In STA mode we | ||
243 | * report connection loss. | ||
244 | */ | ||
245 | if (vector & MAX_TX_RETRY_EVENT_ID) { | ||
246 | wl1271_debug(DEBUG_EVENT, "MAX_TX_RETRY_EVENT_ID"); | ||
247 | if (is_ap) { | ||
248 | sta_bitmap |= le16_to_cpu(mbox->sta_tx_retry_exceeded); | ||
249 | disconnect_sta = true; | ||
250 | } else { | ||
251 | beacon_loss = true; | ||
252 | } | ||
253 | } | ||
254 | |||
255 | if ((vector & INACTIVE_STA_EVENT_ID) && is_ap) { | ||
256 | wl1271_debug(DEBUG_EVENT, "INACTIVE_STA_EVENT_ID"); | ||
257 | sta_bitmap |= le16_to_cpu(mbox->sta_aging_status); | ||
258 | disconnect_sta = true; | ||
259 | } | ||
260 | |||
261 | if (wl->vif && beacon_loss) | 261 | if (wl->vif && beacon_loss) |
262 | ieee80211_connection_loss(wl->vif); | 262 | ieee80211_connection_loss(wl->vif); |
263 | 263 | ||
264 | if (is_ap && disconnect_sta) { | ||
265 | u32 num_packets = wl->conf.tx.max_tx_retries; | ||
266 | struct ieee80211_sta *sta; | ||
267 | const u8 *addr; | ||
268 | int h; | ||
269 | |||
270 | for (h = find_first_bit(&sta_bitmap, AP_MAX_LINKS); | ||
271 | h < AP_MAX_LINKS; | ||
272 | h = find_next_bit(&sta_bitmap, AP_MAX_LINKS, h+1)) { | ||
273 | if (!wl1271_is_active_sta(wl, h)) | ||
274 | continue; | ||
275 | |||
276 | addr = wl->links[h].addr; | ||
277 | |||
278 | rcu_read_lock(); | ||
279 | sta = ieee80211_find_sta(wl->vif, addr); | ||
280 | if (sta) { | ||
281 | wl1271_debug(DEBUG_EVENT, "remove sta %d", h); | ||
282 | ieee80211_report_low_ack(sta, num_packets); | ||
283 | } | ||
284 | rcu_read_unlock(); | ||
285 | } | ||
286 | } | ||
287 | |||
288 | return 0; | 264 | return 0; |
289 | } | 265 | } |
290 | 266 | ||
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h index 7ae5a0821241..b6cf06e565a4 100644 --- a/drivers/net/wireless/wl12xx/event.h +++ b/drivers/net/wireless/wl12xx/event.h | |||
@@ -58,16 +58,13 @@ enum { | |||
58 | CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), | 58 | CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), |
59 | BSS_LOSE_EVENT_ID = BIT(18), | 59 | BSS_LOSE_EVENT_ID = BIT(18), |
60 | REGAINED_BSS_EVENT_ID = BIT(19), | 60 | REGAINED_BSS_EVENT_ID = BIT(19), |
61 | MAX_TX_RETRY_EVENT_ID = BIT(20), | 61 | ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20), |
62 | /* STA: dummy paket for dynamic mem blocks */ | 62 | /* STA: dummy paket for dynamic mem blocks */ |
63 | DUMMY_PACKET_EVENT_ID = BIT(21), | 63 | DUMMY_PACKET_EVENT_ID = BIT(21), |
64 | /* AP: STA remove complete */ | 64 | /* AP: STA remove complete */ |
65 | STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), | 65 | STA_REMOVE_COMPLETE_EVENT_ID = BIT(21), |
66 | SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), | 66 | SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), |
67 | /* STA: SG prediction */ | ||
68 | SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23), | 67 | SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23), |
69 | /* AP: Inactive STA */ | ||
70 | INACTIVE_STA_EVENT_ID = BIT(23), | ||
71 | SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), | 68 | SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), |
72 | PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25), | 69 | PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25), |
73 | DBG_EVENT_ID = BIT(26), | 70 | DBG_EVENT_ID = BIT(26), |
@@ -122,11 +119,7 @@ struct event_mailbox { | |||
122 | 119 | ||
123 | /* AP FW only */ | 120 | /* AP FW only */ |
124 | u8 hlid_removed; | 121 | u8 hlid_removed; |
125 | |||
126 | /* a bitmap of hlids for stations that have been inactive too long */ | ||
127 | __le16 sta_aging_status; | 122 | __le16 sta_aging_status; |
128 | |||
129 | /* a bitmap of hlids for stations which didn't respond to TX */ | ||
130 | __le16 sta_tx_retry_exceeded; | 123 | __le16 sta_tx_retry_exceeded; |
131 | 124 | ||
132 | u8 reserved_5[24]; | 125 | u8 reserved_5[24]; |
@@ -137,7 +130,4 @@ void wl1271_event_mbox_config(struct wl1271 *wl); | |||
137 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); | 130 | int wl1271_event_handle(struct wl1271 *wl, u8 mbox); |
138 | void wl1271_pspoll_work(struct work_struct *work); | 131 | void wl1271_pspoll_work(struct work_struct *work); |
139 | 132 | ||
140 | /* Functions from main.c */ | ||
141 | bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid); | ||
142 | |||
143 | #endif | 133 | #endif |
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c index ab3b1e21de29..a8f4f156c055 100644 --- a/drivers/net/wireless/wl12xx/init.c +++ b/drivers/net/wireless/wl12xx/init.c | |||
@@ -258,7 +258,7 @@ int wl1271_init_phy_config(struct wl1271 *wl) | |||
258 | if (ret < 0) | 258 | if (ret < 0) |
259 | return ret; | 259 | return ret; |
260 | 260 | ||
261 | ret = wl1271_acx_rts_threshold(wl, wl->conf.rx.rts_threshold); | 261 | ret = wl1271_acx_rts_threshold(wl, wl->hw->wiphy->rts_threshold); |
262 | if (ret < 0) | 262 | if (ret < 0) |
263 | return ret; | 263 | return ret; |
264 | 264 | ||
@@ -285,7 +285,10 @@ int wl1271_init_pta(struct wl1271 *wl) | |||
285 | { | 285 | { |
286 | int ret; | 286 | int ret; |
287 | 287 | ||
288 | ret = wl1271_acx_sg_cfg(wl); | 288 | if (wl->bss_type == BSS_TYPE_AP_BSS) |
289 | ret = wl1271_acx_ap_sg_cfg(wl); | ||
290 | else | ||
291 | ret = wl1271_acx_sta_sg_cfg(wl); | ||
289 | if (ret < 0) | 292 | if (ret < 0) |
290 | return ret; | 293 | return ret; |
291 | 294 | ||
@@ -351,8 +354,8 @@ static int wl1271_sta_hw_init(struct wl1271 *wl) | |||
351 | if (ret < 0) | 354 | if (ret < 0) |
352 | return ret; | 355 | return ret; |
353 | 356 | ||
354 | /* Bluetooth WLAN coexistence */ | 357 | /* FM WLAN coexistence */ |
355 | ret = wl1271_init_pta(wl); | 358 | ret = wl1271_acx_fm_coex(wl); |
356 | if (ret < 0) | 359 | if (ret < 0) |
357 | return ret; | 360 | return ret; |
358 | 361 | ||
@@ -375,10 +378,6 @@ static int wl1271_sta_hw_init(struct wl1271 *wl) | |||
375 | if (ret < 0) | 378 | if (ret < 0) |
376 | return ret; | 379 | return ret; |
377 | 380 | ||
378 | ret = wl1271_acx_sta_max_tx_retry(wl); | ||
379 | if (ret < 0) | ||
380 | return ret; | ||
381 | |||
382 | ret = wl1271_acx_sta_mem_cfg(wl); | 381 | ret = wl1271_acx_sta_mem_cfg(wl); |
383 | if (ret < 0) | 382 | if (ret < 0) |
384 | return ret; | 383 | return ret; |
@@ -414,7 +413,7 @@ static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl) | |||
414 | 413 | ||
415 | static int wl1271_ap_hw_init(struct wl1271 *wl) | 414 | static int wl1271_ap_hw_init(struct wl1271 *wl) |
416 | { | 415 | { |
417 | int ret, i; | 416 | int ret; |
418 | 417 | ||
419 | ret = wl1271_ap_init_templates_config(wl); | 418 | ret = wl1271_ap_init_templates_config(wl); |
420 | if (ret < 0) | 419 | if (ret < 0) |
@@ -425,27 +424,11 @@ static int wl1271_ap_hw_init(struct wl1271 *wl) | |||
425 | if (ret < 0) | 424 | if (ret < 0) |
426 | return ret; | 425 | return ret; |
427 | 426 | ||
428 | /* Configure initial TX rate classes */ | 427 | ret = wl1271_init_ap_rates(wl); |
429 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { | ||
430 | ret = wl1271_acx_ap_rate_policy(wl, | ||
431 | &wl->conf.tx.ap_rc_conf[i], i); | ||
432 | if (ret < 0) | ||
433 | return ret; | ||
434 | } | ||
435 | |||
436 | ret = wl1271_acx_ap_rate_policy(wl, | ||
437 | &wl->conf.tx.ap_mgmt_conf, | ||
438 | ACX_TX_AP_MODE_MGMT_RATE); | ||
439 | if (ret < 0) | 428 | if (ret < 0) |
440 | return ret; | 429 | return ret; |
441 | 430 | ||
442 | ret = wl1271_acx_ap_rate_policy(wl, | 431 | ret = wl1271_acx_max_tx_retry(wl); |
443 | &wl->conf.tx.ap_bcst_conf, | ||
444 | ACX_TX_AP_MODE_BCST_RATE); | ||
445 | if (ret < 0) | ||
446 | return ret; | ||
447 | |||
448 | ret = wl1271_acx_ap_max_tx_retry(wl); | ||
449 | if (ret < 0) | 432 | if (ret < 0) |
450 | return ret; | 433 | return ret; |
451 | 434 | ||
@@ -456,7 +439,7 @@ static int wl1271_ap_hw_init(struct wl1271 *wl) | |||
456 | return 0; | 439 | return 0; |
457 | } | 440 | } |
458 | 441 | ||
459 | static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl) | 442 | int wl1271_ap_init_templates(struct wl1271 *wl) |
460 | { | 443 | { |
461 | int ret; | 444 | int ret; |
462 | 445 | ||
@@ -472,6 +455,70 @@ static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl) | |||
472 | if (ret < 0) | 455 | if (ret < 0) |
473 | return ret; | 456 | return ret; |
474 | 457 | ||
458 | /* | ||
459 | * when operating as AP we want to receive external beacons for | ||
460 | * configuring ERP protection. | ||
461 | */ | ||
462 | ret = wl1271_acx_set_ap_beacon_filter(wl, false); | ||
463 | if (ret < 0) | ||
464 | return ret; | ||
465 | |||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl) | ||
470 | { | ||
471 | return wl1271_ap_init_templates(wl); | ||
472 | } | ||
473 | |||
474 | int wl1271_init_ap_rates(struct wl1271 *wl) | ||
475 | { | ||
476 | int i, ret; | ||
477 | struct conf_tx_rate_class rc; | ||
478 | u32 supported_rates; | ||
479 | |||
480 | wl1271_debug(DEBUG_AP, "AP basic rate set: 0x%x", wl->basic_rate_set); | ||
481 | |||
482 | if (wl->basic_rate_set == 0) | ||
483 | return -EINVAL; | ||
484 | |||
485 | rc.enabled_rates = wl->basic_rate_set; | ||
486 | rc.long_retry_limit = 10; | ||
487 | rc.short_retry_limit = 10; | ||
488 | rc.aflags = 0; | ||
489 | ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_MGMT_RATE); | ||
490 | if (ret < 0) | ||
491 | return ret; | ||
492 | |||
493 | /* use the min basic rate for AP broadcast/multicast */ | ||
494 | rc.enabled_rates = wl1271_tx_min_rate_get(wl); | ||
495 | rc.short_retry_limit = 10; | ||
496 | rc.long_retry_limit = 10; | ||
497 | rc.aflags = 0; | ||
498 | ret = wl1271_acx_ap_rate_policy(wl, &rc, ACX_TX_AP_MODE_BCST_RATE); | ||
499 | if (ret < 0) | ||
500 | return ret; | ||
501 | |||
502 | /* | ||
503 | * If the basic rates contain OFDM rates, use OFDM only | ||
504 | * rates for unicast TX as well. Else use all supported rates. | ||
505 | */ | ||
506 | if ((wl->basic_rate_set & CONF_TX_OFDM_RATES)) | ||
507 | supported_rates = CONF_TX_OFDM_RATES; | ||
508 | else | ||
509 | supported_rates = CONF_TX_AP_ENABLED_RATES; | ||
510 | |||
511 | /* configure unicast TX rate classes */ | ||
512 | for (i = 0; i < wl->conf.tx.ac_conf_count; i++) { | ||
513 | rc.enabled_rates = supported_rates; | ||
514 | rc.short_retry_limit = 10; | ||
515 | rc.long_retry_limit = 10; | ||
516 | rc.aflags = 0; | ||
517 | ret = wl1271_acx_ap_rate_policy(wl, &rc, i); | ||
518 | if (ret < 0) | ||
519 | return ret; | ||
520 | } | ||
521 | |||
475 | return 0; | 522 | return 0; |
476 | } | 523 | } |
477 | 524 | ||
@@ -567,6 +614,11 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
567 | if (ret < 0) | 614 | if (ret < 0) |
568 | return ret; | 615 | return ret; |
569 | 616 | ||
617 | /* Bluetooth WLAN coexistence */ | ||
618 | ret = wl1271_init_pta(wl); | ||
619 | if (ret < 0) | ||
620 | return ret; | ||
621 | |||
570 | /* Default memory configuration */ | 622 | /* Default memory configuration */ |
571 | ret = wl1271_acx_init_mem_config(wl); | 623 | ret = wl1271_acx_init_mem_config(wl); |
572 | if (ret < 0) | 624 | if (ret < 0) |
@@ -606,7 +658,7 @@ int wl1271_hw_init(struct wl1271 *wl) | |||
606 | goto out_free_memmap; | 658 | goto out_free_memmap; |
607 | 659 | ||
608 | /* Default fragmentation threshold */ | 660 | /* Default fragmentation threshold */ |
609 | ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold); | 661 | ret = wl1271_acx_frag_threshold(wl, wl->hw->wiphy->frag_threshold); |
610 | if (ret < 0) | 662 | if (ret < 0) |
611 | goto out_free_memmap; | 663 | goto out_free_memmap; |
612 | 664 | ||
diff --git a/drivers/net/wireless/wl12xx/init.h b/drivers/net/wireless/wl12xx/init.h index 4975270a91ab..3a3c230fd292 100644 --- a/drivers/net/wireless/wl12xx/init.h +++ b/drivers/net/wireless/wl12xx/init.h | |||
@@ -33,5 +33,7 @@ int wl1271_init_pta(struct wl1271 *wl); | |||
33 | int wl1271_init_energy_detection(struct wl1271 *wl); | 33 | int wl1271_init_energy_detection(struct wl1271 *wl); |
34 | int wl1271_chip_specific_init(struct wl1271 *wl); | 34 | int wl1271_chip_specific_init(struct wl1271 *wl); |
35 | int wl1271_hw_init(struct wl1271 *wl); | 35 | int wl1271_hw_init(struct wl1271 *wl); |
36 | int wl1271_init_ap_rates(struct wl1271 *wl); | ||
37 | int wl1271_ap_init_templates(struct wl1271 *wl); | ||
36 | 38 | ||
37 | #endif | 39 | #endif |
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c index 0c69e959d0de..610be03a198b 100644 --- a/drivers/net/wireless/wl12xx/main.c +++ b/drivers/net/wireless/wl12xx/main.c | |||
@@ -51,7 +51,7 @@ | |||
51 | 51 | ||
52 | static struct conf_drv_settings default_conf = { | 52 | static struct conf_drv_settings default_conf = { |
53 | .sg = { | 53 | .sg = { |
54 | .params = { | 54 | .sta_params = { |
55 | [CONF_SG_BT_PER_THRESHOLD] = 7500, | 55 | [CONF_SG_BT_PER_THRESHOLD] = 7500, |
56 | [CONF_SG_HV3_MAX_OVERRIDE] = 0, | 56 | [CONF_SG_HV3_MAX_OVERRIDE] = 0, |
57 | [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, | 57 | [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, |
@@ -101,6 +101,61 @@ static struct conf_drv_settings default_conf = { | |||
101 | [CONF_SG_DHCP_TIME] = 5000, | 101 | [CONF_SG_DHCP_TIME] = 5000, |
102 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, | 102 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, |
103 | }, | 103 | }, |
104 | .ap_params = { | ||
105 | [CONF_SG_BT_PER_THRESHOLD] = 7500, | ||
106 | [CONF_SG_HV3_MAX_OVERRIDE] = 0, | ||
107 | [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400, | ||
108 | [CONF_SG_BT_LOAD_RATIO] = 50, | ||
109 | [CONF_SG_AUTO_PS_MODE] = 1, | ||
110 | [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170, | ||
111 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50, | ||
112 | [CONF_SG_ANTENNA_CONFIGURATION] = 0, | ||
113 | [CONF_SG_BEACON_MISS_PERCENT] = 60, | ||
114 | [CONF_SG_RATE_ADAPT_THRESH] = 64, | ||
115 | [CONF_SG_RATE_ADAPT_SNR] = 1, | ||
116 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10, | ||
117 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 25, | ||
118 | [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 25, | ||
119 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20, | ||
120 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 25, | ||
121 | [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 25, | ||
122 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7, | ||
123 | [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25, | ||
124 | [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 25, | ||
125 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8, | ||
126 | [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 25, | ||
127 | [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 25, | ||
128 | [CONF_SG_RXT] = 1200, | ||
129 | [CONF_SG_TXT] = 1000, | ||
130 | [CONF_SG_ADAPTIVE_RXT_TXT] = 1, | ||
131 | [CONF_SG_PS_POLL_TIMEOUT] = 10, | ||
132 | [CONF_SG_UPSD_TIMEOUT] = 10, | ||
133 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7, | ||
134 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15, | ||
135 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15, | ||
136 | [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8, | ||
137 | [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20, | ||
138 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15, | ||
139 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20, | ||
140 | [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50, | ||
141 | [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10, | ||
142 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200, | ||
143 | [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800, | ||
144 | [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75, | ||
145 | [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15, | ||
146 | [CONF_SG_HV3_MAX_SERVED] = 6, | ||
147 | [CONF_SG_DHCP_TIME] = 5000, | ||
148 | [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100, | ||
149 | [CONF_SG_TEMP_PARAM_1] = 0, | ||
150 | [CONF_SG_TEMP_PARAM_2] = 0, | ||
151 | [CONF_SG_TEMP_PARAM_3] = 0, | ||
152 | [CONF_SG_TEMP_PARAM_4] = 0, | ||
153 | [CONF_SG_TEMP_PARAM_5] = 0, | ||
154 | [CONF_SG_AP_BEACON_MISS_TX] = 3, | ||
155 | [CONF_SG_RX_WINDOW_LENGTH] = 6, | ||
156 | [CONF_SG_AP_CONNECTION_PROTECTION_TIME] = 50, | ||
157 | [CONF_SG_TEMP_PARAM_6] = 1, | ||
158 | }, | ||
104 | .state = CONF_SG_PROTECTIVE, | 159 | .state = CONF_SG_PROTECTIVE, |
105 | }, | 160 | }, |
106 | .rx = { | 161 | .rx = { |
@@ -108,7 +163,7 @@ static struct conf_drv_settings default_conf = { | |||
108 | .packet_detection_threshold = 0, | 163 | .packet_detection_threshold = 0, |
109 | .ps_poll_timeout = 15, | 164 | .ps_poll_timeout = 15, |
110 | .upsd_timeout = 15, | 165 | .upsd_timeout = 15, |
111 | .rts_threshold = 2347, | 166 | .rts_threshold = IEEE80211_MAX_RTS_THRESHOLD, |
112 | .rx_cca_threshold = 0, | 167 | .rx_cca_threshold = 0, |
113 | .irq_blk_threshold = 0xFFFF, | 168 | .irq_blk_threshold = 0xFFFF, |
114 | .irq_pkt_threshold = 0, | 169 | .irq_pkt_threshold = 0, |
@@ -154,46 +209,7 @@ static struct conf_drv_settings default_conf = { | |||
154 | .tx_op_limit = 1504, | 209 | .tx_op_limit = 1504, |
155 | }, | 210 | }, |
156 | }, | 211 | }, |
157 | .ap_rc_conf = { | 212 | .ap_max_tx_retries = 100, |
158 | [0] = { | ||
159 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
160 | .short_retry_limit = 10, | ||
161 | .long_retry_limit = 10, | ||
162 | .aflags = 0, | ||
163 | }, | ||
164 | [1] = { | ||
165 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
166 | .short_retry_limit = 10, | ||
167 | .long_retry_limit = 10, | ||
168 | .aflags = 0, | ||
169 | }, | ||
170 | [2] = { | ||
171 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
172 | .short_retry_limit = 10, | ||
173 | .long_retry_limit = 10, | ||
174 | .aflags = 0, | ||
175 | }, | ||
176 | [3] = { | ||
177 | .enabled_rates = CONF_TX_AP_ENABLED_RATES, | ||
178 | .short_retry_limit = 10, | ||
179 | .long_retry_limit = 10, | ||
180 | .aflags = 0, | ||
181 | }, | ||
182 | }, | ||
183 | .ap_mgmt_conf = { | ||
184 | .enabled_rates = CONF_TX_AP_DEFAULT_MGMT_RATES, | ||
185 | .short_retry_limit = 10, | ||
186 | .long_retry_limit = 10, | ||
187 | .aflags = 0, | ||
188 | }, | ||
189 | .ap_bcst_conf = { | ||
190 | .enabled_rates = CONF_HW_BIT_RATE_1MBPS, | ||
191 | .short_retry_limit = 10, | ||
192 | .long_retry_limit = 10, | ||
193 | .aflags = 0, | ||
194 | }, | ||
195 | .max_tx_retries = 100, | ||
196 | .ap_aging_period = 300, | ||
197 | .tid_conf_count = 4, | 213 | .tid_conf_count = 4, |
198 | .tid_conf = { | 214 | .tid_conf = { |
199 | [CONF_TX_AC_BE] = { | 215 | [CONF_TX_AC_BE] = { |
@@ -241,12 +257,16 @@ static struct conf_drv_settings default_conf = { | |||
241 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, | 257 | .wake_up_event = CONF_WAKE_UP_EVENT_DTIM, |
242 | .listen_interval = 1, | 258 | .listen_interval = 1, |
243 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, | 259 | .bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED, |
244 | .bcn_filt_ie_count = 1, | 260 | .bcn_filt_ie_count = 2, |
245 | .bcn_filt_ie = { | 261 | .bcn_filt_ie = { |
246 | [0] = { | 262 | [0] = { |
247 | .ie = WLAN_EID_CHANNEL_SWITCH, | 263 | .ie = WLAN_EID_CHANNEL_SWITCH, |
248 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, | 264 | .rule = CONF_BCN_RULE_PASS_ON_APPEARANCE, |
249 | } | 265 | }, |
266 | [1] = { | ||
267 | .ie = WLAN_EID_HT_INFORMATION, | ||
268 | .rule = CONF_BCN_RULE_PASS_ON_CHANGE, | ||
269 | }, | ||
250 | }, | 270 | }, |
251 | .synch_fail_thold = 10, | 271 | .synch_fail_thold = 10, |
252 | .bss_lose_timeout = 100, | 272 | .bss_lose_timeout = 100, |
@@ -258,7 +278,7 @@ static struct conf_drv_settings default_conf = { | |||
258 | .bet_enable = CONF_BET_MODE_ENABLE, | 278 | .bet_enable = CONF_BET_MODE_ENABLE, |
259 | .bet_max_consecutive = 50, | 279 | .bet_max_consecutive = 50, |
260 | .psm_entry_retries = 5, | 280 | .psm_entry_retries = 5, |
261 | .psm_exit_retries = 255, | 281 | .psm_exit_retries = 16, |
262 | .psm_entry_nullfunc_retries = 3, | 282 | .psm_entry_nullfunc_retries = 3, |
263 | .psm_entry_hangover_period = 1, | 283 | .psm_entry_hangover_period = 1, |
264 | .keep_alive_interval = 55000, | 284 | .keep_alive_interval = 55000, |
@@ -286,6 +306,15 @@ static struct conf_drv_settings default_conf = { | |||
286 | .max_dwell_time_passive = 100000, | 306 | .max_dwell_time_passive = 100000, |
287 | .num_probe_reqs = 2, | 307 | .num_probe_reqs = 2, |
288 | }, | 308 | }, |
309 | .sched_scan = { | ||
310 | /* sched_scan requires dwell times in TU instead of TU/1000 */ | ||
311 | .min_dwell_time_active = 8, | ||
312 | .max_dwell_time_active = 30, | ||
313 | .dwell_time_passive = 100, | ||
314 | .num_probe_reqs = 2, | ||
315 | .rssi_threshold = -90, | ||
316 | .snr_threshold = 0, | ||
317 | }, | ||
289 | .rf = { | 318 | .rf = { |
290 | .tx_per_channel_power_compensation_2 = { | 319 | .tx_per_channel_power_compensation_2 = { |
291 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 320 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
@@ -305,7 +334,7 @@ static struct conf_drv_settings default_conf = { | |||
305 | .ssid_profiles = 1, | 334 | .ssid_profiles = 1, |
306 | .rx_block_num = 70, | 335 | .rx_block_num = 70, |
307 | .tx_min_block_num = 40, | 336 | .tx_min_block_num = 40, |
308 | .dynamic_memory = 0, | 337 | .dynamic_memory = 1, |
309 | .min_req_tx_blocks = 100, | 338 | .min_req_tx_blocks = 100, |
310 | .min_req_rx_blocks = 22, | 339 | .min_req_rx_blocks = 22, |
311 | .tx_min = 27, | 340 | .tx_min = 27, |
@@ -320,10 +349,23 @@ static struct conf_drv_settings default_conf = { | |||
320 | .min_req_rx_blocks = 22, | 349 | .min_req_rx_blocks = 22, |
321 | .tx_min = 27, | 350 | .tx_min = 27, |
322 | }, | 351 | }, |
352 | .fm_coex = { | ||
353 | .enable = true, | ||
354 | .swallow_period = 5, | ||
355 | .n_divider_fref_set_1 = 0xff, /* default */ | ||
356 | .n_divider_fref_set_2 = 12, | ||
357 | .m_divider_fref_set_1 = 148, | ||
358 | .m_divider_fref_set_2 = 0xffff, /* default */ | ||
359 | .coex_pll_stabilization_time = 0xffffffff, /* default */ | ||
360 | .ldo_stabilization_time = 0xffff, /* default */ | ||
361 | .fm_disturbed_band_margin = 0xff, /* default */ | ||
362 | .swallow_clk_diff = 0xff, /* default */ | ||
363 | }, | ||
323 | .hci_io_ds = HCI_IO_DS_6MA, | 364 | .hci_io_ds = HCI_IO_DS_6MA, |
324 | }; | 365 | }; |
325 | 366 | ||
326 | static void __wl1271_op_remove_interface(struct wl1271 *wl); | 367 | static void __wl1271_op_remove_interface(struct wl1271 *wl, |
368 | bool reset_tx_queues); | ||
327 | static void wl1271_free_ap_keys(struct wl1271 *wl); | 369 | static void wl1271_free_ap_keys(struct wl1271 *wl); |
328 | 370 | ||
329 | 371 | ||
@@ -508,6 +550,11 @@ static int wl1271_plt_init(struct wl1271 *wl) | |||
508 | if (ret < 0) | 550 | if (ret < 0) |
509 | goto out_free_memmap; | 551 | goto out_free_memmap; |
510 | 552 | ||
553 | /* FM WLAN coexistence */ | ||
554 | ret = wl1271_acx_fm_coex(wl); | ||
555 | if (ret < 0) | ||
556 | goto out_free_memmap; | ||
557 | |||
511 | /* Energy detection */ | 558 | /* Energy detection */ |
512 | ret = wl1271_init_energy_detection(wl); | 559 | ret = wl1271_init_energy_detection(wl); |
513 | if (ret < 0) | 560 | if (ret < 0) |
@@ -932,15 +979,30 @@ static void wl1271_recovery_work(struct work_struct *work) | |||
932 | if (wl->state != WL1271_STATE_ON) | 979 | if (wl->state != WL1271_STATE_ON) |
933 | goto out; | 980 | goto out; |
934 | 981 | ||
935 | wl1271_info("Hardware recovery in progress."); | 982 | wl1271_info("Hardware recovery in progress. FW ver: %s pc: 0x%x", |
983 | wl->chip.fw_ver_str, wl1271_read32(wl, SCR_PAD4)); | ||
936 | 984 | ||
937 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) | 985 | if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) |
938 | ieee80211_connection_loss(wl->vif); | 986 | ieee80211_connection_loss(wl->vif); |
939 | 987 | ||
988 | /* Prevent spurious TX during FW restart */ | ||
989 | ieee80211_stop_queues(wl->hw); | ||
990 | |||
991 | if (wl->sched_scanning) { | ||
992 | ieee80211_sched_scan_stopped(wl->hw); | ||
993 | wl->sched_scanning = false; | ||
994 | } | ||
995 | |||
940 | /* reboot the chipset */ | 996 | /* reboot the chipset */ |
941 | __wl1271_op_remove_interface(wl); | 997 | __wl1271_op_remove_interface(wl, false); |
942 | ieee80211_restart_hw(wl->hw); | 998 | ieee80211_restart_hw(wl->hw); |
943 | 999 | ||
1000 | /* | ||
1001 | * Its safe to enable TX now - the queues are stopped after a request | ||
1002 | * to restart the HW. | ||
1003 | */ | ||
1004 | ieee80211_wake_queues(wl->hw); | ||
1005 | |||
944 | out: | 1006 | out: |
945 | mutex_unlock(&wl->mutex); | 1007 | mutex_unlock(&wl->mutex); |
946 | } | 1008 | } |
@@ -1011,6 +1073,10 @@ static int wl1271_chip_wakeup(struct wl1271 *wl) | |||
1011 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", | 1073 | wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", |
1012 | wl->chip.id); | 1074 | wl->chip.id); |
1013 | 1075 | ||
1076 | /* end-of-transaction flag should be set in wl127x AP mode */ | ||
1077 | if (wl->bss_type == BSS_TYPE_AP_BSS) | ||
1078 | wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION; | ||
1079 | |||
1014 | ret = wl1271_setup(wl); | 1080 | ret = wl1271_setup(wl); |
1015 | if (ret < 0) | 1081 | if (ret < 0) |
1016 | goto out; | 1082 | goto out; |
@@ -1273,7 +1339,7 @@ static struct sk_buff *wl12xx_alloc_dummy_packet(struct wl1271 *wl) | |||
1273 | skb->priority = WL1271_TID_MGMT; | 1339 | skb->priority = WL1271_TID_MGMT; |
1274 | 1340 | ||
1275 | /* Initialize all fields that might be used */ | 1341 | /* Initialize all fields that might be used */ |
1276 | skb->queue_mapping = 0; | 1342 | skb_set_queue_mapping(skb, 0); |
1277 | memset(IEEE80211_SKB_CB(skb), 0, sizeof(struct ieee80211_tx_info)); | 1343 | memset(IEEE80211_SKB_CB(skb), 0, sizeof(struct ieee80211_tx_info)); |
1278 | 1344 | ||
1279 | return skb; | 1345 | return skb; |
@@ -1284,6 +1350,150 @@ static struct notifier_block wl1271_dev_notifier = { | |||
1284 | .notifier_call = wl1271_dev_notify, | 1350 | .notifier_call = wl1271_dev_notify, |
1285 | }; | 1351 | }; |
1286 | 1352 | ||
1353 | static int wl1271_configure_suspend(struct wl1271 *wl) | ||
1354 | { | ||
1355 | int ret; | ||
1356 | |||
1357 | if (wl->bss_type != BSS_TYPE_STA_BSS) | ||
1358 | return 0; | ||
1359 | |||
1360 | mutex_lock(&wl->mutex); | ||
1361 | |||
1362 | ret = wl1271_ps_elp_wakeup(wl); | ||
1363 | if (ret < 0) | ||
1364 | goto out_unlock; | ||
1365 | |||
1366 | /* enter psm if needed*/ | ||
1367 | if (!test_bit(WL1271_FLAG_PSM, &wl->flags)) { | ||
1368 | DECLARE_COMPLETION_ONSTACK(compl); | ||
1369 | |||
1370 | wl->ps_compl = &compl; | ||
1371 | ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, | ||
1372 | wl->basic_rate, true); | ||
1373 | if (ret < 0) | ||
1374 | goto out_sleep; | ||
1375 | |||
1376 | /* we must unlock here so we will be able to get events */ | ||
1377 | wl1271_ps_elp_sleep(wl); | ||
1378 | mutex_unlock(&wl->mutex); | ||
1379 | |||
1380 | ret = wait_for_completion_timeout( | ||
1381 | &compl, msecs_to_jiffies(WL1271_PS_COMPLETE_TIMEOUT)); | ||
1382 | if (ret <= 0) { | ||
1383 | wl1271_warning("couldn't enter ps mode!"); | ||
1384 | ret = -EBUSY; | ||
1385 | goto out; | ||
1386 | } | ||
1387 | |||
1388 | /* take mutex again, and wakeup */ | ||
1389 | mutex_lock(&wl->mutex); | ||
1390 | |||
1391 | ret = wl1271_ps_elp_wakeup(wl); | ||
1392 | if (ret < 0) | ||
1393 | goto out_unlock; | ||
1394 | } | ||
1395 | out_sleep: | ||
1396 | wl1271_ps_elp_sleep(wl); | ||
1397 | out_unlock: | ||
1398 | mutex_unlock(&wl->mutex); | ||
1399 | out: | ||
1400 | return ret; | ||
1401 | |||
1402 | } | ||
1403 | |||
1404 | static void wl1271_configure_resume(struct wl1271 *wl) | ||
1405 | { | ||
1406 | int ret; | ||
1407 | |||
1408 | if (wl->bss_type != BSS_TYPE_STA_BSS) | ||
1409 | return; | ||
1410 | |||
1411 | mutex_lock(&wl->mutex); | ||
1412 | ret = wl1271_ps_elp_wakeup(wl); | ||
1413 | if (ret < 0) | ||
1414 | goto out; | ||
1415 | |||
1416 | /* exit psm if it wasn't configured */ | ||
1417 | if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) | ||
1418 | wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, | ||
1419 | wl->basic_rate, true); | ||
1420 | |||
1421 | wl1271_ps_elp_sleep(wl); | ||
1422 | out: | ||
1423 | mutex_unlock(&wl->mutex); | ||
1424 | } | ||
1425 | |||
1426 | static int wl1271_op_suspend(struct ieee80211_hw *hw, | ||
1427 | struct cfg80211_wowlan *wow) | ||
1428 | { | ||
1429 | struct wl1271 *wl = hw->priv; | ||
1430 | wl1271_debug(DEBUG_MAC80211, "mac80211 suspend wow=%d", !!wow); | ||
1431 | wl->wow_enabled = !!wow; | ||
1432 | if (wl->wow_enabled) { | ||
1433 | int ret; | ||
1434 | ret = wl1271_configure_suspend(wl); | ||
1435 | if (ret < 0) { | ||
1436 | wl1271_warning("couldn't prepare device to suspend"); | ||
1437 | return ret; | ||
1438 | } | ||
1439 | /* flush any remaining work */ | ||
1440 | wl1271_debug(DEBUG_MAC80211, "flushing remaining works"); | ||
1441 | flush_delayed_work(&wl->scan_complete_work); | ||
1442 | |||
1443 | /* | ||
1444 | * disable and re-enable interrupts in order to flush | ||
1445 | * the threaded_irq | ||
1446 | */ | ||
1447 | wl1271_disable_interrupts(wl); | ||
1448 | |||
1449 | /* | ||
1450 | * set suspended flag to avoid triggering a new threaded_irq | ||
1451 | * work. no need for spinlock as interrupts are disabled. | ||
1452 | */ | ||
1453 | set_bit(WL1271_FLAG_SUSPENDED, &wl->flags); | ||
1454 | |||
1455 | wl1271_enable_interrupts(wl); | ||
1456 | flush_work(&wl->tx_work); | ||
1457 | flush_delayed_work(&wl->pspoll_work); | ||
1458 | flush_delayed_work(&wl->elp_work); | ||
1459 | } | ||
1460 | return 0; | ||
1461 | } | ||
1462 | |||
1463 | static int wl1271_op_resume(struct ieee80211_hw *hw) | ||
1464 | { | ||
1465 | struct wl1271 *wl = hw->priv; | ||
1466 | wl1271_debug(DEBUG_MAC80211, "mac80211 resume wow=%d", | ||
1467 | wl->wow_enabled); | ||
1468 | |||
1469 | /* | ||
1470 | * re-enable irq_work enqueuing, and call irq_work directly if | ||
1471 | * there is a pending work. | ||
1472 | */ | ||
1473 | if (wl->wow_enabled) { | ||
1474 | struct wl1271 *wl = hw->priv; | ||
1475 | unsigned long flags; | ||
1476 | bool run_irq_work = false; | ||
1477 | |||
1478 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
1479 | clear_bit(WL1271_FLAG_SUSPENDED, &wl->flags); | ||
1480 | if (test_and_clear_bit(WL1271_FLAG_PENDING_WORK, &wl->flags)) | ||
1481 | run_irq_work = true; | ||
1482 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
1483 | |||
1484 | if (run_irq_work) { | ||
1485 | wl1271_debug(DEBUG_MAC80211, | ||
1486 | "run postponed irq_work directly"); | ||
1487 | wl1271_irq(0, wl); | ||
1488 | wl1271_enable_interrupts(wl); | ||
1489 | } | ||
1490 | |||
1491 | wl1271_configure_resume(wl); | ||
1492 | } | ||
1493 | |||
1494 | return 0; | ||
1495 | } | ||
1496 | |||
1287 | static int wl1271_op_start(struct ieee80211_hw *hw) | 1497 | static int wl1271_op_start(struct ieee80211_hw *hw) |
1288 | { | 1498 | { |
1289 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); | 1499 | wl1271_debug(DEBUG_MAC80211, "mac80211 start"); |
@@ -1440,7 +1650,8 @@ out: | |||
1440 | return ret; | 1650 | return ret; |
1441 | } | 1651 | } |
1442 | 1652 | ||
1443 | static void __wl1271_op_remove_interface(struct wl1271 *wl) | 1653 | static void __wl1271_op_remove_interface(struct wl1271 *wl, |
1654 | bool reset_tx_queues) | ||
1444 | { | 1655 | { |
1445 | int i; | 1656 | int i; |
1446 | 1657 | ||
@@ -1486,7 +1697,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
1486 | mutex_lock(&wl->mutex); | 1697 | mutex_lock(&wl->mutex); |
1487 | 1698 | ||
1488 | /* let's notify MAC80211 about the remaining pending TX frames */ | 1699 | /* let's notify MAC80211 about the remaining pending TX frames */ |
1489 | wl1271_tx_reset(wl); | 1700 | wl1271_tx_reset(wl, reset_tx_queues); |
1490 | wl1271_power_off(wl); | 1701 | wl1271_power_off(wl); |
1491 | 1702 | ||
1492 | memset(wl->bssid, 0, ETH_ALEN); | 1703 | memset(wl->bssid, 0, ETH_ALEN); |
@@ -1514,6 +1725,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl) | |||
1514 | memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); | 1725 | memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map)); |
1515 | wl->ap_fw_ps_map = 0; | 1726 | wl->ap_fw_ps_map = 0; |
1516 | wl->ap_ps_map = 0; | 1727 | wl->ap_ps_map = 0; |
1728 | wl->sched_scanning = false; | ||
1517 | 1729 | ||
1518 | /* | 1730 | /* |
1519 | * this is performed after the cancel_work calls and the associated | 1731 | * this is performed after the cancel_work calls and the associated |
@@ -1547,7 +1759,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, | |||
1547 | */ | 1759 | */ |
1548 | if (wl->vif) { | 1760 | if (wl->vif) { |
1549 | WARN_ON(wl->vif != vif); | 1761 | WARN_ON(wl->vif != vif); |
1550 | __wl1271_op_remove_interface(wl); | 1762 | __wl1271_op_remove_interface(wl, true); |
1551 | } | 1763 | } |
1552 | 1764 | ||
1553 | mutex_unlock(&wl->mutex); | 1765 | mutex_unlock(&wl->mutex); |
@@ -1716,6 +1928,13 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) | |||
1716 | wl->session_counter++; | 1928 | wl->session_counter++; |
1717 | if (wl->session_counter >= SESSION_COUNTER_MAX) | 1929 | if (wl->session_counter >= SESSION_COUNTER_MAX) |
1718 | wl->session_counter = 0; | 1930 | wl->session_counter = 0; |
1931 | |||
1932 | /* The current firmware only supports sched_scan in idle */ | ||
1933 | if (wl->sched_scanning) { | ||
1934 | wl1271_scan_sched_scan_stop(wl); | ||
1935 | ieee80211_sched_scan_stopped(wl->hw); | ||
1936 | } | ||
1937 | |||
1719 | ret = wl1271_dummy_join(wl); | 1938 | ret = wl1271_dummy_join(wl); |
1720 | if (ret < 0) | 1939 | if (ret < 0) |
1721 | goto out; | 1940 | goto out; |
@@ -2268,6 +2487,60 @@ out: | |||
2268 | return ret; | 2487 | return ret; |
2269 | } | 2488 | } |
2270 | 2489 | ||
2490 | static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, | ||
2491 | struct ieee80211_vif *vif, | ||
2492 | struct cfg80211_sched_scan_request *req, | ||
2493 | struct ieee80211_sched_scan_ies *ies) | ||
2494 | { | ||
2495 | struct wl1271 *wl = hw->priv; | ||
2496 | int ret; | ||
2497 | |||
2498 | wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_start"); | ||
2499 | |||
2500 | mutex_lock(&wl->mutex); | ||
2501 | |||
2502 | ret = wl1271_ps_elp_wakeup(wl); | ||
2503 | if (ret < 0) | ||
2504 | goto out; | ||
2505 | |||
2506 | ret = wl1271_scan_sched_scan_config(wl, req, ies); | ||
2507 | if (ret < 0) | ||
2508 | goto out_sleep; | ||
2509 | |||
2510 | ret = wl1271_scan_sched_scan_start(wl); | ||
2511 | if (ret < 0) | ||
2512 | goto out_sleep; | ||
2513 | |||
2514 | wl->sched_scanning = true; | ||
2515 | |||
2516 | out_sleep: | ||
2517 | wl1271_ps_elp_sleep(wl); | ||
2518 | out: | ||
2519 | mutex_unlock(&wl->mutex); | ||
2520 | return ret; | ||
2521 | } | ||
2522 | |||
2523 | static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw, | ||
2524 | struct ieee80211_vif *vif) | ||
2525 | { | ||
2526 | struct wl1271 *wl = hw->priv; | ||
2527 | int ret; | ||
2528 | |||
2529 | wl1271_debug(DEBUG_MAC80211, "wl1271_op_sched_scan_stop"); | ||
2530 | |||
2531 | mutex_lock(&wl->mutex); | ||
2532 | |||
2533 | ret = wl1271_ps_elp_wakeup(wl); | ||
2534 | if (ret < 0) | ||
2535 | goto out; | ||
2536 | |||
2537 | wl1271_scan_sched_scan_stop(wl); | ||
2538 | |||
2539 | wl1271_ps_elp_sleep(wl); | ||
2540 | out: | ||
2541 | mutex_unlock(&wl->mutex); | ||
2542 | } | ||
2543 | |||
2271 | static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) | 2544 | static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) |
2272 | { | 2545 | { |
2273 | struct wl1271 *wl = hw->priv; | 2546 | struct wl1271 *wl = hw->priv; |
@@ -2284,7 +2557,7 @@ static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) | |||
2284 | if (ret < 0) | 2557 | if (ret < 0) |
2285 | goto out; | 2558 | goto out; |
2286 | 2559 | ||
2287 | ret = wl1271_acx_frag_threshold(wl, (u16)value); | 2560 | ret = wl1271_acx_frag_threshold(wl, value); |
2288 | if (ret < 0) | 2561 | if (ret < 0) |
2289 | wl1271_warning("wl1271_op_set_frag_threshold failed: %d", ret); | 2562 | wl1271_warning("wl1271_op_set_frag_threshold failed: %d", ret); |
2290 | 2563 | ||
@@ -2312,7 +2585,7 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) | |||
2312 | if (ret < 0) | 2585 | if (ret < 0) |
2313 | goto out; | 2586 | goto out; |
2314 | 2587 | ||
2315 | ret = wl1271_acx_rts_threshold(wl, (u16) value); | 2588 | ret = wl1271_acx_rts_threshold(wl, value); |
2316 | if (ret < 0) | 2589 | if (ret < 0) |
2317 | wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret); | 2590 | wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret); |
2318 | 2591 | ||
@@ -2327,20 +2600,24 @@ out: | |||
2327 | static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, | 2600 | static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, |
2328 | int offset) | 2601 | int offset) |
2329 | { | 2602 | { |
2330 | u8 *ptr = skb->data + offset; | 2603 | u8 ssid_len; |
2604 | const u8 *ptr = cfg80211_find_ie(WLAN_EID_SSID, skb->data + offset, | ||
2605 | skb->len - offset); | ||
2331 | 2606 | ||
2332 | /* find the location of the ssid in the beacon */ | 2607 | if (!ptr) { |
2333 | while (ptr < skb->data + skb->len) { | 2608 | wl1271_error("No SSID in IEs!"); |
2334 | if (ptr[0] == WLAN_EID_SSID) { | 2609 | return -ENOENT; |
2335 | wl->ssid_len = ptr[1]; | ||
2336 | memcpy(wl->ssid, ptr+2, wl->ssid_len); | ||
2337 | return 0; | ||
2338 | } | ||
2339 | ptr += (ptr[1] + 2); | ||
2340 | } | 2610 | } |
2341 | 2611 | ||
2342 | wl1271_error("No SSID in IEs!\n"); | 2612 | ssid_len = ptr[1]; |
2343 | return -ENOENT; | 2613 | if (ssid_len > IEEE80211_MAX_SSID_LEN) { |
2614 | wl1271_error("SSID is too long!"); | ||
2615 | return -EINVAL; | ||
2616 | } | ||
2617 | |||
2618 | wl->ssid_len = ssid_len; | ||
2619 | memcpy(wl->ssid, ptr+2, ssid_len); | ||
2620 | return 0; | ||
2344 | } | 2621 | } |
2345 | 2622 | ||
2346 | static int wl1271_bss_erp_info_changed(struct wl1271 *wl, | 2623 | static int wl1271_bss_erp_info_changed(struct wl1271 *wl, |
@@ -2455,24 +2732,19 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, | |||
2455 | 2732 | ||
2456 | if ((changed & BSS_CHANGED_BASIC_RATES)) { | 2733 | if ((changed & BSS_CHANGED_BASIC_RATES)) { |
2457 | u32 rates = bss_conf->basic_rates; | 2734 | u32 rates = bss_conf->basic_rates; |
2458 | struct conf_tx_rate_class mgmt_rc; | ||
2459 | 2735 | ||
2460 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates); | 2736 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates); |
2461 | wl->basic_rate = wl1271_tx_min_rate_get(wl); | 2737 | wl->basic_rate = wl1271_tx_min_rate_get(wl); |
2462 | wl1271_debug(DEBUG_AP, "basic rates: 0x%x", | 2738 | |
2463 | wl->basic_rate_set); | 2739 | ret = wl1271_init_ap_rates(wl); |
2464 | |||
2465 | /* update the AP management rate policy with the new rates */ | ||
2466 | mgmt_rc.enabled_rates = wl->basic_rate_set; | ||
2467 | mgmt_rc.long_retry_limit = 10; | ||
2468 | mgmt_rc.short_retry_limit = 10; | ||
2469 | mgmt_rc.aflags = 0; | ||
2470 | ret = wl1271_acx_ap_rate_policy(wl, &mgmt_rc, | ||
2471 | ACX_TX_AP_MODE_MGMT_RATE); | ||
2472 | if (ret < 0) { | 2740 | if (ret < 0) { |
2473 | wl1271_error("AP mgmt policy change failed %d", ret); | 2741 | wl1271_error("AP rate policy change failed %d", ret); |
2474 | goto out; | 2742 | goto out; |
2475 | } | 2743 | } |
2744 | |||
2745 | ret = wl1271_ap_init_templates(wl); | ||
2746 | if (ret < 0) | ||
2747 | goto out; | ||
2476 | } | 2748 | } |
2477 | 2749 | ||
2478 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, changed); | 2750 | ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, changed); |
@@ -2505,6 +2777,24 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, | |||
2505 | } | 2777 | } |
2506 | } | 2778 | } |
2507 | 2779 | ||
2780 | if (changed & BSS_CHANGED_IBSS) { | ||
2781 | wl1271_debug(DEBUG_ADHOC, "ibss_joined: %d", | ||
2782 | bss_conf->ibss_joined); | ||
2783 | |||
2784 | if (bss_conf->ibss_joined) { | ||
2785 | u32 rates = bss_conf->basic_rates; | ||
2786 | wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, | ||
2787 | rates); | ||
2788 | wl->basic_rate = wl1271_tx_min_rate_get(wl); | ||
2789 | |||
2790 | /* by default, use 11b rates */ | ||
2791 | wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES; | ||
2792 | ret = wl1271_acx_sta_rate_policies(wl); | ||
2793 | if (ret < 0) | ||
2794 | goto out; | ||
2795 | } | ||
2796 | } | ||
2797 | |||
2508 | ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); | 2798 | ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed); |
2509 | if (ret < 0) | 2799 | if (ret < 0) |
2510 | goto out; | 2800 | goto out; |
@@ -2694,8 +2984,10 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
2694 | } | 2984 | } |
2695 | } else { | 2985 | } else { |
2696 | /* use defaults when not associated */ | 2986 | /* use defaults when not associated */ |
2987 | bool was_assoc = | ||
2988 | !!test_and_clear_bit(WL1271_FLAG_STA_ASSOCIATED, | ||
2989 | &wl->flags); | ||
2697 | clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags); | 2990 | clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags); |
2698 | clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); | ||
2699 | wl->aid = 0; | 2991 | wl->aid = 0; |
2700 | 2992 | ||
2701 | /* free probe-request template */ | 2993 | /* free probe-request template */ |
@@ -2721,8 +3013,10 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, | |||
2721 | goto out; | 3013 | goto out; |
2722 | 3014 | ||
2723 | /* restore the bssid filter and go to dummy bssid */ | 3015 | /* restore the bssid filter and go to dummy bssid */ |
2724 | wl1271_unjoin(wl); | 3016 | if (was_assoc) { |
2725 | wl1271_dummy_join(wl); | 3017 | wl1271_unjoin(wl); |
3018 | wl1271_dummy_join(wl); | ||
3019 | } | ||
2726 | } | 3020 | } |
2727 | } | 3021 | } |
2728 | 3022 | ||
@@ -2954,12 +3248,6 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid) | |||
2954 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); | 3248 | __clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map); |
2955 | } | 3249 | } |
2956 | 3250 | ||
2957 | bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid) | ||
2958 | { | ||
2959 | int id = hlid - WL1271_AP_STA_HLID_START; | ||
2960 | return test_bit(id, wl->ap_hlid_map); | ||
2961 | } | ||
2962 | |||
2963 | static int wl1271_op_sta_add(struct ieee80211_hw *hw, | 3251 | static int wl1271_op_sta_add(struct ieee80211_hw *hw, |
2964 | struct ieee80211_vif *vif, | 3252 | struct ieee80211_vif *vif, |
2965 | struct ieee80211_sta *sta) | 3253 | struct ieee80211_sta *sta) |
@@ -3104,6 +3392,28 @@ out: | |||
3104 | return ret; | 3392 | return ret; |
3105 | } | 3393 | } |
3106 | 3394 | ||
3395 | static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) | ||
3396 | { | ||
3397 | struct wl1271 *wl = hw->priv; | ||
3398 | bool ret = false; | ||
3399 | |||
3400 | mutex_lock(&wl->mutex); | ||
3401 | |||
3402 | if (unlikely(wl->state == WL1271_STATE_OFF)) | ||
3403 | goto out; | ||
3404 | |||
3405 | /* packets are considered pending if in the TX queue or the FW */ | ||
3406 | ret = (wl->tx_queue_count > 0) || (wl->tx_frames_cnt > 0); | ||
3407 | |||
3408 | /* the above is appropriate for STA mode for PS purposes */ | ||
3409 | WARN_ON(wl->bss_type != BSS_TYPE_STA_BSS); | ||
3410 | |||
3411 | out: | ||
3412 | mutex_unlock(&wl->mutex); | ||
3413 | |||
3414 | return ret; | ||
3415 | } | ||
3416 | |||
3107 | /* can't be const, mac80211 writes to this */ | 3417 | /* can't be const, mac80211 writes to this */ |
3108 | static struct ieee80211_rate wl1271_rates[] = { | 3418 | static struct ieee80211_rate wl1271_rates[] = { |
3109 | { .bitrate = 10, | 3419 | { .bitrate = 10, |
@@ -3340,12 +3650,16 @@ static const struct ieee80211_ops wl1271_ops = { | |||
3340 | .stop = wl1271_op_stop, | 3650 | .stop = wl1271_op_stop, |
3341 | .add_interface = wl1271_op_add_interface, | 3651 | .add_interface = wl1271_op_add_interface, |
3342 | .remove_interface = wl1271_op_remove_interface, | 3652 | .remove_interface = wl1271_op_remove_interface, |
3653 | .suspend = wl1271_op_suspend, | ||
3654 | .resume = wl1271_op_resume, | ||
3343 | .config = wl1271_op_config, | 3655 | .config = wl1271_op_config, |
3344 | .prepare_multicast = wl1271_op_prepare_multicast, | 3656 | .prepare_multicast = wl1271_op_prepare_multicast, |
3345 | .configure_filter = wl1271_op_configure_filter, | 3657 | .configure_filter = wl1271_op_configure_filter, |
3346 | .tx = wl1271_op_tx, | 3658 | .tx = wl1271_op_tx, |
3347 | .set_key = wl1271_op_set_key, | 3659 | .set_key = wl1271_op_set_key, |
3348 | .hw_scan = wl1271_op_hw_scan, | 3660 | .hw_scan = wl1271_op_hw_scan, |
3661 | .sched_scan_start = wl1271_op_sched_scan_start, | ||
3662 | .sched_scan_stop = wl1271_op_sched_scan_stop, | ||
3349 | .bss_info_changed = wl1271_op_bss_info_changed, | 3663 | .bss_info_changed = wl1271_op_bss_info_changed, |
3350 | .set_frag_threshold = wl1271_op_set_frag_threshold, | 3664 | .set_frag_threshold = wl1271_op_set_frag_threshold, |
3351 | .set_rts_threshold = wl1271_op_set_rts_threshold, | 3665 | .set_rts_threshold = wl1271_op_set_rts_threshold, |
@@ -3355,6 +3669,7 @@ static const struct ieee80211_ops wl1271_ops = { | |||
3355 | .sta_add = wl1271_op_sta_add, | 3669 | .sta_add = wl1271_op_sta_add, |
3356 | .sta_remove = wl1271_op_sta_remove, | 3670 | .sta_remove = wl1271_op_sta_remove, |
3357 | .ampdu_action = wl1271_op_ampdu_action, | 3671 | .ampdu_action = wl1271_op_ampdu_action, |
3672 | .tx_frames_pending = wl1271_tx_frames_pending, | ||
3358 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) | 3673 | CFG80211_TESTMODE_CMD(wl1271_tm_cmd) |
3359 | }; | 3674 | }; |
3360 | 3675 | ||
@@ -3542,6 +3857,8 @@ int wl1271_init_ieee80211(struct wl1271 *wl) | |||
3542 | IEEE80211_HW_HAS_RATE_CONTROL | | 3857 | IEEE80211_HW_HAS_RATE_CONTROL | |
3543 | IEEE80211_HW_CONNECTION_MONITOR | | 3858 | IEEE80211_HW_CONNECTION_MONITOR | |
3544 | IEEE80211_HW_SUPPORTS_CQM_RSSI | | 3859 | IEEE80211_HW_SUPPORTS_CQM_RSSI | |
3860 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | ||
3861 | IEEE80211_HW_SPECTRUM_MGMT | | ||
3545 | IEEE80211_HW_AP_LINK_PS; | 3862 | IEEE80211_HW_AP_LINK_PS; |
3546 | 3863 | ||
3547 | wl->hw->wiphy->cipher_suites = cipher_suites; | 3864 | wl->hw->wiphy->cipher_suites = cipher_suites; |
@@ -3663,6 +3980,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) | |||
3663 | wl->ap_fw_ps_map = 0; | 3980 | wl->ap_fw_ps_map = 0; |
3664 | wl->quirks = 0; | 3981 | wl->quirks = 0; |
3665 | wl->platform_quirks = 0; | 3982 | wl->platform_quirks = 0; |
3983 | wl->sched_scanning = false; | ||
3666 | 3984 | ||
3667 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); | 3985 | memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map)); |
3668 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) | 3986 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) |
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c index b8deada5d020..b59b67711a17 100644 --- a/drivers/net/wireless/wl12xx/ps.c +++ b/drivers/net/wireless/wl12xx/ps.c | |||
@@ -43,6 +43,10 @@ void wl1271_elp_work(struct work_struct *work) | |||
43 | if (unlikely(wl->state == WL1271_STATE_OFF)) | 43 | if (unlikely(wl->state == WL1271_STATE_OFF)) |
44 | goto out; | 44 | goto out; |
45 | 45 | ||
46 | /* our work might have been already cancelled */ | ||
47 | if (unlikely(!test_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))) | ||
48 | goto out; | ||
49 | |||
46 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || | 50 | if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) || |
47 | (!test_bit(WL1271_FLAG_PSM, &wl->flags) && | 51 | (!test_bit(WL1271_FLAG_PSM, &wl->flags) && |
48 | !test_bit(WL1271_FLAG_IDLE, &wl->flags))) | 52 | !test_bit(WL1271_FLAG_IDLE, &wl->flags))) |
@@ -61,12 +65,16 @@ out: | |||
61 | /* Routines to toggle sleep mode while in ELP */ | 65 | /* Routines to toggle sleep mode while in ELP */ |
62 | void wl1271_ps_elp_sleep(struct wl1271 *wl) | 66 | void wl1271_ps_elp_sleep(struct wl1271 *wl) |
63 | { | 67 | { |
64 | if (test_bit(WL1271_FLAG_PSM, &wl->flags) || | 68 | /* we shouldn't get consecutive sleep requests */ |
65 | test_bit(WL1271_FLAG_IDLE, &wl->flags)) { | 69 | if (WARN_ON(test_and_set_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags))) |
66 | cancel_delayed_work(&wl->elp_work); | 70 | return; |
67 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, | 71 | |
68 | msecs_to_jiffies(ELP_ENTRY_DELAY)); | 72 | if (!test_bit(WL1271_FLAG_PSM, &wl->flags) && |
69 | } | 73 | !test_bit(WL1271_FLAG_IDLE, &wl->flags)) |
74 | return; | ||
75 | |||
76 | ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, | ||
77 | msecs_to_jiffies(ELP_ENTRY_DELAY)); | ||
70 | } | 78 | } |
71 | 79 | ||
72 | int wl1271_ps_elp_wakeup(struct wl1271 *wl) | 80 | int wl1271_ps_elp_wakeup(struct wl1271 *wl) |
@@ -77,6 +85,16 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl) | |||
77 | u32 start_time = jiffies; | 85 | u32 start_time = jiffies; |
78 | bool pending = false; | 86 | bool pending = false; |
79 | 87 | ||
88 | /* | ||
89 | * we might try to wake up even if we didn't go to sleep | ||
90 | * before (e.g. on boot) | ||
91 | */ | ||
92 | if (!test_and_clear_bit(WL1271_FLAG_ELP_REQUESTED, &wl->flags)) | ||
93 | return 0; | ||
94 | |||
95 | /* don't cancel_sync as it might contend for a mutex and deadlock */ | ||
96 | cancel_delayed_work(&wl->elp_work); | ||
97 | |||
80 | if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags)) | 98 | if (!test_bit(WL1271_FLAG_IN_ELP, &wl->flags)) |
81 | return 0; | 99 | return 0; |
82 | 100 | ||
diff --git a/drivers/net/wireless/wl12xx/ps.h b/drivers/net/wireless/wl12xx/ps.h index c41bd0a711bc..25eb9bc9b628 100644 --- a/drivers/net/wireless/wl12xx/ps.h +++ b/drivers/net/wireless/wl12xx/ps.h | |||
@@ -35,4 +35,6 @@ void wl1271_elp_work(struct work_struct *work); | |||
35 | void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues); | 35 | void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues); |
36 | void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid); | 36 | void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid); |
37 | 37 | ||
38 | #define WL1271_PS_COMPLETE_TIMEOUT 500 | ||
39 | |||
38 | #endif /* __WL1271_PS_H__ */ | 40 | #endif /* __WL1271_PS_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c index 2a581495d5c9..70091035e019 100644 --- a/drivers/net/wireless/wl12xx/rx.c +++ b/drivers/net/wireless/wl12xx/rx.c | |||
@@ -76,12 +76,15 @@ static void wl1271_rx_status(struct wl1271 *wl, | |||
76 | status->band); | 76 | status->band); |
77 | 77 | ||
78 | if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { | 78 | if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { |
79 | status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; | 79 | u8 desc_err_code = desc->status & WL1271_RX_DESC_STATUS_MASK; |
80 | 80 | ||
81 | if (likely(!(desc->status & WL1271_RX_DESC_DECRYPT_FAIL))) | 81 | status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED | |
82 | status->flag |= RX_FLAG_DECRYPTED; | 82 | RX_FLAG_DECRYPTED; |
83 | if (unlikely(desc->status & WL1271_RX_DESC_MIC_FAIL)) | 83 | |
84 | if (unlikely(desc_err_code == WL1271_RX_DESC_MIC_FAIL)) { | ||
84 | status->flag |= RX_FLAG_MMIC_ERROR; | 85 | status->flag |= RX_FLAG_MMIC_ERROR; |
86 | wl1271_warning("Michael MIC error"); | ||
87 | } | ||
85 | } | 88 | } |
86 | } | 89 | } |
87 | 90 | ||
@@ -100,6 +103,25 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) | |||
100 | if (unlikely(wl->state == WL1271_STATE_PLT)) | 103 | if (unlikely(wl->state == WL1271_STATE_PLT)) |
101 | return -EINVAL; | 104 | return -EINVAL; |
102 | 105 | ||
106 | /* the data read starts with the descriptor */ | ||
107 | desc = (struct wl1271_rx_descriptor *) data; | ||
108 | |||
109 | switch (desc->status & WL1271_RX_DESC_STATUS_MASK) { | ||
110 | /* discard corrupted packets */ | ||
111 | case WL1271_RX_DESC_DRIVER_RX_Q_FAIL: | ||
112 | case WL1271_RX_DESC_DECRYPT_FAIL: | ||
113 | wl1271_warning("corrupted packet in RX with status: 0x%x", | ||
114 | desc->status & WL1271_RX_DESC_STATUS_MASK); | ||
115 | return -EINVAL; | ||
116 | case WL1271_RX_DESC_SUCCESS: | ||
117 | case WL1271_RX_DESC_MIC_FAIL: | ||
118 | break; | ||
119 | default: | ||
120 | wl1271_error("invalid RX descriptor status: 0x%x", | ||
121 | desc->status & WL1271_RX_DESC_STATUS_MASK); | ||
122 | return -EINVAL; | ||
123 | } | ||
124 | |||
103 | skb = __dev_alloc_skb(length, GFP_KERNEL); | 125 | skb = __dev_alloc_skb(length, GFP_KERNEL); |
104 | if (!skb) { | 126 | if (!skb) { |
105 | wl1271_error("Couldn't allocate RX frame"); | 127 | wl1271_error("Couldn't allocate RX frame"); |
@@ -109,9 +131,6 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) | |||
109 | buf = skb_put(skb, length); | 131 | buf = skb_put(skb, length); |
110 | memcpy(buf, data, length); | 132 | memcpy(buf, data, length); |
111 | 133 | ||
112 | /* the data read starts with the descriptor */ | ||
113 | desc = (struct wl1271_rx_descriptor *) buf; | ||
114 | |||
115 | /* now we pull the descriptor out of the buffer */ | 134 | /* now we pull the descriptor out of the buffer */ |
116 | skb_pull(skb, sizeof(*desc)); | 135 | skb_pull(skb, sizeof(*desc)); |
117 | 136 | ||
@@ -121,7 +140,8 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length) | |||
121 | 140 | ||
122 | wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); | 141 | wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon); |
123 | 142 | ||
124 | wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len, | 143 | wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, |
144 | skb->len - desc->pad_len, | ||
125 | beacon ? "beacon" : ""); | 145 | beacon ? "beacon" : ""); |
126 | 146 | ||
127 | skb_trim(skb, skb->len - desc->pad_len); | 147 | skb_trim(skb, skb->len - desc->pad_len); |
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c index 5d0544c8f3f5..f37e5a391976 100644 --- a/drivers/net/wireless/wl12xx/scan.c +++ b/drivers/net/wireless/wl12xx/scan.c | |||
@@ -320,3 +320,246 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, | |||
320 | 320 | ||
321 | return 0; | 321 | return 0; |
322 | } | 322 | } |
323 | |||
324 | static int | ||
325 | wl1271_scan_get_sched_scan_channels(struct wl1271 *wl, | ||
326 | struct cfg80211_sched_scan_request *req, | ||
327 | struct conn_scan_ch_params *channels, | ||
328 | u32 band, bool radar, bool passive, | ||
329 | int start) | ||
330 | { | ||
331 | struct conf_sched_scan_settings *c = &wl->conf.sched_scan; | ||
332 | int i, j; | ||
333 | u32 flags; | ||
334 | |||
335 | for (i = 0, j = start; | ||
336 | i < req->n_channels && j < MAX_CHANNELS_ALL_BANDS; | ||
337 | i++) { | ||
338 | flags = req->channels[i]->flags; | ||
339 | |||
340 | if (!(flags & IEEE80211_CHAN_DISABLED) && | ||
341 | ((flags & IEEE80211_CHAN_PASSIVE_SCAN) == passive) && | ||
342 | ((flags & IEEE80211_CHAN_RADAR) == radar) && | ||
343 | (req->channels[i]->band == band)) { | ||
344 | wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ", | ||
345 | req->channels[i]->band, | ||
346 | req->channels[i]->center_freq); | ||
347 | wl1271_debug(DEBUG_SCAN, "hw_value %d, flags %X", | ||
348 | req->channels[i]->hw_value, | ||
349 | req->channels[i]->flags); | ||
350 | wl1271_debug(DEBUG_SCAN, "max_power %d", | ||
351 | req->channels[i]->max_power); | ||
352 | |||
353 | if (flags & IEEE80211_CHAN_PASSIVE_SCAN) { | ||
354 | channels[j].passive_duration = | ||
355 | cpu_to_le16(c->dwell_time_passive); | ||
356 | } else { | ||
357 | channels[j].min_duration = | ||
358 | cpu_to_le16(c->min_dwell_time_active); | ||
359 | channels[j].max_duration = | ||
360 | cpu_to_le16(c->max_dwell_time_active); | ||
361 | } | ||
362 | channels[j].tx_power_att = req->channels[j]->max_power; | ||
363 | channels[j].channel = req->channels[i]->hw_value; | ||
364 | |||
365 | j++; | ||
366 | } | ||
367 | } | ||
368 | |||
369 | return j - start; | ||
370 | } | ||
371 | |||
372 | static int | ||
373 | wl1271_scan_sched_scan_channels(struct wl1271 *wl, | ||
374 | struct cfg80211_sched_scan_request *req, | ||
375 | struct wl1271_cmd_sched_scan_config *cfg) | ||
376 | { | ||
377 | int idx = 0; | ||
378 | |||
379 | cfg->passive[0] = | ||
380 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, | ||
381 | IEEE80211_BAND_2GHZ, | ||
382 | false, true, idx); | ||
383 | idx += cfg->passive[0]; | ||
384 | |||
385 | cfg->active[0] = | ||
386 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, | ||
387 | IEEE80211_BAND_2GHZ, | ||
388 | false, false, idx); | ||
389 | idx += cfg->active[0]; | ||
390 | |||
391 | cfg->passive[1] = | ||
392 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, | ||
393 | IEEE80211_BAND_5GHZ, | ||
394 | false, true, idx); | ||
395 | idx += cfg->passive[1]; | ||
396 | |||
397 | cfg->active[1] = | ||
398 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, | ||
399 | IEEE80211_BAND_5GHZ, | ||
400 | false, false, 14); | ||
401 | idx += cfg->active[1]; | ||
402 | |||
403 | cfg->dfs = | ||
404 | wl1271_scan_get_sched_scan_channels(wl, req, cfg->channels, | ||
405 | IEEE80211_BAND_5GHZ, | ||
406 | true, false, idx); | ||
407 | idx += cfg->dfs; | ||
408 | |||
409 | wl1271_debug(DEBUG_SCAN, " 2.4GHz: active %d passive %d", | ||
410 | cfg->active[0], cfg->passive[0]); | ||
411 | wl1271_debug(DEBUG_SCAN, " 5GHz: active %d passive %d", | ||
412 | cfg->active[1], cfg->passive[1]); | ||
413 | |||
414 | return idx; | ||
415 | } | ||
416 | |||
417 | int wl1271_scan_sched_scan_config(struct wl1271 *wl, | ||
418 | struct cfg80211_sched_scan_request *req, | ||
419 | struct ieee80211_sched_scan_ies *ies) | ||
420 | { | ||
421 | struct wl1271_cmd_sched_scan_config *cfg = NULL; | ||
422 | struct conf_sched_scan_settings *c = &wl->conf.sched_scan; | ||
423 | int i, total_channels, ret; | ||
424 | |||
425 | wl1271_debug(DEBUG_CMD, "cmd sched_scan scan config"); | ||
426 | |||
427 | cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); | ||
428 | if (!cfg) | ||
429 | return -ENOMEM; | ||
430 | |||
431 | cfg->rssi_threshold = c->rssi_threshold; | ||
432 | cfg->snr_threshold = c->snr_threshold; | ||
433 | cfg->n_probe_reqs = c->num_probe_reqs; | ||
434 | /* cycles set to 0 it means infinite (until manually stopped) */ | ||
435 | cfg->cycles = 0; | ||
436 | /* report APs when at least 1 is found */ | ||
437 | cfg->report_after = 1; | ||
438 | /* don't stop scanning automatically when something is found */ | ||
439 | cfg->terminate = 0; | ||
440 | cfg->tag = WL1271_SCAN_DEFAULT_TAG; | ||
441 | /* don't filter on BSS type */ | ||
442 | cfg->bss_type = SCAN_BSS_TYPE_ANY; | ||
443 | /* currently NL80211 supports only a single interval */ | ||
444 | for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++) | ||
445 | cfg->intervals[i] = cpu_to_le32(req->interval); | ||
446 | |||
447 | if (req->ssids[0].ssid_len && req->ssids[0].ssid) { | ||
448 | cfg->filter_type = SCAN_SSID_FILTER_SPECIFIC; | ||
449 | cfg->ssid_len = req->ssids[0].ssid_len; | ||
450 | memcpy(cfg->ssid, req->ssids[0].ssid, | ||
451 | req->ssids[0].ssid_len); | ||
452 | } else { | ||
453 | cfg->filter_type = SCAN_SSID_FILTER_ANY; | ||
454 | cfg->ssid_len = 0; | ||
455 | } | ||
456 | |||
457 | total_channels = wl1271_scan_sched_scan_channels(wl, req, cfg); | ||
458 | if (total_channels == 0) { | ||
459 | wl1271_error("scan channel list is empty"); | ||
460 | ret = -EINVAL; | ||
461 | goto out; | ||
462 | } | ||
463 | |||
464 | if (cfg->active[0]) { | ||
465 | ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid, | ||
466 | req->ssids[0].ssid_len, | ||
467 | ies->ie[IEEE80211_BAND_2GHZ], | ||
468 | ies->len[IEEE80211_BAND_2GHZ], | ||
469 | IEEE80211_BAND_2GHZ); | ||
470 | if (ret < 0) { | ||
471 | wl1271_error("2.4GHz PROBE request template failed"); | ||
472 | goto out; | ||
473 | } | ||
474 | } | ||
475 | |||
476 | if (cfg->active[1]) { | ||
477 | ret = wl1271_cmd_build_probe_req(wl, req->ssids[0].ssid, | ||
478 | req->ssids[0].ssid_len, | ||
479 | ies->ie[IEEE80211_BAND_5GHZ], | ||
480 | ies->len[IEEE80211_BAND_5GHZ], | ||
481 | IEEE80211_BAND_5GHZ); | ||
482 | if (ret < 0) { | ||
483 | wl1271_error("5GHz PROBE request template failed"); | ||
484 | goto out; | ||
485 | } | ||
486 | } | ||
487 | |||
488 | wl1271_dump(DEBUG_SCAN, "SCAN_CFG: ", cfg, sizeof(*cfg)); | ||
489 | |||
490 | ret = wl1271_cmd_send(wl, CMD_CONNECTION_SCAN_CFG, cfg, | ||
491 | sizeof(*cfg), 0); | ||
492 | if (ret < 0) { | ||
493 | wl1271_error("SCAN configuration failed"); | ||
494 | goto out; | ||
495 | } | ||
496 | out: | ||
497 | kfree(cfg); | ||
498 | return ret; | ||
499 | } | ||
500 | |||
501 | int wl1271_scan_sched_scan_start(struct wl1271 *wl) | ||
502 | { | ||
503 | struct wl1271_cmd_sched_scan_start *start; | ||
504 | int ret = 0; | ||
505 | |||
506 | wl1271_debug(DEBUG_CMD, "cmd periodic scan start"); | ||
507 | |||
508 | if (wl->bss_type != BSS_TYPE_STA_BSS) | ||
509 | return -EOPNOTSUPP; | ||
510 | |||
511 | if (!test_bit(WL1271_FLAG_IDLE, &wl->flags)) | ||
512 | return -EBUSY; | ||
513 | |||
514 | start = kzalloc(sizeof(*start), GFP_KERNEL); | ||
515 | if (!start) | ||
516 | return -ENOMEM; | ||
517 | |||
518 | start->tag = WL1271_SCAN_DEFAULT_TAG; | ||
519 | |||
520 | ret = wl1271_cmd_send(wl, CMD_START_PERIODIC_SCAN, start, | ||
521 | sizeof(*start), 0); | ||
522 | if (ret < 0) { | ||
523 | wl1271_error("failed to send scan start command"); | ||
524 | goto out_free; | ||
525 | } | ||
526 | |||
527 | out_free: | ||
528 | kfree(start); | ||
529 | return ret; | ||
530 | } | ||
531 | |||
532 | void wl1271_scan_sched_scan_results(struct wl1271 *wl) | ||
533 | { | ||
534 | wl1271_debug(DEBUG_SCAN, "got periodic scan results"); | ||
535 | |||
536 | ieee80211_sched_scan_results(wl->hw); | ||
537 | } | ||
538 | |||
539 | void wl1271_scan_sched_scan_stop(struct wl1271 *wl) | ||
540 | { | ||
541 | struct wl1271_cmd_sched_scan_stop *stop; | ||
542 | int ret = 0; | ||
543 | |||
544 | wl1271_debug(DEBUG_CMD, "cmd periodic scan stop"); | ||
545 | |||
546 | /* FIXME: what to do if alloc'ing to stop fails? */ | ||
547 | stop = kzalloc(sizeof(*stop), GFP_KERNEL); | ||
548 | if (!stop) { | ||
549 | wl1271_error("failed to alloc memory to send sched scan stop"); | ||
550 | return; | ||
551 | } | ||
552 | |||
553 | stop->tag = WL1271_SCAN_DEFAULT_TAG; | ||
554 | |||
555 | ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop, | ||
556 | sizeof(*stop), 0); | ||
557 | if (ret < 0) { | ||
558 | wl1271_error("failed to send sched scan stop command"); | ||
559 | goto out_free; | ||
560 | } | ||
561 | wl->sched_scanning = false; | ||
562 | |||
563 | out_free: | ||
564 | kfree(stop); | ||
565 | } | ||
diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/wl12xx/scan.h index 421a750add5a..c83319579ca3 100644 --- a/drivers/net/wireless/wl12xx/scan.h +++ b/drivers/net/wireless/wl12xx/scan.h | |||
@@ -33,6 +33,12 @@ int wl1271_scan_build_probe_req(struct wl1271 *wl, | |||
33 | const u8 *ie, size_t ie_len, u8 band); | 33 | const u8 *ie, size_t ie_len, u8 band); |
34 | void wl1271_scan_stm(struct wl1271 *wl); | 34 | void wl1271_scan_stm(struct wl1271 *wl); |
35 | void wl1271_scan_complete_work(struct work_struct *work); | 35 | void wl1271_scan_complete_work(struct work_struct *work); |
36 | int wl1271_scan_sched_scan_config(struct wl1271 *wl, | ||
37 | struct cfg80211_sched_scan_request *req, | ||
38 | struct ieee80211_sched_scan_ies *ies); | ||
39 | int wl1271_scan_sched_scan_start(struct wl1271 *wl); | ||
40 | void wl1271_scan_sched_scan_stop(struct wl1271 *wl); | ||
41 | void wl1271_scan_sched_scan_results(struct wl1271 *wl); | ||
36 | 42 | ||
37 | #define WL1271_SCAN_MAX_CHANNELS 24 | 43 | #define WL1271_SCAN_MAX_CHANNELS 24 |
38 | #define WL1271_SCAN_DEFAULT_TAG 1 | 44 | #define WL1271_SCAN_DEFAULT_TAG 1 |
@@ -106,4 +112,112 @@ struct wl1271_cmd_trigger_scan_to { | |||
106 | __le32 timeout; | 112 | __le32 timeout; |
107 | } __packed; | 113 | } __packed; |
108 | 114 | ||
115 | #define MAX_CHANNELS_ALL_BANDS 41 | ||
116 | #define SCAN_MAX_CYCLE_INTERVALS 16 | ||
117 | #define SCAN_MAX_BANDS 3 | ||
118 | |||
119 | enum { | ||
120 | SCAN_CHANNEL_TYPE_2GHZ_PASSIVE, | ||
121 | SCAN_CHANNEL_TYPE_2GHZ_ACTIVE, | ||
122 | SCAN_CHANNEL_TYPE_5GHZ_PASSIVE, | ||
123 | SCAN_CHANNEL_TYPE_5GHZ_ACTIVE, | ||
124 | SCAN_CHANNEL_TYPE_5GHZ_DFS, | ||
125 | }; | ||
126 | |||
127 | enum { | ||
128 | SCAN_SSID_FILTER_ANY = 0, | ||
129 | SCAN_SSID_FILTER_SPECIFIC = 1, | ||
130 | SCAN_SSID_FILTER_LIST = 2, | ||
131 | SCAN_SSID_FILTER_DISABLED = 3 | ||
132 | }; | ||
133 | |||
134 | enum { | ||
135 | SCAN_BSS_TYPE_INDEPENDENT, | ||
136 | SCAN_BSS_TYPE_INFRASTRUCTURE, | ||
137 | SCAN_BSS_TYPE_ANY, | ||
138 | }; | ||
139 | |||
140 | struct conn_scan_ch_params { | ||
141 | __le16 min_duration; | ||
142 | __le16 max_duration; | ||
143 | __le16 passive_duration; | ||
144 | |||
145 | u8 channel; | ||
146 | u8 tx_power_att; | ||
147 | |||
148 | /* bit 0: DFS channel; bit 1: DFS enabled */ | ||
149 | u8 flags; | ||
150 | |||
151 | u8 padding[3]; | ||
152 | } __packed; | ||
153 | |||
154 | struct wl1271_cmd_sched_scan_config { | ||
155 | struct wl1271_cmd_header header; | ||
156 | |||
157 | __le32 intervals[SCAN_MAX_CYCLE_INTERVALS]; | ||
158 | |||
159 | s8 rssi_threshold; /* for filtering (in dBm) */ | ||
160 | s8 snr_threshold; /* for filtering (in dB) */ | ||
161 | |||
162 | u8 cycles; /* maximum number of scan cycles */ | ||
163 | u8 report_after; /* report when this number of results are received */ | ||
164 | u8 terminate; /* stop scanning after reporting */ | ||
165 | |||
166 | u8 tag; | ||
167 | u8 bss_type; /* for filtering */ | ||
168 | u8 filter_type; | ||
169 | |||
170 | u8 ssid_len; /* For SCAN_SSID_FILTER_SPECIFIC */ | ||
171 | u8 ssid[IW_ESSID_MAX_SIZE]; | ||
172 | |||
173 | u8 n_probe_reqs; /* Number of probes requests per channel */ | ||
174 | |||
175 | u8 passive[SCAN_MAX_BANDS]; | ||
176 | u8 active[SCAN_MAX_BANDS]; | ||
177 | |||
178 | u8 dfs; | ||
179 | |||
180 | u8 padding[3]; | ||
181 | |||
182 | struct conn_scan_ch_params channels[MAX_CHANNELS_ALL_BANDS]; | ||
183 | } __packed; | ||
184 | |||
185 | |||
186 | #define SCHED_SCAN_MAX_SSIDS 8 | ||
187 | |||
188 | enum { | ||
189 | SCAN_SSID_TYPE_PUBLIC = 0, | ||
190 | SCAN_SSID_TYPE_HIDDEN = 1, | ||
191 | }; | ||
192 | |||
193 | struct wl1271_ssid { | ||
194 | u8 type; | ||
195 | u8 len; | ||
196 | u8 ssid[IW_ESSID_MAX_SIZE]; | ||
197 | /* u8 padding[2]; */ | ||
198 | } __packed; | ||
199 | |||
200 | struct wl1271_cmd_sched_scan_ssid_list { | ||
201 | struct wl1271_cmd_header header; | ||
202 | |||
203 | u8 n_ssids; | ||
204 | struct wl1271_ssid ssids[SCHED_SCAN_MAX_SSIDS]; | ||
205 | u8 padding[3]; | ||
206 | } __packed; | ||
207 | |||
208 | struct wl1271_cmd_sched_scan_start { | ||
209 | struct wl1271_cmd_header header; | ||
210 | |||
211 | u8 tag; | ||
212 | u8 padding[3]; | ||
213 | } __packed; | ||
214 | |||
215 | struct wl1271_cmd_sched_scan_stop { | ||
216 | struct wl1271_cmd_header header; | ||
217 | |||
218 | u8 tag; | ||
219 | u8 padding[3]; | ||
220 | } __packed; | ||
221 | |||
222 | |||
109 | #endif /* __WL1271_SCAN_H__ */ | 223 | #endif /* __WL1271_SCAN_H__ */ |
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c index bcd4ad7ba90d..92d29a860fc0 100644 --- a/drivers/net/wireless/wl12xx/sdio.c +++ b/drivers/net/wireless/wl12xx/sdio.c | |||
@@ -82,6 +82,16 @@ static irqreturn_t wl1271_hardirq(int irq, void *cookie) | |||
82 | complete(wl->elp_compl); | 82 | complete(wl->elp_compl); |
83 | wl->elp_compl = NULL; | 83 | wl->elp_compl = NULL; |
84 | } | 84 | } |
85 | |||
86 | if (test_bit(WL1271_FLAG_SUSPENDED, &wl->flags)) { | ||
87 | /* don't enqueue a work right now. mark it as pending */ | ||
88 | set_bit(WL1271_FLAG_PENDING_WORK, &wl->flags); | ||
89 | wl1271_debug(DEBUG_IRQ, "should not enqueue work"); | ||
90 | disable_irq_nosync(wl->irq); | ||
91 | pm_wakeup_event(wl1271_sdio_wl_to_dev(wl), 0); | ||
92 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
93 | return IRQ_HANDLED; | ||
94 | } | ||
85 | spin_unlock_irqrestore(&wl->wl_lock, flags); | 95 | spin_unlock_irqrestore(&wl->wl_lock, flags); |
86 | 96 | ||
87 | return IRQ_WAKE_THREAD; | 97 | return IRQ_WAKE_THREAD; |
@@ -221,6 +231,7 @@ static int __devinit wl1271_probe(struct sdio_func *func, | |||
221 | const struct wl12xx_platform_data *wlan_data; | 231 | const struct wl12xx_platform_data *wlan_data; |
222 | struct wl1271 *wl; | 232 | struct wl1271 *wl; |
223 | unsigned long irqflags; | 233 | unsigned long irqflags; |
234 | mmc_pm_flag_t mmcflags; | ||
224 | int ret; | 235 | int ret; |
225 | 236 | ||
226 | /* We are only able to handle the wlan function */ | 237 | /* We are only able to handle the wlan function */ |
@@ -267,8 +278,18 @@ static int __devinit wl1271_probe(struct sdio_func *func, | |||
267 | goto out_free; | 278 | goto out_free; |
268 | } | 279 | } |
269 | 280 | ||
281 | enable_irq_wake(wl->irq); | ||
282 | device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 1); | ||
283 | |||
270 | disable_irq(wl->irq); | 284 | disable_irq(wl->irq); |
271 | 285 | ||
286 | /* if sdio can keep power while host is suspended, enable wow */ | ||
287 | mmcflags = sdio_get_host_pm_caps(func); | ||
288 | wl1271_debug(DEBUG_SDIO, "sdio PM caps = 0x%x", mmcflags); | ||
289 | |||
290 | if (mmcflags & MMC_PM_KEEP_POWER) | ||
291 | hw->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY; | ||
292 | |||
272 | ret = wl1271_init_ieee80211(wl); | 293 | ret = wl1271_init_ieee80211(wl); |
273 | if (ret) | 294 | if (ret) |
274 | goto out_irq; | 295 | goto out_irq; |
@@ -303,6 +324,8 @@ static void __devexit wl1271_remove(struct sdio_func *func) | |||
303 | pm_runtime_get_noresume(&func->dev); | 324 | pm_runtime_get_noresume(&func->dev); |
304 | 325 | ||
305 | wl1271_unregister_hw(wl); | 326 | wl1271_unregister_hw(wl); |
327 | device_init_wakeup(wl1271_sdio_wl_to_dev(wl), 0); | ||
328 | disable_irq_wake(wl->irq); | ||
306 | free_irq(wl->irq, wl); | 329 | free_irq(wl->irq, wl); |
307 | wl1271_free_hw(wl); | 330 | wl1271_free_hw(wl); |
308 | } | 331 | } |
@@ -311,11 +334,50 @@ static int wl1271_suspend(struct device *dev) | |||
311 | { | 334 | { |
312 | /* Tell MMC/SDIO core it's OK to power down the card | 335 | /* Tell MMC/SDIO core it's OK to power down the card |
313 | * (if it isn't already), but not to remove it completely */ | 336 | * (if it isn't already), but not to remove it completely */ |
314 | return 0; | 337 | struct sdio_func *func = dev_to_sdio_func(dev); |
338 | struct wl1271 *wl = sdio_get_drvdata(func); | ||
339 | mmc_pm_flag_t sdio_flags; | ||
340 | int ret = 0; | ||
341 | |||
342 | wl1271_debug(DEBUG_MAC80211, "wl1271 suspend. wow_enabled: %d", | ||
343 | wl->wow_enabled); | ||
344 | |||
345 | /* check whether sdio should keep power */ | ||
346 | if (wl->wow_enabled) { | ||
347 | sdio_flags = sdio_get_host_pm_caps(func); | ||
348 | |||
349 | if (!(sdio_flags & MMC_PM_KEEP_POWER)) { | ||
350 | wl1271_error("can't keep power while host " | ||
351 | "is suspended"); | ||
352 | ret = -EINVAL; | ||
353 | goto out; | ||
354 | } | ||
355 | |||
356 | /* keep power while host suspended */ | ||
357 | ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); | ||
358 | if (ret) { | ||
359 | wl1271_error("error while trying to keep power"); | ||
360 | goto out; | ||
361 | } | ||
362 | |||
363 | /* release host */ | ||
364 | sdio_release_host(func); | ||
365 | } | ||
366 | out: | ||
367 | return ret; | ||
315 | } | 368 | } |
316 | 369 | ||
317 | static int wl1271_resume(struct device *dev) | 370 | static int wl1271_resume(struct device *dev) |
318 | { | 371 | { |
372 | struct sdio_func *func = dev_to_sdio_func(dev); | ||
373 | struct wl1271 *wl = sdio_get_drvdata(func); | ||
374 | |||
375 | wl1271_debug(DEBUG_MAC80211, "wl1271 resume"); | ||
376 | if (wl->wow_enabled) { | ||
377 | /* claim back host */ | ||
378 | sdio_claim_host(func); | ||
379 | } | ||
380 | |||
319 | return 0; | 381 | return 0; |
320 | } | 382 | } |
321 | 383 | ||
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c index 7a3339fd3415..ca3ab1c1acef 100644 --- a/drivers/net/wireless/wl12xx/tx.c +++ b/drivers/net/wireless/wl12xx/tx.c | |||
@@ -65,6 +65,9 @@ static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb) | |||
65 | static void wl1271_free_tx_id(struct wl1271 *wl, int id) | 65 | static void wl1271_free_tx_id(struct wl1271 *wl, int id) |
66 | { | 66 | { |
67 | if (__test_and_clear_bit(id, wl->tx_frames_map)) { | 67 | if (__test_and_clear_bit(id, wl->tx_frames_map)) { |
68 | if (unlikely(wl->tx_frames_cnt == ACX_TX_DESCRIPTORS)) | ||
69 | clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags); | ||
70 | |||
68 | wl->tx_frames[id] = NULL; | 71 | wl->tx_frames[id] = NULL; |
69 | wl->tx_frames_cnt--; | 72 | wl->tx_frames_cnt--; |
70 | } | 73 | } |
@@ -630,7 +633,7 @@ void wl1271_tx_work(struct work_struct *work) | |||
630 | 633 | ||
631 | wl1271_tx_work_locked(wl); | 634 | wl1271_tx_work_locked(wl); |
632 | 635 | ||
633 | wl1271_ps_elp_wakeup(wl); | 636 | wl1271_ps_elp_sleep(wl); |
634 | out: | 637 | out: |
635 | mutex_unlock(&wl->mutex); | 638 | mutex_unlock(&wl->mutex); |
636 | } | 639 | } |
@@ -766,8 +769,8 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid) | |||
766 | wl1271_handle_tx_low_watermark(wl); | 769 | wl1271_handle_tx_low_watermark(wl); |
767 | } | 770 | } |
768 | 771 | ||
769 | /* caller must hold wl->mutex */ | 772 | /* caller must hold wl->mutex and TX must be stopped */ |
770 | void wl1271_tx_reset(struct wl1271 *wl) | 773 | void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues) |
771 | { | 774 | { |
772 | int i; | 775 | int i; |
773 | struct sk_buff *skb; | 776 | struct sk_buff *skb; |
@@ -803,8 +806,10 @@ void wl1271_tx_reset(struct wl1271 *wl) | |||
803 | /* | 806 | /* |
804 | * Make sure the driver is at a consistent state, in case this | 807 | * Make sure the driver is at a consistent state, in case this |
805 | * function is called from a context other than interface removal. | 808 | * function is called from a context other than interface removal. |
809 | * This call will always wake the TX queues. | ||
806 | */ | 810 | */ |
807 | wl1271_handle_tx_low_watermark(wl); | 811 | if (reset_tx_queues) |
812 | wl1271_handle_tx_low_watermark(wl); | ||
808 | 813 | ||
809 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) { | 814 | for (i = 0; i < ACX_TX_DESCRIPTORS; i++) { |
810 | if (wl->tx_frames[i] == NULL) | 815 | if (wl->tx_frames[i] == NULL) |
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h index fc7835c4cf63..832f9258d675 100644 --- a/drivers/net/wireless/wl12xx/tx.h +++ b/drivers/net/wireless/wl12xx/tx.h | |||
@@ -185,7 +185,7 @@ static inline int wl1271_tx_get_queue(int queue) | |||
185 | void wl1271_tx_work(struct work_struct *work); | 185 | void wl1271_tx_work(struct work_struct *work); |
186 | void wl1271_tx_work_locked(struct wl1271 *wl); | 186 | void wl1271_tx_work_locked(struct wl1271 *wl); |
187 | void wl1271_tx_complete(struct wl1271 *wl); | 187 | void wl1271_tx_complete(struct wl1271 *wl); |
188 | void wl1271_tx_reset(struct wl1271 *wl); | 188 | void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues); |
189 | void wl1271_tx_flush(struct wl1271 *wl); | 189 | void wl1271_tx_flush(struct wl1271 *wl); |
190 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); | 190 | u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); |
191 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); | 191 | u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); |
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h index 7c521af58e7d..fbe8f46d1232 100644 --- a/drivers/net/wireless/wl12xx/wl12xx.h +++ b/drivers/net/wireless/wl12xx/wl12xx.h | |||
@@ -172,6 +172,7 @@ extern u32 wl12xx_debug_level; | |||
172 | #define WL1271_PS_STA_MAX_BLOCKS (2 * 9) | 172 | #define WL1271_PS_STA_MAX_BLOCKS (2 * 9) |
173 | 173 | ||
174 | #define WL1271_AP_BSS_INDEX 0 | 174 | #define WL1271_AP_BSS_INDEX 0 |
175 | #define WL1271_AP_DEF_INACTIV_SEC 300 | ||
175 | #define WL1271_AP_DEF_BEACON_EXP 20 | 176 | #define WL1271_AP_DEF_BEACON_EXP 20 |
176 | 177 | ||
177 | #define ACX_TX_DESCRIPTORS 32 | 178 | #define ACX_TX_DESCRIPTORS 32 |
@@ -345,17 +346,19 @@ enum wl12xx_flags { | |||
345 | WL1271_FLAG_TX_QUEUE_STOPPED, | 346 | WL1271_FLAG_TX_QUEUE_STOPPED, |
346 | WL1271_FLAG_TX_PENDING, | 347 | WL1271_FLAG_TX_PENDING, |
347 | WL1271_FLAG_IN_ELP, | 348 | WL1271_FLAG_IN_ELP, |
349 | WL1271_FLAG_ELP_REQUESTED, | ||
348 | WL1271_FLAG_PSM, | 350 | WL1271_FLAG_PSM, |
349 | WL1271_FLAG_PSM_REQUESTED, | 351 | WL1271_FLAG_PSM_REQUESTED, |
350 | WL1271_FLAG_IRQ_RUNNING, | 352 | WL1271_FLAG_IRQ_RUNNING, |
351 | WL1271_FLAG_IDLE, | 353 | WL1271_FLAG_IDLE, |
352 | WL1271_FLAG_IDLE_REQUESTED, | ||
353 | WL1271_FLAG_PSPOLL_FAILURE, | 354 | WL1271_FLAG_PSPOLL_FAILURE, |
354 | WL1271_FLAG_STA_STATE_SENT, | 355 | WL1271_FLAG_STA_STATE_SENT, |
355 | WL1271_FLAG_FW_TX_BUSY, | 356 | WL1271_FLAG_FW_TX_BUSY, |
356 | WL1271_FLAG_AP_STARTED, | 357 | WL1271_FLAG_AP_STARTED, |
357 | WL1271_FLAG_IF_INITIALIZED, | 358 | WL1271_FLAG_IF_INITIALIZED, |
358 | WL1271_FLAG_DUMMY_PACKET_PENDING, | 359 | WL1271_FLAG_DUMMY_PACKET_PENDING, |
360 | WL1271_FLAG_SUSPENDED, | ||
361 | WL1271_FLAG_PENDING_WORK, | ||
359 | }; | 362 | }; |
360 | 363 | ||
361 | struct wl1271_link { | 364 | struct wl1271_link { |
@@ -478,6 +481,8 @@ struct wl1271 { | |||
478 | struct wl1271_scan scan; | 481 | struct wl1271_scan scan; |
479 | struct delayed_work scan_complete_work; | 482 | struct delayed_work scan_complete_work; |
480 | 483 | ||
484 | bool sched_scanning; | ||
485 | |||
481 | /* probe-req template for the current AP */ | 486 | /* probe-req template for the current AP */ |
482 | struct sk_buff *probereq; | 487 | struct sk_buff *probereq; |
483 | 488 | ||
@@ -508,6 +513,7 @@ struct wl1271 { | |||
508 | unsigned int rx_filter; | 513 | unsigned int rx_filter; |
509 | 514 | ||
510 | struct completion *elp_compl; | 515 | struct completion *elp_compl; |
516 | struct completion *ps_compl; | ||
511 | struct delayed_work elp_work; | 517 | struct delayed_work elp_work; |
512 | struct delayed_work pspoll_work; | 518 | struct delayed_work pspoll_work; |
513 | 519 | ||
@@ -562,6 +568,12 @@ struct wl1271 { | |||
562 | int tcxo_clock; | 568 | int tcxo_clock; |
563 | 569 | ||
564 | /* | 570 | /* |
571 | * wowlan trigger was configured during suspend. | ||
572 | * (currently, only "ANY" trigger is supported) | ||
573 | */ | ||
574 | bool wow_enabled; | ||
575 | |||
576 | /* | ||
565 | * AP-mode - links indexed by HLID. The global and broadcast links | 577 | * AP-mode - links indexed by HLID. The global and broadcast links |
566 | * are always active. | 578 | * are always active. |
567 | */ | 579 | */ |
diff --git a/drivers/ssb/driver_pcicore.c b/drivers/ssb/driver_pcicore.c index 8fde1220bc89..82feb348c8bb 100644 --- a/drivers/ssb/driver_pcicore.c +++ b/drivers/ssb/driver_pcicore.c | |||
@@ -21,8 +21,6 @@ static u16 ssb_pcie_mdio_read(struct ssb_pcicore *pc, u8 device, u8 address); | |||
21 | static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, | 21 | static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, |
22 | u8 address, u16 data); | 22 | u8 address, u16 data); |
23 | 23 | ||
24 | static void ssb_commit_settings(struct ssb_bus *bus); | ||
25 | |||
26 | static inline | 24 | static inline |
27 | u32 pcicore_read32(struct ssb_pcicore *pc, u16 offset) | 25 | u32 pcicore_read32(struct ssb_pcicore *pc, u16 offset) |
28 | { | 26 | { |
@@ -659,30 +657,6 @@ static void ssb_pcie_mdio_write(struct ssb_pcicore *pc, u8 device, | |||
659 | pcicore_write32(pc, mdio_control, 0); | 657 | pcicore_write32(pc, mdio_control, 0); |
660 | } | 658 | } |
661 | 659 | ||
662 | static void ssb_broadcast_value(struct ssb_device *dev, | ||
663 | u32 address, u32 data) | ||
664 | { | ||
665 | /* This is used for both, PCI and ChipCommon core, so be careful. */ | ||
666 | BUILD_BUG_ON(SSB_PCICORE_BCAST_ADDR != SSB_CHIPCO_BCAST_ADDR); | ||
667 | BUILD_BUG_ON(SSB_PCICORE_BCAST_DATA != SSB_CHIPCO_BCAST_DATA); | ||
668 | |||
669 | ssb_write32(dev, SSB_PCICORE_BCAST_ADDR, address); | ||
670 | ssb_read32(dev, SSB_PCICORE_BCAST_ADDR); /* flush */ | ||
671 | ssb_write32(dev, SSB_PCICORE_BCAST_DATA, data); | ||
672 | ssb_read32(dev, SSB_PCICORE_BCAST_DATA); /* flush */ | ||
673 | } | ||
674 | |||
675 | static void ssb_commit_settings(struct ssb_bus *bus) | ||
676 | { | ||
677 | struct ssb_device *dev; | ||
678 | |||
679 | dev = bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev; | ||
680 | if (WARN_ON(!dev)) | ||
681 | return; | ||
682 | /* This forces an update of the cached registers. */ | ||
683 | ssb_broadcast_value(dev, 0xFD8, 0); | ||
684 | } | ||
685 | |||
686 | int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, | 660 | int ssb_pcicore_dev_irqvecs_enable(struct ssb_pcicore *pc, |
687 | struct ssb_device *dev) | 661 | struct ssb_device *dev) |
688 | { | 662 | { |
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index ad3da93a428c..f8a13f863217 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -1329,6 +1329,37 @@ error: | |||
1329 | } | 1329 | } |
1330 | EXPORT_SYMBOL(ssb_bus_powerup); | 1330 | EXPORT_SYMBOL(ssb_bus_powerup); |
1331 | 1331 | ||
1332 | static void ssb_broadcast_value(struct ssb_device *dev, | ||
1333 | u32 address, u32 data) | ||
1334 | { | ||
1335 | #ifdef CONFIG_SSB_DRIVER_PCICORE | ||
1336 | /* This is used for both, PCI and ChipCommon core, so be careful. */ | ||
1337 | BUILD_BUG_ON(SSB_PCICORE_BCAST_ADDR != SSB_CHIPCO_BCAST_ADDR); | ||
1338 | BUILD_BUG_ON(SSB_PCICORE_BCAST_DATA != SSB_CHIPCO_BCAST_DATA); | ||
1339 | #endif | ||
1340 | |||
1341 | ssb_write32(dev, SSB_CHIPCO_BCAST_ADDR, address); | ||
1342 | ssb_read32(dev, SSB_CHIPCO_BCAST_ADDR); /* flush */ | ||
1343 | ssb_write32(dev, SSB_CHIPCO_BCAST_DATA, data); | ||
1344 | ssb_read32(dev, SSB_CHIPCO_BCAST_DATA); /* flush */ | ||
1345 | } | ||
1346 | |||
1347 | void ssb_commit_settings(struct ssb_bus *bus) | ||
1348 | { | ||
1349 | struct ssb_device *dev; | ||
1350 | |||
1351 | #ifdef CONFIG_SSB_DRIVER_PCICORE | ||
1352 | dev = bus->chipco.dev ? bus->chipco.dev : bus->pcicore.dev; | ||
1353 | #else | ||
1354 | dev = bus->chipco.dev; | ||
1355 | #endif | ||
1356 | if (WARN_ON(!dev)) | ||
1357 | return; | ||
1358 | /* This forces an update of the cached registers. */ | ||
1359 | ssb_broadcast_value(dev, 0xFD8, 0); | ||
1360 | } | ||
1361 | EXPORT_SYMBOL(ssb_commit_settings); | ||
1362 | |||
1332 | u32 ssb_admatch_base(u32 adm) | 1363 | u32 ssb_admatch_base(u32 adm) |
1333 | { | 1364 | { |
1334 | u32 base = 0; | 1365 | u32 base = 0; |
diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c index 7dca719fbcfb..45e5babd3961 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c | |||
@@ -258,7 +258,10 @@ static int we_support_multiple_80211_cores(struct ssb_bus *bus) | |||
258 | #ifdef CONFIG_SSB_PCIHOST | 258 | #ifdef CONFIG_SSB_PCIHOST |
259 | if (bus->bustype == SSB_BUSTYPE_PCI) { | 259 | if (bus->bustype == SSB_BUSTYPE_PCI) { |
260 | if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM && | 260 | if (bus->host_pci->vendor == PCI_VENDOR_ID_BROADCOM && |
261 | bus->host_pci->device == 0x4324) | 261 | ((bus->host_pci->device == 0x4313) || |
262 | (bus->host_pci->device == 0x431A) || | ||
263 | (bus->host_pci->device == 0x4321) || | ||
264 | (bus->host_pci->device == 0x4324))) | ||
262 | return 1; | 265 | return 1; |
263 | } | 266 | } |
264 | #endif /* CONFIG_SSB_PCIHOST */ | 267 | #endif /* CONFIG_SSB_PCIHOST */ |
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h new file mode 100644 index 000000000000..08763e4e848f --- /dev/null +++ b/include/linux/bcma/bcma.h | |||
@@ -0,0 +1,224 @@ | |||
1 | #ifndef LINUX_BCMA_H_ | ||
2 | #define LINUX_BCMA_H_ | ||
3 | |||
4 | #include <linux/pci.h> | ||
5 | #include <linux/mod_devicetable.h> | ||
6 | |||
7 | #include <linux/bcma/bcma_driver_chipcommon.h> | ||
8 | #include <linux/bcma/bcma_driver_pci.h> | ||
9 | |||
10 | #include "bcma_regs.h" | ||
11 | |||
12 | struct bcma_device; | ||
13 | struct bcma_bus; | ||
14 | |||
15 | enum bcma_hosttype { | ||
16 | BCMA_HOSTTYPE_NONE, | ||
17 | BCMA_HOSTTYPE_PCI, | ||
18 | BCMA_HOSTTYPE_SDIO, | ||
19 | }; | ||
20 | |||
21 | struct bcma_chipinfo { | ||
22 | u16 id; | ||
23 | u8 rev; | ||
24 | u8 pkg; | ||
25 | }; | ||
26 | |||
27 | struct bcma_host_ops { | ||
28 | u8 (*read8)(struct bcma_device *core, u16 offset); | ||
29 | u16 (*read16)(struct bcma_device *core, u16 offset); | ||
30 | u32 (*read32)(struct bcma_device *core, u16 offset); | ||
31 | void (*write8)(struct bcma_device *core, u16 offset, u8 value); | ||
32 | void (*write16)(struct bcma_device *core, u16 offset, u16 value); | ||
33 | void (*write32)(struct bcma_device *core, u16 offset, u32 value); | ||
34 | /* Agent ops */ | ||
35 | u32 (*aread32)(struct bcma_device *core, u16 offset); | ||
36 | void (*awrite32)(struct bcma_device *core, u16 offset, u32 value); | ||
37 | }; | ||
38 | |||
39 | /* Core manufacturers */ | ||
40 | #define BCMA_MANUF_ARM 0x43B | ||
41 | #define BCMA_MANUF_MIPS 0x4A7 | ||
42 | #define BCMA_MANUF_BCM 0x4BF | ||
43 | |||
44 | /* Core class values. */ | ||
45 | #define BCMA_CL_SIM 0x0 | ||
46 | #define BCMA_CL_EROM 0x1 | ||
47 | #define BCMA_CL_CORESIGHT 0x9 | ||
48 | #define BCMA_CL_VERIF 0xB | ||
49 | #define BCMA_CL_OPTIMO 0xD | ||
50 | #define BCMA_CL_GEN 0xE | ||
51 | #define BCMA_CL_PRIMECELL 0xF | ||
52 | |||
53 | /* Core-ID values. */ | ||
54 | #define BCMA_CORE_OOB_ROUTER 0x367 /* Out of band */ | ||
55 | #define BCMA_CORE_INVALID 0x700 | ||
56 | #define BCMA_CORE_CHIPCOMMON 0x800 | ||
57 | #define BCMA_CORE_ILINE20 0x801 | ||
58 | #define BCMA_CORE_SRAM 0x802 | ||
59 | #define BCMA_CORE_SDRAM 0x803 | ||
60 | #define BCMA_CORE_PCI 0x804 | ||
61 | #define BCMA_CORE_MIPS 0x805 | ||
62 | #define BCMA_CORE_ETHERNET 0x806 | ||
63 | #define BCMA_CORE_V90 0x807 | ||
64 | #define BCMA_CORE_USB11_HOSTDEV 0x808 | ||
65 | #define BCMA_CORE_ADSL 0x809 | ||
66 | #define BCMA_CORE_ILINE100 0x80A | ||
67 | #define BCMA_CORE_IPSEC 0x80B | ||
68 | #define BCMA_CORE_UTOPIA 0x80C | ||
69 | #define BCMA_CORE_PCMCIA 0x80D | ||
70 | #define BCMA_CORE_INTERNAL_MEM 0x80E | ||
71 | #define BCMA_CORE_MEMC_SDRAM 0x80F | ||
72 | #define BCMA_CORE_OFDM 0x810 | ||
73 | #define BCMA_CORE_EXTIF 0x811 | ||
74 | #define BCMA_CORE_80211 0x812 | ||
75 | #define BCMA_CORE_PHY_A 0x813 | ||
76 | #define BCMA_CORE_PHY_B 0x814 | ||
77 | #define BCMA_CORE_PHY_G 0x815 | ||
78 | #define BCMA_CORE_MIPS_3302 0x816 | ||
79 | #define BCMA_CORE_USB11_HOST 0x817 | ||
80 | #define BCMA_CORE_USB11_DEV 0x818 | ||
81 | #define BCMA_CORE_USB20_HOST 0x819 | ||
82 | #define BCMA_CORE_USB20_DEV 0x81A | ||
83 | #define BCMA_CORE_SDIO_HOST 0x81B | ||
84 | #define BCMA_CORE_ROBOSWITCH 0x81C | ||
85 | #define BCMA_CORE_PARA_ATA 0x81D | ||
86 | #define BCMA_CORE_SATA_XORDMA 0x81E | ||
87 | #define BCMA_CORE_ETHERNET_GBIT 0x81F | ||
88 | #define BCMA_CORE_PCIE 0x820 | ||
89 | #define BCMA_CORE_PHY_N 0x821 | ||
90 | #define BCMA_CORE_SRAM_CTL 0x822 | ||
91 | #define BCMA_CORE_MINI_MACPHY 0x823 | ||
92 | #define BCMA_CORE_ARM_1176 0x824 | ||
93 | #define BCMA_CORE_ARM_7TDMI 0x825 | ||
94 | #define BCMA_CORE_PHY_LP 0x826 | ||
95 | #define BCMA_CORE_PMU 0x827 | ||
96 | #define BCMA_CORE_PHY_SSN 0x828 | ||
97 | #define BCMA_CORE_SDIO_DEV 0x829 | ||
98 | #define BCMA_CORE_ARM_CM3 0x82A | ||
99 | #define BCMA_CORE_PHY_HT 0x82B | ||
100 | #define BCMA_CORE_MIPS_74K 0x82C | ||
101 | #define BCMA_CORE_MAC_GBIT 0x82D | ||
102 | #define BCMA_CORE_DDR12_MEM_CTL 0x82E | ||
103 | #define BCMA_CORE_PCIE_RC 0x82F /* PCIe Root Complex */ | ||
104 | #define BCMA_CORE_OCP_OCP_BRIDGE 0x830 | ||
105 | #define BCMA_CORE_SHARED_COMMON 0x831 | ||
106 | #define BCMA_CORE_OCP_AHB_BRIDGE 0x832 | ||
107 | #define BCMA_CORE_SPI_HOST 0x833 | ||
108 | #define BCMA_CORE_I2S 0x834 | ||
109 | #define BCMA_CORE_SDR_DDR1_MEM_CTL 0x835 /* SDR/DDR1 memory controller core */ | ||
110 | #define BCMA_CORE_SHIM 0x837 /* SHIM component in ubus/6362 */ | ||
111 | #define BCMA_CORE_DEFAULT 0xFFF | ||
112 | |||
113 | #define BCMA_MAX_NR_CORES 16 | ||
114 | |||
115 | struct bcma_device { | ||
116 | struct bcma_bus *bus; | ||
117 | struct bcma_device_id id; | ||
118 | |||
119 | struct device dev; | ||
120 | bool dev_registered; | ||
121 | |||
122 | u8 core_index; | ||
123 | |||
124 | u32 addr; | ||
125 | u32 wrap; | ||
126 | |||
127 | void *drvdata; | ||
128 | struct list_head list; | ||
129 | }; | ||
130 | |||
131 | static inline void *bcma_get_drvdata(struct bcma_device *core) | ||
132 | { | ||
133 | return core->drvdata; | ||
134 | } | ||
135 | static inline void bcma_set_drvdata(struct bcma_device *core, void *drvdata) | ||
136 | { | ||
137 | core->drvdata = drvdata; | ||
138 | } | ||
139 | |||
140 | struct bcma_driver { | ||
141 | const char *name; | ||
142 | const struct bcma_device_id *id_table; | ||
143 | |||
144 | int (*probe)(struct bcma_device *dev); | ||
145 | void (*remove)(struct bcma_device *dev); | ||
146 | int (*suspend)(struct bcma_device *dev, pm_message_t state); | ||
147 | int (*resume)(struct bcma_device *dev); | ||
148 | void (*shutdown)(struct bcma_device *dev); | ||
149 | |||
150 | struct device_driver drv; | ||
151 | }; | ||
152 | extern | ||
153 | int __bcma_driver_register(struct bcma_driver *drv, struct module *owner); | ||
154 | static inline int bcma_driver_register(struct bcma_driver *drv) | ||
155 | { | ||
156 | return __bcma_driver_register(drv, THIS_MODULE); | ||
157 | } | ||
158 | extern void bcma_driver_unregister(struct bcma_driver *drv); | ||
159 | |||
160 | struct bcma_bus { | ||
161 | /* The MMIO area. */ | ||
162 | void __iomem *mmio; | ||
163 | |||
164 | const struct bcma_host_ops *ops; | ||
165 | |||
166 | enum bcma_hosttype hosttype; | ||
167 | union { | ||
168 | /* Pointer to the PCI bus (only for BCMA_HOSTTYPE_PCI) */ | ||
169 | struct pci_dev *host_pci; | ||
170 | /* Pointer to the SDIO device (only for BCMA_HOSTTYPE_SDIO) */ | ||
171 | struct sdio_func *host_sdio; | ||
172 | }; | ||
173 | |||
174 | struct bcma_chipinfo chipinfo; | ||
175 | |||
176 | struct bcma_device *mapped_core; | ||
177 | struct list_head cores; | ||
178 | u8 nr_cores; | ||
179 | |||
180 | struct bcma_drv_cc drv_cc; | ||
181 | struct bcma_drv_pci drv_pci; | ||
182 | }; | ||
183 | |||
184 | extern inline u32 bcma_read8(struct bcma_device *core, u16 offset) | ||
185 | { | ||
186 | return core->bus->ops->read8(core, offset); | ||
187 | } | ||
188 | extern inline u32 bcma_read16(struct bcma_device *core, u16 offset) | ||
189 | { | ||
190 | return core->bus->ops->read16(core, offset); | ||
191 | } | ||
192 | extern inline u32 bcma_read32(struct bcma_device *core, u16 offset) | ||
193 | { | ||
194 | return core->bus->ops->read32(core, offset); | ||
195 | } | ||
196 | extern inline | ||
197 | void bcma_write8(struct bcma_device *core, u16 offset, u32 value) | ||
198 | { | ||
199 | core->bus->ops->write8(core, offset, value); | ||
200 | } | ||
201 | extern inline | ||
202 | void bcma_write16(struct bcma_device *core, u16 offset, u32 value) | ||
203 | { | ||
204 | core->bus->ops->write16(core, offset, value); | ||
205 | } | ||
206 | extern inline | ||
207 | void bcma_write32(struct bcma_device *core, u16 offset, u32 value) | ||
208 | { | ||
209 | core->bus->ops->write32(core, offset, value); | ||
210 | } | ||
211 | extern inline u32 bcma_aread32(struct bcma_device *core, u16 offset) | ||
212 | { | ||
213 | return core->bus->ops->aread32(core, offset); | ||
214 | } | ||
215 | extern inline | ||
216 | void bcma_awrite32(struct bcma_device *core, u16 offset, u32 value) | ||
217 | { | ||
218 | core->bus->ops->awrite32(core, offset, value); | ||
219 | } | ||
220 | |||
221 | extern bool bcma_core_is_enabled(struct bcma_device *core); | ||
222 | extern int bcma_core_enable(struct bcma_device *core, u32 flags); | ||
223 | |||
224 | #endif /* LINUX_BCMA_H_ */ | ||
diff --git a/include/linux/bcma/bcma_driver_chipcommon.h b/include/linux/bcma/bcma_driver_chipcommon.h new file mode 100644 index 000000000000..083c3b6cd5ce --- /dev/null +++ b/include/linux/bcma/bcma_driver_chipcommon.h | |||
@@ -0,0 +1,302 @@ | |||
1 | #ifndef LINUX_BCMA_DRIVER_CC_H_ | ||
2 | #define LINUX_BCMA_DRIVER_CC_H_ | ||
3 | |||
4 | /** ChipCommon core registers. **/ | ||
5 | #define BCMA_CC_ID 0x0000 | ||
6 | #define BCMA_CC_ID_ID 0x0000FFFF | ||
7 | #define BCMA_CC_ID_ID_SHIFT 0 | ||
8 | #define BCMA_CC_ID_REV 0x000F0000 | ||
9 | #define BCMA_CC_ID_REV_SHIFT 16 | ||
10 | #define BCMA_CC_ID_PKG 0x00F00000 | ||
11 | #define BCMA_CC_ID_PKG_SHIFT 20 | ||
12 | #define BCMA_CC_ID_NRCORES 0x0F000000 | ||
13 | #define BCMA_CC_ID_NRCORES_SHIFT 24 | ||
14 | #define BCMA_CC_ID_TYPE 0xF0000000 | ||
15 | #define BCMA_CC_ID_TYPE_SHIFT 28 | ||
16 | #define BCMA_CC_CAP 0x0004 /* Capabilities */ | ||
17 | #define BCMA_CC_CAP_NRUART 0x00000003 /* # of UARTs */ | ||
18 | #define BCMA_CC_CAP_MIPSEB 0x00000004 /* MIPS in BigEndian Mode */ | ||
19 | #define BCMA_CC_CAP_UARTCLK 0x00000018 /* UART clock select */ | ||
20 | #define BCMA_CC_CAP_UARTCLK_INT 0x00000008 /* UARTs are driven by internal divided clock */ | ||
21 | #define BCMA_CC_CAP_UARTGPIO 0x00000020 /* UARTs on GPIO 15-12 */ | ||
22 | #define BCMA_CC_CAP_EXTBUS 0x000000C0 /* External buses present */ | ||
23 | #define BCMA_CC_CAP_FLASHT 0x00000700 /* Flash Type */ | ||
24 | #define BCMA_CC_FLASHT_NONE 0x00000000 /* No flash */ | ||
25 | #define BCMA_CC_FLASHT_STSER 0x00000100 /* ST serial flash */ | ||
26 | #define BCMA_CC_FLASHT_ATSER 0x00000200 /* Atmel serial flash */ | ||
27 | #define BCMA_CC_FLASHT_PARA 0x00000700 /* Parallel flash */ | ||
28 | #define BCMA_CC_CAP_PLLT 0x00038000 /* PLL Type */ | ||
29 | #define BCMA_PLLTYPE_NONE 0x00000000 | ||
30 | #define BCMA_PLLTYPE_1 0x00010000 /* 48Mhz base, 3 dividers */ | ||
31 | #define BCMA_PLLTYPE_2 0x00020000 /* 48Mhz, 4 dividers */ | ||
32 | #define BCMA_PLLTYPE_3 0x00030000 /* 25Mhz, 2 dividers */ | ||
33 | #define BCMA_PLLTYPE_4 0x00008000 /* 48Mhz, 4 dividers */ | ||
34 | #define BCMA_PLLTYPE_5 0x00018000 /* 25Mhz, 4 dividers */ | ||
35 | #define BCMA_PLLTYPE_6 0x00028000 /* 100/200 or 120/240 only */ | ||
36 | #define BCMA_PLLTYPE_7 0x00038000 /* 25Mhz, 4 dividers */ | ||
37 | #define BCMA_CC_CAP_PCTL 0x00040000 /* Power Control */ | ||
38 | #define BCMA_CC_CAP_OTPS 0x00380000 /* OTP size */ | ||
39 | #define BCMA_CC_CAP_OTPS_SHIFT 19 | ||
40 | #define BCMA_CC_CAP_OTPS_BASE 5 | ||
41 | #define BCMA_CC_CAP_JTAGM 0x00400000 /* JTAG master present */ | ||
42 | #define BCMA_CC_CAP_BROM 0x00800000 /* Internal boot ROM active */ | ||
43 | #define BCMA_CC_CAP_64BIT 0x08000000 /* 64-bit Backplane */ | ||
44 | #define BCMA_CC_CAP_PMU 0x10000000 /* PMU available (rev >= 20) */ | ||
45 | #define BCMA_CC_CAP_ECI 0x20000000 /* ECI available (rev >= 20) */ | ||
46 | #define BCMA_CC_CAP_SPROM 0x40000000 /* SPROM present */ | ||
47 | #define BCMA_CC_CORECTL 0x0008 | ||
48 | #define BCMA_CC_CORECTL_UARTCLK0 0x00000001 /* Drive UART with internal clock */ | ||
49 | #define BCMA_CC_CORECTL_SE 0x00000002 /* sync clk out enable (corerev >= 3) */ | ||
50 | #define BCMA_CC_CORECTL_UARTCLKEN 0x00000008 /* UART clock enable (rev >= 21) */ | ||
51 | #define BCMA_CC_BIST 0x000C | ||
52 | #define BCMA_CC_OTPS 0x0010 /* OTP status */ | ||
53 | #define BCMA_CC_OTPS_PROGFAIL 0x80000000 | ||
54 | #define BCMA_CC_OTPS_PROTECT 0x00000007 | ||
55 | #define BCMA_CC_OTPS_HW_PROTECT 0x00000001 | ||
56 | #define BCMA_CC_OTPS_SW_PROTECT 0x00000002 | ||
57 | #define BCMA_CC_OTPS_CID_PROTECT 0x00000004 | ||
58 | #define BCMA_CC_OTPC 0x0014 /* OTP control */ | ||
59 | #define BCMA_CC_OTPC_RECWAIT 0xFF000000 | ||
60 | #define BCMA_CC_OTPC_PROGWAIT 0x00FFFF00 | ||
61 | #define BCMA_CC_OTPC_PRW_SHIFT 8 | ||
62 | #define BCMA_CC_OTPC_MAXFAIL 0x00000038 | ||
63 | #define BCMA_CC_OTPC_VSEL 0x00000006 | ||
64 | #define BCMA_CC_OTPC_SELVL 0x00000001 | ||
65 | #define BCMA_CC_OTPP 0x0018 /* OTP prog */ | ||
66 | #define BCMA_CC_OTPP_COL 0x000000FF | ||
67 | #define BCMA_CC_OTPP_ROW 0x0000FF00 | ||
68 | #define BCMA_CC_OTPP_ROW_SHIFT 8 | ||
69 | #define BCMA_CC_OTPP_READERR 0x10000000 | ||
70 | #define BCMA_CC_OTPP_VALUE 0x20000000 | ||
71 | #define BCMA_CC_OTPP_READ 0x40000000 | ||
72 | #define BCMA_CC_OTPP_START 0x80000000 | ||
73 | #define BCMA_CC_OTPP_BUSY 0x80000000 | ||
74 | #define BCMA_CC_IRQSTAT 0x0020 | ||
75 | #define BCMA_CC_IRQMASK 0x0024 | ||
76 | #define BCMA_CC_IRQ_GPIO 0x00000001 /* gpio intr */ | ||
77 | #define BCMA_CC_IRQ_EXT 0x00000002 /* ro: ext intr pin (corerev >= 3) */ | ||
78 | #define BCMA_CC_IRQ_WDRESET 0x80000000 /* watchdog reset occurred */ | ||
79 | #define BCMA_CC_CHIPCTL 0x0028 /* Rev >= 11 only */ | ||
80 | #define BCMA_CC_CHIPSTAT 0x002C /* Rev >= 11 only */ | ||
81 | #define BCMA_CC_JCMD 0x0030 /* Rev >= 10 only */ | ||
82 | #define BCMA_CC_JCMD_START 0x80000000 | ||
83 | #define BCMA_CC_JCMD_BUSY 0x80000000 | ||
84 | #define BCMA_CC_JCMD_PAUSE 0x40000000 | ||
85 | #define BCMA_CC_JCMD0_ACC_MASK 0x0000F000 | ||
86 | #define BCMA_CC_JCMD0_ACC_IRDR 0x00000000 | ||
87 | #define BCMA_CC_JCMD0_ACC_DR 0x00001000 | ||
88 | #define BCMA_CC_JCMD0_ACC_IR 0x00002000 | ||
89 | #define BCMA_CC_JCMD0_ACC_RESET 0x00003000 | ||
90 | #define BCMA_CC_JCMD0_ACC_IRPDR 0x00004000 | ||
91 | #define BCMA_CC_JCMD0_ACC_PDR 0x00005000 | ||
92 | #define BCMA_CC_JCMD0_IRW_MASK 0x00000F00 | ||
93 | #define BCMA_CC_JCMD_ACC_MASK 0x000F0000 /* Changes for corerev 11 */ | ||
94 | #define BCMA_CC_JCMD_ACC_IRDR 0x00000000 | ||
95 | #define BCMA_CC_JCMD_ACC_DR 0x00010000 | ||
96 | #define BCMA_CC_JCMD_ACC_IR 0x00020000 | ||
97 | #define BCMA_CC_JCMD_ACC_RESET 0x00030000 | ||
98 | #define BCMA_CC_JCMD_ACC_IRPDR 0x00040000 | ||
99 | #define BCMA_CC_JCMD_ACC_PDR 0x00050000 | ||
100 | #define BCMA_CC_JCMD_IRW_MASK 0x00001F00 | ||
101 | #define BCMA_CC_JCMD_IRW_SHIFT 8 | ||
102 | #define BCMA_CC_JCMD_DRW_MASK 0x0000003F | ||
103 | #define BCMA_CC_JIR 0x0034 /* Rev >= 10 only */ | ||
104 | #define BCMA_CC_JDR 0x0038 /* Rev >= 10 only */ | ||
105 | #define BCMA_CC_JCTL 0x003C /* Rev >= 10 only */ | ||
106 | #define BCMA_CC_JCTL_FORCE_CLK 4 /* Force clock */ | ||
107 | #define BCMA_CC_JCTL_EXT_EN 2 /* Enable external targets */ | ||
108 | #define BCMA_CC_JCTL_EN 1 /* Enable Jtag master */ | ||
109 | #define BCMA_CC_FLASHCTL 0x0040 | ||
110 | #define BCMA_CC_FLASHCTL_START 0x80000000 | ||
111 | #define BCMA_CC_FLASHCTL_BUSY BCMA_CC_FLASHCTL_START | ||
112 | #define BCMA_CC_FLASHADDR 0x0044 | ||
113 | #define BCMA_CC_FLASHDATA 0x0048 | ||
114 | #define BCMA_CC_BCAST_ADDR 0x0050 | ||
115 | #define BCMA_CC_BCAST_DATA 0x0054 | ||
116 | #define BCMA_CC_GPIOPULLUP 0x0058 /* Rev >= 20 only */ | ||
117 | #define BCMA_CC_GPIOPULLDOWN 0x005C /* Rev >= 20 only */ | ||
118 | #define BCMA_CC_GPIOIN 0x0060 | ||
119 | #define BCMA_CC_GPIOOUT 0x0064 | ||
120 | #define BCMA_CC_GPIOOUTEN 0x0068 | ||
121 | #define BCMA_CC_GPIOCTL 0x006C | ||
122 | #define BCMA_CC_GPIOPOL 0x0070 | ||
123 | #define BCMA_CC_GPIOIRQ 0x0074 | ||
124 | #define BCMA_CC_WATCHDOG 0x0080 | ||
125 | #define BCMA_CC_GPIOTIMER 0x0088 /* LED powersave (corerev >= 16) */ | ||
126 | #define BCMA_CC_GPIOTIMER_OFFTIME 0x0000FFFF | ||
127 | #define BCMA_CC_GPIOTIMER_OFFTIME_SHIFT 0 | ||
128 | #define BCMA_CC_GPIOTIMER_ONTIME 0xFFFF0000 | ||
129 | #define BCMA_CC_GPIOTIMER_ONTIME_SHIFT 16 | ||
130 | #define BCMA_CC_GPIOTOUTM 0x008C /* LED powersave (corerev >= 16) */ | ||
131 | #define BCMA_CC_CLOCK_N 0x0090 | ||
132 | #define BCMA_CC_CLOCK_SB 0x0094 | ||
133 | #define BCMA_CC_CLOCK_PCI 0x0098 | ||
134 | #define BCMA_CC_CLOCK_M2 0x009C | ||
135 | #define BCMA_CC_CLOCK_MIPS 0x00A0 | ||
136 | #define BCMA_CC_CLKDIV 0x00A4 /* Rev >= 3 only */ | ||
137 | #define BCMA_CC_CLKDIV_SFLASH 0x0F000000 | ||
138 | #define BCMA_CC_CLKDIV_SFLASH_SHIFT 24 | ||
139 | #define BCMA_CC_CLKDIV_OTP 0x000F0000 | ||
140 | #define BCMA_CC_CLKDIV_OTP_SHIFT 16 | ||
141 | #define BCMA_CC_CLKDIV_JTAG 0x00000F00 | ||
142 | #define BCMA_CC_CLKDIV_JTAG_SHIFT 8 | ||
143 | #define BCMA_CC_CLKDIV_UART 0x000000FF | ||
144 | #define BCMA_CC_CAP_EXT 0x00AC /* Capabilities */ | ||
145 | #define BCMA_CC_PLLONDELAY 0x00B0 /* Rev >= 4 only */ | ||
146 | #define BCMA_CC_FREFSELDELAY 0x00B4 /* Rev >= 4 only */ | ||
147 | #define BCMA_CC_SLOWCLKCTL 0x00B8 /* 6 <= Rev <= 9 only */ | ||
148 | #define BCMA_CC_SLOWCLKCTL_SRC 0x00000007 /* slow clock source mask */ | ||
149 | #define BCMA_CC_SLOWCLKCTL_SRC_LPO 0x00000000 /* source of slow clock is LPO */ | ||
150 | #define BCMA_CC_SLOWCLKCTL_SRC_XTAL 0x00000001 /* source of slow clock is crystal */ | ||
151 | #define BCMA_CC_SLOECLKCTL_SRC_PCI 0x00000002 /* source of slow clock is PCI */ | ||
152 | #define BCMA_CC_SLOWCLKCTL_LPOFREQ 0x00000200 /* LPOFreqSel, 1: 160Khz, 0: 32KHz */ | ||
153 | #define BCMA_CC_SLOWCLKCTL_LPOPD 0x00000400 /* LPOPowerDown, 1: LPO is disabled, 0: LPO is enabled */ | ||
154 | #define BCMA_CC_SLOWCLKCTL_FSLOW 0x00000800 /* ForceSlowClk, 1: sb/cores running on slow clock, 0: power logic control */ | ||
155 | #define BCMA_CC_SLOWCLKCTL_IPLL 0x00001000 /* IgnorePllOffReq, 1/0: power logic ignores/honors PLL clock disable requests from core */ | ||
156 | #define BCMA_CC_SLOWCLKCTL_ENXTAL 0x00002000 /* XtalControlEn, 1/0: power logic does/doesn't disable crystal when appropriate */ | ||
157 | #define BCMA_CC_SLOWCLKCTL_XTALPU 0x00004000 /* XtalPU (RO), 1/0: crystal running/disabled */ | ||
158 | #define BCMA_CC_SLOWCLKCTL_CLKDIV 0xFFFF0000 /* ClockDivider (SlowClk = 1/(4+divisor)) */ | ||
159 | #define BCMA_CC_SLOWCLKCTL_CLKDIV_SHIFT 16 | ||
160 | #define BCMA_CC_SYSCLKCTL 0x00C0 /* Rev >= 3 only */ | ||
161 | #define BCMA_CC_SYSCLKCTL_IDLPEN 0x00000001 /* ILPen: Enable Idle Low Power */ | ||
162 | #define BCMA_CC_SYSCLKCTL_ALPEN 0x00000002 /* ALPen: Enable Active Low Power */ | ||
163 | #define BCMA_CC_SYSCLKCTL_PLLEN 0x00000004 /* ForcePLLOn */ | ||
164 | #define BCMA_CC_SYSCLKCTL_FORCEALP 0x00000008 /* Force ALP (or HT if ALPen is not set */ | ||
165 | #define BCMA_CC_SYSCLKCTL_FORCEHT 0x00000010 /* Force HT */ | ||
166 | #define BCMA_CC_SYSCLKCTL_CLKDIV 0xFFFF0000 /* ClkDiv (ILP = 1/(4+divisor)) */ | ||
167 | #define BCMA_CC_SYSCLKCTL_CLKDIV_SHIFT 16 | ||
168 | #define BCMA_CC_CLKSTSTR 0x00C4 /* Rev >= 3 only */ | ||
169 | #define BCMA_CC_EROM 0x00FC | ||
170 | #define BCMA_CC_PCMCIA_CFG 0x0100 | ||
171 | #define BCMA_CC_PCMCIA_MEMWAIT 0x0104 | ||
172 | #define BCMA_CC_PCMCIA_ATTRWAIT 0x0108 | ||
173 | #define BCMA_CC_PCMCIA_IOWAIT 0x010C | ||
174 | #define BCMA_CC_IDE_CFG 0x0110 | ||
175 | #define BCMA_CC_IDE_MEMWAIT 0x0114 | ||
176 | #define BCMA_CC_IDE_ATTRWAIT 0x0118 | ||
177 | #define BCMA_CC_IDE_IOWAIT 0x011C | ||
178 | #define BCMA_CC_PROG_CFG 0x0120 | ||
179 | #define BCMA_CC_PROG_WAITCNT 0x0124 | ||
180 | #define BCMA_CC_FLASH_CFG 0x0128 | ||
181 | #define BCMA_CC_FLASH_WAITCNT 0x012C | ||
182 | #define BCMA_CC_CLKCTLST 0x01E0 /* Clock control and status (rev >= 20) */ | ||
183 | #define BCMA_CC_CLKCTLST_FORCEALP 0x00000001 /* Force ALP request */ | ||
184 | #define BCMA_CC_CLKCTLST_FORCEHT 0x00000002 /* Force HT request */ | ||
185 | #define BCMA_CC_CLKCTLST_FORCEILP 0x00000004 /* Force ILP request */ | ||
186 | #define BCMA_CC_CLKCTLST_HAVEALPREQ 0x00000008 /* ALP available request */ | ||
187 | #define BCMA_CC_CLKCTLST_HAVEHTREQ 0x00000010 /* HT available request */ | ||
188 | #define BCMA_CC_CLKCTLST_HWCROFF 0x00000020 /* Force HW clock request off */ | ||
189 | #define BCMA_CC_CLKCTLST_HAVEHT 0x00010000 /* HT available */ | ||
190 | #define BCMA_CC_CLKCTLST_HAVEALP 0x00020000 /* APL available */ | ||
191 | #define BCMA_CC_HW_WORKAROUND 0x01E4 /* Hardware workaround (rev >= 20) */ | ||
192 | #define BCMA_CC_UART0_DATA 0x0300 | ||
193 | #define BCMA_CC_UART0_IMR 0x0304 | ||
194 | #define BCMA_CC_UART0_FCR 0x0308 | ||
195 | #define BCMA_CC_UART0_LCR 0x030C | ||
196 | #define BCMA_CC_UART0_MCR 0x0310 | ||
197 | #define BCMA_CC_UART0_LSR 0x0314 | ||
198 | #define BCMA_CC_UART0_MSR 0x0318 | ||
199 | #define BCMA_CC_UART0_SCRATCH 0x031C | ||
200 | #define BCMA_CC_UART1_DATA 0x0400 | ||
201 | #define BCMA_CC_UART1_IMR 0x0404 | ||
202 | #define BCMA_CC_UART1_FCR 0x0408 | ||
203 | #define BCMA_CC_UART1_LCR 0x040C | ||
204 | #define BCMA_CC_UART1_MCR 0x0410 | ||
205 | #define BCMA_CC_UART1_LSR 0x0414 | ||
206 | #define BCMA_CC_UART1_MSR 0x0418 | ||
207 | #define BCMA_CC_UART1_SCRATCH 0x041C | ||
208 | /* PMU registers (rev >= 20) */ | ||
209 | #define BCMA_CC_PMU_CTL 0x0600 /* PMU control */ | ||
210 | #define BCMA_CC_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */ | ||
211 | #define BCMA_CC_PMU_CTL_ILP_DIV_SHIFT 16 | ||
212 | #define BCMA_CC_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */ | ||
213 | #define BCMA_CC_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */ | ||
214 | #define BCMA_CC_PMU_CTL_ALPREQEN 0x00000080 /* ALP req enable */ | ||
215 | #define BCMA_CC_PMU_CTL_XTALFREQ 0x0000007C /* Crystal freq */ | ||
216 | #define BCMA_CC_PMU_CTL_XTALFREQ_SHIFT 2 | ||
217 | #define BCMA_CC_PMU_CTL_ILPDIVEN 0x00000002 /* ILP div enable */ | ||
218 | #define BCMA_CC_PMU_CTL_LPOSEL 0x00000001 /* LPO sel */ | ||
219 | #define BCMA_CC_PMU_CAP 0x0604 /* PMU capabilities */ | ||
220 | #define BCMA_CC_PMU_CAP_REVISION 0x000000FF /* Revision mask */ | ||
221 | #define BCMA_CC_PMU_STAT 0x0608 /* PMU status */ | ||
222 | #define BCMA_CC_PMU_STAT_INTPEND 0x00000040 /* Interrupt pending */ | ||
223 | #define BCMA_CC_PMU_STAT_SBCLKST 0x00000030 /* Backplane clock status? */ | ||
224 | #define BCMA_CC_PMU_STAT_HAVEALP 0x00000008 /* ALP available */ | ||
225 | #define BCMA_CC_PMU_STAT_HAVEHT 0x00000004 /* HT available */ | ||
226 | #define BCMA_CC_PMU_STAT_RESINIT 0x00000003 /* Res init */ | ||
227 | #define BCMA_CC_PMU_RES_STAT 0x060C /* PMU res status */ | ||
228 | #define BCMA_CC_PMU_RES_PEND 0x0610 /* PMU res pending */ | ||
229 | #define BCMA_CC_PMU_TIMER 0x0614 /* PMU timer */ | ||
230 | #define BCMA_CC_PMU_MINRES_MSK 0x0618 /* PMU min res mask */ | ||
231 | #define BCMA_CC_PMU_MAXRES_MSK 0x061C /* PMU max res mask */ | ||
232 | #define BCMA_CC_PMU_RES_TABSEL 0x0620 /* PMU res table sel */ | ||
233 | #define BCMA_CC_PMU_RES_DEPMSK 0x0624 /* PMU res dep mask */ | ||
234 | #define BCMA_CC_PMU_RES_UPDNTM 0x0628 /* PMU res updown timer */ | ||
235 | #define BCMA_CC_PMU_RES_TIMER 0x062C /* PMU res timer */ | ||
236 | #define BCMA_CC_PMU_CLKSTRETCH 0x0630 /* PMU clockstretch */ | ||
237 | #define BCMA_CC_PMU_WATCHDOG 0x0634 /* PMU watchdog */ | ||
238 | #define BCMA_CC_PMU_RES_REQTS 0x0640 /* PMU res req timer sel */ | ||
239 | #define BCMA_CC_PMU_RES_REQT 0x0644 /* PMU res req timer */ | ||
240 | #define BCMA_CC_PMU_RES_REQM 0x0648 /* PMU res req mask */ | ||
241 | #define BCMA_CC_CHIPCTL_ADDR 0x0650 | ||
242 | #define BCMA_CC_CHIPCTL_DATA 0x0654 | ||
243 | #define BCMA_CC_REGCTL_ADDR 0x0658 | ||
244 | #define BCMA_CC_REGCTL_DATA 0x065C | ||
245 | #define BCMA_CC_PLLCTL_ADDR 0x0660 | ||
246 | #define BCMA_CC_PLLCTL_DATA 0x0664 | ||
247 | |||
248 | /* Data for the PMU, if available. | ||
249 | * Check availability with ((struct bcma_chipcommon)->capabilities & BCMA_CC_CAP_PMU) | ||
250 | */ | ||
251 | struct bcma_chipcommon_pmu { | ||
252 | u8 rev; /* PMU revision */ | ||
253 | u32 crystalfreq; /* The active crystal frequency (in kHz) */ | ||
254 | }; | ||
255 | |||
256 | struct bcma_drv_cc { | ||
257 | struct bcma_device *core; | ||
258 | u32 status; | ||
259 | u32 capabilities; | ||
260 | u32 capabilities_ext; | ||
261 | /* Fast Powerup Delay constant */ | ||
262 | u16 fast_pwrup_delay; | ||
263 | struct bcma_chipcommon_pmu pmu; | ||
264 | }; | ||
265 | |||
266 | /* Register access */ | ||
267 | #define bcma_cc_read32(cc, offset) \ | ||
268 | bcma_read32((cc)->core, offset) | ||
269 | #define bcma_cc_write32(cc, offset, val) \ | ||
270 | bcma_write32((cc)->core, offset, val) | ||
271 | |||
272 | #define bcma_cc_mask32(cc, offset, mask) \ | ||
273 | bcma_cc_write32(cc, offset, bcma_cc_read32(cc, offset) & (mask)) | ||
274 | #define bcma_cc_set32(cc, offset, set) \ | ||
275 | bcma_cc_write32(cc, offset, bcma_cc_read32(cc, offset) | (set)) | ||
276 | #define bcma_cc_maskset32(cc, offset, mask, set) \ | ||
277 | bcma_cc_write32(cc, offset, (bcma_cc_read32(cc, offset) & (mask)) | (set)) | ||
278 | |||
279 | extern void bcma_core_chipcommon_init(struct bcma_drv_cc *cc); | ||
280 | |||
281 | extern void bcma_chipco_suspend(struct bcma_drv_cc *cc); | ||
282 | extern void bcma_chipco_resume(struct bcma_drv_cc *cc); | ||
283 | |||
284 | extern void bcma_chipco_watchdog_timer_set(struct bcma_drv_cc *cc, | ||
285 | u32 ticks); | ||
286 | |||
287 | void bcma_chipco_irq_mask(struct bcma_drv_cc *cc, u32 mask, u32 value); | ||
288 | |||
289 | u32 bcma_chipco_irq_status(struct bcma_drv_cc *cc, u32 mask); | ||
290 | |||
291 | /* Chipcommon GPIO pin access. */ | ||
292 | u32 bcma_chipco_gpio_in(struct bcma_drv_cc *cc, u32 mask); | ||
293 | u32 bcma_chipco_gpio_out(struct bcma_drv_cc *cc, u32 mask, u32 value); | ||
294 | u32 bcma_chipco_gpio_outen(struct bcma_drv_cc *cc, u32 mask, u32 value); | ||
295 | u32 bcma_chipco_gpio_control(struct bcma_drv_cc *cc, u32 mask, u32 value); | ||
296 | u32 bcma_chipco_gpio_intmask(struct bcma_drv_cc *cc, u32 mask, u32 value); | ||
297 | u32 bcma_chipco_gpio_polarity(struct bcma_drv_cc *cc, u32 mask, u32 value); | ||
298 | |||
299 | /* PMU support */ | ||
300 | extern void bcma_pmu_init(struct bcma_drv_cc *cc); | ||
301 | |||
302 | #endif /* LINUX_BCMA_DRIVER_CC_H_ */ | ||
diff --git a/include/linux/bcma/bcma_driver_pci.h b/include/linux/bcma/bcma_driver_pci.h new file mode 100644 index 000000000000..b7e191cf00ec --- /dev/null +++ b/include/linux/bcma/bcma_driver_pci.h | |||
@@ -0,0 +1,89 @@ | |||
1 | #ifndef LINUX_BCMA_DRIVER_PCI_H_ | ||
2 | #define LINUX_BCMA_DRIVER_PCI_H_ | ||
3 | |||
4 | #include <linux/types.h> | ||
5 | |||
6 | struct pci_dev; | ||
7 | |||
8 | /** PCI core registers. **/ | ||
9 | #define BCMA_CORE_PCI_CTL 0x0000 /* PCI Control */ | ||
10 | #define BCMA_CORE_PCI_CTL_RST_OE 0x00000001 /* PCI_RESET Output Enable */ | ||
11 | #define BCMA_CORE_PCI_CTL_RST 0x00000002 /* PCI_RESET driven out to pin */ | ||
12 | #define BCMA_CORE_PCI_CTL_CLK_OE 0x00000004 /* Clock gate Output Enable */ | ||
13 | #define BCMA_CORE_PCI_CTL_CLK 0x00000008 /* Gate for clock driven out to pin */ | ||
14 | #define BCMA_CORE_PCI_ARBCTL 0x0010 /* PCI Arbiter Control */ | ||
15 | #define BCMA_CORE_PCI_ARBCTL_INTERN 0x00000001 /* Use internal arbiter */ | ||
16 | #define BCMA_CORE_PCI_ARBCTL_EXTERN 0x00000002 /* Use external arbiter */ | ||
17 | #define BCMA_CORE_PCI_ARBCTL_PARKID 0x00000006 /* Mask, selects which agent is parked on an idle bus */ | ||
18 | #define BCMA_CORE_PCI_ARBCTL_PARKID_LAST 0x00000000 /* Last requestor */ | ||
19 | #define BCMA_CORE_PCI_ARBCTL_PARKID_4710 0x00000002 /* 4710 */ | ||
20 | #define BCMA_CORE_PCI_ARBCTL_PARKID_EXT0 0x00000004 /* External requestor 0 */ | ||
21 | #define BCMA_CORE_PCI_ARBCTL_PARKID_EXT1 0x00000006 /* External requestor 1 */ | ||
22 | #define BCMA_CORE_PCI_ISTAT 0x0020 /* Interrupt status */ | ||
23 | #define BCMA_CORE_PCI_ISTAT_INTA 0x00000001 /* PCI INTA# */ | ||
24 | #define BCMA_CORE_PCI_ISTAT_INTB 0x00000002 /* PCI INTB# */ | ||
25 | #define BCMA_CORE_PCI_ISTAT_SERR 0x00000004 /* PCI SERR# (write to clear) */ | ||
26 | #define BCMA_CORE_PCI_ISTAT_PERR 0x00000008 /* PCI PERR# (write to clear) */ | ||
27 | #define BCMA_CORE_PCI_ISTAT_PME 0x00000010 /* PCI PME# */ | ||
28 | #define BCMA_CORE_PCI_IMASK 0x0024 /* Interrupt mask */ | ||
29 | #define BCMA_CORE_PCI_IMASK_INTA 0x00000001 /* PCI INTA# */ | ||
30 | #define BCMA_CORE_PCI_IMASK_INTB 0x00000002 /* PCI INTB# */ | ||
31 | #define BCMA_CORE_PCI_IMASK_SERR 0x00000004 /* PCI SERR# */ | ||
32 | #define BCMA_CORE_PCI_IMASK_PERR 0x00000008 /* PCI PERR# */ | ||
33 | #define BCMA_CORE_PCI_IMASK_PME 0x00000010 /* PCI PME# */ | ||
34 | #define BCMA_CORE_PCI_MBOX 0x0028 /* Backplane to PCI Mailbox */ | ||
35 | #define BCMA_CORE_PCI_MBOX_F0_0 0x00000100 /* PCI function 0, INT 0 */ | ||
36 | #define BCMA_CORE_PCI_MBOX_F0_1 0x00000200 /* PCI function 0, INT 1 */ | ||
37 | #define BCMA_CORE_PCI_MBOX_F1_0 0x00000400 /* PCI function 1, INT 0 */ | ||
38 | #define BCMA_CORE_PCI_MBOX_F1_1 0x00000800 /* PCI function 1, INT 1 */ | ||
39 | #define BCMA_CORE_PCI_MBOX_F2_0 0x00001000 /* PCI function 2, INT 0 */ | ||
40 | #define BCMA_CORE_PCI_MBOX_F2_1 0x00002000 /* PCI function 2, INT 1 */ | ||
41 | #define BCMA_CORE_PCI_MBOX_F3_0 0x00004000 /* PCI function 3, INT 0 */ | ||
42 | #define BCMA_CORE_PCI_MBOX_F3_1 0x00008000 /* PCI function 3, INT 1 */ | ||
43 | #define BCMA_CORE_PCI_BCAST_ADDR 0x0050 /* Backplane Broadcast Address */ | ||
44 | #define BCMA_CORE_PCI_BCAST_ADDR_MASK 0x000000FF | ||
45 | #define BCMA_CORE_PCI_BCAST_DATA 0x0054 /* Backplane Broadcast Data */ | ||
46 | #define BCMA_CORE_PCI_GPIO_IN 0x0060 /* rev >= 2 only */ | ||
47 | #define BCMA_CORE_PCI_GPIO_OUT 0x0064 /* rev >= 2 only */ | ||
48 | #define BCMA_CORE_PCI_GPIO_ENABLE 0x0068 /* rev >= 2 only */ | ||
49 | #define BCMA_CORE_PCI_GPIO_CTL 0x006C /* rev >= 2 only */ | ||
50 | #define BCMA_CORE_PCI_SBTOPCI0 0x0100 /* Backplane to PCI translation 0 (sbtopci0) */ | ||
51 | #define BCMA_CORE_PCI_SBTOPCI0_MASK 0xFC000000 | ||
52 | #define BCMA_CORE_PCI_SBTOPCI1 0x0104 /* Backplane to PCI translation 1 (sbtopci1) */ | ||
53 | #define BCMA_CORE_PCI_SBTOPCI1_MASK 0xFC000000 | ||
54 | #define BCMA_CORE_PCI_SBTOPCI2 0x0108 /* Backplane to PCI translation 2 (sbtopci2) */ | ||
55 | #define BCMA_CORE_PCI_SBTOPCI2_MASK 0xC0000000 | ||
56 | #define BCMA_CORE_PCI_PCICFG0 0x0400 /* PCI config space 0 (rev >= 8) */ | ||
57 | #define BCMA_CORE_PCI_PCICFG1 0x0500 /* PCI config space 1 (rev >= 8) */ | ||
58 | #define BCMA_CORE_PCI_PCICFG2 0x0600 /* PCI config space 2 (rev >= 8) */ | ||
59 | #define BCMA_CORE_PCI_PCICFG3 0x0700 /* PCI config space 3 (rev >= 8) */ | ||
60 | #define BCMA_CORE_PCI_SPROM(wordoffset) (0x0800 + ((wordoffset) * 2)) /* SPROM shadow area (72 bytes) */ | ||
61 | |||
62 | /* SBtoPCIx */ | ||
63 | #define BCMA_CORE_PCI_SBTOPCI_MEM 0x00000000 | ||
64 | #define BCMA_CORE_PCI_SBTOPCI_IO 0x00000001 | ||
65 | #define BCMA_CORE_PCI_SBTOPCI_CFG0 0x00000002 | ||
66 | #define BCMA_CORE_PCI_SBTOPCI_CFG1 0x00000003 | ||
67 | #define BCMA_CORE_PCI_SBTOPCI_PREF 0x00000004 /* Prefetch enable */ | ||
68 | #define BCMA_CORE_PCI_SBTOPCI_BURST 0x00000008 /* Burst enable */ | ||
69 | #define BCMA_CORE_PCI_SBTOPCI_MRM 0x00000020 /* Memory Read Multiple */ | ||
70 | #define BCMA_CORE_PCI_SBTOPCI_RC 0x00000030 /* Read Command mask (rev >= 11) */ | ||
71 | #define BCMA_CORE_PCI_SBTOPCI_RC_READ 0x00000000 /* Memory read */ | ||
72 | #define BCMA_CORE_PCI_SBTOPCI_RC_READL 0x00000010 /* Memory read line */ | ||
73 | #define BCMA_CORE_PCI_SBTOPCI_RC_READM 0x00000020 /* Memory read multiple */ | ||
74 | |||
75 | /* PCIcore specific boardflags */ | ||
76 | #define BCMA_CORE_PCI_BFL_NOPCI 0x00000400 /* Board leaves PCI floating */ | ||
77 | |||
78 | struct bcma_drv_pci { | ||
79 | struct bcma_device *core; | ||
80 | u8 setup_done:1; | ||
81 | }; | ||
82 | |||
83 | /* Register access */ | ||
84 | #define pcicore_read32(pc, offset) bcma_read32((pc)->core, offset) | ||
85 | #define pcicore_write32(pc, offset, val) bcma_write32((pc)->core, offset, val) | ||
86 | |||
87 | extern void bcma_core_pci_init(struct bcma_drv_pci *pc); | ||
88 | |||
89 | #endif /* LINUX_BCMA_DRIVER_PCI_H_ */ | ||
diff --git a/include/linux/bcma/bcma_regs.h b/include/linux/bcma/bcma_regs.h new file mode 100644 index 000000000000..f82d88a960ce --- /dev/null +++ b/include/linux/bcma/bcma_regs.h | |||
@@ -0,0 +1,34 @@ | |||
1 | #ifndef LINUX_BCMA_REGS_H_ | ||
2 | #define LINUX_BCMA_REGS_H_ | ||
3 | |||
4 | /* Agent registers (common for every core) */ | ||
5 | #define BCMA_IOCTL 0x0408 | ||
6 | #define BCMA_IOCTL_CLK 0x0001 | ||
7 | #define BCMA_IOCTL_FGC 0x0002 | ||
8 | #define BCMA_IOCTL_CORE_BITS 0x3FFC | ||
9 | #define BCMA_IOCTL_PME_EN 0x4000 | ||
10 | #define BCMA_IOCTL_BIST_EN 0x8000 | ||
11 | #define BCMA_RESET_CTL 0x0800 | ||
12 | #define BCMA_RESET_CTL_RESET 0x0001 | ||
13 | |||
14 | /* BCMA PCI config space registers. */ | ||
15 | #define BCMA_PCI_PMCSR 0x44 | ||
16 | #define BCMA_PCI_PE 0x100 | ||
17 | #define BCMA_PCI_BAR0_WIN 0x80 /* Backplane address space 0 */ | ||
18 | #define BCMA_PCI_BAR1_WIN 0x84 /* Backplane address space 1 */ | ||
19 | #define BCMA_PCI_SPROMCTL 0x88 /* SPROM control */ | ||
20 | #define BCMA_PCI_SPROMCTL_WE 0x10 /* SPROM write enable */ | ||
21 | #define BCMA_PCI_BAR1_CONTROL 0x8c /* Address space 1 burst control */ | ||
22 | #define BCMA_PCI_IRQS 0x90 /* PCI interrupts */ | ||
23 | #define BCMA_PCI_IRQMASK 0x94 /* PCI IRQ control and mask (pcirev >= 6 only) */ | ||
24 | #define BCMA_PCI_BACKPLANE_IRQS 0x98 /* Backplane Interrupts */ | ||
25 | #define BCMA_PCI_BAR0_WIN2 0xAC | ||
26 | #define BCMA_PCI_GPIO_IN 0xB0 /* GPIO Input (pcirev >= 3 only) */ | ||
27 | #define BCMA_PCI_GPIO_OUT 0xB4 /* GPIO Output (pcirev >= 3 only) */ | ||
28 | #define BCMA_PCI_GPIO_OUT_ENABLE 0xB8 /* GPIO Output Enable/Disable (pcirev >= 3 only) */ | ||
29 | #define BCMA_PCI_GPIO_SCS 0x10 /* PCI config space bit 4 for 4306c0 slow clock source */ | ||
30 | #define BCMA_PCI_GPIO_HWRAD 0x20 /* PCI config space GPIO 13 for hw radio disable */ | ||
31 | #define BCMA_PCI_GPIO_XTAL 0x40 /* PCI config space GPIO 14 for Xtal powerup */ | ||
32 | #define BCMA_PCI_GPIO_PLL 0x80 /* PCI config space GPIO 15 for PLL powerdown */ | ||
33 | |||
34 | #endif /* LINUX_BCMA_REGS_H_ */ | ||
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 79690b710665..b2eee5879883 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h | |||
@@ -1002,6 +1002,11 @@ struct ieee80211_ht_info { | |||
1002 | 1002 | ||
1003 | #define WLAN_CAPABILITY_ESS (1<<0) | 1003 | #define WLAN_CAPABILITY_ESS (1<<0) |
1004 | #define WLAN_CAPABILITY_IBSS (1<<1) | 1004 | #define WLAN_CAPABILITY_IBSS (1<<1) |
1005 | |||
1006 | /* A mesh STA sets the ESS and IBSS capability bits to zero */ | ||
1007 | #define WLAN_CAPABILITY_IS_MBSS(cap) \ | ||
1008 | (!((cap) & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS))) | ||
1009 | |||
1005 | #define WLAN_CAPABILITY_CF_POLLABLE (1<<2) | 1010 | #define WLAN_CAPABILITY_CF_POLLABLE (1<<2) |
1006 | #define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) | 1011 | #define WLAN_CAPABILITY_CF_POLL_REQUEST (1<<3) |
1007 | #define WLAN_CAPABILITY_PRIVACY (1<<4) | 1012 | #define WLAN_CAPABILITY_PRIVACY (1<<4) |
@@ -1261,9 +1266,8 @@ enum ieee80211_category { | |||
1261 | WLAN_CATEGORY_MULTIHOP_ACTION = 14, | 1266 | WLAN_CATEGORY_MULTIHOP_ACTION = 14, |
1262 | WLAN_CATEGORY_SELF_PROTECTED = 15, | 1267 | WLAN_CATEGORY_SELF_PROTECTED = 15, |
1263 | WLAN_CATEGORY_WMM = 17, | 1268 | WLAN_CATEGORY_WMM = 17, |
1264 | /* TODO: remove MESH_PLINK and MESH_PATH_SEL after */ | 1269 | /* TODO: remove MESH_PATH_SEL after mesh is updated |
1265 | /* mesh is updated to current 802.11s draft */ | 1270 | * to current 802.11s draft */ |
1266 | WLAN_CATEGORY_MESH_PLINK = 30, | ||
1267 | WLAN_CATEGORY_MESH_PATH_SEL = 32, | 1271 | WLAN_CATEGORY_MESH_PATH_SEL = 32, |
1268 | WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, | 1272 | WLAN_CATEGORY_VENDOR_SPECIFIC_PROTECTED = 126, |
1269 | WLAN_CATEGORY_VENDOR_SPECIFIC = 127, | 1273 | WLAN_CATEGORY_VENDOR_SPECIFIC = 127, |
@@ -1516,6 +1520,7 @@ static inline bool ieee80211_is_robust_mgmt_frame(struct ieee80211_hdr *hdr) | |||
1516 | category = ((u8 *) hdr) + 24; | 1520 | category = ((u8 *) hdr) + 24; |
1517 | return *category != WLAN_CATEGORY_PUBLIC && | 1521 | return *category != WLAN_CATEGORY_PUBLIC && |
1518 | *category != WLAN_CATEGORY_HT && | 1522 | *category != WLAN_CATEGORY_HT && |
1523 | *category != WLAN_CATEGORY_SELF_PROTECTED && | ||
1519 | *category != WLAN_CATEGORY_VENDOR_SPECIFIC; | 1524 | *category != WLAN_CATEGORY_VENDOR_SPECIFIC; |
1520 | } | 1525 | } |
1521 | 1526 | ||
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 48c007dae476..ae28e93fd072 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h | |||
@@ -382,6 +382,23 @@ struct ssb_device_id { | |||
382 | #define SSB_ANY_ID 0xFFFF | 382 | #define SSB_ANY_ID 0xFFFF |
383 | #define SSB_ANY_REV 0xFF | 383 | #define SSB_ANY_REV 0xFF |
384 | 384 | ||
385 | /* Broadcom's specific AMBA core, see drivers/bcma/ */ | ||
386 | struct bcma_device_id { | ||
387 | __u16 manuf; | ||
388 | __u16 id; | ||
389 | __u8 rev; | ||
390 | __u8 class; | ||
391 | }; | ||
392 | #define BCMA_CORE(_manuf, _id, _rev, _class) \ | ||
393 | { .manuf = _manuf, .id = _id, .rev = _rev, .class = _class, } | ||
394 | #define BCMA_CORETABLE_END \ | ||
395 | { 0, }, | ||
396 | |||
397 | #define BCMA_ANY_MANUF 0xFFFF | ||
398 | #define BCMA_ANY_ID 0xFFFF | ||
399 | #define BCMA_ANY_REV 0xFF | ||
400 | #define BCMA_ANY_CLASS 0xFF | ||
401 | |||
385 | struct virtio_device_id { | 402 | struct virtio_device_id { |
386 | __u32 device; | 403 | __u32 device; |
387 | __u32 vendor; | 404 | __u32 vendor; |
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 216b1d8a862f..c7ccaae15af6 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -77,6 +77,39 @@ | |||
77 | */ | 77 | */ |
78 | 78 | ||
79 | /** | 79 | /** |
80 | * DOC: Virtual interface / concurrency capabilities | ||
81 | * | ||
82 | * Some devices are able to operate with virtual MACs, they can have | ||
83 | * more than one virtual interface. The capability handling for this | ||
84 | * is a bit complex though, as there may be a number of restrictions | ||
85 | * on the types of concurrency that are supported. | ||
86 | * | ||
87 | * To start with, each device supports the interface types listed in | ||
88 | * the %NL80211_ATTR_SUPPORTED_IFTYPES attribute, but by listing the | ||
89 | * types there no concurrency is implied. | ||
90 | * | ||
91 | * Once concurrency is desired, more attributes must be observed: | ||
92 | * To start with, since some interface types are purely managed in | ||
93 | * software, like the AP-VLAN type in mac80211 for example, there's | ||
94 | * an additional list of these, they can be added at any time and | ||
95 | * are only restricted by some semantic restrictions (e.g. AP-VLAN | ||
96 | * cannot be added without a corresponding AP interface). This list | ||
97 | * is exported in the %NL80211_ATTR_SOFTWARE_IFTYPES attribute. | ||
98 | * | ||
99 | * Further, the list of supported combinations is exported. This is | ||
100 | * in the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute. Basically, | ||
101 | * it exports a list of "groups", and at any point in time the | ||
102 | * interfaces that are currently active must fall into any one of | ||
103 | * the advertised groups. Within each group, there are restrictions | ||
104 | * on the number of interfaces of different types that are supported | ||
105 | * and also the number of different channels, along with potentially | ||
106 | * some other restrictions. See &enum nl80211_if_combination_attrs. | ||
107 | * | ||
108 | * All together, these attributes define the concurrency of virtual | ||
109 | * interfaces that a given device supports. | ||
110 | */ | ||
111 | |||
112 | /** | ||
80 | * enum nl80211_commands - supported nl80211 commands | 113 | * enum nl80211_commands - supported nl80211 commands |
81 | * | 114 | * |
82 | * @NL80211_CMD_UNSPEC: unspecified command to catch errors | 115 | * @NL80211_CMD_UNSPEC: unspecified command to catch errors |
@@ -203,6 +236,28 @@ | |||
203 | * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, | 236 | * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, |
204 | * partial scan results may be available | 237 | * partial scan results may be available |
205 | * | 238 | * |
239 | * @NL80211_CMD_START_SCHED_SCAN: start a scheduled scan at certain | ||
240 | * intervals, as specified by %NL80211_ATTR_SCHED_SCAN_INTERVAL. | ||
241 | * Like with normal scans, if SSIDs (%NL80211_ATTR_SCAN_SSIDS) | ||
242 | * are passed, they are used in the probe requests. For | ||
243 | * broadcast, a broadcast SSID must be passed (ie. an empty | ||
244 | * string). If no SSID is passed, no probe requests are sent and | ||
245 | * a passive scan is performed. %NL80211_ATTR_SCAN_FREQUENCIES, | ||
246 | * if passed, define which channels should be scanned; if not | ||
247 | * passed, all channels allowed for the current regulatory domain | ||
248 | * are used. Extra IEs can also be passed from the userspace by | ||
249 | * using the %NL80211_ATTR_IE attribute. | ||
250 | * @NL80211_CMD_STOP_SCHED_SCAN: stop a scheduled scan | ||
251 | * @NL80211_CMD_SCHED_SCAN_RESULTS: indicates that there are scheduled scan | ||
252 | * results available. | ||
253 | * @NL80211_CMD_SCHED_SCAN_STOPPED: indicates that the scheduled scan has | ||
254 | * stopped. The driver may issue this event at any time during a | ||
255 | * scheduled scan. One reason for stopping the scan is if the hardware | ||
256 | * does not support starting an association or a normal scan while running | ||
257 | * a scheduled scan. This event is also sent when the | ||
258 | * %NL80211_CMD_STOP_SCHED_SCAN command is received or when the interface | ||
259 | * is brought down while a scheduled scan was running. | ||
260 | * | ||
206 | * @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation | 261 | * @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation |
207 | * or noise level | 262 | * or noise level |
208 | * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to | 263 | * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to |
@@ -420,6 +475,14 @@ | |||
420 | * new station with the AUTHENTICATED flag unset and maybe change it later | 475 | * new station with the AUTHENTICATED flag unset and maybe change it later |
421 | * depending on the authentication result. | 476 | * depending on the authentication result. |
422 | * | 477 | * |
478 | * @NL80211_CMD_GET_WOWLAN: get Wake-on-Wireless-LAN (WoWLAN) settings. | ||
479 | * @NL80211_CMD_SET_WOWLAN: set Wake-on-Wireless-LAN (WoWLAN) settings. | ||
480 | * Since wireless is more complex than wired ethernet, it supports | ||
481 | * various triggers. These triggers can be configured through this | ||
482 | * command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For | ||
483 | * more background information, see | ||
484 | * http://wireless.kernel.org/en/users/Documentation/WoWLAN. | ||
485 | * | ||
423 | * @NL80211_CMD_MAX: highest used command number | 486 | * @NL80211_CMD_MAX: highest used command number |
424 | * @__NL80211_CMD_AFTER_LAST: internal use | 487 | * @__NL80211_CMD_AFTER_LAST: internal use |
425 | */ | 488 | */ |
@@ -534,6 +597,14 @@ enum nl80211_commands { | |||
534 | 597 | ||
535 | NL80211_CMD_NEW_PEER_CANDIDATE, | 598 | NL80211_CMD_NEW_PEER_CANDIDATE, |
536 | 599 | ||
600 | NL80211_CMD_GET_WOWLAN, | ||
601 | NL80211_CMD_SET_WOWLAN, | ||
602 | |||
603 | NL80211_CMD_START_SCHED_SCAN, | ||
604 | NL80211_CMD_STOP_SCHED_SCAN, | ||
605 | NL80211_CMD_SCHED_SCAN_RESULTS, | ||
606 | NL80211_CMD_SCHED_SCAN_STOPPED, | ||
607 | |||
537 | /* add new commands above here */ | 608 | /* add new commands above here */ |
538 | 609 | ||
539 | /* used to define NL80211_CMD_MAX below */ | 610 | /* used to define NL80211_CMD_MAX below */ |
@@ -902,6 +973,28 @@ enum nl80211_commands { | |||
902 | * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver | 973 | * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver |
903 | * allows auth frames in a mesh to be passed to userspace for processing via | 974 | * allows auth frames in a mesh to be passed to userspace for processing via |
904 | * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag. | 975 | * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag. |
976 | * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as | ||
977 | * defined in &enum nl80211_plink_state. Used when userspace is | ||
978 | * driving the peer link management state machine. | ||
979 | * @NL80211_MESH_SETUP_USERSPACE_AMPE must be enabled. | ||
980 | * | ||
981 | * @NL80211_ATTR_WOWLAN_SUPPORTED: indicates, as part of the wiphy capabilities, | ||
982 | * the supported WoWLAN triggers | ||
983 | * @NL80211_ATTR_WOWLAN_TRIGGERS: used by %NL80211_CMD_SET_WOWLAN to | ||
984 | * indicate which WoW triggers should be enabled. This is also | ||
985 | * used by %NL80211_CMD_GET_WOWLAN to get the currently enabled WoWLAN | ||
986 | * triggers. | ||
987 | |||
988 | * @NL80211_ATTR_SCHED_SCAN_INTERVAL: Interval between scheduled scan | ||
989 | * cycles, in msecs. | ||
990 | * | ||
991 | * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported | ||
992 | * interface combinations. In each nested item, it contains attributes | ||
993 | * defined in &enum nl80211_if_combination_attrs. | ||
994 | * @NL80211_ATTR_SOFTWARE_IFTYPES: Nested attribute (just like | ||
995 | * %NL80211_ATTR_SUPPORTED_IFTYPES) containing the interface types that | ||
996 | * are managed in software: interfaces of these types aren't subject to | ||
997 | * any restrictions in their number or combinations. | ||
905 | * | 998 | * |
906 | * @NL80211_ATTR_MAX: highest attribute number currently defined | 999 | * @NL80211_ATTR_MAX: highest attribute number currently defined |
907 | * @__NL80211_ATTR_AFTER_LAST: internal use | 1000 | * @__NL80211_ATTR_AFTER_LAST: internal use |
@@ -1091,6 +1184,15 @@ enum nl80211_attrs { | |||
1091 | NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, | 1184 | NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, |
1092 | 1185 | ||
1093 | NL80211_ATTR_SUPPORT_MESH_AUTH, | 1186 | NL80211_ATTR_SUPPORT_MESH_AUTH, |
1187 | NL80211_ATTR_STA_PLINK_STATE, | ||
1188 | |||
1189 | NL80211_ATTR_WOWLAN_TRIGGERS, | ||
1190 | NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, | ||
1191 | |||
1192 | NL80211_ATTR_SCHED_SCAN_INTERVAL, | ||
1193 | |||
1194 | NL80211_ATTR_INTERFACE_COMBINATIONS, | ||
1195 | NL80211_ATTR_SOFTWARE_IFTYPES, | ||
1094 | 1196 | ||
1095 | /* add attributes here, update the policy in nl80211.c */ | 1197 | /* add attributes here, update the policy in nl80211.c */ |
1096 | 1198 | ||
@@ -1144,7 +1246,9 @@ enum nl80211_attrs { | |||
1144 | * @NL80211_IFTYPE_ADHOC: independent BSS member | 1246 | * @NL80211_IFTYPE_ADHOC: independent BSS member |
1145 | * @NL80211_IFTYPE_STATION: managed BSS member | 1247 | * @NL80211_IFTYPE_STATION: managed BSS member |
1146 | * @NL80211_IFTYPE_AP: access point | 1248 | * @NL80211_IFTYPE_AP: access point |
1147 | * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points | 1249 | * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points; VLAN interfaces |
1250 | * are a bit special in that they must always be tied to a pre-existing | ||
1251 | * AP type interface. | ||
1148 | * @NL80211_IFTYPE_WDS: wireless distribution interface | 1252 | * @NL80211_IFTYPE_WDS: wireless distribution interface |
1149 | * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames | 1253 | * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames |
1150 | * @NL80211_IFTYPE_MESH_POINT: mesh point | 1254 | * @NL80211_IFTYPE_MESH_POINT: mesh point |
@@ -1293,6 +1397,7 @@ enum nl80211_sta_bss_param { | |||
1293 | * @NL80211_STA_INFO_LLID: the station's mesh LLID | 1397 | * @NL80211_STA_INFO_LLID: the station's mesh LLID |
1294 | * @NL80211_STA_INFO_PLID: the station's mesh PLID | 1398 | * @NL80211_STA_INFO_PLID: the station's mesh PLID |
1295 | * @NL80211_STA_INFO_PLINK_STATE: peer link state for the station | 1399 | * @NL80211_STA_INFO_PLINK_STATE: peer link state for the station |
1400 | * (see %enum nl80211_plink_state) | ||
1296 | * @NL80211_STA_INFO_RX_BITRATE: last unicast data frame rx rate, nested | 1401 | * @NL80211_STA_INFO_RX_BITRATE: last unicast data frame rx rate, nested |
1297 | * attribute, like NL80211_STA_INFO_TX_BITRATE. | 1402 | * attribute, like NL80211_STA_INFO_TX_BITRATE. |
1298 | * @NL80211_STA_INFO_BSS_PARAM: current station's view of BSS, nested attribute | 1403 | * @NL80211_STA_INFO_BSS_PARAM: current station's view of BSS, nested attribute |
@@ -1748,6 +1853,15 @@ enum nl80211_meshconf_params { | |||
1748 | * @NL80211_MESH_SETUP_USERSPACE_AUTH: Enable this option if an authentication | 1853 | * @NL80211_MESH_SETUP_USERSPACE_AUTH: Enable this option if an authentication |
1749 | * daemon will be authenticating mesh candidates. | 1854 | * daemon will be authenticating mesh candidates. |
1750 | * | 1855 | * |
1856 | * @NL80211_MESH_SETUP_USERSPACE_AMPE: Enable this option if an authentication | ||
1857 | * daemon will be securing peer link frames. AMPE is a secured version of Mesh | ||
1858 | * Peering Management (MPM) and is implemented with the assistance of a | ||
1859 | * userspace daemon. When this flag is set, the kernel will send peer | ||
1860 | * management frames to a userspace daemon that will implement AMPE | ||
1861 | * functionality (security capabilities selection, key confirmation, and key | ||
1862 | * management). When the flag is unset (default), the kernel can autonomously | ||
1863 | * complete (unsecured) mesh peering without the need of a userspace daemon. | ||
1864 | * | ||
1751 | * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number | 1865 | * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number |
1752 | * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use | 1866 | * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use |
1753 | */ | 1867 | */ |
@@ -1757,6 +1871,7 @@ enum nl80211_mesh_setup_params { | |||
1757 | NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC, | 1871 | NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC, |
1758 | NL80211_MESH_SETUP_IE, | 1872 | NL80211_MESH_SETUP_IE, |
1759 | NL80211_MESH_SETUP_USERSPACE_AUTH, | 1873 | NL80211_MESH_SETUP_USERSPACE_AUTH, |
1874 | NL80211_MESH_SETUP_USERSPACE_AMPE, | ||
1760 | 1875 | ||
1761 | /* keep last */ | 1876 | /* keep last */ |
1762 | __NL80211_MESH_SETUP_ATTR_AFTER_LAST, | 1877 | __NL80211_MESH_SETUP_ATTR_AFTER_LAST, |
@@ -2061,4 +2176,189 @@ enum nl80211_tx_power_setting { | |||
2061 | NL80211_TX_POWER_FIXED, | 2176 | NL80211_TX_POWER_FIXED, |
2062 | }; | 2177 | }; |
2063 | 2178 | ||
2179 | /** | ||
2180 | * enum nl80211_wowlan_packet_pattern_attr - WoWLAN packet pattern attribute | ||
2181 | * @__NL80211_WOWLAN_PKTPAT_INVALID: invalid number for nested attribute | ||
2182 | * @NL80211_WOWLAN_PKTPAT_PATTERN: the pattern, values where the mask has | ||
2183 | * a zero bit are ignored | ||
2184 | * @NL80211_WOWLAN_PKTPAT_MASK: pattern mask, must be long enough to have | ||
2185 | * a bit for each byte in the pattern. The lowest-order bit corresponds | ||
2186 | * to the first byte of the pattern, but the bytes of the pattern are | ||
2187 | * in a little-endian-like format, i.e. the 9th byte of the pattern | ||
2188 | * corresponds to the lowest-order bit in the second byte of the mask. | ||
2189 | * For example: The match 00:xx:00:00:xx:00:00:00:00:xx:xx:xx (where | ||
2190 | * xx indicates "don't care") would be represented by a pattern of | ||
2191 | * twelve zero bytes, and a mask of "0xed,0x07". | ||
2192 | * Note that the pattern matching is done as though frames were not | ||
2193 | * 802.11 frames but 802.3 frames, i.e. the frame is fully unpacked | ||
2194 | * first (including SNAP header unpacking) and then matched. | ||
2195 | * @NUM_NL80211_WOWLAN_PKTPAT: number of attributes | ||
2196 | * @MAX_NL80211_WOWLAN_PKTPAT: max attribute number | ||
2197 | */ | ||
2198 | enum nl80211_wowlan_packet_pattern_attr { | ||
2199 | __NL80211_WOWLAN_PKTPAT_INVALID, | ||
2200 | NL80211_WOWLAN_PKTPAT_MASK, | ||
2201 | NL80211_WOWLAN_PKTPAT_PATTERN, | ||
2202 | |||
2203 | NUM_NL80211_WOWLAN_PKTPAT, | ||
2204 | MAX_NL80211_WOWLAN_PKTPAT = NUM_NL80211_WOWLAN_PKTPAT - 1, | ||
2205 | }; | ||
2206 | |||
2207 | /** | ||
2208 | * struct nl80211_wowlan_pattern_support - pattern support information | ||
2209 | * @max_patterns: maximum number of patterns supported | ||
2210 | * @min_pattern_len: minimum length of each pattern | ||
2211 | * @max_pattern_len: maximum length of each pattern | ||
2212 | * | ||
2213 | * This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when | ||
2214 | * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED in the | ||
2215 | * capability information given by the kernel to userspace. | ||
2216 | */ | ||
2217 | struct nl80211_wowlan_pattern_support { | ||
2218 | __u32 max_patterns; | ||
2219 | __u32 min_pattern_len; | ||
2220 | __u32 max_pattern_len; | ||
2221 | } __attribute__((packed)); | ||
2222 | |||
2223 | /** | ||
2224 | * enum nl80211_wowlan_triggers - WoWLAN trigger definitions | ||
2225 | * @__NL80211_WOWLAN_TRIG_INVALID: invalid number for nested attributes | ||
2226 | * @NL80211_WOWLAN_TRIG_ANY: wake up on any activity, do not really put | ||
2227 | * the chip into a special state -- works best with chips that have | ||
2228 | * support for low-power operation already (flag) | ||
2229 | * @NL80211_WOWLAN_TRIG_DISCONNECT: wake up on disconnect, the way disconnect | ||
2230 | * is detected is implementation-specific (flag) | ||
2231 | * @NL80211_WOWLAN_TRIG_MAGIC_PKT: wake up on magic packet (6x 0xff, followed | ||
2232 | * by 16 repetitions of MAC addr, anywhere in payload) (flag) | ||
2233 | * @NL80211_WOWLAN_TRIG_PKT_PATTERN: wake up on the specified packet patterns | ||
2234 | * which are passed in an array of nested attributes, each nested attribute | ||
2235 | * defining a with attributes from &struct nl80211_wowlan_trig_pkt_pattern. | ||
2236 | * Each pattern defines a wakeup packet. The matching is done on the MSDU, | ||
2237 | * i.e. as though the packet was an 802.3 packet, so the pattern matching | ||
2238 | * is done after the packet is converted to the MSDU. | ||
2239 | * | ||
2240 | * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute | ||
2241 | * carrying a &struct nl80211_wowlan_pattern_support. | ||
2242 | * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers | ||
2243 | * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number | ||
2244 | */ | ||
2245 | enum nl80211_wowlan_triggers { | ||
2246 | __NL80211_WOWLAN_TRIG_INVALID, | ||
2247 | NL80211_WOWLAN_TRIG_ANY, | ||
2248 | NL80211_WOWLAN_TRIG_DISCONNECT, | ||
2249 | NL80211_WOWLAN_TRIG_MAGIC_PKT, | ||
2250 | NL80211_WOWLAN_TRIG_PKT_PATTERN, | ||
2251 | |||
2252 | /* keep last */ | ||
2253 | NUM_NL80211_WOWLAN_TRIG, | ||
2254 | MAX_NL80211_WOWLAN_TRIG = NUM_NL80211_WOWLAN_TRIG - 1 | ||
2255 | }; | ||
2256 | |||
2257 | /** | ||
2258 | * enum nl80211_iface_limit_attrs - limit attributes | ||
2259 | * @NL80211_IFACE_LIMIT_UNSPEC: (reserved) | ||
2260 | * @NL80211_IFACE_LIMIT_MAX: maximum number of interfaces that | ||
2261 | * can be chosen from this set of interface types (u32) | ||
2262 | * @NL80211_IFACE_LIMIT_TYPES: nested attribute containing a | ||
2263 | * flag attribute for each interface type in this set | ||
2264 | * @NUM_NL80211_IFACE_LIMIT: number of attributes | ||
2265 | * @MAX_NL80211_IFACE_LIMIT: highest attribute number | ||
2266 | */ | ||
2267 | enum nl80211_iface_limit_attrs { | ||
2268 | NL80211_IFACE_LIMIT_UNSPEC, | ||
2269 | NL80211_IFACE_LIMIT_MAX, | ||
2270 | NL80211_IFACE_LIMIT_TYPES, | ||
2271 | |||
2272 | /* keep last */ | ||
2273 | NUM_NL80211_IFACE_LIMIT, | ||
2274 | MAX_NL80211_IFACE_LIMIT = NUM_NL80211_IFACE_LIMIT - 1 | ||
2275 | }; | ||
2276 | |||
2277 | /** | ||
2278 | * enum nl80211_if_combination_attrs -- interface combination attributes | ||
2279 | * | ||
2280 | * @NL80211_IFACE_COMB_UNSPEC: (reserved) | ||
2281 | * @NL80211_IFACE_COMB_LIMITS: Nested attributes containing the limits | ||
2282 | * for given interface types, see &enum nl80211_iface_limit_attrs. | ||
2283 | * @NL80211_IFACE_COMB_MAXNUM: u32 attribute giving the total number of | ||
2284 | * interfaces that can be created in this group. This number doesn't | ||
2285 | * apply to interfaces purely managed in software, which are listed | ||
2286 | * in a separate attribute %NL80211_ATTR_INTERFACES_SOFTWARE. | ||
2287 | * @NL80211_IFACE_COMB_STA_AP_BI_MATCH: flag attribute specifying that | ||
2288 | * beacon intervals within this group must be all the same even for | ||
2289 | * infrastructure and AP/GO combinations, i.e. the GO(s) must adopt | ||
2290 | * the infrastructure network's beacon interval. | ||
2291 | * @NL80211_IFACE_COMB_NUM_CHANNELS: u32 attribute specifying how many | ||
2292 | * different channels may be used within this group. | ||
2293 | * @NUM_NL80211_IFACE_COMB: number of attributes | ||
2294 | * @MAX_NL80211_IFACE_COMB: highest attribute number | ||
2295 | * | ||
2296 | * Examples: | ||
2297 | * limits = [ #{STA} <= 1, #{AP} <= 1 ], matching BI, channels = 1, max = 2 | ||
2298 | * => allows an AP and a STA that must match BIs | ||
2299 | * | ||
2300 | * numbers = [ #{AP, P2P-GO} <= 8 ], channels = 1, max = 8 | ||
2301 | * => allows 8 of AP/GO | ||
2302 | * | ||
2303 | * numbers = [ #{STA} <= 2 ], channels = 2, max = 2 | ||
2304 | * => allows two STAs on different channels | ||
2305 | * | ||
2306 | * numbers = [ #{STA} <= 1, #{P2P-client,P2P-GO} <= 3 ], max = 4 | ||
2307 | * => allows a STA plus three P2P interfaces | ||
2308 | * | ||
2309 | * The list of these four possiblities could completely be contained | ||
2310 | * within the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute to indicate | ||
2311 | * that any of these groups must match. | ||
2312 | * | ||
2313 | * "Combinations" of just a single interface will not be listed here, | ||
2314 | * a single interface of any valid interface type is assumed to always | ||
2315 | * be possible by itself. This means that implicitly, for each valid | ||
2316 | * interface type, the following group always exists: | ||
2317 | * numbers = [ #{<type>} <= 1 ], channels = 1, max = 1 | ||
2318 | */ | ||
2319 | enum nl80211_if_combination_attrs { | ||
2320 | NL80211_IFACE_COMB_UNSPEC, | ||
2321 | NL80211_IFACE_COMB_LIMITS, | ||
2322 | NL80211_IFACE_COMB_MAXNUM, | ||
2323 | NL80211_IFACE_COMB_STA_AP_BI_MATCH, | ||
2324 | NL80211_IFACE_COMB_NUM_CHANNELS, | ||
2325 | |||
2326 | /* keep last */ | ||
2327 | NUM_NL80211_IFACE_COMB, | ||
2328 | MAX_NL80211_IFACE_COMB = NUM_NL80211_IFACE_COMB - 1 | ||
2329 | }; | ||
2330 | |||
2331 | |||
2332 | /** | ||
2333 | * enum nl80211_plink_state - state of a mesh peer link finite state machine | ||
2334 | * | ||
2335 | * @NL80211_PLINK_LISTEN: initial state, considered the implicit | ||
2336 | * state of non existant mesh peer links | ||
2337 | * @NL80211_PLINK_OPN_SNT: mesh plink open frame has been sent to | ||
2338 | * this mesh peer | ||
2339 | * @NL80211_PLINK_OPN_RCVD: mesh plink open frame has been received | ||
2340 | * from this mesh peer | ||
2341 | * @NL80211_PLINK_CNF_RCVD: mesh plink confirm frame has been | ||
2342 | * received from this mesh peer | ||
2343 | * @NL80211_PLINK_ESTAB: mesh peer link is established | ||
2344 | * @NL80211_PLINK_HOLDING: mesh peer link is being closed or cancelled | ||
2345 | * @NL80211_PLINK_BLOCKED: all frames transmitted from this mesh | ||
2346 | * plink are discarded | ||
2347 | * @NUM_NL80211_PLINK_STATES: number of peer link states | ||
2348 | * @MAX_NL80211_PLINK_STATES: highest numerical value of plink states | ||
2349 | */ | ||
2350 | enum nl80211_plink_state { | ||
2351 | NL80211_PLINK_LISTEN, | ||
2352 | NL80211_PLINK_OPN_SNT, | ||
2353 | NL80211_PLINK_OPN_RCVD, | ||
2354 | NL80211_PLINK_CNF_RCVD, | ||
2355 | NL80211_PLINK_ESTAB, | ||
2356 | NL80211_PLINK_HOLDING, | ||
2357 | NL80211_PLINK_BLOCKED, | ||
2358 | |||
2359 | /* keep last */ | ||
2360 | NUM_NL80211_PLINK_STATES, | ||
2361 | MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1 | ||
2362 | }; | ||
2363 | |||
2064 | #endif /* __LINUX_NL80211_H */ | 2364 | #endif /* __LINUX_NL80211_H */ |
diff --git a/include/linux/ssb/ssb.h b/include/linux/ssb/ssb.h index 7e99b348834c..f017b8900f78 100644 --- a/include/linux/ssb/ssb.h +++ b/include/linux/ssb/ssb.h | |||
@@ -518,6 +518,7 @@ extern int ssb_bus_may_powerdown(struct ssb_bus *bus); | |||
518 | * Otherwise static always-on powercontrol will be used. */ | 518 | * Otherwise static always-on powercontrol will be used. */ |
519 | extern int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl); | 519 | extern int ssb_bus_powerup(struct ssb_bus *bus, bool dynamic_pctl); |
520 | 520 | ||
521 | extern void ssb_commit_settings(struct ssb_bus *bus); | ||
521 | 522 | ||
522 | /* Various helper functions */ | 523 | /* Various helper functions */ |
523 | extern u32 ssb_admatch_base(u32 adm); | 524 | extern u32 ssb_admatch_base(u32 adm); |
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 14cc3249c1eb..6c994c004d15 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -422,6 +422,7 @@ void hci_conn_check_pending(struct hci_dev *hdev); | |||
422 | 422 | ||
423 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type); | 423 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type); |
424 | int hci_conn_check_link_mode(struct hci_conn *conn); | 424 | int hci_conn_check_link_mode(struct hci_conn *conn); |
425 | int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level); | ||
425 | int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type); | 426 | int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type); |
426 | int hci_conn_change_link_key(struct hci_conn *conn); | 427 | int hci_conn_change_link_key(struct hci_conn *conn); |
427 | int hci_conn_switch_role(struct hci_conn *conn, __u8 role); | 428 | int hci_conn_switch_role(struct hci_conn *conn, __u8 role); |
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index c34b1c126363..d09c9b1118e3 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h | |||
@@ -350,6 +350,7 @@ struct l2cap_chan { | |||
350 | struct list_head srej_l; | 350 | struct list_head srej_l; |
351 | 351 | ||
352 | struct list_head list; | 352 | struct list_head list; |
353 | struct list_head global_l; | ||
353 | }; | 354 | }; |
354 | 355 | ||
355 | struct l2cap_conn { | 356 | struct l2cap_conn { |
@@ -441,7 +442,6 @@ static inline int l2cap_tx_window_full(struct l2cap_chan *ch) | |||
441 | #define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START) | 442 | #define __is_sar_start(ctrl) (((ctrl) & L2CAP_CTRL_SAR) == L2CAP_SDU_START) |
442 | 443 | ||
443 | extern int disable_ertm; | 444 | extern int disable_ertm; |
444 | extern struct bt_sock_list l2cap_sk_list; | ||
445 | 445 | ||
446 | int l2cap_init_sockets(void); | 446 | int l2cap_init_sockets(void); |
447 | void l2cap_cleanup_sockets(void); | 447 | void l2cap_cleanup_sockets(void); |
@@ -458,6 +458,9 @@ void l2cap_do_send(struct l2cap_chan *chan, struct sk_buff *skb); | |||
458 | void l2cap_streaming_send(struct l2cap_chan *chan); | 458 | void l2cap_streaming_send(struct l2cap_chan *chan); |
459 | int l2cap_ertm_send(struct l2cap_chan *chan); | 459 | int l2cap_ertm_send(struct l2cap_chan *chan); |
460 | 460 | ||
461 | int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm); | ||
462 | int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); | ||
463 | |||
461 | void l2cap_sock_set_timer(struct sock *sk, long timeout); | 464 | void l2cap_sock_set_timer(struct sock *sk, long timeout); |
462 | void l2cap_sock_clear_timer(struct sock *sk); | 465 | void l2cap_sock_clear_timer(struct sock *sk); |
463 | void __l2cap_sock_close(struct sock *sk, int reason); | 466 | void __l2cap_sock_close(struct sock *sk, int reason); |
@@ -466,9 +469,9 @@ void l2cap_sock_init(struct sock *sk, struct sock *parent); | |||
466 | struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, | 469 | struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, |
467 | int proto, gfp_t prio); | 470 | int proto, gfp_t prio); |
468 | void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err); | 471 | void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *chan, int err); |
469 | struct l2cap_chan *l2cap_chan_alloc(struct sock *sk); | 472 | struct l2cap_chan *l2cap_chan_create(struct sock *sk); |
470 | void l2cap_chan_del(struct l2cap_chan *chan, int err); | 473 | void l2cap_chan_del(struct l2cap_chan *chan, int err); |
471 | void l2cap_chan_free(struct l2cap_chan *chan); | 474 | void l2cap_chan_destroy(struct l2cap_chan *chan); |
472 | int l2cap_chan_connect(struct l2cap_chan *chan); | 475 | int l2cap_chan_connect(struct l2cap_chan *chan); |
473 | 476 | ||
474 | #endif /* __L2CAP_H */ | 477 | #endif /* __L2CAP_H */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index d30eada7c6cd..bfd6557946be 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -387,6 +387,7 @@ enum plink_actions { | |||
387 | * @listen_interval: listen interval or -1 for no change | 387 | * @listen_interval: listen interval or -1 for no change |
388 | * @aid: AID or zero for no change | 388 | * @aid: AID or zero for no change |
389 | * @plink_action: plink action to take | 389 | * @plink_action: plink action to take |
390 | * @plink_state: set the peer link state for a station | ||
390 | * @ht_capa: HT capabilities of station | 391 | * @ht_capa: HT capabilities of station |
391 | */ | 392 | */ |
392 | struct station_parameters { | 393 | struct station_parameters { |
@@ -397,6 +398,7 @@ struct station_parameters { | |||
397 | u16 aid; | 398 | u16 aid; |
398 | u8 supported_rates_len; | 399 | u8 supported_rates_len; |
399 | u8 plink_action; | 400 | u8 plink_action; |
401 | u8 plink_state; | ||
400 | struct ieee80211_ht_cap *ht_capa; | 402 | struct ieee80211_ht_cap *ht_capa; |
401 | }; | 403 | }; |
402 | 404 | ||
@@ -695,7 +697,8 @@ struct mesh_config { | |||
695 | * @path_metric: which metric to use | 697 | * @path_metric: which metric to use |
696 | * @ie: vendor information elements (optional) | 698 | * @ie: vendor information elements (optional) |
697 | * @ie_len: length of vendor information elements | 699 | * @ie_len: length of vendor information elements |
698 | * @is_secure: or not | 700 | * @is_authenticated: this mesh requires authentication |
701 | * @is_secure: this mesh uses security | ||
699 | * | 702 | * |
700 | * These parameters are fixed when the mesh is created. | 703 | * These parameters are fixed when the mesh is created. |
701 | */ | 704 | */ |
@@ -706,6 +709,7 @@ struct mesh_setup { | |||
706 | u8 path_metric; | 709 | u8 path_metric; |
707 | const u8 *ie; | 710 | const u8 *ie; |
708 | u8 ie_len; | 711 | u8 ie_len; |
712 | bool is_authenticated; | ||
709 | bool is_secure; | 713 | bool is_secure; |
710 | }; | 714 | }; |
711 | 715 | ||
@@ -793,6 +797,35 @@ struct cfg80211_scan_request { | |||
793 | }; | 797 | }; |
794 | 798 | ||
795 | /** | 799 | /** |
800 | * struct cfg80211_sched_scan_request - scheduled scan request description | ||
801 | * | ||
802 | * @ssids: SSIDs to scan for (passed in the probe_reqs in active scans) | ||
803 | * @n_ssids: number of SSIDs | ||
804 | * @n_channels: total number of channels to scan | ||
805 | * @interval: interval between each scheduled scan cycle | ||
806 | * @ie: optional information element(s) to add into Probe Request or %NULL | ||
807 | * @ie_len: length of ie in octets | ||
808 | * @wiphy: the wiphy this was for | ||
809 | * @dev: the interface | ||
810 | * @channels: channels to scan | ||
811 | */ | ||
812 | struct cfg80211_sched_scan_request { | ||
813 | struct cfg80211_ssid *ssids; | ||
814 | int n_ssids; | ||
815 | u32 n_channels; | ||
816 | u32 interval; | ||
817 | const u8 *ie; | ||
818 | size_t ie_len; | ||
819 | |||
820 | /* internal */ | ||
821 | struct wiphy *wiphy; | ||
822 | struct net_device *dev; | ||
823 | |||
824 | /* keep last */ | ||
825 | struct ieee80211_channel *channels[0]; | ||
826 | }; | ||
827 | |||
828 | /** | ||
796 | * enum cfg80211_signal_type - signal type | 829 | * enum cfg80211_signal_type - signal type |
797 | * | 830 | * |
798 | * @CFG80211_SIGNAL_TYPE_NONE: no signal strength information available | 831 | * @CFG80211_SIGNAL_TYPE_NONE: no signal strength information available |
@@ -1088,6 +1121,38 @@ struct cfg80211_pmksa { | |||
1088 | }; | 1121 | }; |
1089 | 1122 | ||
1090 | /** | 1123 | /** |
1124 | * struct cfg80211_wowlan_trig_pkt_pattern - packet pattern | ||
1125 | * @mask: bitmask where to match pattern and where to ignore bytes, | ||
1126 | * one bit per byte, in same format as nl80211 | ||
1127 | * @pattern: bytes to match where bitmask is 1 | ||
1128 | * @pattern_len: length of pattern (in bytes) | ||
1129 | * | ||
1130 | * Internal note: @mask and @pattern are allocated in one chunk of | ||
1131 | * memory, free @mask only! | ||
1132 | */ | ||
1133 | struct cfg80211_wowlan_trig_pkt_pattern { | ||
1134 | u8 *mask, *pattern; | ||
1135 | int pattern_len; | ||
1136 | }; | ||
1137 | |||
1138 | /** | ||
1139 | * struct cfg80211_wowlan - Wake on Wireless-LAN support info | ||
1140 | * | ||
1141 | * This structure defines the enabled WoWLAN triggers for the device. | ||
1142 | * @any: wake up on any activity -- special trigger if device continues | ||
1143 | * operating as normal during suspend | ||
1144 | * @disconnect: wake up if getting disconnected | ||
1145 | * @magic_pkt: wake up on receiving magic packet | ||
1146 | * @patterns: wake up on receiving packet matching a pattern | ||
1147 | * @n_patterns: number of patterns | ||
1148 | */ | ||
1149 | struct cfg80211_wowlan { | ||
1150 | bool any, disconnect, magic_pkt; | ||
1151 | struct cfg80211_wowlan_trig_pkt_pattern *patterns; | ||
1152 | int n_patterns; | ||
1153 | }; | ||
1154 | |||
1155 | /** | ||
1091 | * struct cfg80211_ops - backend description for wireless configuration | 1156 | * struct cfg80211_ops - backend description for wireless configuration |
1092 | * | 1157 | * |
1093 | * This struct is registered by fullmac card drivers and/or wireless stacks | 1158 | * This struct is registered by fullmac card drivers and/or wireless stacks |
@@ -1100,7 +1165,9 @@ struct cfg80211_pmksa { | |||
1100 | * wireless extensions but this is subject to reevaluation as soon as this | 1165 | * wireless extensions but this is subject to reevaluation as soon as this |
1101 | * code is used more widely and we have a first user without wext. | 1166 | * code is used more widely and we have a first user without wext. |
1102 | * | 1167 | * |
1103 | * @suspend: wiphy device needs to be suspended | 1168 | * @suspend: wiphy device needs to be suspended. The variable @wow will |
1169 | * be %NULL or contain the enabled Wake-on-Wireless triggers that are | ||
1170 | * configured for the device. | ||
1104 | * @resume: wiphy device needs to be resumed | 1171 | * @resume: wiphy device needs to be resumed |
1105 | * | 1172 | * |
1106 | * @add_virtual_intf: create a new virtual interface with the given name, | 1173 | * @add_virtual_intf: create a new virtual interface with the given name, |
@@ -1227,6 +1294,10 @@ struct cfg80211_pmksa { | |||
1227 | * @set_power_mgmt: Configure WLAN power management. A timeout value of -1 | 1294 | * @set_power_mgmt: Configure WLAN power management. A timeout value of -1 |
1228 | * allows the driver to adjust the dynamic ps timeout value. | 1295 | * allows the driver to adjust the dynamic ps timeout value. |
1229 | * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold. | 1296 | * @set_cqm_rssi_config: Configure connection quality monitor RSSI threshold. |
1297 | * @sched_scan_start: Tell the driver to start a scheduled scan. | ||
1298 | * @sched_scan_stop: Tell the driver to stop an ongoing scheduled | ||
1299 | * scan. The driver_initiated flag specifies whether the driver | ||
1300 | * itself has informed that the scan has stopped. | ||
1230 | * | 1301 | * |
1231 | * @mgmt_frame_register: Notify driver that a management frame type was | 1302 | * @mgmt_frame_register: Notify driver that a management frame type was |
1232 | * registered. Note that this callback may not sleep, and cannot run | 1303 | * registered. Note that this callback may not sleep, and cannot run |
@@ -1244,7 +1315,7 @@ struct cfg80211_pmksa { | |||
1244 | * @get_ringparam: Get tx and rx ring current and maximum sizes. | 1315 | * @get_ringparam: Get tx and rx ring current and maximum sizes. |
1245 | */ | 1316 | */ |
1246 | struct cfg80211_ops { | 1317 | struct cfg80211_ops { |
1247 | int (*suspend)(struct wiphy *wiphy); | 1318 | int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); |
1248 | int (*resume)(struct wiphy *wiphy); | 1319 | int (*resume)(struct wiphy *wiphy); |
1249 | 1320 | ||
1250 | struct net_device * (*add_virtual_intf)(struct wiphy *wiphy, | 1321 | struct net_device * (*add_virtual_intf)(struct wiphy *wiphy, |
@@ -1413,6 +1484,11 @@ struct cfg80211_ops { | |||
1413 | int (*set_ringparam)(struct wiphy *wiphy, u32 tx, u32 rx); | 1484 | int (*set_ringparam)(struct wiphy *wiphy, u32 tx, u32 rx); |
1414 | void (*get_ringparam)(struct wiphy *wiphy, | 1485 | void (*get_ringparam)(struct wiphy *wiphy, |
1415 | u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); | 1486 | u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max); |
1487 | |||
1488 | int (*sched_scan_start)(struct wiphy *wiphy, | ||
1489 | struct net_device *dev, | ||
1490 | struct cfg80211_sched_scan_request *request); | ||
1491 | int (*sched_scan_stop)(struct wiphy *wiphy, struct net_device *dev); | ||
1416 | }; | 1492 | }; |
1417 | 1493 | ||
1418 | /* | 1494 | /* |
@@ -1444,6 +1520,10 @@ struct cfg80211_ops { | |||
1444 | * hints read the documenation for regulatory_hint_found_beacon() | 1520 | * hints read the documenation for regulatory_hint_found_beacon() |
1445 | * @WIPHY_FLAG_NETNS_OK: if not set, do not allow changing the netns of this | 1521 | * @WIPHY_FLAG_NETNS_OK: if not set, do not allow changing the netns of this |
1446 | * wiphy at all | 1522 | * wiphy at all |
1523 | * @WIPHY_FLAG_ENFORCE_COMBINATIONS: Set this flag to enforce interface | ||
1524 | * combinations for this device. This flag is used for backward | ||
1525 | * compatibility only until all drivers advertise combinations and | ||
1526 | * they will always be enforced. | ||
1447 | * @WIPHY_FLAG_PS_ON_BY_DEFAULT: if set to true, powersave will be enabled | 1527 | * @WIPHY_FLAG_PS_ON_BY_DEFAULT: if set to true, powersave will be enabled |
1448 | * by default -- this flag will be set depending on the kernel's default | 1528 | * by default -- this flag will be set depending on the kernel's default |
1449 | * on wiphy_new(), but can be changed by the driver if it has a good | 1529 | * on wiphy_new(), but can be changed by the driver if it has a good |
@@ -1455,10 +1535,9 @@ struct cfg80211_ops { | |||
1455 | * control port protocol ethertype. The device also honours the | 1535 | * control port protocol ethertype. The device also honours the |
1456 | * control_port_no_encrypt flag. | 1536 | * control_port_no_encrypt flag. |
1457 | * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN. | 1537 | * @WIPHY_FLAG_IBSS_RSN: The device supports IBSS RSN. |
1458 | * @WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS: The device supports separate | ||
1459 | * unicast and multicast TX keys. | ||
1460 | * @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing | 1538 | * @WIPHY_FLAG_MESH_AUTH: The device supports mesh authentication by routing |
1461 | * auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH. | 1539 | * auth frames to userspace. See @NL80211_MESH_SETUP_USERSPACE_AUTH. |
1540 | * @WIPHY_FLAG_SCHED_SCAN: The device supports scheduled scans. | ||
1462 | */ | 1541 | */ |
1463 | enum wiphy_flags { | 1542 | enum wiphy_flags { |
1464 | WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), | 1543 | WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0), |
@@ -1470,8 +1549,83 @@ enum wiphy_flags { | |||
1470 | WIPHY_FLAG_4ADDR_STATION = BIT(6), | 1549 | WIPHY_FLAG_4ADDR_STATION = BIT(6), |
1471 | WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7), | 1550 | WIPHY_FLAG_CONTROL_PORT_PROTOCOL = BIT(7), |
1472 | WIPHY_FLAG_IBSS_RSN = BIT(8), | 1551 | WIPHY_FLAG_IBSS_RSN = BIT(8), |
1473 | WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS= BIT(9), | ||
1474 | WIPHY_FLAG_MESH_AUTH = BIT(10), | 1552 | WIPHY_FLAG_MESH_AUTH = BIT(10), |
1553 | WIPHY_FLAG_SUPPORTS_SCHED_SCAN = BIT(11), | ||
1554 | WIPHY_FLAG_ENFORCE_COMBINATIONS = BIT(12), | ||
1555 | }; | ||
1556 | |||
1557 | /** | ||
1558 | * struct ieee80211_iface_limit - limit on certain interface types | ||
1559 | * @max: maximum number of interfaces of these types | ||
1560 | * @types: interface types (bits) | ||
1561 | */ | ||
1562 | struct ieee80211_iface_limit { | ||
1563 | u16 max; | ||
1564 | u16 types; | ||
1565 | }; | ||
1566 | |||
1567 | /** | ||
1568 | * struct ieee80211_iface_combination - possible interface combination | ||
1569 | * @limits: limits for the given interface types | ||
1570 | * @n_limits: number of limitations | ||
1571 | * @num_different_channels: can use up to this many different channels | ||
1572 | * @max_interfaces: maximum number of interfaces in total allowed in this | ||
1573 | * group | ||
1574 | * @beacon_int_infra_match: In this combination, the beacon intervals | ||
1575 | * between infrastructure and AP types must match. This is required | ||
1576 | * only in special cases. | ||
1577 | * | ||
1578 | * These examples can be expressed as follows: | ||
1579 | * | ||
1580 | * Allow #STA <= 1, #AP <= 1, matching BI, channels = 1, 2 total: | ||
1581 | * | ||
1582 | * struct ieee80211_iface_limit limits1[] = { | ||
1583 | * { .max = 1, .types = BIT(NL80211_IFTYPE_STATION), }, | ||
1584 | * { .max = 1, .types = BIT(NL80211_IFTYPE_AP}, }, | ||
1585 | * }; | ||
1586 | * struct ieee80211_iface_combination combination1 = { | ||
1587 | * .limits = limits1, | ||
1588 | * .n_limits = ARRAY_SIZE(limits1), | ||
1589 | * .max_interfaces = 2, | ||
1590 | * .beacon_int_infra_match = true, | ||
1591 | * }; | ||
1592 | * | ||
1593 | * | ||
1594 | * Allow #{AP, P2P-GO} <= 8, channels = 1, 8 total: | ||
1595 | * | ||
1596 | * struct ieee80211_iface_limit limits2[] = { | ||
1597 | * { .max = 8, .types = BIT(NL80211_IFTYPE_AP) | | ||
1598 | * BIT(NL80211_IFTYPE_P2P_GO), }, | ||
1599 | * }; | ||
1600 | * struct ieee80211_iface_combination combination2 = { | ||
1601 | * .limits = limits2, | ||
1602 | * .n_limits = ARRAY_SIZE(limits2), | ||
1603 | * .max_interfaces = 8, | ||
1604 | * .num_different_channels = 1, | ||
1605 | * }; | ||
1606 | * | ||
1607 | * | ||
1608 | * Allow #STA <= 1, #{P2P-client,P2P-GO} <= 3 on two channels, 4 total. | ||
1609 | * This allows for an infrastructure connection and three P2P connections. | ||
1610 | * | ||
1611 | * struct ieee80211_iface_limit limits3[] = { | ||
1612 | * { .max = 1, .types = BIT(NL80211_IFTYPE_STATION), }, | ||
1613 | * { .max = 3, .types = BIT(NL80211_IFTYPE_P2P_GO) | | ||
1614 | * BIT(NL80211_IFTYPE_P2P_CLIENT), }, | ||
1615 | * }; | ||
1616 | * struct ieee80211_iface_combination combination3 = { | ||
1617 | * .limits = limits3, | ||
1618 | * .n_limits = ARRAY_SIZE(limits3), | ||
1619 | * .max_interfaces = 4, | ||
1620 | * .num_different_channels = 2, | ||
1621 | * }; | ||
1622 | */ | ||
1623 | struct ieee80211_iface_combination { | ||
1624 | const struct ieee80211_iface_limit *limits; | ||
1625 | u32 num_different_channels; | ||
1626 | u16 max_interfaces; | ||
1627 | u8 n_limits; | ||
1628 | bool beacon_int_infra_match; | ||
1475 | }; | 1629 | }; |
1476 | 1630 | ||
1477 | struct mac_address { | 1631 | struct mac_address { |
@@ -1483,6 +1637,38 @@ struct ieee80211_txrx_stypes { | |||
1483 | }; | 1637 | }; |
1484 | 1638 | ||
1485 | /** | 1639 | /** |
1640 | * enum wiphy_wowlan_support_flags - WoWLAN support flags | ||
1641 | * @WIPHY_WOWLAN_ANY: supports wakeup for the special "any" | ||
1642 | * trigger that keeps the device operating as-is and | ||
1643 | * wakes up the host on any activity, for example a | ||
1644 | * received packet that passed filtering; note that the | ||
1645 | * packet should be preserved in that case | ||
1646 | * @WIPHY_WOWLAN_MAGIC_PKT: supports wakeup on magic packet | ||
1647 | * (see nl80211.h) | ||
1648 | * @WIPHY_WOWLAN_DISCONNECT: supports wakeup on disconnect | ||
1649 | */ | ||
1650 | enum wiphy_wowlan_support_flags { | ||
1651 | WIPHY_WOWLAN_ANY = BIT(0), | ||
1652 | WIPHY_WOWLAN_MAGIC_PKT = BIT(1), | ||
1653 | WIPHY_WOWLAN_DISCONNECT = BIT(2), | ||
1654 | }; | ||
1655 | |||
1656 | /** | ||
1657 | * struct wiphy_wowlan_support - WoWLAN support data | ||
1658 | * @flags: see &enum wiphy_wowlan_support_flags | ||
1659 | * @n_patterns: number of supported wakeup patterns | ||
1660 | * (see nl80211.h for the pattern definition) | ||
1661 | * @pattern_max_len: maximum length of each pattern | ||
1662 | * @pattern_min_len: minimum length of each pattern | ||
1663 | */ | ||
1664 | struct wiphy_wowlan_support { | ||
1665 | u32 flags; | ||
1666 | int n_patterns; | ||
1667 | int pattern_max_len; | ||
1668 | int pattern_min_len; | ||
1669 | }; | ||
1670 | |||
1671 | /** | ||
1486 | * struct wiphy - wireless hardware description | 1672 | * struct wiphy - wireless hardware description |
1487 | * @reg_notifier: the driver's regulatory notification callback, | 1673 | * @reg_notifier: the driver's regulatory notification callback, |
1488 | * note that if your driver uses wiphy_apply_custom_regulatory() | 1674 | * note that if your driver uses wiphy_apply_custom_regulatory() |
@@ -1519,6 +1705,11 @@ struct ieee80211_txrx_stypes { | |||
1519 | * @priv: driver private data (sized according to wiphy_new() parameter) | 1705 | * @priv: driver private data (sized according to wiphy_new() parameter) |
1520 | * @interface_modes: bitmask of interfaces types valid for this wiphy, | 1706 | * @interface_modes: bitmask of interfaces types valid for this wiphy, |
1521 | * must be set by driver | 1707 | * must be set by driver |
1708 | * @iface_combinations: Valid interface combinations array, should not | ||
1709 | * list single interface types. | ||
1710 | * @n_iface_combinations: number of entries in @iface_combinations array. | ||
1711 | * @software_iftypes: bitmask of software interface types, these are not | ||
1712 | * subject to any restrictions since they are purely managed in SW. | ||
1522 | * @flags: wiphy flags, see &enum wiphy_flags | 1713 | * @flags: wiphy flags, see &enum wiphy_flags |
1523 | * @bss_priv_size: each BSS struct has private data allocated with it, | 1714 | * @bss_priv_size: each BSS struct has private data allocated with it, |
1524 | * this variable determines its size | 1715 | * this variable determines its size |
@@ -1549,6 +1740,8 @@ struct ieee80211_txrx_stypes { | |||
1549 | * | 1740 | * |
1550 | * @max_remain_on_channel_duration: Maximum time a remain-on-channel operation | 1741 | * @max_remain_on_channel_duration: Maximum time a remain-on-channel operation |
1551 | * may request, if implemented. | 1742 | * may request, if implemented. |
1743 | * | ||
1744 | * @wowlan: WoWLAN support information | ||
1552 | */ | 1745 | */ |
1553 | struct wiphy { | 1746 | struct wiphy { |
1554 | /* assign these fields before you register the wiphy */ | 1747 | /* assign these fields before you register the wiphy */ |
@@ -1561,6 +1754,10 @@ struct wiphy { | |||
1561 | 1754 | ||
1562 | const struct ieee80211_txrx_stypes *mgmt_stypes; | 1755 | const struct ieee80211_txrx_stypes *mgmt_stypes; |
1563 | 1756 | ||
1757 | const struct ieee80211_iface_combination *iface_combinations; | ||
1758 | int n_iface_combinations; | ||
1759 | u16 software_iftypes; | ||
1760 | |||
1564 | u16 n_addresses; | 1761 | u16 n_addresses; |
1565 | 1762 | ||
1566 | /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ | 1763 | /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ |
@@ -1586,6 +1783,8 @@ struct wiphy { | |||
1586 | char fw_version[ETHTOOL_BUSINFO_LEN]; | 1783 | char fw_version[ETHTOOL_BUSINFO_LEN]; |
1587 | u32 hw_version; | 1784 | u32 hw_version; |
1588 | 1785 | ||
1786 | struct wiphy_wowlan_support wowlan; | ||
1787 | |||
1589 | u16 max_remain_on_channel_duration; | 1788 | u16 max_remain_on_channel_duration; |
1590 | 1789 | ||
1591 | u8 max_num_pmkids; | 1790 | u8 max_num_pmkids; |
@@ -1769,6 +1968,8 @@ struct cfg80211_cached_keys; | |||
1769 | * @mgmt_registrations_lock: lock for the list | 1968 | * @mgmt_registrations_lock: lock for the list |
1770 | * @mtx: mutex used to lock data in this struct | 1969 | * @mtx: mutex used to lock data in this struct |
1771 | * @cleanup_work: work struct used for cleanup that can't be done directly | 1970 | * @cleanup_work: work struct used for cleanup that can't be done directly |
1971 | * @beacon_interval: beacon interval used on this device for transmitting | ||
1972 | * beacons, 0 when not valid | ||
1772 | */ | 1973 | */ |
1773 | struct wireless_dev { | 1974 | struct wireless_dev { |
1774 | struct wiphy *wiphy; | 1975 | struct wiphy *wiphy; |
@@ -1809,6 +2010,8 @@ struct wireless_dev { | |||
1809 | bool ps; | 2010 | bool ps; |
1810 | int ps_timeout; | 2011 | int ps_timeout; |
1811 | 2012 | ||
2013 | int beacon_interval; | ||
2014 | |||
1812 | #ifdef CONFIG_CFG80211_WEXT | 2015 | #ifdef CONFIG_CFG80211_WEXT |
1813 | /* wext data */ | 2016 | /* wext data */ |
1814 | struct { | 2017 | struct { |
@@ -2034,10 +2237,12 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr, | |||
2034 | * @addr: The device MAC address. | 2237 | * @addr: The device MAC address. |
2035 | * @iftype: The device interface type. | 2238 | * @iftype: The device interface type. |
2036 | * @extra_headroom: The hardware extra headroom for SKBs in the @list. | 2239 | * @extra_headroom: The hardware extra headroom for SKBs in the @list. |
2240 | * @has_80211_header: Set it true if SKB is with IEEE 802.11 header. | ||
2037 | */ | 2241 | */ |
2038 | void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, | 2242 | void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, |
2039 | const u8 *addr, enum nl80211_iftype iftype, | 2243 | const u8 *addr, enum nl80211_iftype iftype, |
2040 | const unsigned int extra_headroom); | 2244 | const unsigned int extra_headroom, |
2245 | bool has_80211_header); | ||
2041 | 2246 | ||
2042 | /** | 2247 | /** |
2043 | * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame | 2248 | * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame |
@@ -2257,6 +2462,24 @@ int cfg80211_wext_siwpmksa(struct net_device *dev, | |||
2257 | void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted); | 2462 | void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted); |
2258 | 2463 | ||
2259 | /** | 2464 | /** |
2465 | * cfg80211_sched_scan_results - notify that new scan results are available | ||
2466 | * | ||
2467 | * @wiphy: the wiphy which got scheduled scan results | ||
2468 | */ | ||
2469 | void cfg80211_sched_scan_results(struct wiphy *wiphy); | ||
2470 | |||
2471 | /** | ||
2472 | * cfg80211_sched_scan_stopped - notify that the scheduled scan has stopped | ||
2473 | * | ||
2474 | * @wiphy: the wiphy on which the scheduled scan stopped | ||
2475 | * | ||
2476 | * The driver can call this function to inform cfg80211 that the | ||
2477 | * scheduled scan had to be stopped, for whatever reason. The driver | ||
2478 | * is then called back via the sched_scan_stop operation when done. | ||
2479 | */ | ||
2480 | void cfg80211_sched_scan_stopped(struct wiphy *wiphy); | ||
2481 | |||
2482 | /** | ||
2260 | * cfg80211_inform_bss_frame - inform cfg80211 of a received BSS frame | 2483 | * cfg80211_inform_bss_frame - inform cfg80211 of a received BSS frame |
2261 | * | 2484 | * |
2262 | * @wiphy: the wiphy reporting the BSS | 2485 | * @wiphy: the wiphy reporting the BSS |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index db4b6b9f3977..8c7189c3f6ed 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -537,6 +537,21 @@ struct ieee80211_tx_info { | |||
537 | }; | 537 | }; |
538 | }; | 538 | }; |
539 | 539 | ||
540 | /** | ||
541 | * ieee80211_sched_scan_ies - scheduled scan IEs | ||
542 | * | ||
543 | * This structure is used to pass the appropriate IEs to be used in scheduled | ||
544 | * scans for all bands. It contains both the IEs passed from the userspace | ||
545 | * and the ones generated by mac80211. | ||
546 | * | ||
547 | * @ie: array with the IEs for each supported band | ||
548 | * @len: array with the total length of the IEs for each band | ||
549 | */ | ||
550 | struct ieee80211_sched_scan_ies { | ||
551 | u8 *ie[IEEE80211_NUM_BANDS]; | ||
552 | size_t len[IEEE80211_NUM_BANDS]; | ||
553 | }; | ||
554 | |||
540 | static inline struct ieee80211_tx_info *IEEE80211_SKB_CB(struct sk_buff *skb) | 555 | static inline struct ieee80211_tx_info *IEEE80211_SKB_CB(struct sk_buff *skb) |
541 | { | 556 | { |
542 | return (struct ieee80211_tx_info *)skb->cb; | 557 | return (struct ieee80211_tx_info *)skb->cb; |
@@ -1606,6 +1621,18 @@ enum ieee80211_ampdu_mlme_action { | |||
1606 | * you should ensure to cancel it on this callback. | 1621 | * you should ensure to cancel it on this callback. |
1607 | * Must be implemented and can sleep. | 1622 | * Must be implemented and can sleep. |
1608 | * | 1623 | * |
1624 | * @suspend: Suspend the device; mac80211 itself will quiesce before and | ||
1625 | * stop transmitting and doing any other configuration, and then | ||
1626 | * ask the device to suspend. This is only invoked when WoWLAN is | ||
1627 | * configured, otherwise the device is deconfigured completely and | ||
1628 | * reconfigured at resume time. | ||
1629 | * | ||
1630 | * @resume: If WoWLAN was configured, this indicates that mac80211 is | ||
1631 | * now resuming its operation, after this the device must be fully | ||
1632 | * functional again. If this returns an error, the only way out is | ||
1633 | * to also unregister the device. If it returns 1, then mac80211 | ||
1634 | * will also go through the regular complete restart on resume. | ||
1635 | * | ||
1609 | * @add_interface: Called when a netdevice attached to the hardware is | 1636 | * @add_interface: Called when a netdevice attached to the hardware is |
1610 | * enabled. Because it is not called for monitor mode devices, @start | 1637 | * enabled. Because it is not called for monitor mode devices, @start |
1611 | * and @stop must be implemented. | 1638 | * and @stop must be implemented. |
@@ -1681,6 +1708,13 @@ enum ieee80211_ampdu_mlme_action { | |||
1681 | * any error unless this callback returned a negative error code. | 1708 | * any error unless this callback returned a negative error code. |
1682 | * The callback can sleep. | 1709 | * The callback can sleep. |
1683 | * | 1710 | * |
1711 | * @sched_scan_start: Ask the hardware to start scanning repeatedly at | ||
1712 | * specific intervals. The driver must call the | ||
1713 | * ieee80211_sched_scan_results() function whenever it finds results. | ||
1714 | * This process will continue until sched_scan_stop is called. | ||
1715 | * | ||
1716 | * @sched_scan_stop: Tell the hardware to stop an ongoing scheduled scan. | ||
1717 | * | ||
1684 | * @sw_scan_start: Notifier function that is called just before a software scan | 1718 | * @sw_scan_start: Notifier function that is called just before a software scan |
1685 | * is started. Can be NULL, if the driver doesn't need this notification. | 1719 | * is started. Can be NULL, if the driver doesn't need this notification. |
1686 | * The callback can sleep. | 1720 | * The callback can sleep. |
@@ -1831,6 +1865,10 @@ struct ieee80211_ops { | |||
1831 | void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); | 1865 | void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); |
1832 | int (*start)(struct ieee80211_hw *hw); | 1866 | int (*start)(struct ieee80211_hw *hw); |
1833 | void (*stop)(struct ieee80211_hw *hw); | 1867 | void (*stop)(struct ieee80211_hw *hw); |
1868 | #ifdef CONFIG_PM | ||
1869 | int (*suspend)(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan); | ||
1870 | int (*resume)(struct ieee80211_hw *hw); | ||
1871 | #endif | ||
1834 | int (*add_interface)(struct ieee80211_hw *hw, | 1872 | int (*add_interface)(struct ieee80211_hw *hw, |
1835 | struct ieee80211_vif *vif); | 1873 | struct ieee80211_vif *vif); |
1836 | int (*change_interface)(struct ieee80211_hw *hw, | 1874 | int (*change_interface)(struct ieee80211_hw *hw, |
@@ -1861,6 +1899,12 @@ struct ieee80211_ops { | |||
1861 | u32 iv32, u16 *phase1key); | 1899 | u32 iv32, u16 *phase1key); |
1862 | int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 1900 | int (*hw_scan)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
1863 | struct cfg80211_scan_request *req); | 1901 | struct cfg80211_scan_request *req); |
1902 | int (*sched_scan_start)(struct ieee80211_hw *hw, | ||
1903 | struct ieee80211_vif *vif, | ||
1904 | struct cfg80211_sched_scan_request *req, | ||
1905 | struct ieee80211_sched_scan_ies *ies); | ||
1906 | void (*sched_scan_stop)(struct ieee80211_hw *hw, | ||
1907 | struct ieee80211_vif *vif); | ||
1864 | void (*sw_scan_start)(struct ieee80211_hw *hw); | 1908 | void (*sw_scan_start)(struct ieee80211_hw *hw); |
1865 | void (*sw_scan_complete)(struct ieee80211_hw *hw); | 1909 | void (*sw_scan_complete)(struct ieee80211_hw *hw); |
1866 | int (*get_stats)(struct ieee80211_hw *hw, | 1910 | int (*get_stats)(struct ieee80211_hw *hw, |
@@ -2578,6 +2622,28 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw); | |||
2578 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted); | 2622 | void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted); |
2579 | 2623 | ||
2580 | /** | 2624 | /** |
2625 | * ieee80211_sched_scan_results - got results from scheduled scan | ||
2626 | * | ||
2627 | * When a scheduled scan is running, this function needs to be called by the | ||
2628 | * driver whenever there are new scan results available. | ||
2629 | * | ||
2630 | * @hw: the hardware that is performing scheduled scans | ||
2631 | */ | ||
2632 | void ieee80211_sched_scan_results(struct ieee80211_hw *hw); | ||
2633 | |||
2634 | /** | ||
2635 | * ieee80211_sched_scan_stopped - inform that the scheduled scan has stopped | ||
2636 | * | ||
2637 | * When a scheduled scan is running, this function can be called by | ||
2638 | * the driver if it needs to stop the scan to perform another task. | ||
2639 | * Usual scenarios are drivers that cannot continue the scheduled scan | ||
2640 | * while associating, for instance. | ||
2641 | * | ||
2642 | * @hw: the hardware that is performing scheduled scans | ||
2643 | */ | ||
2644 | void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw); | ||
2645 | |||
2646 | /** | ||
2581 | * ieee80211_iterate_active_interfaces - iterate active interfaces | 2647 | * ieee80211_iterate_active_interfaces - iterate active interfaces |
2582 | * | 2648 | * |
2583 | * This function iterates over the interfaces associated with a given | 2649 | * This function iterates over the interfaces associated with a given |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 7f5ad8a2b22d..3163330cd4f1 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -623,6 +623,23 @@ encrypt: | |||
623 | } | 623 | } |
624 | EXPORT_SYMBOL(hci_conn_security); | 624 | EXPORT_SYMBOL(hci_conn_security); |
625 | 625 | ||
626 | /* Check secure link requirement */ | ||
627 | int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level) | ||
628 | { | ||
629 | BT_DBG("conn %p", conn); | ||
630 | |||
631 | if (sec_level != BT_SECURITY_HIGH) | ||
632 | return 1; /* Accept if non-secure is required */ | ||
633 | |||
634 | if (conn->key_type == HCI_LK_AUTH_COMBINATION || | ||
635 | (conn->key_type == HCI_LK_COMBINATION && | ||
636 | conn->pin_length == 16)) | ||
637 | return 1; | ||
638 | |||
639 | return 0; /* Reject not secure link */ | ||
640 | } | ||
641 | EXPORT_SYMBOL(hci_conn_check_secure); | ||
642 | |||
626 | /* Change link key */ | 643 | /* Change link key */ |
627 | int hci_conn_change_link_key(struct hci_conn *conn) | 644 | int hci_conn_change_link_key(struct hci_conn *conn) |
628 | { | 645 | { |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d5aa97ee6ffa..f13ddbf858ba 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -1440,7 +1440,7 @@ static inline void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff | |||
1440 | 1440 | ||
1441 | conn->state = BT_CLOSED; | 1441 | conn->state = BT_CLOSED; |
1442 | 1442 | ||
1443 | if (conn->type == ACL_LINK) | 1443 | if (conn->type == ACL_LINK || conn->type == LE_LINK) |
1444 | mgmt_disconnected(hdev->id, &conn->dst); | 1444 | mgmt_disconnected(hdev->id, &conn->dst); |
1445 | 1445 | ||
1446 | hci_proto_disconn_cfm(conn, ev->reason); | 1446 | hci_proto_disconn_cfm(conn, ev->reason); |
@@ -2659,12 +2659,15 @@ static inline void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff | |||
2659 | } | 2659 | } |
2660 | 2660 | ||
2661 | if (ev->status) { | 2661 | if (ev->status) { |
2662 | mgmt_connect_failed(hdev->id, &ev->bdaddr, ev->status); | ||
2662 | hci_proto_connect_cfm(conn, ev->status); | 2663 | hci_proto_connect_cfm(conn, ev->status); |
2663 | conn->state = BT_CLOSED; | 2664 | conn->state = BT_CLOSED; |
2664 | hci_conn_del(conn); | 2665 | hci_conn_del(conn); |
2665 | goto unlock; | 2666 | goto unlock; |
2666 | } | 2667 | } |
2667 | 2668 | ||
2669 | mgmt_connected(hdev->id, &ev->bdaddr); | ||
2670 | |||
2668 | conn->handle = __le16_to_cpu(ev->handle); | 2671 | conn->handle = __le16_to_cpu(ev->handle); |
2669 | conn->state = BT_CONNECTED; | 2672 | conn->state = BT_CONNECTED; |
2670 | 2673 | ||
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a378acc491ec..4f3bc741183c 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -62,9 +62,8 @@ static u8 l2cap_fixed_chan[8] = { 0x02, }; | |||
62 | 62 | ||
63 | static struct workqueue_struct *_busy_wq; | 63 | static struct workqueue_struct *_busy_wq; |
64 | 64 | ||
65 | struct bt_sock_list l2cap_sk_list = { | 65 | LIST_HEAD(chan_list); |
66 | .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) | 66 | DEFINE_RWLOCK(chan_list_lock); |
67 | }; | ||
68 | 67 | ||
69 | static void l2cap_busy_work(struct work_struct *work); | 68 | static void l2cap_busy_work(struct work_struct *work); |
70 | 69 | ||
@@ -135,6 +134,64 @@ static inline struct l2cap_chan *l2cap_get_chan_by_ident(struct l2cap_conn *conn | |||
135 | return c; | 134 | return c; |
136 | } | 135 | } |
137 | 136 | ||
137 | static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) | ||
138 | { | ||
139 | struct l2cap_chan *c; | ||
140 | |||
141 | list_for_each_entry(c, &chan_list, global_l) { | ||
142 | if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) | ||
143 | goto found; | ||
144 | } | ||
145 | |||
146 | c = NULL; | ||
147 | found: | ||
148 | return c; | ||
149 | } | ||
150 | |||
151 | int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) | ||
152 | { | ||
153 | int err; | ||
154 | |||
155 | write_lock_bh(&chan_list_lock); | ||
156 | |||
157 | if (psm && __l2cap_global_chan_by_addr(psm, src)) { | ||
158 | err = -EADDRINUSE; | ||
159 | goto done; | ||
160 | } | ||
161 | |||
162 | if (psm) { | ||
163 | chan->psm = psm; | ||
164 | chan->sport = psm; | ||
165 | err = 0; | ||
166 | } else { | ||
167 | u16 p; | ||
168 | |||
169 | err = -EINVAL; | ||
170 | for (p = 0x1001; p < 0x1100; p += 2) | ||
171 | if (!__l2cap_global_chan_by_addr(cpu_to_le16(p), src)) { | ||
172 | chan->psm = cpu_to_le16(p); | ||
173 | chan->sport = cpu_to_le16(p); | ||
174 | err = 0; | ||
175 | break; | ||
176 | } | ||
177 | } | ||
178 | |||
179 | done: | ||
180 | write_unlock_bh(&chan_list_lock); | ||
181 | return err; | ||
182 | } | ||
183 | |||
184 | int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) | ||
185 | { | ||
186 | write_lock_bh(&chan_list_lock); | ||
187 | |||
188 | chan->scid = scid; | ||
189 | |||
190 | write_unlock_bh(&chan_list_lock); | ||
191 | |||
192 | return 0; | ||
193 | } | ||
194 | |||
138 | static u16 l2cap_alloc_cid(struct l2cap_conn *conn) | 195 | static u16 l2cap_alloc_cid(struct l2cap_conn *conn) |
139 | { | 196 | { |
140 | u16 cid = L2CAP_CID_DYN_START; | 197 | u16 cid = L2CAP_CID_DYN_START; |
@@ -147,7 +204,7 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn) | |||
147 | return 0; | 204 | return 0; |
148 | } | 205 | } |
149 | 206 | ||
150 | struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) | 207 | struct l2cap_chan *l2cap_chan_create(struct sock *sk) |
151 | { | 208 | { |
152 | struct l2cap_chan *chan; | 209 | struct l2cap_chan *chan; |
153 | 210 | ||
@@ -157,11 +214,19 @@ struct l2cap_chan *l2cap_chan_alloc(struct sock *sk) | |||
157 | 214 | ||
158 | chan->sk = sk; | 215 | chan->sk = sk; |
159 | 216 | ||
217 | write_lock_bh(&chan_list_lock); | ||
218 | list_add(&chan->global_l, &chan_list); | ||
219 | write_unlock_bh(&chan_list_lock); | ||
220 | |||
160 | return chan; | 221 | return chan; |
161 | } | 222 | } |
162 | 223 | ||
163 | void l2cap_chan_free(struct l2cap_chan *chan) | 224 | void l2cap_chan_destroy(struct l2cap_chan *chan) |
164 | { | 225 | { |
226 | write_lock_bh(&chan_list_lock); | ||
227 | list_del(&chan->global_l); | ||
228 | write_unlock_bh(&chan_list_lock); | ||
229 | |||
165 | kfree(chan); | 230 | kfree(chan); |
166 | } | 231 | } |
167 | 232 | ||
@@ -591,48 +656,51 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
591 | /* Find socket with cid and source bdaddr. | 656 | /* Find socket with cid and source bdaddr. |
592 | * Returns closest match, locked. | 657 | * Returns closest match, locked. |
593 | */ | 658 | */ |
594 | static struct sock *l2cap_get_sock_by_scid(int state, __le16 cid, bdaddr_t *src) | 659 | static struct l2cap_chan *l2cap_global_chan_by_scid(int state, __le16 cid, bdaddr_t *src) |
595 | { | 660 | { |
596 | struct sock *sk = NULL, *sk1 = NULL; | 661 | struct l2cap_chan *c, *c1 = NULL; |
597 | struct hlist_node *node; | ||
598 | 662 | ||
599 | read_lock(&l2cap_sk_list.lock); | 663 | read_lock(&chan_list_lock); |
600 | 664 | ||
601 | sk_for_each(sk, node, &l2cap_sk_list.head) { | 665 | list_for_each_entry(c, &chan_list, global_l) { |
602 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 666 | struct sock *sk = c->sk; |
603 | 667 | ||
604 | if (state && sk->sk_state != state) | 668 | if (state && sk->sk_state != state) |
605 | continue; | 669 | continue; |
606 | 670 | ||
607 | if (chan->scid == cid) { | 671 | if (c->scid == cid) { |
608 | /* Exact match. */ | 672 | /* Exact match. */ |
609 | if (!bacmp(&bt_sk(sk)->src, src)) | 673 | if (!bacmp(&bt_sk(sk)->src, src)) { |
610 | break; | 674 | read_unlock(&chan_list_lock); |
675 | return c; | ||
676 | } | ||
611 | 677 | ||
612 | /* Closest match */ | 678 | /* Closest match */ |
613 | if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) | 679 | if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) |
614 | sk1 = sk; | 680 | c1 = c; |
615 | } | 681 | } |
616 | } | 682 | } |
617 | 683 | ||
618 | read_unlock(&l2cap_sk_list.lock); | 684 | read_unlock(&chan_list_lock); |
619 | 685 | ||
620 | return node ? sk : sk1; | 686 | return c1; |
621 | } | 687 | } |
622 | 688 | ||
623 | static void l2cap_le_conn_ready(struct l2cap_conn *conn) | 689 | static void l2cap_le_conn_ready(struct l2cap_conn *conn) |
624 | { | 690 | { |
625 | struct sock *parent, *sk; | 691 | struct sock *parent, *sk; |
626 | struct l2cap_chan *chan; | 692 | struct l2cap_chan *chan, *pchan; |
627 | 693 | ||
628 | BT_DBG(""); | 694 | BT_DBG(""); |
629 | 695 | ||
630 | /* Check if we have socket listening on cid */ | 696 | /* Check if we have socket listening on cid */ |
631 | parent = l2cap_get_sock_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, | 697 | pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_LE_DATA, |
632 | conn->src); | 698 | conn->src); |
633 | if (!parent) | 699 | if (!pchan) |
634 | return; | 700 | return; |
635 | 701 | ||
702 | parent = pchan->sk; | ||
703 | |||
636 | bh_lock_sock(parent); | 704 | bh_lock_sock(parent); |
637 | 705 | ||
638 | /* Check for backlog size */ | 706 | /* Check for backlog size */ |
@@ -645,7 +713,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
645 | if (!sk) | 713 | if (!sk) |
646 | goto clean; | 714 | goto clean; |
647 | 715 | ||
648 | chan = l2cap_chan_alloc(sk); | 716 | chan = l2cap_chan_create(sk); |
649 | if (!chan) { | 717 | if (!chan) { |
650 | l2cap_sock_kill(sk); | 718 | l2cap_sock_kill(sk); |
651 | goto clean; | 719 | goto clean; |
@@ -823,33 +891,34 @@ static inline void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *ch | |||
823 | /* Find socket with psm and source bdaddr. | 891 | /* Find socket with psm and source bdaddr. |
824 | * Returns closest match. | 892 | * Returns closest match. |
825 | */ | 893 | */ |
826 | static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) | 894 | static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, bdaddr_t *src) |
827 | { | 895 | { |
828 | struct sock *sk = NULL, *sk1 = NULL; | 896 | struct l2cap_chan *c, *c1 = NULL; |
829 | struct hlist_node *node; | ||
830 | 897 | ||
831 | read_lock(&l2cap_sk_list.lock); | 898 | read_lock(&chan_list_lock); |
832 | 899 | ||
833 | sk_for_each(sk, node, &l2cap_sk_list.head) { | 900 | list_for_each_entry(c, &chan_list, global_l) { |
834 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 901 | struct sock *sk = c->sk; |
835 | 902 | ||
836 | if (state && sk->sk_state != state) | 903 | if (state && sk->sk_state != state) |
837 | continue; | 904 | continue; |
838 | 905 | ||
839 | if (chan->psm == psm) { | 906 | if (c->psm == psm) { |
840 | /* Exact match. */ | 907 | /* Exact match. */ |
841 | if (!bacmp(&bt_sk(sk)->src, src)) | 908 | if (!bacmp(&bt_sk(sk)->src, src)) { |
842 | break; | 909 | read_unlock_bh(&chan_list_lock); |
910 | return c; | ||
911 | } | ||
843 | 912 | ||
844 | /* Closest match */ | 913 | /* Closest match */ |
845 | if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) | 914 | if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) |
846 | sk1 = sk; | 915 | c1 = c; |
847 | } | 916 | } |
848 | } | 917 | } |
849 | 918 | ||
850 | read_unlock(&l2cap_sk_list.lock); | 919 | read_unlock(&chan_list_lock); |
851 | 920 | ||
852 | return node ? sk : sk1; | 921 | return c1; |
853 | } | 922 | } |
854 | 923 | ||
855 | int l2cap_chan_connect(struct l2cap_chan *chan) | 924 | int l2cap_chan_connect(struct l2cap_chan *chan) |
@@ -2019,7 +2088,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2019 | { | 2088 | { |
2020 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; | 2089 | struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; |
2021 | struct l2cap_conn_rsp rsp; | 2090 | struct l2cap_conn_rsp rsp; |
2022 | struct l2cap_chan *chan = NULL; | 2091 | struct l2cap_chan *chan = NULL, *pchan; |
2023 | struct sock *parent, *sk = NULL; | 2092 | struct sock *parent, *sk = NULL; |
2024 | int result, status = L2CAP_CS_NO_INFO; | 2093 | int result, status = L2CAP_CS_NO_INFO; |
2025 | 2094 | ||
@@ -2029,12 +2098,14 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2029 | BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); | 2098 | BT_DBG("psm 0x%2.2x scid 0x%4.4x", psm, scid); |
2030 | 2099 | ||
2031 | /* Check if we have socket listening on psm */ | 2100 | /* Check if we have socket listening on psm */ |
2032 | parent = l2cap_get_sock_by_psm(BT_LISTEN, psm, conn->src); | 2101 | pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src); |
2033 | if (!parent) { | 2102 | if (!pchan) { |
2034 | result = L2CAP_CR_BAD_PSM; | 2103 | result = L2CAP_CR_BAD_PSM; |
2035 | goto sendresp; | 2104 | goto sendresp; |
2036 | } | 2105 | } |
2037 | 2106 | ||
2107 | parent = pchan->sk; | ||
2108 | |||
2038 | bh_lock_sock(parent); | 2109 | bh_lock_sock(parent); |
2039 | 2110 | ||
2040 | /* Check if the ACL is secure enough (if not SDP) */ | 2111 | /* Check if the ACL is secure enough (if not SDP) */ |
@@ -2057,7 +2128,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2057 | if (!sk) | 2128 | if (!sk) |
2058 | goto response; | 2129 | goto response; |
2059 | 2130 | ||
2060 | chan = l2cap_chan_alloc(sk); | 2131 | chan = l2cap_chan_create(sk); |
2061 | if (!chan) { | 2132 | if (!chan) { |
2062 | l2cap_sock_kill(sk); | 2133 | l2cap_sock_kill(sk); |
2063 | goto response; | 2134 | goto response; |
@@ -3685,11 +3756,14 @@ done: | |||
3685 | static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) | 3756 | static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, struct sk_buff *skb) |
3686 | { | 3757 | { |
3687 | struct sock *sk; | 3758 | struct sock *sk; |
3759 | struct l2cap_chan *chan; | ||
3688 | 3760 | ||
3689 | sk = l2cap_get_sock_by_psm(0, psm, conn->src); | 3761 | chan = l2cap_global_chan_by_psm(0, psm, conn->src); |
3690 | if (!sk) | 3762 | if (!chan) |
3691 | goto drop; | 3763 | goto drop; |
3692 | 3764 | ||
3765 | sk = chan->sk; | ||
3766 | |||
3693 | bh_lock_sock(sk); | 3767 | bh_lock_sock(sk); |
3694 | 3768 | ||
3695 | BT_DBG("sk %p, len %d", sk, skb->len); | 3769 | BT_DBG("sk %p, len %d", sk, skb->len); |
@@ -3715,11 +3789,14 @@ done: | |||
3715 | static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb) | 3789 | static inline int l2cap_att_channel(struct l2cap_conn *conn, __le16 cid, struct sk_buff *skb) |
3716 | { | 3790 | { |
3717 | struct sock *sk; | 3791 | struct sock *sk; |
3792 | struct l2cap_chan *chan; | ||
3718 | 3793 | ||
3719 | sk = l2cap_get_sock_by_scid(0, cid, conn->src); | 3794 | chan = l2cap_global_chan_by_scid(0, cid, conn->src); |
3720 | if (!sk) | 3795 | if (!chan) |
3721 | goto drop; | 3796 | goto drop; |
3722 | 3797 | ||
3798 | sk = chan->sk; | ||
3799 | |||
3723 | bh_lock_sock(sk); | 3800 | bh_lock_sock(sk); |
3724 | 3801 | ||
3725 | BT_DBG("sk %p, len %d", sk, skb->len); | 3802 | BT_DBG("sk %p, len %d", sk, skb->len); |
@@ -3786,8 +3863,7 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) | |||
3786 | static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | 3863 | static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) |
3787 | { | 3864 | { |
3788 | int exact = 0, lm1 = 0, lm2 = 0; | 3865 | int exact = 0, lm1 = 0, lm2 = 0; |
3789 | register struct sock *sk; | 3866 | struct l2cap_chan *c; |
3790 | struct hlist_node *node; | ||
3791 | 3867 | ||
3792 | if (type != ACL_LINK) | 3868 | if (type != ACL_LINK) |
3793 | return -EINVAL; | 3869 | return -EINVAL; |
@@ -3795,25 +3871,25 @@ static int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | |||
3795 | BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); | 3871 | BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); |
3796 | 3872 | ||
3797 | /* Find listening sockets and check their link_mode */ | 3873 | /* Find listening sockets and check their link_mode */ |
3798 | read_lock(&l2cap_sk_list.lock); | 3874 | read_lock(&chan_list_lock); |
3799 | sk_for_each(sk, node, &l2cap_sk_list.head) { | 3875 | list_for_each_entry(c, &chan_list, global_l) { |
3800 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | 3876 | struct sock *sk = c->sk; |
3801 | 3877 | ||
3802 | if (sk->sk_state != BT_LISTEN) | 3878 | if (sk->sk_state != BT_LISTEN) |
3803 | continue; | 3879 | continue; |
3804 | 3880 | ||
3805 | if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { | 3881 | if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { |
3806 | lm1 |= HCI_LM_ACCEPT; | 3882 | lm1 |= HCI_LM_ACCEPT; |
3807 | if (chan->role_switch) | 3883 | if (c->role_switch) |
3808 | lm1 |= HCI_LM_MASTER; | 3884 | lm1 |= HCI_LM_MASTER; |
3809 | exact++; | 3885 | exact++; |
3810 | } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { | 3886 | } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { |
3811 | lm2 |= HCI_LM_ACCEPT; | 3887 | lm2 |= HCI_LM_ACCEPT; |
3812 | if (chan->role_switch) | 3888 | if (c->role_switch) |
3813 | lm2 |= HCI_LM_MASTER; | 3889 | lm2 |= HCI_LM_MASTER; |
3814 | } | 3890 | } |
3815 | } | 3891 | } |
3816 | read_unlock(&l2cap_sk_list.lock); | 3892 | read_unlock(&chan_list_lock); |
3817 | 3893 | ||
3818 | return exact ? lm1 : lm2; | 3894 | return exact ? lm1 : lm2; |
3819 | } | 3895 | } |
@@ -4066,25 +4142,22 @@ drop: | |||
4066 | 4142 | ||
4067 | static int l2cap_debugfs_show(struct seq_file *f, void *p) | 4143 | static int l2cap_debugfs_show(struct seq_file *f, void *p) |
4068 | { | 4144 | { |
4069 | struct sock *sk; | 4145 | struct l2cap_chan *c; |
4070 | struct hlist_node *node; | ||
4071 | 4146 | ||
4072 | read_lock_bh(&l2cap_sk_list.lock); | 4147 | read_lock_bh(&chan_list_lock); |
4073 | 4148 | ||
4074 | sk_for_each(sk, node, &l2cap_sk_list.head) { | 4149 | list_for_each_entry(c, &chan_list, global_l) { |
4075 | struct l2cap_pinfo *pi = l2cap_pi(sk); | 4150 | struct sock *sk = c->sk; |
4076 | struct l2cap_chan *chan = pi->chan; | ||
4077 | 4151 | ||
4078 | seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", | 4152 | seq_printf(f, "%s %s %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", |
4079 | batostr(&bt_sk(sk)->src), | 4153 | batostr(&bt_sk(sk)->src), |
4080 | batostr(&bt_sk(sk)->dst), | 4154 | batostr(&bt_sk(sk)->dst), |
4081 | sk->sk_state, __le16_to_cpu(chan->psm), | 4155 | sk->sk_state, __le16_to_cpu(c->psm), |
4082 | chan->scid, chan->dcid, | 4156 | c->scid, c->dcid, c->imtu, c->omtu, |
4083 | chan->imtu, chan->omtu, chan->sec_level, | 4157 | c->sec_level, c->mode); |
4084 | chan->mode); | ||
4085 | } | 4158 | } |
4086 | 4159 | ||
4087 | read_unlock_bh(&l2cap_sk_list.lock); | 4160 | read_unlock_bh(&chan_list_lock); |
4088 | 4161 | ||
4089 | return 0; | 4162 | return 0; |
4090 | } | 4163 | } |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 7c4a9ae9b3ce..18dc9888d8c2 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -78,22 +78,6 @@ void l2cap_sock_clear_timer(struct sock *sk) | |||
78 | sk_stop_timer(sk, &sk->sk_timer); | 78 | sk_stop_timer(sk, &sk->sk_timer); |
79 | } | 79 | } |
80 | 80 | ||
81 | static struct sock *__l2cap_get_sock_by_addr(__le16 psm, bdaddr_t *src) | ||
82 | { | ||
83 | struct sock *sk; | ||
84 | struct hlist_node *node; | ||
85 | sk_for_each(sk, node, &l2cap_sk_list.head) { | ||
86 | struct l2cap_chan *chan = l2cap_pi(sk)->chan; | ||
87 | |||
88 | if (chan->sport == psm && !bacmp(&bt_sk(sk)->src, src)) | ||
89 | goto found; | ||
90 | } | ||
91 | |||
92 | sk = NULL; | ||
93 | found: | ||
94 | return sk; | ||
95 | } | ||
96 | |||
97 | static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | 81 | static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) |
98 | { | 82 | { |
99 | struct sock *sk = sock->sk; | 83 | struct sock *sk = sock->sk; |
@@ -136,26 +120,20 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
136 | } | 120 | } |
137 | } | 121 | } |
138 | 122 | ||
139 | write_lock_bh(&l2cap_sk_list.lock); | 123 | if (la.l2_cid) |
124 | err = l2cap_add_scid(chan, la.l2_cid); | ||
125 | else | ||
126 | err = l2cap_add_psm(chan, &la.l2_bdaddr, la.l2_psm); | ||
140 | 127 | ||
141 | if (la.l2_psm && __l2cap_get_sock_by_addr(la.l2_psm, &la.l2_bdaddr)) { | 128 | if (err < 0) |
142 | err = -EADDRINUSE; | 129 | goto done; |
143 | } else { | ||
144 | /* Save source address */ | ||
145 | bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); | ||
146 | chan->psm = la.l2_psm; | ||
147 | chan->sport = la.l2_psm; | ||
148 | sk->sk_state = BT_BOUND; | ||
149 | |||
150 | if (__le16_to_cpu(la.l2_psm) == 0x0001 || | ||
151 | __le16_to_cpu(la.l2_psm) == 0x0003) | ||
152 | chan->sec_level = BT_SECURITY_SDP; | ||
153 | } | ||
154 | 130 | ||
155 | if (la.l2_cid) | 131 | if (__le16_to_cpu(la.l2_psm) == 0x0001 || |
156 | chan->scid = la.l2_cid; | 132 | __le16_to_cpu(la.l2_psm) == 0x0003) |
133 | chan->sec_level = BT_SECURITY_SDP; | ||
157 | 134 | ||
158 | write_unlock_bh(&l2cap_sk_list.lock); | 135 | bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); |
136 | sk->sk_state = BT_BOUND; | ||
159 | 137 | ||
160 | done: | 138 | done: |
161 | release_sock(sk); | 139 | release_sock(sk); |
@@ -278,28 +256,6 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) | |||
278 | goto done; | 256 | goto done; |
279 | } | 257 | } |
280 | 258 | ||
281 | if (!chan->psm && !chan->scid) { | ||
282 | bdaddr_t *src = &bt_sk(sk)->src; | ||
283 | u16 psm; | ||
284 | |||
285 | err = -EINVAL; | ||
286 | |||
287 | write_lock_bh(&l2cap_sk_list.lock); | ||
288 | |||
289 | for (psm = 0x1001; psm < 0x1100; psm += 2) | ||
290 | if (!__l2cap_get_sock_by_addr(cpu_to_le16(psm), src)) { | ||
291 | chan->psm = cpu_to_le16(psm); | ||
292 | chan->sport = cpu_to_le16(psm); | ||
293 | err = 0; | ||
294 | break; | ||
295 | } | ||
296 | |||
297 | write_unlock_bh(&l2cap_sk_list.lock); | ||
298 | |||
299 | if (err < 0) | ||
300 | goto done; | ||
301 | } | ||
302 | |||
303 | sk->sk_max_ack_backlog = backlog; | 259 | sk->sk_max_ack_backlog = backlog; |
304 | sk->sk_ack_backlog = 0; | 260 | sk->sk_ack_backlog = 0; |
305 | sk->sk_state = BT_LISTEN; | 261 | sk->sk_state = BT_LISTEN; |
@@ -852,8 +808,7 @@ void l2cap_sock_kill(struct sock *sk) | |||
852 | 808 | ||
853 | /* Kill poor orphan */ | 809 | /* Kill poor orphan */ |
854 | 810 | ||
855 | l2cap_chan_free(l2cap_pi(sk)->chan); | 811 | l2cap_chan_destroy(l2cap_pi(sk)->chan); |
856 | bt_sock_unlink(&l2cap_sk_list, sk); | ||
857 | sock_set_flag(sk, SOCK_DEAD); | 812 | sock_set_flag(sk, SOCK_DEAD); |
858 | sock_put(sk); | 813 | sock_put(sk); |
859 | } | 814 | } |
@@ -1069,7 +1024,6 @@ struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, g | |||
1069 | 1024 | ||
1070 | setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk); | 1025 | setup_timer(&sk->sk_timer, l2cap_sock_timeout, (unsigned long) sk); |
1071 | 1026 | ||
1072 | bt_sock_link(&l2cap_sk_list, sk); | ||
1073 | return sk; | 1027 | return sk; |
1074 | } | 1028 | } |
1075 | 1029 | ||
@@ -1096,7 +1050,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, | |||
1096 | if (!sk) | 1050 | if (!sk) |
1097 | return -ENOMEM; | 1051 | return -ENOMEM; |
1098 | 1052 | ||
1099 | chan = l2cap_chan_alloc(sk); | 1053 | chan = l2cap_chan_create(sk); |
1100 | if (!chan) { | 1054 | if (!chan) { |
1101 | l2cap_sock_kill(sk); | 1055 | l2cap_sock_kill(sk); |
1102 | return -ENOMEM; | 1056 | return -ENOMEM; |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 2481d257ed98..dae382ce7020 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -1033,6 +1033,9 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len) | |||
1033 | } | 1033 | } |
1034 | 1034 | ||
1035 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); | 1035 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); |
1036 | if (!conn) | ||
1037 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr); | ||
1038 | |||
1036 | if (!conn) { | 1039 | if (!conn) { |
1037 | err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENOTCONN); | 1040 | err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENOTCONN); |
1038 | goto failed; | 1041 | goto failed; |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 121a5c13b989..5759bb7054f7 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -2096,7 +2096,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) | |||
2096 | if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags)) | 2096 | if (!test_and_clear_bit(RFCOMM_AUTH_PENDING, &d->flags)) |
2097 | continue; | 2097 | continue; |
2098 | 2098 | ||
2099 | if (!status) | 2099 | if (!status && hci_conn_check_secure(conn, d->sec_level)) |
2100 | set_bit(RFCOMM_AUTH_ACCEPT, &d->flags); | 2100 | set_bit(RFCOMM_AUTH_ACCEPT, &d->flags); |
2101 | else | 2101 | else |
2102 | set_bit(RFCOMM_AUTH_REJECT, &d->flags); | 2102 | set_bit(RFCOMM_AUTH_REJECT, &d->flags); |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 0c9d0c07eae6..9c0d76cdca92 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -63,7 +63,8 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
63 | 63 | ||
64 | lockdep_assert_held(&sta->ampdu_mlme.mtx); | 64 | lockdep_assert_held(&sta->ampdu_mlme.mtx); |
65 | 65 | ||
66 | tid_rx = sta->ampdu_mlme.tid_rx[tid]; | 66 | tid_rx = rcu_dereference_protected(sta->ampdu_mlme.tid_rx[tid], |
67 | lockdep_is_held(&sta->ampdu_mlme.mtx)); | ||
67 | 68 | ||
68 | if (!tid_rx) | 69 | if (!tid_rx) |
69 | return; | 70 | return; |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 63d852cb4ca2..cd5125f77cc5 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -136,6 +136,14 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 | |||
136 | ieee80211_tx_skb(sdata, skb); | 136 | ieee80211_tx_skb(sdata, skb); |
137 | } | 137 | } |
138 | 138 | ||
139 | void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, | ||
140 | struct tid_ampdu_tx *tid_tx) | ||
141 | { | ||
142 | lockdep_assert_held(&sta->ampdu_mlme.mtx); | ||
143 | lockdep_assert_held(&sta->lock); | ||
144 | rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx); | ||
145 | } | ||
146 | |||
139 | static void kfree_tid_tx(struct rcu_head *rcu_head) | 147 | static void kfree_tid_tx(struct rcu_head *rcu_head) |
140 | { | 148 | { |
141 | struct tid_ampdu_tx *tid_tx = | 149 | struct tid_ampdu_tx *tid_tx = |
@@ -149,19 +157,22 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
149 | bool tx) | 157 | bool tx) |
150 | { | 158 | { |
151 | struct ieee80211_local *local = sta->local; | 159 | struct ieee80211_local *local = sta->local; |
152 | struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 160 | struct tid_ampdu_tx *tid_tx; |
153 | int ret; | 161 | int ret; |
154 | 162 | ||
155 | lockdep_assert_held(&sta->ampdu_mlme.mtx); | 163 | lockdep_assert_held(&sta->ampdu_mlme.mtx); |
156 | 164 | ||
157 | if (!tid_tx) | ||
158 | return -ENOENT; | ||
159 | |||
160 | spin_lock_bh(&sta->lock); | 165 | spin_lock_bh(&sta->lock); |
161 | 166 | ||
167 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | ||
168 | if (!tid_tx) { | ||
169 | spin_unlock_bh(&sta->lock); | ||
170 | return -ENOENT; | ||
171 | } | ||
172 | |||
162 | if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { | 173 | if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { |
163 | /* not even started yet! */ | 174 | /* not even started yet! */ |
164 | rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); | 175 | ieee80211_assign_tid_tx(sta, tid, NULL); |
165 | spin_unlock_bh(&sta->lock); | 176 | spin_unlock_bh(&sta->lock); |
166 | call_rcu(&tid_tx->rcu_head, kfree_tid_tx); | 177 | call_rcu(&tid_tx->rcu_head, kfree_tid_tx); |
167 | return 0; | 178 | return 0; |
@@ -283,13 +294,13 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) | |||
283 | 294 | ||
284 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | 295 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) |
285 | { | 296 | { |
286 | struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 297 | struct tid_ampdu_tx *tid_tx; |
287 | struct ieee80211_local *local = sta->local; | 298 | struct ieee80211_local *local = sta->local; |
288 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 299 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
289 | u16 start_seq_num; | 300 | u16 start_seq_num; |
290 | int ret; | 301 | int ret; |
291 | 302 | ||
292 | lockdep_assert_held(&sta->ampdu_mlme.mtx); | 303 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
293 | 304 | ||
294 | /* | 305 | /* |
295 | * While we're asking the driver about the aggregation, | 306 | * While we're asking the driver about the aggregation, |
@@ -318,7 +329,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
318 | " tid %d\n", tid); | 329 | " tid %d\n", tid); |
319 | #endif | 330 | #endif |
320 | spin_lock_bh(&sta->lock); | 331 | spin_lock_bh(&sta->lock); |
321 | rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); | 332 | ieee80211_assign_tid_tx(sta, tid, NULL); |
322 | spin_unlock_bh(&sta->lock); | 333 | spin_unlock_bh(&sta->lock); |
323 | 334 | ||
324 | ieee80211_wake_queue_agg(local, tid); | 335 | ieee80211_wake_queue_agg(local, tid); |
@@ -396,9 +407,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
396 | goto err_unlock_sta; | 407 | goto err_unlock_sta; |
397 | } | 408 | } |
398 | 409 | ||
399 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 410 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
400 | /* check if the TID is not in aggregation flow already */ | 411 | /* check if the TID is not in aggregation flow already */ |
401 | if (tid_tx) { | 412 | if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) { |
402 | #ifdef CONFIG_MAC80211_HT_DEBUG | 413 | #ifdef CONFIG_MAC80211_HT_DEBUG |
403 | printk(KERN_DEBUG "BA request denied - session is not " | 414 | printk(KERN_DEBUG "BA request denied - session is not " |
404 | "idle on tid %u\n", tid); | 415 | "idle on tid %u\n", tid); |
@@ -433,8 +444,11 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
433 | sta->ampdu_mlme.dialog_token_allocator++; | 444 | sta->ampdu_mlme.dialog_token_allocator++; |
434 | tid_tx->dialog_token = sta->ampdu_mlme.dialog_token_allocator; | 445 | tid_tx->dialog_token = sta->ampdu_mlme.dialog_token_allocator; |
435 | 446 | ||
436 | /* finally, assign it to the array */ | 447 | /* |
437 | rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx); | 448 | * Finally, assign it to the start array; the work item will |
449 | * collect it and move it to the normal array. | ||
450 | */ | ||
451 | sta->ampdu_mlme.tid_start_tx[tid] = tid_tx; | ||
438 | 452 | ||
439 | ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work); | 453 | ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work); |
440 | 454 | ||
@@ -480,16 +494,19 @@ ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) | |||
480 | static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | 494 | static void ieee80211_agg_tx_operational(struct ieee80211_local *local, |
481 | struct sta_info *sta, u16 tid) | 495 | struct sta_info *sta, u16 tid) |
482 | { | 496 | { |
497 | struct tid_ampdu_tx *tid_tx; | ||
498 | |||
483 | lockdep_assert_held(&sta->ampdu_mlme.mtx); | 499 | lockdep_assert_held(&sta->ampdu_mlme.mtx); |
484 | 500 | ||
501 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | ||
502 | |||
485 | #ifdef CONFIG_MAC80211_HT_DEBUG | 503 | #ifdef CONFIG_MAC80211_HT_DEBUG |
486 | printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid); | 504 | printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid); |
487 | #endif | 505 | #endif |
488 | 506 | ||
489 | drv_ampdu_action(local, sta->sdata, | 507 | drv_ampdu_action(local, sta->sdata, |
490 | IEEE80211_AMPDU_TX_OPERATIONAL, | 508 | IEEE80211_AMPDU_TX_OPERATIONAL, |
491 | &sta->sta, tid, NULL, | 509 | &sta->sta, tid, NULL, tid_tx->buf_size); |
492 | sta->ampdu_mlme.tid_tx[tid]->buf_size); | ||
493 | 510 | ||
494 | /* | 511 | /* |
495 | * synchronize with TX path, while splicing the TX path | 512 | * synchronize with TX path, while splicing the TX path |
@@ -497,13 +514,13 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
497 | */ | 514 | */ |
498 | spin_lock_bh(&sta->lock); | 515 | spin_lock_bh(&sta->lock); |
499 | 516 | ||
500 | ieee80211_agg_splice_packets(local, sta->ampdu_mlme.tid_tx[tid], tid); | 517 | ieee80211_agg_splice_packets(local, tid_tx, tid); |
501 | /* | 518 | /* |
502 | * Now mark as operational. This will be visible | 519 | * Now mark as operational. This will be visible |
503 | * in the TX path, and lets it go lock-free in | 520 | * in the TX path, and lets it go lock-free in |
504 | * the common case. | 521 | * the common case. |
505 | */ | 522 | */ |
506 | set_bit(HT_AGG_STATE_OPERATIONAL, &sta->ampdu_mlme.tid_tx[tid]->state); | 523 | set_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); |
507 | ieee80211_agg_splice_finish(local, tid); | 524 | ieee80211_agg_splice_finish(local, tid); |
508 | 525 | ||
509 | spin_unlock_bh(&sta->lock); | 526 | spin_unlock_bh(&sta->lock); |
@@ -537,7 +554,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | |||
537 | } | 554 | } |
538 | 555 | ||
539 | mutex_lock(&sta->ampdu_mlme.mtx); | 556 | mutex_lock(&sta->ampdu_mlme.mtx); |
540 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 557 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
541 | 558 | ||
542 | if (WARN_ON(!tid_tx)) { | 559 | if (WARN_ON(!tid_tx)) { |
543 | #ifdef CONFIG_MAC80211_HT_DEBUG | 560 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -615,7 +632,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
615 | return -EINVAL; | 632 | return -EINVAL; |
616 | 633 | ||
617 | spin_lock_bh(&sta->lock); | 634 | spin_lock_bh(&sta->lock); |
618 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 635 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
619 | 636 | ||
620 | if (!tid_tx) { | 637 | if (!tid_tx) { |
621 | ret = -ENOENT; | 638 | ret = -ENOENT; |
@@ -671,7 +688,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
671 | 688 | ||
672 | mutex_lock(&sta->ampdu_mlme.mtx); | 689 | mutex_lock(&sta->ampdu_mlme.mtx); |
673 | spin_lock_bh(&sta->lock); | 690 | spin_lock_bh(&sta->lock); |
674 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 691 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
675 | 692 | ||
676 | if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { | 693 | if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { |
677 | #ifdef CONFIG_MAC80211_HT_DEBUG | 694 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -697,7 +714,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
697 | ieee80211_agg_splice_packets(local, tid_tx, tid); | 714 | ieee80211_agg_splice_packets(local, tid_tx, tid); |
698 | 715 | ||
699 | /* future packets must not find the tid_tx struct any more */ | 716 | /* future packets must not find the tid_tx struct any more */ |
700 | rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); | 717 | ieee80211_assign_tid_tx(sta, tid, NULL); |
701 | 718 | ||
702 | ieee80211_agg_splice_finish(local, tid); | 719 | ieee80211_agg_splice_finish(local, tid); |
703 | 720 | ||
@@ -752,7 +769,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
752 | 769 | ||
753 | mutex_lock(&sta->ampdu_mlme.mtx); | 770 | mutex_lock(&sta->ampdu_mlme.mtx); |
754 | 771 | ||
755 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 772 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
756 | if (!tid_tx) | 773 | if (!tid_tx) |
757 | goto out; | 774 | goto out; |
758 | 775 | ||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 12d52cec9515..be70c70d3f5b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -136,7 +136,10 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
136 | mutex_lock(&sdata->local->sta_mtx); | 136 | mutex_lock(&sdata->local->sta_mtx); |
137 | 137 | ||
138 | if (mac_addr) { | 138 | if (mac_addr) { |
139 | sta = sta_info_get_bss(sdata, mac_addr); | 139 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
140 | sta = sta_info_get(sdata, mac_addr); | ||
141 | else | ||
142 | sta = sta_info_get_bss(sdata, mac_addr); | ||
140 | if (!sta) { | 143 | if (!sta) { |
141 | ieee80211_key_free(sdata->local, key); | 144 | ieee80211_key_free(sdata->local, key); |
142 | err = -ENOENT; | 145 | err = -ENOENT; |
@@ -157,13 +160,14 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, | |||
157 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | 160 | static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, |
158 | u8 key_idx, bool pairwise, const u8 *mac_addr) | 161 | u8 key_idx, bool pairwise, const u8 *mac_addr) |
159 | { | 162 | { |
160 | struct ieee80211_sub_if_data *sdata; | 163 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
164 | struct ieee80211_local *local = sdata->local; | ||
161 | struct sta_info *sta; | 165 | struct sta_info *sta; |
166 | struct ieee80211_key *key = NULL; | ||
162 | int ret; | 167 | int ret; |
163 | 168 | ||
164 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 169 | mutex_lock(&local->sta_mtx); |
165 | 170 | mutex_lock(&local->key_mtx); | |
166 | mutex_lock(&sdata->local->sta_mtx); | ||
167 | 171 | ||
168 | if (mac_addr) { | 172 | if (mac_addr) { |
169 | ret = -ENOENT; | 173 | ret = -ENOENT; |
@@ -172,33 +176,24 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev, | |||
172 | if (!sta) | 176 | if (!sta) |
173 | goto out_unlock; | 177 | goto out_unlock; |
174 | 178 | ||
175 | if (pairwise) { | 179 | if (pairwise) |
176 | if (sta->ptk) { | 180 | key = key_mtx_dereference(local, sta->ptk); |
177 | ieee80211_key_free(sdata->local, sta->ptk); | 181 | else |
178 | ret = 0; | 182 | key = key_mtx_dereference(local, sta->gtk[key_idx]); |
179 | } | 183 | } else |
180 | } else { | 184 | key = key_mtx_dereference(local, sdata->keys[key_idx]); |
181 | if (sta->gtk[key_idx]) { | ||
182 | ieee80211_key_free(sdata->local, | ||
183 | sta->gtk[key_idx]); | ||
184 | ret = 0; | ||
185 | } | ||
186 | } | ||
187 | |||
188 | goto out_unlock; | ||
189 | } | ||
190 | 185 | ||
191 | if (!sdata->keys[key_idx]) { | 186 | if (!key) { |
192 | ret = -ENOENT; | 187 | ret = -ENOENT; |
193 | goto out_unlock; | 188 | goto out_unlock; |
194 | } | 189 | } |
195 | 190 | ||
196 | ieee80211_key_free(sdata->local, sdata->keys[key_idx]); | 191 | __ieee80211_key_free(key); |
197 | WARN_ON(sdata->keys[key_idx]); | ||
198 | 192 | ||
199 | ret = 0; | 193 | ret = 0; |
200 | out_unlock: | 194 | out_unlock: |
201 | mutex_unlock(&sdata->local->sta_mtx); | 195 | mutex_unlock(&local->key_mtx); |
196 | mutex_unlock(&local->sta_mtx); | ||
202 | 197 | ||
203 | return ret; | 198 | return ret; |
204 | } | 199 | } |
@@ -228,11 +223,11 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev, | |||
228 | goto out; | 223 | goto out; |
229 | 224 | ||
230 | if (pairwise) | 225 | if (pairwise) |
231 | key = sta->ptk; | 226 | key = rcu_dereference(sta->ptk); |
232 | else if (key_idx < NUM_DEFAULT_KEYS) | 227 | else if (key_idx < NUM_DEFAULT_KEYS) |
233 | key = sta->gtk[key_idx]; | 228 | key = rcu_dereference(sta->gtk[key_idx]); |
234 | } else | 229 | } else |
235 | key = sdata->keys[key_idx]; | 230 | key = rcu_dereference(sdata->keys[key_idx]); |
236 | 231 | ||
237 | if (!key) | 232 | if (!key) |
238 | goto out; | 233 | goto out; |
@@ -468,7 +463,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
468 | int size; | 463 | int size; |
469 | int err = -EINVAL; | 464 | int err = -EINVAL; |
470 | 465 | ||
471 | old = sdata->u.ap.beacon; | 466 | old = rtnl_dereference(sdata->u.ap.beacon); |
472 | 467 | ||
473 | /* head must not be zero-length */ | 468 | /* head must not be zero-length */ |
474 | if (params->head && !params->head_len) | 469 | if (params->head && !params->head_len) |
@@ -563,8 +558,7 @@ static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
563 | 558 | ||
564 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 559 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
565 | 560 | ||
566 | old = sdata->u.ap.beacon; | 561 | old = rtnl_dereference(sdata->u.ap.beacon); |
567 | |||
568 | if (old) | 562 | if (old) |
569 | return -EALREADY; | 563 | return -EALREADY; |
570 | 564 | ||
@@ -579,8 +573,7 @@ static int ieee80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
579 | 573 | ||
580 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 574 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
581 | 575 | ||
582 | old = sdata->u.ap.beacon; | 576 | old = rtnl_dereference(sdata->u.ap.beacon); |
583 | |||
584 | if (!old) | 577 | if (!old) |
585 | return -ENOENT; | 578 | return -ENOENT; |
586 | 579 | ||
@@ -594,8 +587,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | |||
594 | 587 | ||
595 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 588 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
596 | 589 | ||
597 | old = sdata->u.ap.beacon; | 590 | old = rtnl_dereference(sdata->u.ap.beacon); |
598 | |||
599 | if (!old) | 591 | if (!old) |
600 | return -ENOENT; | 592 | return -ENOENT; |
601 | 593 | ||
@@ -734,15 +726,29 @@ static void sta_apply_parameters(struct ieee80211_local *local, | |||
734 | params->ht_capa, | 726 | params->ht_capa, |
735 | &sta->sta.ht_cap); | 727 | &sta->sta.ht_cap); |
736 | 728 | ||
737 | if (ieee80211_vif_is_mesh(&sdata->vif) && params->plink_action) { | 729 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
738 | switch (params->plink_action) { | 730 | #ifdef CONFIG_MAC80211_MESH |
739 | case PLINK_ACTION_OPEN: | 731 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_SECURED) |
740 | mesh_plink_open(sta); | 732 | switch (params->plink_state) { |
741 | break; | 733 | case NL80211_PLINK_LISTEN: |
742 | case PLINK_ACTION_BLOCK: | 734 | case NL80211_PLINK_ESTAB: |
743 | mesh_plink_block(sta); | 735 | case NL80211_PLINK_BLOCKED: |
744 | break; | 736 | sta->plink_state = params->plink_state; |
745 | } | 737 | break; |
738 | default: | ||
739 | /* nothing */ | ||
740 | break; | ||
741 | } | ||
742 | else | ||
743 | switch (params->plink_action) { | ||
744 | case PLINK_ACTION_OPEN: | ||
745 | mesh_plink_open(sta); | ||
746 | break; | ||
747 | case PLINK_ACTION_BLOCK: | ||
748 | mesh_plink_block(sta); | ||
749 | break; | ||
750 | } | ||
751 | #endif | ||
746 | } | 752 | } |
747 | } | 753 | } |
748 | 754 | ||
@@ -943,8 +949,10 @@ static int ieee80211_change_mpath(struct wiphy *wiphy, | |||
943 | static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, | 949 | static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop, |
944 | struct mpath_info *pinfo) | 950 | struct mpath_info *pinfo) |
945 | { | 951 | { |
946 | if (mpath->next_hop) | 952 | struct sta_info *next_hop_sta = rcu_dereference(mpath->next_hop); |
947 | memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); | 953 | |
954 | if (next_hop_sta) | ||
955 | memcpy(next_hop, next_hop_sta->sta.addr, ETH_ALEN); | ||
948 | else | 956 | else |
949 | memset(next_hop, 0, ETH_ALEN); | 957 | memset(next_hop, 0, ETH_ALEN); |
950 | 958 | ||
@@ -1064,7 +1072,11 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, | |||
1064 | memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); | 1072 | memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); |
1065 | ifmsh->mesh_pp_id = setup->path_sel_proto; | 1073 | ifmsh->mesh_pp_id = setup->path_sel_proto; |
1066 | ifmsh->mesh_pm_id = setup->path_metric; | 1074 | ifmsh->mesh_pm_id = setup->path_metric; |
1067 | ifmsh->is_secure = setup->is_secure; | 1075 | ifmsh->security = IEEE80211_MESH_SEC_NONE; |
1076 | if (setup->is_authenticated) | ||
1077 | ifmsh->security |= IEEE80211_MESH_SEC_AUTHED; | ||
1078 | if (setup->is_secure) | ||
1079 | ifmsh->security |= IEEE80211_MESH_SEC_SECURED; | ||
1068 | 1080 | ||
1069 | return 0; | 1081 | return 0; |
1070 | } | 1082 | } |
@@ -1297,9 +1309,10 @@ static int ieee80211_set_channel(struct wiphy *wiphy, | |||
1297 | } | 1309 | } |
1298 | 1310 | ||
1299 | #ifdef CONFIG_PM | 1311 | #ifdef CONFIG_PM |
1300 | static int ieee80211_suspend(struct wiphy *wiphy) | 1312 | static int ieee80211_suspend(struct wiphy *wiphy, |
1313 | struct cfg80211_wowlan *wowlan) | ||
1301 | { | 1314 | { |
1302 | return __ieee80211_suspend(wiphy_priv(wiphy)); | 1315 | return __ieee80211_suspend(wiphy_priv(wiphy), wowlan); |
1303 | } | 1316 | } |
1304 | 1317 | ||
1305 | static int ieee80211_resume(struct wiphy *wiphy) | 1318 | static int ieee80211_resume(struct wiphy *wiphy) |
@@ -1342,6 +1355,30 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1342 | return ieee80211_request_scan(sdata, req); | 1355 | return ieee80211_request_scan(sdata, req); |
1343 | } | 1356 | } |
1344 | 1357 | ||
1358 | static int | ||
1359 | ieee80211_sched_scan_start(struct wiphy *wiphy, | ||
1360 | struct net_device *dev, | ||
1361 | struct cfg80211_sched_scan_request *req) | ||
1362 | { | ||
1363 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1364 | |||
1365 | if (!sdata->local->ops->sched_scan_start) | ||
1366 | return -EOPNOTSUPP; | ||
1367 | |||
1368 | return ieee80211_request_sched_scan_start(sdata, req); | ||
1369 | } | ||
1370 | |||
1371 | static int | ||
1372 | ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev) | ||
1373 | { | ||
1374 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1375 | |||
1376 | if (!sdata->local->ops->sched_scan_stop) | ||
1377 | return -EOPNOTSUPP; | ||
1378 | |||
1379 | return ieee80211_request_sched_scan_stop(sdata); | ||
1380 | } | ||
1381 | |||
1345 | static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, | 1382 | static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev, |
1346 | struct cfg80211_auth_request *req) | 1383 | struct cfg80211_auth_request *req) |
1347 | { | 1384 | { |
@@ -2083,6 +2120,8 @@ struct cfg80211_ops mac80211_config_ops = { | |||
2083 | .suspend = ieee80211_suspend, | 2120 | .suspend = ieee80211_suspend, |
2084 | .resume = ieee80211_resume, | 2121 | .resume = ieee80211_resume, |
2085 | .scan = ieee80211_scan, | 2122 | .scan = ieee80211_scan, |
2123 | .sched_scan_start = ieee80211_sched_scan_start, | ||
2124 | .sched_scan_stop = ieee80211_sched_scan_stop, | ||
2086 | .auth = ieee80211_auth, | 2125 | .auth = ieee80211_auth, |
2087 | .assoc = ieee80211_assoc, | 2126 | .assoc = ieee80211_assoc, |
2088 | .deauth = ieee80211_deauth, | 2127 | .deauth = ieee80211_deauth, |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index 0a602dbfdb2b..186e02f7cc32 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -135,7 +135,7 @@ static ssize_t reset_write(struct file *file, const char __user *user_buf, | |||
135 | struct ieee80211_local *local = file->private_data; | 135 | struct ieee80211_local *local = file->private_data; |
136 | 136 | ||
137 | rtnl_lock(); | 137 | rtnl_lock(); |
138 | __ieee80211_suspend(&local->hw); | 138 | __ieee80211_suspend(&local->hw, NULL); |
139 | __ieee80211_resume(&local->hw); | 139 | __ieee80211_resume(&local->hw); |
140 | rtnl_unlock(); | 140 | rtnl_unlock(); |
141 | 141 | ||
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index f7ef3477c24a..33c58b85c911 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c | |||
@@ -241,16 +241,12 @@ void ieee80211_debugfs_key_add(struct ieee80211_key *key) | |||
241 | if (!key->debugfs.dir) | 241 | if (!key->debugfs.dir) |
242 | return; | 242 | return; |
243 | 243 | ||
244 | rcu_read_lock(); | 244 | sta = key->sta; |
245 | sta = rcu_dereference(key->sta); | 245 | if (sta) { |
246 | if (sta) | ||
247 | sprintf(buf, "../../stations/%pM", sta->sta.addr); | 246 | sprintf(buf, "../../stations/%pM", sta->sta.addr); |
248 | rcu_read_unlock(); | ||
249 | |||
250 | /* using sta as a boolean is fine outside RCU lock */ | ||
251 | if (sta) | ||
252 | key->debugfs.stalink = | 247 | key->debugfs.stalink = |
253 | debugfs_create_symlink("station", key->debugfs.dir, buf); | 248 | debugfs_create_symlink("station", key->debugfs.dir, buf); |
249 | } | ||
254 | 250 | ||
255 | DEBUGFS_ADD(keylen); | 251 | DEBUGFS_ADD(keylen); |
256 | DEBUGFS_ADD(flags); | 252 | DEBUGFS_ADD(flags); |
@@ -286,7 +282,8 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) | |||
286 | lockdep_assert_held(&sdata->local->key_mtx); | 282 | lockdep_assert_held(&sdata->local->key_mtx); |
287 | 283 | ||
288 | if (sdata->default_unicast_key) { | 284 | if (sdata->default_unicast_key) { |
289 | key = sdata->default_unicast_key; | 285 | key = key_mtx_dereference(sdata->local, |
286 | sdata->default_unicast_key); | ||
290 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | 287 | sprintf(buf, "../keys/%d", key->debugfs.cnt); |
291 | sdata->debugfs.default_unicast_key = | 288 | sdata->debugfs.default_unicast_key = |
292 | debugfs_create_symlink("default_unicast_key", | 289 | debugfs_create_symlink("default_unicast_key", |
@@ -297,7 +294,8 @@ void ieee80211_debugfs_key_update_default(struct ieee80211_sub_if_data *sdata) | |||
297 | } | 294 | } |
298 | 295 | ||
299 | if (sdata->default_multicast_key) { | 296 | if (sdata->default_multicast_key) { |
300 | key = sdata->default_multicast_key; | 297 | key = key_mtx_dereference(sdata->local, |
298 | sdata->default_multicast_key); | ||
301 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | 299 | sprintf(buf, "../keys/%d", key->debugfs.cnt); |
302 | sdata->debugfs.default_multicast_key = | 300 | sdata->debugfs.default_multicast_key = |
303 | debugfs_create_symlink("default_multicast_key", | 301 | debugfs_create_symlink("default_multicast_key", |
@@ -316,9 +314,8 @@ void ieee80211_debugfs_key_add_mgmt_default(struct ieee80211_sub_if_data *sdata) | |||
316 | if (!sdata->debugfs.dir) | 314 | if (!sdata->debugfs.dir) |
317 | return; | 315 | return; |
318 | 316 | ||
319 | /* this is running under the key lock */ | 317 | key = key_mtx_dereference(sdata->local, |
320 | 318 | sdata->default_mgmt_key); | |
321 | key = sdata->default_mgmt_key; | ||
322 | if (key) { | 319 | if (key) { |
323 | sprintf(buf, "../keys/%d", key->debugfs.cnt); | 320 | sprintf(buf, "../keys/%d", key->debugfs.cnt); |
324 | sdata->debugfs.default_mgmt_key = | 321 | sdata->debugfs.default_mgmt_key = |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 2ddb56e5b51f..eebf7a67daf7 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -41,6 +41,33 @@ static inline void drv_stop(struct ieee80211_local *local) | |||
41 | local->started = false; | 41 | local->started = false; |
42 | } | 42 | } |
43 | 43 | ||
44 | #ifdef CONFIG_PM | ||
45 | static inline int drv_suspend(struct ieee80211_local *local, | ||
46 | struct cfg80211_wowlan *wowlan) | ||
47 | { | ||
48 | int ret; | ||
49 | |||
50 | might_sleep(); | ||
51 | |||
52 | trace_drv_suspend(local); | ||
53 | ret = local->ops->suspend(&local->hw, wowlan); | ||
54 | trace_drv_return_int(local, ret); | ||
55 | return ret; | ||
56 | } | ||
57 | |||
58 | static inline int drv_resume(struct ieee80211_local *local) | ||
59 | { | ||
60 | int ret; | ||
61 | |||
62 | might_sleep(); | ||
63 | |||
64 | trace_drv_resume(local); | ||
65 | ret = local->ops->resume(&local->hw); | ||
66 | trace_drv_return_int(local, ret); | ||
67 | return ret; | ||
68 | } | ||
69 | #endif | ||
70 | |||
44 | static inline int drv_add_interface(struct ieee80211_local *local, | 71 | static inline int drv_add_interface(struct ieee80211_local *local, |
45 | struct ieee80211_vif *vif) | 72 | struct ieee80211_vif *vif) |
46 | { | 73 | { |
@@ -185,12 +212,39 @@ static inline int drv_hw_scan(struct ieee80211_local *local, | |||
185 | 212 | ||
186 | might_sleep(); | 213 | might_sleep(); |
187 | 214 | ||
188 | trace_drv_hw_scan(local, sdata, req); | 215 | trace_drv_hw_scan(local, sdata); |
189 | ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); | 216 | ret = local->ops->hw_scan(&local->hw, &sdata->vif, req); |
190 | trace_drv_return_int(local, ret); | 217 | trace_drv_return_int(local, ret); |
191 | return ret; | 218 | return ret; |
192 | } | 219 | } |
193 | 220 | ||
221 | static inline int | ||
222 | drv_sched_scan_start(struct ieee80211_local *local, | ||
223 | struct ieee80211_sub_if_data *sdata, | ||
224 | struct cfg80211_sched_scan_request *req, | ||
225 | struct ieee80211_sched_scan_ies *ies) | ||
226 | { | ||
227 | int ret; | ||
228 | |||
229 | might_sleep(); | ||
230 | |||
231 | trace_drv_sched_scan_start(local, sdata); | ||
232 | ret = local->ops->sched_scan_start(&local->hw, &sdata->vif, | ||
233 | req, ies); | ||
234 | trace_drv_return_int(local, ret); | ||
235 | return ret; | ||
236 | } | ||
237 | |||
238 | static inline void drv_sched_scan_stop(struct ieee80211_local *local, | ||
239 | struct ieee80211_sub_if_data *sdata) | ||
240 | { | ||
241 | might_sleep(); | ||
242 | |||
243 | trace_drv_sched_scan_stop(local, sdata); | ||
244 | local->ops->sched_scan_stop(&local->hw, &sdata->vif); | ||
245 | trace_drv_return_void(local); | ||
246 | } | ||
247 | |||
194 | static inline void drv_sw_scan_start(struct ieee80211_local *local) | 248 | static inline void drv_sw_scan_start(struct ieee80211_local *local) |
195 | { | 249 | { |
196 | might_sleep(); | 250 | might_sleep(); |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 191e834ec46b..ed9edcbd9aa5 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -55,6 +55,70 @@ DECLARE_EVENT_CLASS(local_only_evt, | |||
55 | TP_printk(LOCAL_PR_FMT, LOCAL_PR_ARG) | 55 | TP_printk(LOCAL_PR_FMT, LOCAL_PR_ARG) |
56 | ); | 56 | ); |
57 | 57 | ||
58 | DECLARE_EVENT_CLASS(local_sdata_addr_evt, | ||
59 | TP_PROTO(struct ieee80211_local *local, | ||
60 | struct ieee80211_sub_if_data *sdata), | ||
61 | TP_ARGS(local, sdata), | ||
62 | |||
63 | TP_STRUCT__entry( | ||
64 | LOCAL_ENTRY | ||
65 | VIF_ENTRY | ||
66 | __array(char, addr, 6) | ||
67 | ), | ||
68 | |||
69 | TP_fast_assign( | ||
70 | LOCAL_ASSIGN; | ||
71 | VIF_ASSIGN; | ||
72 | memcpy(__entry->addr, sdata->vif.addr, 6); | ||
73 | ), | ||
74 | |||
75 | TP_printk( | ||
76 | LOCAL_PR_FMT VIF_PR_FMT " addr:%pM", | ||
77 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr | ||
78 | ) | ||
79 | ); | ||
80 | |||
81 | DECLARE_EVENT_CLASS(local_u32_evt, | ||
82 | TP_PROTO(struct ieee80211_local *local, u32 value), | ||
83 | TP_ARGS(local, value), | ||
84 | |||
85 | TP_STRUCT__entry( | ||
86 | LOCAL_ENTRY | ||
87 | __field(u32, value) | ||
88 | ), | ||
89 | |||
90 | TP_fast_assign( | ||
91 | LOCAL_ASSIGN; | ||
92 | __entry->value = value; | ||
93 | ), | ||
94 | |||
95 | TP_printk( | ||
96 | LOCAL_PR_FMT " value:%d", | ||
97 | LOCAL_PR_ARG, __entry->value | ||
98 | ) | ||
99 | ); | ||
100 | |||
101 | DECLARE_EVENT_CLASS(local_sdata_evt, | ||
102 | TP_PROTO(struct ieee80211_local *local, | ||
103 | struct ieee80211_sub_if_data *sdata), | ||
104 | TP_ARGS(local, sdata), | ||
105 | |||
106 | TP_STRUCT__entry( | ||
107 | LOCAL_ENTRY | ||
108 | VIF_ENTRY | ||
109 | ), | ||
110 | |||
111 | TP_fast_assign( | ||
112 | LOCAL_ASSIGN; | ||
113 | VIF_ASSIGN; | ||
114 | ), | ||
115 | |||
116 | TP_printk( | ||
117 | LOCAL_PR_FMT VIF_PR_FMT, | ||
118 | LOCAL_PR_ARG, VIF_PR_ARG | ||
119 | ) | ||
120 | ); | ||
121 | |||
58 | DEFINE_EVENT(local_only_evt, drv_return_void, | 122 | DEFINE_EVENT(local_only_evt, drv_return_void, |
59 | TP_PROTO(struct ieee80211_local *local), | 123 | TP_PROTO(struct ieee80211_local *local), |
60 | TP_ARGS(local) | 124 | TP_ARGS(local) |
@@ -108,33 +172,25 @@ DEFINE_EVENT(local_only_evt, drv_start, | |||
108 | TP_ARGS(local) | 172 | TP_ARGS(local) |
109 | ); | 173 | ); |
110 | 174 | ||
175 | DEFINE_EVENT(local_only_evt, drv_suspend, | ||
176 | TP_PROTO(struct ieee80211_local *local), | ||
177 | TP_ARGS(local) | ||
178 | ); | ||
179 | |||
180 | DEFINE_EVENT(local_only_evt, drv_resume, | ||
181 | TP_PROTO(struct ieee80211_local *local), | ||
182 | TP_ARGS(local) | ||
183 | ); | ||
184 | |||
111 | DEFINE_EVENT(local_only_evt, drv_stop, | 185 | DEFINE_EVENT(local_only_evt, drv_stop, |
112 | TP_PROTO(struct ieee80211_local *local), | 186 | TP_PROTO(struct ieee80211_local *local), |
113 | TP_ARGS(local) | 187 | TP_ARGS(local) |
114 | ); | 188 | ); |
115 | 189 | ||
116 | TRACE_EVENT(drv_add_interface, | 190 | DEFINE_EVENT(local_sdata_addr_evt, drv_add_interface, |
117 | TP_PROTO(struct ieee80211_local *local, | 191 | TP_PROTO(struct ieee80211_local *local, |
118 | struct ieee80211_sub_if_data *sdata), | 192 | struct ieee80211_sub_if_data *sdata), |
119 | 193 | TP_ARGS(local, sdata) | |
120 | TP_ARGS(local, sdata), | ||
121 | |||
122 | TP_STRUCT__entry( | ||
123 | LOCAL_ENTRY | ||
124 | VIF_ENTRY | ||
125 | __array(char, addr, 6) | ||
126 | ), | ||
127 | |||
128 | TP_fast_assign( | ||
129 | LOCAL_ASSIGN; | ||
130 | VIF_ASSIGN; | ||
131 | memcpy(__entry->addr, sdata->vif.addr, 6); | ||
132 | ), | ||
133 | |||
134 | TP_printk( | ||
135 | LOCAL_PR_FMT VIF_PR_FMT " addr:%pM", | ||
136 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr | ||
137 | ) | ||
138 | ); | 194 | ); |
139 | 195 | ||
140 | TRACE_EVENT(drv_change_interface, | 196 | TRACE_EVENT(drv_change_interface, |
@@ -165,27 +221,10 @@ TRACE_EVENT(drv_change_interface, | |||
165 | ) | 221 | ) |
166 | ); | 222 | ); |
167 | 223 | ||
168 | TRACE_EVENT(drv_remove_interface, | 224 | DEFINE_EVENT(local_sdata_addr_evt, drv_remove_interface, |
169 | TP_PROTO(struct ieee80211_local *local, struct ieee80211_sub_if_data *sdata), | 225 | TP_PROTO(struct ieee80211_local *local, |
170 | 226 | struct ieee80211_sub_if_data *sdata), | |
171 | TP_ARGS(local, sdata), | 227 | TP_ARGS(local, sdata) |
172 | |||
173 | TP_STRUCT__entry( | ||
174 | LOCAL_ENTRY | ||
175 | VIF_ENTRY | ||
176 | __array(char, addr, 6) | ||
177 | ), | ||
178 | |||
179 | TP_fast_assign( | ||
180 | LOCAL_ASSIGN; | ||
181 | VIF_ASSIGN; | ||
182 | memcpy(__entry->addr, sdata->vif.addr, 6); | ||
183 | ), | ||
184 | |||
185 | TP_printk( | ||
186 | LOCAL_PR_FMT VIF_PR_FMT " addr:%pM", | ||
187 | LOCAL_PR_ARG, VIF_PR_ARG, __entry->addr | ||
188 | ) | ||
189 | ); | 228 | ); |
190 | 229 | ||
191 | TRACE_EVENT(drv_config, | 230 | TRACE_EVENT(drv_config, |
@@ -415,27 +454,22 @@ TRACE_EVENT(drv_update_tkip_key, | |||
415 | ) | 454 | ) |
416 | ); | 455 | ); |
417 | 456 | ||
418 | TRACE_EVENT(drv_hw_scan, | 457 | DEFINE_EVENT(local_sdata_evt, drv_hw_scan, |
419 | TP_PROTO(struct ieee80211_local *local, | 458 | TP_PROTO(struct ieee80211_local *local, |
420 | struct ieee80211_sub_if_data *sdata, | 459 | struct ieee80211_sub_if_data *sdata), |
421 | struct cfg80211_scan_request *req), | 460 | TP_ARGS(local, sdata) |
422 | 461 | ); | |
423 | TP_ARGS(local, sdata, req), | ||
424 | |||
425 | TP_STRUCT__entry( | ||
426 | LOCAL_ENTRY | ||
427 | VIF_ENTRY | ||
428 | ), | ||
429 | 462 | ||
430 | TP_fast_assign( | 463 | DEFINE_EVENT(local_sdata_evt, drv_sched_scan_start, |
431 | LOCAL_ASSIGN; | 464 | TP_PROTO(struct ieee80211_local *local, |
432 | VIF_ASSIGN; | 465 | struct ieee80211_sub_if_data *sdata), |
433 | ), | 466 | TP_ARGS(local, sdata) |
467 | ); | ||
434 | 468 | ||
435 | TP_printk( | 469 | DEFINE_EVENT(local_sdata_evt, drv_sched_scan_stop, |
436 | LOCAL_PR_FMT VIF_PR_FMT, | 470 | TP_PROTO(struct ieee80211_local *local, |
437 | LOCAL_PR_ARG,VIF_PR_ARG | 471 | struct ieee80211_sub_if_data *sdata), |
438 | ) | 472 | TP_ARGS(local, sdata) |
439 | ); | 473 | ); |
440 | 474 | ||
441 | DEFINE_EVENT(local_only_evt, drv_sw_scan_start, | 475 | DEFINE_EVENT(local_only_evt, drv_sw_scan_start, |
@@ -504,46 +538,14 @@ TRACE_EVENT(drv_get_tkip_seq, | |||
504 | ) | 538 | ) |
505 | ); | 539 | ); |
506 | 540 | ||
507 | TRACE_EVENT(drv_set_frag_threshold, | 541 | DEFINE_EVENT(local_u32_evt, drv_set_frag_threshold, |
508 | TP_PROTO(struct ieee80211_local *local, u32 value), | 542 | TP_PROTO(struct ieee80211_local *local, u32 value), |
509 | 543 | TP_ARGS(local, value) | |
510 | TP_ARGS(local, value), | ||
511 | |||
512 | TP_STRUCT__entry( | ||
513 | LOCAL_ENTRY | ||
514 | __field(u32, value) | ||
515 | ), | ||
516 | |||
517 | TP_fast_assign( | ||
518 | LOCAL_ASSIGN; | ||
519 | __entry->value = value; | ||
520 | ), | ||
521 | |||
522 | TP_printk( | ||
523 | LOCAL_PR_FMT " value:%d", | ||
524 | LOCAL_PR_ARG, __entry->value | ||
525 | ) | ||
526 | ); | 544 | ); |
527 | 545 | ||
528 | TRACE_EVENT(drv_set_rts_threshold, | 546 | DEFINE_EVENT(local_u32_evt, drv_set_rts_threshold, |
529 | TP_PROTO(struct ieee80211_local *local, u32 value), | 547 | TP_PROTO(struct ieee80211_local *local, u32 value), |
530 | 548 | TP_ARGS(local, value) | |
531 | TP_ARGS(local, value), | ||
532 | |||
533 | TP_STRUCT__entry( | ||
534 | LOCAL_ENTRY | ||
535 | __field(u32, value) | ||
536 | ), | ||
537 | |||
538 | TP_fast_assign( | ||
539 | LOCAL_ASSIGN; | ||
540 | __entry->value = value; | ||
541 | ), | ||
542 | |||
543 | TP_printk( | ||
544 | LOCAL_PR_FMT " value:%d", | ||
545 | LOCAL_PR_ARG, __entry->value | ||
546 | ) | ||
547 | ); | 549 | ); |
548 | 550 | ||
549 | TRACE_EVENT(drv_set_coverage_class, | 551 | TRACE_EVENT(drv_set_coverage_class, |
@@ -1194,6 +1196,42 @@ TRACE_EVENT(api_scan_completed, | |||
1194 | ) | 1196 | ) |
1195 | ); | 1197 | ); |
1196 | 1198 | ||
1199 | TRACE_EVENT(api_sched_scan_results, | ||
1200 | TP_PROTO(struct ieee80211_local *local), | ||
1201 | |||
1202 | TP_ARGS(local), | ||
1203 | |||
1204 | TP_STRUCT__entry( | ||
1205 | LOCAL_ENTRY | ||
1206 | ), | ||
1207 | |||
1208 | TP_fast_assign( | ||
1209 | LOCAL_ASSIGN; | ||
1210 | ), | ||
1211 | |||
1212 | TP_printk( | ||
1213 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
1214 | ) | ||
1215 | ); | ||
1216 | |||
1217 | TRACE_EVENT(api_sched_scan_stopped, | ||
1218 | TP_PROTO(struct ieee80211_local *local), | ||
1219 | |||
1220 | TP_ARGS(local), | ||
1221 | |||
1222 | TP_STRUCT__entry( | ||
1223 | LOCAL_ENTRY | ||
1224 | ), | ||
1225 | |||
1226 | TP_fast_assign( | ||
1227 | LOCAL_ASSIGN; | ||
1228 | ), | ||
1229 | |||
1230 | TP_printk( | ||
1231 | LOCAL_PR_FMT, LOCAL_PR_ARG | ||
1232 | ) | ||
1233 | ); | ||
1234 | |||
1197 | TRACE_EVENT(api_sta_block_awake, | 1235 | TRACE_EVENT(api_sta_block_awake, |
1198 | TP_PROTO(struct ieee80211_local *local, | 1236 | TP_PROTO(struct ieee80211_local *local, |
1199 | struct ieee80211_sta *sta, bool block), | 1237 | struct ieee80211_sta *sta, bool block), |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index b9e4b9bd2179..591add22bcc0 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -140,14 +140,29 @@ void ieee80211_ba_session_work(struct work_struct *work) | |||
140 | sta, tid, WLAN_BACK_RECIPIENT, | 140 | sta, tid, WLAN_BACK_RECIPIENT, |
141 | WLAN_REASON_QSTA_TIMEOUT, true); | 141 | WLAN_REASON_QSTA_TIMEOUT, true); |
142 | 142 | ||
143 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 143 | tid_tx = sta->ampdu_mlme.tid_start_tx[tid]; |
144 | if (!tid_tx) | 144 | if (tid_tx) { |
145 | continue; | 145 | /* |
146 | * Assign it over to the normal tid_tx array | ||
147 | * where it "goes live". | ||
148 | */ | ||
149 | spin_lock_bh(&sta->lock); | ||
150 | |||
151 | sta->ampdu_mlme.tid_start_tx[tid] = NULL; | ||
152 | /* could there be a race? */ | ||
153 | if (sta->ampdu_mlme.tid_tx[tid]) | ||
154 | kfree(tid_tx); | ||
155 | else | ||
156 | ieee80211_assign_tid_tx(sta, tid, tid_tx); | ||
157 | spin_unlock_bh(&sta->lock); | ||
146 | 158 | ||
147 | if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) | ||
148 | ieee80211_tx_ba_session_handle_start(sta, tid); | 159 | ieee80211_tx_ba_session_handle_start(sta, tid); |
149 | else if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP, | 160 | continue; |
150 | &tid_tx->state)) | 161 | } |
162 | |||
163 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | ||
164 | if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP, | ||
165 | &tid_tx->state)) | ||
151 | ___ieee80211_stop_tx_ba_session(sta, tid, | 166 | ___ieee80211_stop_tx_ba_session(sta, tid, |
152 | WLAN_BACK_INITIATOR, | 167 | WLAN_BACK_INITIATOR, |
153 | true); | 168 | true); |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index b81860c94698..421eaa6b0c2b 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -662,12 +662,16 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
662 | int tx_last_beacon, len = req->len; | 662 | int tx_last_beacon, len = req->len; |
663 | struct sk_buff *skb; | 663 | struct sk_buff *skb; |
664 | struct ieee80211_mgmt *resp; | 664 | struct ieee80211_mgmt *resp; |
665 | struct sk_buff *presp; | ||
665 | u8 *pos, *end; | 666 | u8 *pos, *end; |
666 | 667 | ||
667 | lockdep_assert_held(&ifibss->mtx); | 668 | lockdep_assert_held(&ifibss->mtx); |
668 | 669 | ||
670 | presp = rcu_dereference_protected(ifibss->presp, | ||
671 | lockdep_is_held(&ifibss->mtx)); | ||
672 | |||
669 | if (ifibss->state != IEEE80211_IBSS_MLME_JOINED || | 673 | if (ifibss->state != IEEE80211_IBSS_MLME_JOINED || |
670 | len < 24 + 2 || !ifibss->presp) | 674 | len < 24 + 2 || !presp) |
671 | return; | 675 | return; |
672 | 676 | ||
673 | tx_last_beacon = drv_tx_last_beacon(local); | 677 | tx_last_beacon = drv_tx_last_beacon(local); |
@@ -705,7 +709,7 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
705 | } | 709 | } |
706 | 710 | ||
707 | /* Reply with ProbeResp */ | 711 | /* Reply with ProbeResp */ |
708 | skb = skb_copy(ifibss->presp, GFP_KERNEL); | 712 | skb = skb_copy(presp, GFP_KERNEL); |
709 | if (!skb) | 713 | if (!skb) |
710 | return; | 714 | return; |
711 | 715 | ||
@@ -985,7 +989,8 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) | |||
985 | 989 | ||
986 | /* remove beacon */ | 990 | /* remove beacon */ |
987 | kfree(sdata->u.ibss.ie); | 991 | kfree(sdata->u.ibss.ie); |
988 | skb = sdata->u.ibss.presp; | 992 | skb = rcu_dereference_protected(sdata->u.ibss.presp, |
993 | lockdep_is_held(&sdata->u.ibss.mtx)); | ||
989 | rcu_assign_pointer(sdata->u.ibss.presp, NULL); | 994 | rcu_assign_pointer(sdata->u.ibss.presp, NULL); |
990 | sdata->vif.bss_conf.ibss_joined = false; | 995 | sdata->vif.bss_conf.ibss_joined = false; |
991 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | | 996 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED | |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 027c0467d7a3..2025af52b195 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -214,7 +214,7 @@ struct beacon_data { | |||
214 | }; | 214 | }; |
215 | 215 | ||
216 | struct ieee80211_if_ap { | 216 | struct ieee80211_if_ap { |
217 | struct beacon_data *beacon; | 217 | struct beacon_data __rcu *beacon; |
218 | 218 | ||
219 | struct list_head vlans; | 219 | struct list_head vlans; |
220 | 220 | ||
@@ -237,7 +237,7 @@ struct ieee80211_if_vlan { | |||
237 | struct list_head list; | 237 | struct list_head list; |
238 | 238 | ||
239 | /* used for all tx if the VLAN is configured to 4-addr mode */ | 239 | /* used for all tx if the VLAN is configured to 4-addr mode */ |
240 | struct sta_info *sta; | 240 | struct sta_info __rcu *sta; |
241 | }; | 241 | }; |
242 | 242 | ||
243 | struct mesh_stats { | 243 | struct mesh_stats { |
@@ -442,7 +442,8 @@ struct ieee80211_if_ibss { | |||
442 | 442 | ||
443 | unsigned long ibss_join_req; | 443 | unsigned long ibss_join_req; |
444 | /* probe response/beacon for IBSS */ | 444 | /* probe response/beacon for IBSS */ |
445 | struct sk_buff *presp, *skb; | 445 | struct sk_buff __rcu *presp; |
446 | struct sk_buff *skb; | ||
446 | 447 | ||
447 | enum { | 448 | enum { |
448 | IEEE80211_IBSS_MLME_SEARCH, | 449 | IEEE80211_IBSS_MLME_SEARCH, |
@@ -490,7 +491,11 @@ struct ieee80211_if_mesh { | |||
490 | bool accepting_plinks; | 491 | bool accepting_plinks; |
491 | const u8 *ie; | 492 | const u8 *ie; |
492 | u8 ie_len; | 493 | u8 ie_len; |
493 | bool is_secure; | 494 | enum { |
495 | IEEE80211_MESH_SEC_NONE = 0x0, | ||
496 | IEEE80211_MESH_SEC_AUTHED = 0x1, | ||
497 | IEEE80211_MESH_SEC_SECURED = 0x2, | ||
498 | } security; | ||
494 | }; | 499 | }; |
495 | 500 | ||
496 | #ifdef CONFIG_MAC80211_MESH | 501 | #ifdef CONFIG_MAC80211_MESH |
@@ -563,9 +568,10 @@ struct ieee80211_sub_if_data { | |||
563 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; | 568 | struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; |
564 | unsigned int fragment_next; | 569 | unsigned int fragment_next; |
565 | 570 | ||
566 | struct ieee80211_key *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; | 571 | struct ieee80211_key __rcu *keys[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; |
567 | struct ieee80211_key *default_unicast_key, *default_multicast_key; | 572 | struct ieee80211_key __rcu *default_unicast_key; |
568 | struct ieee80211_key *default_mgmt_key; | 573 | struct ieee80211_key __rcu *default_multicast_key; |
574 | struct ieee80211_key __rcu *default_mgmt_key; | ||
569 | 575 | ||
570 | u16 sequence_number; | 576 | u16 sequence_number; |
571 | __be16 control_port_protocol; | 577 | __be16 control_port_protocol; |
@@ -764,6 +770,9 @@ struct ieee80211_local { | |||
764 | /* device is started */ | 770 | /* device is started */ |
765 | bool started; | 771 | bool started; |
766 | 772 | ||
773 | /* wowlan is enabled -- don't reconfig on resume */ | ||
774 | bool wowlan; | ||
775 | |||
767 | int tx_headroom; /* required headroom for hardware/radiotap */ | 776 | int tx_headroom; /* required headroom for hardware/radiotap */ |
768 | 777 | ||
769 | /* count for keys needing tailroom space allocation */ | 778 | /* count for keys needing tailroom space allocation */ |
@@ -798,7 +807,7 @@ struct ieee80211_local { | |||
798 | spinlock_t sta_lock; | 807 | spinlock_t sta_lock; |
799 | unsigned long num_sta; | 808 | unsigned long num_sta; |
800 | struct list_head sta_list, sta_pending_list; | 809 | struct list_head sta_list, sta_pending_list; |
801 | struct sta_info *sta_hash[STA_HASH_SIZE]; | 810 | struct sta_info __rcu *sta_hash[STA_HASH_SIZE]; |
802 | struct timer_list sta_cleanup; | 811 | struct timer_list sta_cleanup; |
803 | struct work_struct sta_finish_work; | 812 | struct work_struct sta_finish_work; |
804 | int sta_generation; | 813 | int sta_generation; |
@@ -840,6 +849,10 @@ struct ieee80211_local { | |||
840 | int scan_channel_idx; | 849 | int scan_channel_idx; |
841 | int scan_ies_len; | 850 | int scan_ies_len; |
842 | 851 | ||
852 | bool sched_scanning; | ||
853 | struct ieee80211_sched_scan_ies sched_scan_ies; | ||
854 | struct work_struct sched_scan_stopped_work; | ||
855 | |||
843 | unsigned long leave_oper_channel_time; | 856 | unsigned long leave_oper_channel_time; |
844 | enum mac80211_scan_state next_scan_state; | 857 | enum mac80211_scan_state next_scan_state; |
845 | struct delayed_work scan_work; | 858 | struct delayed_work scan_work; |
@@ -1147,6 +1160,12 @@ ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, | |||
1147 | void ieee80211_rx_bss_put(struct ieee80211_local *local, | 1160 | void ieee80211_rx_bss_put(struct ieee80211_local *local, |
1148 | struct ieee80211_bss *bss); | 1161 | struct ieee80211_bss *bss); |
1149 | 1162 | ||
1163 | /* scheduled scan handling */ | ||
1164 | int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | ||
1165 | struct cfg80211_sched_scan_request *req); | ||
1166 | int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); | ||
1167 | void ieee80211_sched_scan_stopped_work(struct work_struct *work); | ||
1168 | |||
1150 | /* off-channel helpers */ | 1169 | /* off-channel helpers */ |
1151 | bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local); | 1170 | bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local); |
1152 | void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, | 1171 | void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, |
@@ -1250,7 +1269,8 @@ int ieee80211_reconfig(struct ieee80211_local *local); | |||
1250 | void ieee80211_stop_device(struct ieee80211_local *local); | 1269 | void ieee80211_stop_device(struct ieee80211_local *local); |
1251 | 1270 | ||
1252 | #ifdef CONFIG_PM | 1271 | #ifdef CONFIG_PM |
1253 | int __ieee80211_suspend(struct ieee80211_hw *hw); | 1272 | int __ieee80211_suspend(struct ieee80211_hw *hw, |
1273 | struct cfg80211_wowlan *wowlan); | ||
1254 | 1274 | ||
1255 | static inline int __ieee80211_resume(struct ieee80211_hw *hw) | 1275 | static inline int __ieee80211_resume(struct ieee80211_hw *hw) |
1256 | { | 1276 | { |
@@ -1263,7 +1283,8 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw) | |||
1263 | return ieee80211_reconfig(hw_to_local(hw)); | 1283 | return ieee80211_reconfig(hw_to_local(hw)); |
1264 | } | 1284 | } |
1265 | #else | 1285 | #else |
1266 | static inline int __ieee80211_suspend(struct ieee80211_hw *hw) | 1286 | static inline int __ieee80211_suspend(struct ieee80211_hw *hw, |
1287 | struct cfg80211_wowlan *wowlan) | ||
1267 | { | 1288 | { |
1268 | return 0; | 1289 | return 0; |
1269 | } | 1290 | } |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 80c29d626aa4..7dfbe71dc637 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -449,7 +449,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
449 | /* APs need special treatment */ | 449 | /* APs need special treatment */ |
450 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 450 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
451 | struct ieee80211_sub_if_data *vlan, *tmpsdata; | 451 | struct ieee80211_sub_if_data *vlan, *tmpsdata; |
452 | struct beacon_data *old_beacon = sdata->u.ap.beacon; | 452 | struct beacon_data *old_beacon = |
453 | rtnl_dereference(sdata->u.ap.beacon); | ||
453 | 454 | ||
454 | /* sdata_running will return false, so this will disable */ | 455 | /* sdata_running will return false, so this will disable */ |
455 | ieee80211_bss_info_change_notify(sdata, | 456 | ieee80211_bss_info_change_notify(sdata, |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index b510721e3b3d..31afd712930d 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -195,7 +195,7 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, | |||
195 | assert_key_lock(sdata->local); | 195 | assert_key_lock(sdata->local); |
196 | 196 | ||
197 | if (idx >= 0 && idx < NUM_DEFAULT_KEYS) | 197 | if (idx >= 0 && idx < NUM_DEFAULT_KEYS) |
198 | key = sdata->keys[idx]; | 198 | key = key_mtx_dereference(sdata->local, sdata->keys[idx]); |
199 | 199 | ||
200 | if (uni) | 200 | if (uni) |
201 | rcu_assign_pointer(sdata->default_unicast_key, key); | 201 | rcu_assign_pointer(sdata->default_unicast_key, key); |
@@ -222,7 +222,7 @@ __ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx) | |||
222 | 222 | ||
223 | if (idx >= NUM_DEFAULT_KEYS && | 223 | if (idx >= NUM_DEFAULT_KEYS && |
224 | idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) | 224 | idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) |
225 | key = sdata->keys[idx]; | 225 | key = key_mtx_dereference(sdata->local, sdata->keys[idx]); |
226 | 226 | ||
227 | rcu_assign_pointer(sdata->default_mgmt_key, key); | 227 | rcu_assign_pointer(sdata->default_mgmt_key, key); |
228 | 228 | ||
@@ -266,9 +266,15 @@ static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata, | |||
266 | else | 266 | else |
267 | idx = new->conf.keyidx; | 267 | idx = new->conf.keyidx; |
268 | 268 | ||
269 | defunikey = old && sdata->default_unicast_key == old; | 269 | defunikey = old && |
270 | defmultikey = old && sdata->default_multicast_key == old; | 270 | old == key_mtx_dereference(sdata->local, |
271 | defmgmtkey = old && sdata->default_mgmt_key == old; | 271 | sdata->default_unicast_key); |
272 | defmultikey = old && | ||
273 | old == key_mtx_dereference(sdata->local, | ||
274 | sdata->default_multicast_key); | ||
275 | defmgmtkey = old && | ||
276 | old == key_mtx_dereference(sdata->local, | ||
277 | sdata->default_mgmt_key); | ||
272 | 278 | ||
273 | if (defunikey && !new) | 279 | if (defunikey && !new) |
274 | __ieee80211_set_default_key(sdata, -1, true, false); | 280 | __ieee80211_set_default_key(sdata, -1, true, false); |
@@ -451,11 +457,11 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
451 | mutex_lock(&sdata->local->key_mtx); | 457 | mutex_lock(&sdata->local->key_mtx); |
452 | 458 | ||
453 | if (sta && pairwise) | 459 | if (sta && pairwise) |
454 | old_key = sta->ptk; | 460 | old_key = key_mtx_dereference(sdata->local, sta->ptk); |
455 | else if (sta) | 461 | else if (sta) |
456 | old_key = sta->gtk[idx]; | 462 | old_key = key_mtx_dereference(sdata->local, sta->gtk[idx]); |
457 | else | 463 | else |
458 | old_key = sdata->keys[idx]; | 464 | old_key = key_mtx_dereference(sdata->local, sdata->keys[idx]); |
459 | 465 | ||
460 | __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); | 466 | __ieee80211_key_replace(sdata, sta, pairwise, old_key, key); |
461 | __ieee80211_key_destroy(old_key); | 467 | __ieee80211_key_destroy(old_key); |
@@ -471,8 +477,11 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
471 | return ret; | 477 | return ret; |
472 | } | 478 | } |
473 | 479 | ||
474 | static void __ieee80211_key_free(struct ieee80211_key *key) | 480 | void __ieee80211_key_free(struct ieee80211_key *key) |
475 | { | 481 | { |
482 | if (!key) | ||
483 | return; | ||
484 | |||
476 | /* | 485 | /* |
477 | * Replace key with nothingness if it was ever used. | 486 | * Replace key with nothingness if it was ever used. |
478 | */ | 487 | */ |
@@ -486,9 +495,6 @@ static void __ieee80211_key_free(struct ieee80211_key *key) | |||
486 | void ieee80211_key_free(struct ieee80211_local *local, | 495 | void ieee80211_key_free(struct ieee80211_local *local, |
487 | struct ieee80211_key *key) | 496 | struct ieee80211_key *key) |
488 | { | 497 | { |
489 | if (!key) | ||
490 | return; | ||
491 | |||
492 | mutex_lock(&local->key_mtx); | 498 | mutex_lock(&local->key_mtx); |
493 | __ieee80211_key_free(key); | 499 | __ieee80211_key_free(key); |
494 | mutex_unlock(&local->key_mtx); | 500 | mutex_unlock(&local->key_mtx); |
diff --git a/net/mac80211/key.h b/net/mac80211/key.h index 4ddbe27eb570..d801d5351336 100644 --- a/net/mac80211/key.h +++ b/net/mac80211/key.h | |||
@@ -135,6 +135,7 @@ struct ieee80211_key *ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | |||
135 | int __must_check ieee80211_key_link(struct ieee80211_key *key, | 135 | int __must_check ieee80211_key_link(struct ieee80211_key *key, |
136 | struct ieee80211_sub_if_data *sdata, | 136 | struct ieee80211_sub_if_data *sdata, |
137 | struct sta_info *sta); | 137 | struct sta_info *sta); |
138 | void __ieee80211_key_free(struct ieee80211_key *key); | ||
138 | void ieee80211_key_free(struct ieee80211_local *local, | 139 | void ieee80211_key_free(struct ieee80211_local *local, |
139 | struct ieee80211_key *key); | 140 | struct ieee80211_key *key); |
140 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, | 141 | void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx, |
@@ -145,4 +146,7 @@ void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata); | |||
145 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); | 146 | void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata); |
146 | void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata); | 147 | void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata); |
147 | 148 | ||
149 | #define key_mtx_dereference(local, ref) \ | ||
150 | rcu_dereference_protected(ref, lockdep_is_held(&((local)->key_mtx))) | ||
151 | |||
148 | #endif /* IEEE80211_KEY_H */ | 152 | #endif /* IEEE80211_KEY_H */ |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 61877662e8f8..0d7b08db8e56 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -358,7 +358,8 @@ static void ieee80211_restart_work(struct work_struct *work) | |||
358 | flush_workqueue(local->workqueue); | 358 | flush_workqueue(local->workqueue); |
359 | 359 | ||
360 | mutex_lock(&local->mtx); | 360 | mutex_lock(&local->mtx); |
361 | WARN(test_bit(SCAN_HW_SCANNING, &local->scanning), | 361 | WARN(test_bit(SCAN_HW_SCANNING, &local->scanning) || |
362 | local->sched_scanning, | ||
362 | "%s called with hardware scan in progress\n", __func__); | 363 | "%s called with hardware scan in progress\n", __func__); |
363 | mutex_unlock(&local->mtx); | 364 | mutex_unlock(&local->mtx); |
364 | 365 | ||
@@ -580,8 +581,7 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
580 | 581 | ||
581 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | | 582 | wiphy->flags |= WIPHY_FLAG_NETNS_OK | |
582 | WIPHY_FLAG_4ADDR_AP | | 583 | WIPHY_FLAG_4ADDR_AP | |
583 | WIPHY_FLAG_4ADDR_STATION | | 584 | WIPHY_FLAG_4ADDR_STATION; |
584 | WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS; | ||
585 | 585 | ||
586 | if (!ops->set_key) | 586 | if (!ops->set_key) |
587 | wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | 587 | wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
@@ -652,6 +652,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
652 | setup_timer(&local->dynamic_ps_timer, | 652 | setup_timer(&local->dynamic_ps_timer, |
653 | ieee80211_dynamic_ps_timer, (unsigned long) local); | 653 | ieee80211_dynamic_ps_timer, (unsigned long) local); |
654 | 654 | ||
655 | INIT_WORK(&local->sched_scan_stopped_work, | ||
656 | ieee80211_sched_scan_stopped_work); | ||
657 | |||
655 | sta_info_init(local); | 658 | sta_info_init(local); |
656 | 659 | ||
657 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { | 660 | for (i = 0; i < IEEE80211_MAX_QUEUES; i++) { |
@@ -682,7 +685,7 @@ EXPORT_SYMBOL(ieee80211_alloc_hw); | |||
682 | int ieee80211_register_hw(struct ieee80211_hw *hw) | 685 | int ieee80211_register_hw(struct ieee80211_hw *hw) |
683 | { | 686 | { |
684 | struct ieee80211_local *local = hw_to_local(hw); | 687 | struct ieee80211_local *local = hw_to_local(hw); |
685 | int result; | 688 | int result, i; |
686 | enum ieee80211_band band; | 689 | enum ieee80211_band band; |
687 | int channels, max_bitrates; | 690 | int channels, max_bitrates; |
688 | bool supp_ht; | 691 | bool supp_ht; |
@@ -697,6 +700,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
697 | WLAN_CIPHER_SUITE_AES_CMAC | 700 | WLAN_CIPHER_SUITE_AES_CMAC |
698 | }; | 701 | }; |
699 | 702 | ||
703 | if ((hw->wiphy->wowlan.flags || hw->wiphy->wowlan.n_patterns) | ||
704 | #ifdef CONFIG_PM | ||
705 | && (!local->ops->suspend || !local->ops->resume) | ||
706 | #endif | ||
707 | ) | ||
708 | return -EINVAL; | ||
709 | |||
700 | if (hw->max_report_rates == 0) | 710 | if (hw->max_report_rates == 0) |
701 | hw->max_report_rates = hw->max_rates; | 711 | hw->max_report_rates = hw->max_rates; |
702 | 712 | ||
@@ -733,11 +743,19 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
733 | return -ENOMEM; | 743 | return -ENOMEM; |
734 | 744 | ||
735 | /* if low-level driver supports AP, we also support VLAN */ | 745 | /* if low-level driver supports AP, we also support VLAN */ |
736 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) | 746 | if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_AP)) { |
737 | local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); | 747 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP_VLAN); |
748 | hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_AP_VLAN); | ||
749 | } | ||
738 | 750 | ||
739 | /* mac80211 always supports monitor */ | 751 | /* mac80211 always supports monitor */ |
740 | local->hw.wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); | 752 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); |
753 | hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR); | ||
754 | |||
755 | /* mac80211 doesn't support more than 1 channel */ | ||
756 | for (i = 0; i < hw->wiphy->n_iface_combinations; i++) | ||
757 | if (hw->wiphy->iface_combinations[i].num_different_channels > 1) | ||
758 | return -EINVAL; | ||
741 | 759 | ||
742 | #ifndef CONFIG_MAC80211_MESH | 760 | #ifndef CONFIG_MAC80211_MESH |
743 | /* mesh depends on Kconfig, but drivers should set it if they want */ | 761 | /* mesh depends on Kconfig, but drivers should set it if they want */ |
@@ -827,6 +845,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
827 | if (!local->ops->remain_on_channel) | 845 | if (!local->ops->remain_on_channel) |
828 | local->hw.wiphy->max_remain_on_channel_duration = 5000; | 846 | local->hw.wiphy->max_remain_on_channel_duration = 5000; |
829 | 847 | ||
848 | if (local->ops->sched_scan_start) | ||
849 | local->hw.wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | ||
850 | |||
830 | result = wiphy_register(local->hw.wiphy); | 851 | result = wiphy_register(local->hw.wiphy); |
831 | if (result < 0) | 852 | if (result < 0) |
832 | goto fail_wiphy_register; | 853 | goto fail_wiphy_register; |
@@ -850,8 +871,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
850 | * and we need some headroom for passing the frame to monitor | 871 | * and we need some headroom for passing the frame to monitor |
851 | * interfaces, but never both at the same time. | 872 | * interfaces, but never both at the same time. |
852 | */ | 873 | */ |
874 | #ifndef __CHECKER__ | ||
853 | BUILD_BUG_ON(IEEE80211_TX_STATUS_HEADROOM != | 875 | BUILD_BUG_ON(IEEE80211_TX_STATUS_HEADROOM != |
854 | sizeof(struct ieee80211_tx_status_rtap_hdr)); | 876 | sizeof(struct ieee80211_tx_status_rtap_hdr)); |
877 | #endif | ||
855 | local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom, | 878 | local->tx_headroom = max_t(unsigned int , local->hw.extra_tx_headroom, |
856 | sizeof(struct ieee80211_tx_status_rtap_hdr)); | 879 | sizeof(struct ieee80211_tx_status_rtap_hdr)); |
857 | 880 | ||
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index c1299e249541..29e9980c8e60 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -287,49 +287,6 @@ void mesh_mgmt_ies_add(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
287 | } | 287 | } |
288 | } | 288 | } |
289 | 289 | ||
290 | u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, struct mesh_table *tbl) | ||
291 | { | ||
292 | /* Use last four bytes of hw addr and interface index as hash index */ | ||
293 | return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, tbl->hash_rnd) | ||
294 | & tbl->hash_mask; | ||
295 | } | ||
296 | |||
297 | struct mesh_table *mesh_table_alloc(int size_order) | ||
298 | { | ||
299 | int i; | ||
300 | struct mesh_table *newtbl; | ||
301 | |||
302 | newtbl = kmalloc(sizeof(struct mesh_table), GFP_KERNEL); | ||
303 | if (!newtbl) | ||
304 | return NULL; | ||
305 | |||
306 | newtbl->hash_buckets = kzalloc(sizeof(struct hlist_head) * | ||
307 | (1 << size_order), GFP_KERNEL); | ||
308 | |||
309 | if (!newtbl->hash_buckets) { | ||
310 | kfree(newtbl); | ||
311 | return NULL; | ||
312 | } | ||
313 | |||
314 | newtbl->hashwlock = kmalloc(sizeof(spinlock_t) * | ||
315 | (1 << size_order), GFP_KERNEL); | ||
316 | if (!newtbl->hashwlock) { | ||
317 | kfree(newtbl->hash_buckets); | ||
318 | kfree(newtbl); | ||
319 | return NULL; | ||
320 | } | ||
321 | |||
322 | newtbl->size_order = size_order; | ||
323 | newtbl->hash_mask = (1 << size_order) - 1; | ||
324 | atomic_set(&newtbl->entries, 0); | ||
325 | get_random_bytes(&newtbl->hash_rnd, | ||
326 | sizeof(newtbl->hash_rnd)); | ||
327 | for (i = 0; i <= newtbl->hash_mask; i++) | ||
328 | spin_lock_init(&newtbl->hashwlock[i]); | ||
329 | |||
330 | return newtbl; | ||
331 | } | ||
332 | |||
333 | 290 | ||
334 | static void ieee80211_mesh_path_timer(unsigned long data) | 291 | static void ieee80211_mesh_path_timer(unsigned long data) |
335 | { | 292 | { |
@@ -574,7 +531,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
574 | &elems); | 531 | &elems); |
575 | 532 | ||
576 | /* ignore beacons from secure mesh peers if our security is off */ | 533 | /* ignore beacons from secure mesh peers if our security is off */ |
577 | if (elems.rsn_len && !sdata->u.mesh.is_secure) | 534 | if (elems.rsn_len && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) |
578 | return; | 535 | return; |
579 | 536 | ||
580 | if (elems.ds_params && elems.ds_params_len == 1) | 537 | if (elems.ds_params && elems.ds_params_len == 1) |
@@ -600,7 +557,7 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, | |||
600 | struct ieee80211_rx_status *rx_status) | 557 | struct ieee80211_rx_status *rx_status) |
601 | { | 558 | { |
602 | switch (mgmt->u.action.category) { | 559 | switch (mgmt->u.action.category) { |
603 | case WLAN_CATEGORY_MESH_PLINK: | 560 | case WLAN_CATEGORY_MESH_ACTION: |
604 | mesh_rx_plink_frame(sdata, mgmt, len, rx_status); | 561 | mesh_rx_plink_frame(sdata, mgmt, len, rx_status); |
605 | break; | 562 | break; |
606 | case WLAN_CATEGORY_MESH_PATH_SEL: | 563 | case WLAN_CATEGORY_MESH_PATH_SEL: |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 10acf1cc8082..e7c5fddb4804 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -92,7 +92,7 @@ struct mesh_path { | |||
92 | u8 dst[ETH_ALEN]; | 92 | u8 dst[ETH_ALEN]; |
93 | u8 mpp[ETH_ALEN]; /* used for MPP or MAP */ | 93 | u8 mpp[ETH_ALEN]; /* used for MPP or MAP */ |
94 | struct ieee80211_sub_if_data *sdata; | 94 | struct ieee80211_sub_if_data *sdata; |
95 | struct sta_info *next_hop; | 95 | struct sta_info __rcu *next_hop; |
96 | struct timer_list timer; | 96 | struct timer_list timer; |
97 | struct sk_buff_head frame_queue; | 97 | struct sk_buff_head frame_queue; |
98 | struct rcu_head rcu; | 98 | struct rcu_head rcu; |
@@ -240,12 +240,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, | |||
240 | 240 | ||
241 | /* Private interfaces */ | 241 | /* Private interfaces */ |
242 | /* Mesh tables */ | 242 | /* Mesh tables */ |
243 | struct mesh_table *mesh_table_alloc(int size_order); | ||
244 | void mesh_table_free(struct mesh_table *tbl, bool free_leafs); | ||
245 | void mesh_mpath_table_grow(void); | 243 | void mesh_mpath_table_grow(void); |
246 | void mesh_mpp_table_grow(void); | 244 | void mesh_mpp_table_grow(void); |
247 | u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, | ||
248 | struct mesh_table *tbl); | ||
249 | /* Mesh paths */ | 245 | /* Mesh paths */ |
250 | int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, __le16 target_rcode, | 246 | int mesh_path_error_tx(u8 ttl, u8 *target, __le32 target_sn, __le16 target_rcode, |
251 | const u8 *ra, struct ieee80211_sub_if_data *sdata); | 247 | const u8 *ra, struct ieee80211_sub_if_data *sdata); |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index e57f2e728cfe..2b18053070c1 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -391,7 +391,6 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata, | |||
391 | (mpath->flags & MESH_PATH_SN_VALID)) { | 391 | (mpath->flags & MESH_PATH_SN_VALID)) { |
392 | if (SN_GT(mpath->sn, orig_sn) || | 392 | if (SN_GT(mpath->sn, orig_sn) || |
393 | (mpath->sn == orig_sn && | 393 | (mpath->sn == orig_sn && |
394 | action == MPATH_PREQ && | ||
395 | new_metric >= mpath->metric)) { | 394 | new_metric >= mpath->metric)) { |
396 | process = false; | 395 | process = false; |
397 | fresh_info = false; | 396 | fresh_info = false; |
@@ -561,6 +560,14 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata, | |||
561 | } | 560 | } |
562 | 561 | ||
563 | 562 | ||
563 | static inline struct sta_info * | ||
564 | next_hop_deref_protected(struct mesh_path *mpath) | ||
565 | { | ||
566 | return rcu_dereference_protected(mpath->next_hop, | ||
567 | lockdep_is_held(&mpath->state_lock)); | ||
568 | } | ||
569 | |||
570 | |||
564 | static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | 571 | static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, |
565 | struct ieee80211_mgmt *mgmt, | 572 | struct ieee80211_mgmt *mgmt, |
566 | u8 *prep_elem, u32 metric) | 573 | u8 *prep_elem, u32 metric) |
@@ -600,7 +607,7 @@ static void hwmp_prep_frame_process(struct ieee80211_sub_if_data *sdata, | |||
600 | spin_unlock_bh(&mpath->state_lock); | 607 | spin_unlock_bh(&mpath->state_lock); |
601 | goto fail; | 608 | goto fail; |
602 | } | 609 | } |
603 | memcpy(next_hop, mpath->next_hop->sta.addr, ETH_ALEN); | 610 | memcpy(next_hop, next_hop_deref_protected(mpath)->sta.addr, ETH_ALEN); |
604 | spin_unlock_bh(&mpath->state_lock); | 611 | spin_unlock_bh(&mpath->state_lock); |
605 | --ttl; | 612 | --ttl; |
606 | flags = PREP_IE_FLAGS(prep_elem); | 613 | flags = PREP_IE_FLAGS(prep_elem); |
@@ -652,7 +659,8 @@ static void hwmp_perr_frame_process(struct ieee80211_sub_if_data *sdata, | |||
652 | if (mpath) { | 659 | if (mpath) { |
653 | spin_lock_bh(&mpath->state_lock); | 660 | spin_lock_bh(&mpath->state_lock); |
654 | if (mpath->flags & MESH_PATH_ACTIVE && | 661 | if (mpath->flags & MESH_PATH_ACTIVE && |
655 | memcmp(ta, mpath->next_hop->sta.addr, ETH_ALEN) == 0 && | 662 | memcmp(ta, next_hop_deref_protected(mpath)->sta.addr, |
663 | ETH_ALEN) == 0 && | ||
656 | (!(mpath->flags & MESH_PATH_SN_VALID) || | 664 | (!(mpath->flags & MESH_PATH_SN_VALID) || |
657 | SN_GT(target_sn, mpath->sn))) { | 665 | SN_GT(target_sn, mpath->sn))) { |
658 | mpath->flags &= ~MESH_PATH_ACTIVE; | 666 | mpath->flags &= ~MESH_PATH_ACTIVE; |
@@ -914,6 +922,7 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
914 | { | 922 | { |
915 | struct sk_buff *skb_to_free = NULL; | 923 | struct sk_buff *skb_to_free = NULL; |
916 | struct mesh_path *mpath; | 924 | struct mesh_path *mpath; |
925 | struct sta_info *next_hop; | ||
917 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 926 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
918 | u8 *target_addr = hdr->addr3; | 927 | u8 *target_addr = hdr->addr3; |
919 | int err = 0; | 928 | int err = 0; |
@@ -941,7 +950,11 @@ int mesh_nexthop_lookup(struct sk_buff *skb, | |||
941 | mesh_queue_preq(mpath, | 950 | mesh_queue_preq(mpath, |
942 | PREQ_Q_F_START | PREQ_Q_F_REFRESH); | 951 | PREQ_Q_F_START | PREQ_Q_F_REFRESH); |
943 | } | 952 | } |
944 | memcpy(hdr->addr1, mpath->next_hop->sta.addr, ETH_ALEN); | 953 | next_hop = rcu_dereference(mpath->next_hop); |
954 | if (next_hop) | ||
955 | memcpy(hdr->addr1, next_hop->sta.addr, ETH_ALEN); | ||
956 | else | ||
957 | err = -ENOENT; | ||
945 | } else { | 958 | } else { |
946 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 959 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
947 | if (!(mpath->flags & MESH_PATH_RESOLVING)) { | 960 | if (!(mpath->flags & MESH_PATH_RESOLVING)) { |
@@ -967,20 +980,11 @@ endlookup: | |||
967 | 980 | ||
968 | void mesh_path_timer(unsigned long data) | 981 | void mesh_path_timer(unsigned long data) |
969 | { | 982 | { |
970 | struct ieee80211_sub_if_data *sdata; | 983 | struct mesh_path *mpath = (void *) data; |
971 | struct mesh_path *mpath; | 984 | struct ieee80211_sub_if_data *sdata = mpath->sdata; |
972 | |||
973 | rcu_read_lock(); | ||
974 | mpath = (struct mesh_path *) data; | ||
975 | mpath = rcu_dereference(mpath); | ||
976 | if (!mpath) | ||
977 | goto endmpathtimer; | ||
978 | sdata = mpath->sdata; | ||
979 | 985 | ||
980 | if (sdata->local->quiescing) { | 986 | if (sdata->local->quiescing) |
981 | rcu_read_unlock(); | ||
982 | return; | 987 | return; |
983 | } | ||
984 | 988 | ||
985 | spin_lock_bh(&mpath->state_lock); | 989 | spin_lock_bh(&mpath->state_lock); |
986 | if (mpath->flags & MESH_PATH_RESOLVED || | 990 | if (mpath->flags & MESH_PATH_RESOLVED || |
@@ -997,8 +1001,6 @@ void mesh_path_timer(unsigned long data) | |||
997 | } | 1001 | } |
998 | 1002 | ||
999 | spin_unlock_bh(&mpath->state_lock); | 1003 | spin_unlock_bh(&mpath->state_lock); |
1000 | endmpathtimer: | ||
1001 | rcu_read_unlock(); | ||
1002 | } | 1004 | } |
1003 | 1005 | ||
1004 | void | 1006 | void |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 35c715adaae2..83ce48e31913 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -40,6 +40,50 @@ static struct mesh_table *mesh_paths; | |||
40 | static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */ | 40 | static struct mesh_table *mpp_paths; /* Store paths for MPP&MAP */ |
41 | 41 | ||
42 | int mesh_paths_generation; | 42 | int mesh_paths_generation; |
43 | |||
44 | /* This lock will have the grow table function as writer and add / delete nodes | ||
45 | * as readers. When reading the table (i.e. doing lookups) we are well protected | ||
46 | * by RCU | ||
47 | */ | ||
48 | static DEFINE_RWLOCK(pathtbl_resize_lock); | ||
49 | |||
50 | |||
51 | static struct mesh_table *mesh_table_alloc(int size_order) | ||
52 | { | ||
53 | int i; | ||
54 | struct mesh_table *newtbl; | ||
55 | |||
56 | newtbl = kmalloc(sizeof(struct mesh_table), GFP_KERNEL); | ||
57 | if (!newtbl) | ||
58 | return NULL; | ||
59 | |||
60 | newtbl->hash_buckets = kzalloc(sizeof(struct hlist_head) * | ||
61 | (1 << size_order), GFP_KERNEL); | ||
62 | |||
63 | if (!newtbl->hash_buckets) { | ||
64 | kfree(newtbl); | ||
65 | return NULL; | ||
66 | } | ||
67 | |||
68 | newtbl->hashwlock = kmalloc(sizeof(spinlock_t) * | ||
69 | (1 << size_order), GFP_KERNEL); | ||
70 | if (!newtbl->hashwlock) { | ||
71 | kfree(newtbl->hash_buckets); | ||
72 | kfree(newtbl); | ||
73 | return NULL; | ||
74 | } | ||
75 | |||
76 | newtbl->size_order = size_order; | ||
77 | newtbl->hash_mask = (1 << size_order) - 1; | ||
78 | atomic_set(&newtbl->entries, 0); | ||
79 | get_random_bytes(&newtbl->hash_rnd, | ||
80 | sizeof(newtbl->hash_rnd)); | ||
81 | for (i = 0; i <= newtbl->hash_mask; i++) | ||
82 | spin_lock_init(&newtbl->hashwlock[i]); | ||
83 | |||
84 | return newtbl; | ||
85 | } | ||
86 | |||
43 | static void __mesh_table_free(struct mesh_table *tbl) | 87 | static void __mesh_table_free(struct mesh_table *tbl) |
44 | { | 88 | { |
45 | kfree(tbl->hash_buckets); | 89 | kfree(tbl->hash_buckets); |
@@ -47,7 +91,7 @@ static void __mesh_table_free(struct mesh_table *tbl) | |||
47 | kfree(tbl); | 91 | kfree(tbl); |
48 | } | 92 | } |
49 | 93 | ||
50 | void mesh_table_free(struct mesh_table *tbl, bool free_leafs) | 94 | static void mesh_table_free(struct mesh_table *tbl, bool free_leafs) |
51 | { | 95 | { |
52 | struct hlist_head *mesh_hash; | 96 | struct hlist_head *mesh_hash; |
53 | struct hlist_node *p, *q; | 97 | struct hlist_node *p, *q; |
@@ -55,18 +99,18 @@ void mesh_table_free(struct mesh_table *tbl, bool free_leafs) | |||
55 | 99 | ||
56 | mesh_hash = tbl->hash_buckets; | 100 | mesh_hash = tbl->hash_buckets; |
57 | for (i = 0; i <= tbl->hash_mask; i++) { | 101 | for (i = 0; i <= tbl->hash_mask; i++) { |
58 | spin_lock(&tbl->hashwlock[i]); | 102 | spin_lock_bh(&tbl->hashwlock[i]); |
59 | hlist_for_each_safe(p, q, &mesh_hash[i]) { | 103 | hlist_for_each_safe(p, q, &mesh_hash[i]) { |
60 | tbl->free_node(p, free_leafs); | 104 | tbl->free_node(p, free_leafs); |
61 | atomic_dec(&tbl->entries); | 105 | atomic_dec(&tbl->entries); |
62 | } | 106 | } |
63 | spin_unlock(&tbl->hashwlock[i]); | 107 | spin_unlock_bh(&tbl->hashwlock[i]); |
64 | } | 108 | } |
65 | __mesh_table_free(tbl); | 109 | __mesh_table_free(tbl); |
66 | } | 110 | } |
67 | 111 | ||
68 | static int mesh_table_grow(struct mesh_table *oldtbl, | 112 | static int mesh_table_grow(struct mesh_table *oldtbl, |
69 | struct mesh_table *newtbl) | 113 | struct mesh_table *newtbl) |
70 | { | 114 | { |
71 | struct hlist_head *oldhash; | 115 | struct hlist_head *oldhash; |
72 | struct hlist_node *p, *q; | 116 | struct hlist_node *p, *q; |
@@ -76,7 +120,6 @@ static int mesh_table_grow(struct mesh_table *oldtbl, | |||
76 | < oldtbl->mean_chain_len * (oldtbl->hash_mask + 1)) | 120 | < oldtbl->mean_chain_len * (oldtbl->hash_mask + 1)) |
77 | return -EAGAIN; | 121 | return -EAGAIN; |
78 | 122 | ||
79 | |||
80 | newtbl->free_node = oldtbl->free_node; | 123 | newtbl->free_node = oldtbl->free_node; |
81 | newtbl->mean_chain_len = oldtbl->mean_chain_len; | 124 | newtbl->mean_chain_len = oldtbl->mean_chain_len; |
82 | newtbl->copy_node = oldtbl->copy_node; | 125 | newtbl->copy_node = oldtbl->copy_node; |
@@ -98,12 +141,14 @@ errcopy: | |||
98 | return -ENOMEM; | 141 | return -ENOMEM; |
99 | } | 142 | } |
100 | 143 | ||
144 | static u32 mesh_table_hash(u8 *addr, struct ieee80211_sub_if_data *sdata, | ||
145 | struct mesh_table *tbl) | ||
146 | { | ||
147 | /* Use last four bytes of hw addr and interface index as hash index */ | ||
148 | return jhash_2words(*(u32 *)(addr+2), sdata->dev->ifindex, tbl->hash_rnd) | ||
149 | & tbl->hash_mask; | ||
150 | } | ||
101 | 151 | ||
102 | /* This lock will have the grow table function as writer and add / delete nodes | ||
103 | * as readers. When reading the table (i.e. doing lookups) we are well protected | ||
104 | * by RCU | ||
105 | */ | ||
106 | static DEFINE_RWLOCK(pathtbl_resize_lock); | ||
107 | 152 | ||
108 | /** | 153 | /** |
109 | * | 154 | * |
@@ -275,7 +320,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
275 | if (!new_node) | 320 | if (!new_node) |
276 | goto err_node_alloc; | 321 | goto err_node_alloc; |
277 | 322 | ||
278 | read_lock(&pathtbl_resize_lock); | 323 | read_lock_bh(&pathtbl_resize_lock); |
279 | memcpy(new_mpath->dst, dst, ETH_ALEN); | 324 | memcpy(new_mpath->dst, dst, ETH_ALEN); |
280 | new_mpath->sdata = sdata; | 325 | new_mpath->sdata = sdata; |
281 | new_mpath->flags = 0; | 326 | new_mpath->flags = 0; |
@@ -290,7 +335,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
290 | hash_idx = mesh_table_hash(dst, sdata, mesh_paths); | 335 | hash_idx = mesh_table_hash(dst, sdata, mesh_paths); |
291 | bucket = &mesh_paths->hash_buckets[hash_idx]; | 336 | bucket = &mesh_paths->hash_buckets[hash_idx]; |
292 | 337 | ||
293 | spin_lock(&mesh_paths->hashwlock[hash_idx]); | 338 | spin_lock_bh(&mesh_paths->hashwlock[hash_idx]); |
294 | 339 | ||
295 | err = -EEXIST; | 340 | err = -EEXIST; |
296 | hlist_for_each_entry(node, n, bucket, list) { | 341 | hlist_for_each_entry(node, n, bucket, list) { |
@@ -306,8 +351,8 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
306 | 351 | ||
307 | mesh_paths_generation++; | 352 | mesh_paths_generation++; |
308 | 353 | ||
309 | spin_unlock(&mesh_paths->hashwlock[hash_idx]); | 354 | spin_unlock_bh(&mesh_paths->hashwlock[hash_idx]); |
310 | read_unlock(&pathtbl_resize_lock); | 355 | read_unlock_bh(&pathtbl_resize_lock); |
311 | if (grow) { | 356 | if (grow) { |
312 | set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags); | 357 | set_bit(MESH_WORK_GROW_MPATH_TABLE, &ifmsh->wrkq_flags); |
313 | ieee80211_queue_work(&local->hw, &sdata->work); | 358 | ieee80211_queue_work(&local->hw, &sdata->work); |
@@ -315,8 +360,8 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
315 | return 0; | 360 | return 0; |
316 | 361 | ||
317 | err_exists: | 362 | err_exists: |
318 | spin_unlock(&mesh_paths->hashwlock[hash_idx]); | 363 | spin_unlock_bh(&mesh_paths->hashwlock[hash_idx]); |
319 | read_unlock(&pathtbl_resize_lock); | 364 | read_unlock_bh(&pathtbl_resize_lock); |
320 | kfree(new_node); | 365 | kfree(new_node); |
321 | err_node_alloc: | 366 | err_node_alloc: |
322 | kfree(new_mpath); | 367 | kfree(new_mpath); |
@@ -329,18 +374,21 @@ void mesh_mpath_table_grow(void) | |||
329 | { | 374 | { |
330 | struct mesh_table *oldtbl, *newtbl; | 375 | struct mesh_table *oldtbl, *newtbl; |
331 | 376 | ||
332 | newtbl = mesh_table_alloc(mesh_paths->size_order + 1); | 377 | rcu_read_lock(); |
378 | newtbl = mesh_table_alloc(rcu_dereference(mesh_paths)->size_order + 1); | ||
333 | if (!newtbl) | 379 | if (!newtbl) |
334 | return; | 380 | return; |
335 | write_lock(&pathtbl_resize_lock); | 381 | write_lock_bh(&pathtbl_resize_lock); |
336 | oldtbl = mesh_paths; | 382 | oldtbl = mesh_paths; |
337 | if (mesh_table_grow(mesh_paths, newtbl) < 0) { | 383 | if (mesh_table_grow(mesh_paths, newtbl) < 0) { |
384 | rcu_read_unlock(); | ||
338 | __mesh_table_free(newtbl); | 385 | __mesh_table_free(newtbl); |
339 | write_unlock(&pathtbl_resize_lock); | 386 | write_unlock_bh(&pathtbl_resize_lock); |
340 | return; | 387 | return; |
341 | } | 388 | } |
389 | rcu_read_unlock(); | ||
342 | rcu_assign_pointer(mesh_paths, newtbl); | 390 | rcu_assign_pointer(mesh_paths, newtbl); |
343 | write_unlock(&pathtbl_resize_lock); | 391 | write_unlock_bh(&pathtbl_resize_lock); |
344 | 392 | ||
345 | synchronize_rcu(); | 393 | synchronize_rcu(); |
346 | mesh_table_free(oldtbl, false); | 394 | mesh_table_free(oldtbl, false); |
@@ -350,18 +398,21 @@ void mesh_mpp_table_grow(void) | |||
350 | { | 398 | { |
351 | struct mesh_table *oldtbl, *newtbl; | 399 | struct mesh_table *oldtbl, *newtbl; |
352 | 400 | ||
353 | newtbl = mesh_table_alloc(mpp_paths->size_order + 1); | 401 | rcu_read_lock(); |
402 | newtbl = mesh_table_alloc(rcu_dereference(mpp_paths)->size_order + 1); | ||
354 | if (!newtbl) | 403 | if (!newtbl) |
355 | return; | 404 | return; |
356 | write_lock(&pathtbl_resize_lock); | 405 | write_lock_bh(&pathtbl_resize_lock); |
357 | oldtbl = mpp_paths; | 406 | oldtbl = mpp_paths; |
358 | if (mesh_table_grow(mpp_paths, newtbl) < 0) { | 407 | if (mesh_table_grow(mpp_paths, newtbl) < 0) { |
408 | rcu_read_unlock(); | ||
359 | __mesh_table_free(newtbl); | 409 | __mesh_table_free(newtbl); |
360 | write_unlock(&pathtbl_resize_lock); | 410 | write_unlock_bh(&pathtbl_resize_lock); |
361 | return; | 411 | return; |
362 | } | 412 | } |
413 | rcu_read_unlock(); | ||
363 | rcu_assign_pointer(mpp_paths, newtbl); | 414 | rcu_assign_pointer(mpp_paths, newtbl); |
364 | write_unlock(&pathtbl_resize_lock); | 415 | write_unlock_bh(&pathtbl_resize_lock); |
365 | 416 | ||
366 | synchronize_rcu(); | 417 | synchronize_rcu(); |
367 | mesh_table_free(oldtbl, false); | 418 | mesh_table_free(oldtbl, false); |
@@ -395,7 +446,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | |||
395 | if (!new_node) | 446 | if (!new_node) |
396 | goto err_node_alloc; | 447 | goto err_node_alloc; |
397 | 448 | ||
398 | read_lock(&pathtbl_resize_lock); | 449 | read_lock_bh(&pathtbl_resize_lock); |
399 | memcpy(new_mpath->dst, dst, ETH_ALEN); | 450 | memcpy(new_mpath->dst, dst, ETH_ALEN); |
400 | memcpy(new_mpath->mpp, mpp, ETH_ALEN); | 451 | memcpy(new_mpath->mpp, mpp, ETH_ALEN); |
401 | new_mpath->sdata = sdata; | 452 | new_mpath->sdata = sdata; |
@@ -408,7 +459,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | |||
408 | hash_idx = mesh_table_hash(dst, sdata, mpp_paths); | 459 | hash_idx = mesh_table_hash(dst, sdata, mpp_paths); |
409 | bucket = &mpp_paths->hash_buckets[hash_idx]; | 460 | bucket = &mpp_paths->hash_buckets[hash_idx]; |
410 | 461 | ||
411 | spin_lock(&mpp_paths->hashwlock[hash_idx]); | 462 | spin_lock_bh(&mpp_paths->hashwlock[hash_idx]); |
412 | 463 | ||
413 | err = -EEXIST; | 464 | err = -EEXIST; |
414 | hlist_for_each_entry(node, n, bucket, list) { | 465 | hlist_for_each_entry(node, n, bucket, list) { |
@@ -422,8 +473,8 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | |||
422 | mpp_paths->mean_chain_len * (mpp_paths->hash_mask + 1)) | 473 | mpp_paths->mean_chain_len * (mpp_paths->hash_mask + 1)) |
423 | grow = 1; | 474 | grow = 1; |
424 | 475 | ||
425 | spin_unlock(&mpp_paths->hashwlock[hash_idx]); | 476 | spin_unlock_bh(&mpp_paths->hashwlock[hash_idx]); |
426 | read_unlock(&pathtbl_resize_lock); | 477 | read_unlock_bh(&pathtbl_resize_lock); |
427 | if (grow) { | 478 | if (grow) { |
428 | set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags); | 479 | set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags); |
429 | ieee80211_queue_work(&local->hw, &sdata->work); | 480 | ieee80211_queue_work(&local->hw, &sdata->work); |
@@ -431,8 +482,8 @@ int mpp_path_add(u8 *dst, u8 *mpp, struct ieee80211_sub_if_data *sdata) | |||
431 | return 0; | 482 | return 0; |
432 | 483 | ||
433 | err_exists: | 484 | err_exists: |
434 | spin_unlock(&mpp_paths->hashwlock[hash_idx]); | 485 | spin_unlock_bh(&mpp_paths->hashwlock[hash_idx]); |
435 | read_unlock(&pathtbl_resize_lock); | 486 | read_unlock_bh(&pathtbl_resize_lock); |
436 | kfree(new_node); | 487 | kfree(new_node); |
437 | err_node_alloc: | 488 | err_node_alloc: |
438 | kfree(new_mpath); | 489 | kfree(new_mpath); |
@@ -545,11 +596,11 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) | |||
545 | int hash_idx; | 596 | int hash_idx; |
546 | int err = 0; | 597 | int err = 0; |
547 | 598 | ||
548 | read_lock(&pathtbl_resize_lock); | 599 | read_lock_bh(&pathtbl_resize_lock); |
549 | hash_idx = mesh_table_hash(addr, sdata, mesh_paths); | 600 | hash_idx = mesh_table_hash(addr, sdata, mesh_paths); |
550 | bucket = &mesh_paths->hash_buckets[hash_idx]; | 601 | bucket = &mesh_paths->hash_buckets[hash_idx]; |
551 | 602 | ||
552 | spin_lock(&mesh_paths->hashwlock[hash_idx]); | 603 | spin_lock_bh(&mesh_paths->hashwlock[hash_idx]); |
553 | hlist_for_each_entry(node, n, bucket, list) { | 604 | hlist_for_each_entry(node, n, bucket, list) { |
554 | mpath = node->mpath; | 605 | mpath = node->mpath; |
555 | if (mpath->sdata == sdata && | 606 | if (mpath->sdata == sdata && |
@@ -567,8 +618,8 @@ int mesh_path_del(u8 *addr, struct ieee80211_sub_if_data *sdata) | |||
567 | err = -ENXIO; | 618 | err = -ENXIO; |
568 | enddel: | 619 | enddel: |
569 | mesh_paths_generation++; | 620 | mesh_paths_generation++; |
570 | spin_unlock(&mesh_paths->hashwlock[hash_idx]); | 621 | spin_unlock_bh(&mesh_paths->hashwlock[hash_idx]); |
571 | read_unlock(&pathtbl_resize_lock); | 622 | read_unlock_bh(&pathtbl_resize_lock); |
572 | return err; | 623 | return err; |
573 | } | 624 | } |
574 | 625 | ||
@@ -720,7 +771,7 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata) | |||
720 | struct hlist_node *p; | 771 | struct hlist_node *p; |
721 | int i; | 772 | int i; |
722 | 773 | ||
723 | read_lock(&pathtbl_resize_lock); | 774 | read_lock_bh(&pathtbl_resize_lock); |
724 | for_each_mesh_entry(mesh_paths, p, node, i) { | 775 | for_each_mesh_entry(mesh_paths, p, node, i) { |
725 | if (node->mpath->sdata != sdata) | 776 | if (node->mpath->sdata != sdata) |
726 | continue; | 777 | continue; |
@@ -735,7 +786,7 @@ void mesh_path_expire(struct ieee80211_sub_if_data *sdata) | |||
735 | } else | 786 | } else |
736 | spin_unlock_bh(&mpath->state_lock); | 787 | spin_unlock_bh(&mpath->state_lock); |
737 | } | 788 | } |
738 | read_unlock(&pathtbl_resize_lock); | 789 | read_unlock_bh(&pathtbl_resize_lock); |
739 | } | 790 | } |
740 | 791 | ||
741 | void mesh_pathtbl_unregister(void) | 792 | void mesh_pathtbl_unregister(void) |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 84e5b056af02..f4adc0917888 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -43,7 +43,7 @@ | |||
43 | #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks) | 43 | #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks) |
44 | 44 | ||
45 | enum plink_frame_type { | 45 | enum plink_frame_type { |
46 | PLINK_OPEN = 0, | 46 | PLINK_OPEN = 1, |
47 | PLINK_CONFIRM, | 47 | PLINK_CONFIRM, |
48 | PLINK_CLOSE | 48 | PLINK_CLOSE |
49 | }; | 49 | }; |
@@ -83,7 +83,7 @@ void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) | |||
83 | */ | 83 | */ |
84 | static inline void mesh_plink_fsm_restart(struct sta_info *sta) | 84 | static inline void mesh_plink_fsm_restart(struct sta_info *sta) |
85 | { | 85 | { |
86 | sta->plink_state = PLINK_LISTEN; | 86 | sta->plink_state = NL80211_PLINK_LISTEN; |
87 | sta->llid = sta->plid = sta->reason = 0; | 87 | sta->llid = sta->plid = sta->reason = 0; |
88 | sta->plink_retries = 0; | 88 | sta->plink_retries = 0; |
89 | } | 89 | } |
@@ -126,11 +126,11 @@ static bool __mesh_plink_deactivate(struct sta_info *sta) | |||
126 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 126 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
127 | bool deactivated = false; | 127 | bool deactivated = false; |
128 | 128 | ||
129 | if (sta->plink_state == PLINK_ESTAB) { | 129 | if (sta->plink_state == NL80211_PLINK_ESTAB) { |
130 | mesh_plink_dec_estab_count(sdata); | 130 | mesh_plink_dec_estab_count(sdata); |
131 | deactivated = true; | 131 | deactivated = true; |
132 | } | 132 | } |
133 | sta->plink_state = PLINK_BLOCKED; | 133 | sta->plink_state = NL80211_PLINK_BLOCKED; |
134 | mesh_path_flush_by_nexthop(sta); | 134 | mesh_path_flush_by_nexthop(sta); |
135 | 135 | ||
136 | return deactivated; | 136 | return deactivated; |
@@ -181,8 +181,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
181 | IEEE80211_STYPE_ACTION); | 181 | IEEE80211_STYPE_ACTION); |
182 | memcpy(mgmt->da, da, ETH_ALEN); | 182 | memcpy(mgmt->da, da, ETH_ALEN); |
183 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 183 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
184 | /* BSSID is left zeroed, wildcard value */ | 184 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
185 | mgmt->u.action.category = WLAN_CATEGORY_MESH_PLINK; | 185 | mgmt->u.action.category = WLAN_CATEGORY_MESH_ACTION; |
186 | mgmt->u.action.u.plink_action.action_code = action; | 186 | mgmt->u.action.u.plink_action.action_code = action; |
187 | 187 | ||
188 | if (action == PLINK_CLOSE) | 188 | if (action == PLINK_CLOSE) |
@@ -251,7 +251,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, | |||
251 | rcu_read_unlock(); | 251 | rcu_read_unlock(); |
252 | /* Userspace handles peer allocation when security is enabled | 252 | /* Userspace handles peer allocation when security is enabled |
253 | * */ | 253 | * */ |
254 | if (sdata->u.mesh.is_secure) | 254 | if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED) |
255 | cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr, | 255 | cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr, |
256 | elems->ie_start, elems->total_len, | 256 | elems->ie_start, elems->total_len, |
257 | GFP_KERNEL); | 257 | GFP_KERNEL); |
@@ -268,7 +268,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, | |||
268 | sta->last_rx = jiffies; | 268 | sta->last_rx = jiffies; |
269 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; | 269 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; |
270 | if (mesh_peer_accepts_plinks(elems) && | 270 | if (mesh_peer_accepts_plinks(elems) && |
271 | sta->plink_state == PLINK_LISTEN && | 271 | sta->plink_state == NL80211_PLINK_LISTEN && |
272 | sdata->u.mesh.accepting_plinks && | 272 | sdata->u.mesh.accepting_plinks && |
273 | sdata->u.mesh.mshcfg.auto_open_plinks) | 273 | sdata->u.mesh.mshcfg.auto_open_plinks) |
274 | mesh_plink_open(sta); | 274 | mesh_plink_open(sta); |
@@ -308,8 +308,8 @@ static void mesh_plink_timer(unsigned long data) | |||
308 | sdata = sta->sdata; | 308 | sdata = sta->sdata; |
309 | 309 | ||
310 | switch (sta->plink_state) { | 310 | switch (sta->plink_state) { |
311 | case PLINK_OPN_RCVD: | 311 | case NL80211_PLINK_OPN_RCVD: |
312 | case PLINK_OPN_SNT: | 312 | case NL80211_PLINK_OPN_SNT: |
313 | /* retry timer */ | 313 | /* retry timer */ |
314 | if (sta->plink_retries < dot11MeshMaxRetries(sdata)) { | 314 | if (sta->plink_retries < dot11MeshMaxRetries(sdata)) { |
315 | u32 rand; | 315 | u32 rand; |
@@ -328,17 +328,17 @@ static void mesh_plink_timer(unsigned long data) | |||
328 | } | 328 | } |
329 | reason = cpu_to_le16(MESH_MAX_RETRIES); | 329 | reason = cpu_to_le16(MESH_MAX_RETRIES); |
330 | /* fall through on else */ | 330 | /* fall through on else */ |
331 | case PLINK_CNF_RCVD: | 331 | case NL80211_PLINK_CNF_RCVD: |
332 | /* confirm timer */ | 332 | /* confirm timer */ |
333 | if (!reason) | 333 | if (!reason) |
334 | reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT); | 334 | reason = cpu_to_le16(MESH_CONFIRM_TIMEOUT); |
335 | sta->plink_state = PLINK_HOLDING; | 335 | sta->plink_state = NL80211_PLINK_HOLDING; |
336 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | 336 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); |
337 | spin_unlock_bh(&sta->lock); | 337 | spin_unlock_bh(&sta->lock); |
338 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid, | 338 | mesh_plink_frame_tx(sdata, PLINK_CLOSE, sta->sta.addr, llid, plid, |
339 | reason); | 339 | reason); |
340 | break; | 340 | break; |
341 | case PLINK_HOLDING: | 341 | case NL80211_PLINK_HOLDING: |
342 | /* holding timer */ | 342 | /* holding timer */ |
343 | del_timer(&sta->plink_timer); | 343 | del_timer(&sta->plink_timer); |
344 | mesh_plink_fsm_restart(sta); | 344 | mesh_plink_fsm_restart(sta); |
@@ -386,11 +386,11 @@ int mesh_plink_open(struct sta_info *sta) | |||
386 | spin_lock_bh(&sta->lock); | 386 | spin_lock_bh(&sta->lock); |
387 | get_random_bytes(&llid, 2); | 387 | get_random_bytes(&llid, 2); |
388 | sta->llid = llid; | 388 | sta->llid = llid; |
389 | if (sta->plink_state != PLINK_LISTEN) { | 389 | if (sta->plink_state != NL80211_PLINK_LISTEN) { |
390 | spin_unlock_bh(&sta->lock); | 390 | spin_unlock_bh(&sta->lock); |
391 | return -EBUSY; | 391 | return -EBUSY; |
392 | } | 392 | } |
393 | sta->plink_state = PLINK_OPN_SNT; | 393 | sta->plink_state = NL80211_PLINK_OPN_SNT; |
394 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); | 394 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); |
395 | spin_unlock_bh(&sta->lock); | 395 | spin_unlock_bh(&sta->lock); |
396 | mpl_dbg("Mesh plink: starting establishment with %pM\n", | 396 | mpl_dbg("Mesh plink: starting establishment with %pM\n", |
@@ -407,7 +407,7 @@ void mesh_plink_block(struct sta_info *sta) | |||
407 | 407 | ||
408 | spin_lock_bh(&sta->lock); | 408 | spin_lock_bh(&sta->lock); |
409 | deactivated = __mesh_plink_deactivate(sta); | 409 | deactivated = __mesh_plink_deactivate(sta); |
410 | sta->plink_state = PLINK_BLOCKED; | 410 | sta->plink_state = NL80211_PLINK_BLOCKED; |
411 | spin_unlock_bh(&sta->lock); | 411 | spin_unlock_bh(&sta->lock); |
412 | 412 | ||
413 | if (deactivated) | 413 | if (deactivated) |
@@ -430,13 +430,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
430 | __le16 plid, llid, reason; | 430 | __le16 plid, llid, reason; |
431 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG | 431 | #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG |
432 | static const char *mplstates[] = { | 432 | static const char *mplstates[] = { |
433 | [PLINK_LISTEN] = "LISTEN", | 433 | [NL80211_PLINK_LISTEN] = "LISTEN", |
434 | [PLINK_OPN_SNT] = "OPN-SNT", | 434 | [NL80211_PLINK_OPN_SNT] = "OPN-SNT", |
435 | [PLINK_OPN_RCVD] = "OPN-RCVD", | 435 | [NL80211_PLINK_OPN_RCVD] = "OPN-RCVD", |
436 | [PLINK_CNF_RCVD] = "CNF_RCVD", | 436 | [NL80211_PLINK_CNF_RCVD] = "CNF_RCVD", |
437 | [PLINK_ESTAB] = "ESTAB", | 437 | [NL80211_PLINK_ESTAB] = "ESTAB", |
438 | [PLINK_HOLDING] = "HOLDING", | 438 | [NL80211_PLINK_HOLDING] = "HOLDING", |
439 | [PLINK_BLOCKED] = "BLOCKED" | 439 | [NL80211_PLINK_BLOCKED] = "BLOCKED" |
440 | }; | 440 | }; |
441 | #endif | 441 | #endif |
442 | 442 | ||
@@ -460,7 +460,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
460 | mpl_dbg("Mesh plink: missing necessary peer link ie\n"); | 460 | mpl_dbg("Mesh plink: missing necessary peer link ie\n"); |
461 | return; | 461 | return; |
462 | } | 462 | } |
463 | if (elems.rsn_len && !sdata->u.mesh.is_secure) { | 463 | if (elems.rsn_len && |
464 | sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) { | ||
464 | mpl_dbg("Mesh plink: can't establish link with secure peer\n"); | 465 | mpl_dbg("Mesh plink: can't establish link with secure peer\n"); |
465 | return; | 466 | return; |
466 | } | 467 | } |
@@ -501,7 +502,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
501 | return; | 502 | return; |
502 | } | 503 | } |
503 | 504 | ||
504 | if (sta && sta->plink_state == PLINK_BLOCKED) { | 505 | if (sta && sta->plink_state == NL80211_PLINK_BLOCKED) { |
505 | rcu_read_unlock(); | 506 | rcu_read_unlock(); |
506 | return; | 507 | return; |
507 | } | 508 | } |
@@ -571,7 +572,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
571 | event = CNF_ACPT; | 572 | event = CNF_ACPT; |
572 | break; | 573 | break; |
573 | case PLINK_CLOSE: | 574 | case PLINK_CLOSE: |
574 | if (sta->plink_state == PLINK_ESTAB) | 575 | if (sta->plink_state == NL80211_PLINK_ESTAB) |
575 | /* Do not check for llid or plid. This does not | 576 | /* Do not check for llid or plid. This does not |
576 | * follow the standard but since multiple plinks | 577 | * follow the standard but since multiple plinks |
577 | * per sta are not supported, it is necessary in | 578 | * per sta are not supported, it is necessary in |
@@ -606,14 +607,14 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
606 | reason = 0; | 607 | reason = 0; |
607 | switch (sta->plink_state) { | 608 | switch (sta->plink_state) { |
608 | /* spin_unlock as soon as state is updated at each case */ | 609 | /* spin_unlock as soon as state is updated at each case */ |
609 | case PLINK_LISTEN: | 610 | case NL80211_PLINK_LISTEN: |
610 | switch (event) { | 611 | switch (event) { |
611 | case CLS_ACPT: | 612 | case CLS_ACPT: |
612 | mesh_plink_fsm_restart(sta); | 613 | mesh_plink_fsm_restart(sta); |
613 | spin_unlock_bh(&sta->lock); | 614 | spin_unlock_bh(&sta->lock); |
614 | break; | 615 | break; |
615 | case OPN_ACPT: | 616 | case OPN_ACPT: |
616 | sta->plink_state = PLINK_OPN_RCVD; | 617 | sta->plink_state = NL80211_PLINK_OPN_RCVD; |
617 | sta->plid = plid; | 618 | sta->plid = plid; |
618 | get_random_bytes(&llid, 2); | 619 | get_random_bytes(&llid, 2); |
619 | sta->llid = llid; | 620 | sta->llid = llid; |
@@ -630,7 +631,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
630 | } | 631 | } |
631 | break; | 632 | break; |
632 | 633 | ||
633 | case PLINK_OPN_SNT: | 634 | case NL80211_PLINK_OPN_SNT: |
634 | switch (event) { | 635 | switch (event) { |
635 | case OPN_RJCT: | 636 | case OPN_RJCT: |
636 | case CNF_RJCT: | 637 | case CNF_RJCT: |
@@ -639,7 +640,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
639 | if (!reason) | 640 | if (!reason) |
640 | reason = cpu_to_le16(MESH_CLOSE_RCVD); | 641 | reason = cpu_to_le16(MESH_CLOSE_RCVD); |
641 | sta->reason = reason; | 642 | sta->reason = reason; |
642 | sta->plink_state = PLINK_HOLDING; | 643 | sta->plink_state = NL80211_PLINK_HOLDING; |
643 | if (!mod_plink_timer(sta, | 644 | if (!mod_plink_timer(sta, |
644 | dot11MeshHoldingTimeout(sdata))) | 645 | dot11MeshHoldingTimeout(sdata))) |
645 | sta->ignore_plink_timer = true; | 646 | sta->ignore_plink_timer = true; |
@@ -651,7 +652,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
651 | break; | 652 | break; |
652 | case OPN_ACPT: | 653 | case OPN_ACPT: |
653 | /* retry timer is left untouched */ | 654 | /* retry timer is left untouched */ |
654 | sta->plink_state = PLINK_OPN_RCVD; | 655 | sta->plink_state = NL80211_PLINK_OPN_RCVD; |
655 | sta->plid = plid; | 656 | sta->plid = plid; |
656 | llid = sta->llid; | 657 | llid = sta->llid; |
657 | spin_unlock_bh(&sta->lock); | 658 | spin_unlock_bh(&sta->lock); |
@@ -659,7 +660,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
659 | plid, 0); | 660 | plid, 0); |
660 | break; | 661 | break; |
661 | case CNF_ACPT: | 662 | case CNF_ACPT: |
662 | sta->plink_state = PLINK_CNF_RCVD; | 663 | sta->plink_state = NL80211_PLINK_CNF_RCVD; |
663 | if (!mod_plink_timer(sta, | 664 | if (!mod_plink_timer(sta, |
664 | dot11MeshConfirmTimeout(sdata))) | 665 | dot11MeshConfirmTimeout(sdata))) |
665 | sta->ignore_plink_timer = true; | 666 | sta->ignore_plink_timer = true; |
@@ -672,7 +673,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
672 | } | 673 | } |
673 | break; | 674 | break; |
674 | 675 | ||
675 | case PLINK_OPN_RCVD: | 676 | case NL80211_PLINK_OPN_RCVD: |
676 | switch (event) { | 677 | switch (event) { |
677 | case OPN_RJCT: | 678 | case OPN_RJCT: |
678 | case CNF_RJCT: | 679 | case CNF_RJCT: |
@@ -681,7 +682,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
681 | if (!reason) | 682 | if (!reason) |
682 | reason = cpu_to_le16(MESH_CLOSE_RCVD); | 683 | reason = cpu_to_le16(MESH_CLOSE_RCVD); |
683 | sta->reason = reason; | 684 | sta->reason = reason; |
684 | sta->plink_state = PLINK_HOLDING; | 685 | sta->plink_state = NL80211_PLINK_HOLDING; |
685 | if (!mod_plink_timer(sta, | 686 | if (!mod_plink_timer(sta, |
686 | dot11MeshHoldingTimeout(sdata))) | 687 | dot11MeshHoldingTimeout(sdata))) |
687 | sta->ignore_plink_timer = true; | 688 | sta->ignore_plink_timer = true; |
@@ -699,7 +700,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
699 | break; | 700 | break; |
700 | case CNF_ACPT: | 701 | case CNF_ACPT: |
701 | del_timer(&sta->plink_timer); | 702 | del_timer(&sta->plink_timer); |
702 | sta->plink_state = PLINK_ESTAB; | 703 | sta->plink_state = NL80211_PLINK_ESTAB; |
703 | spin_unlock_bh(&sta->lock); | 704 | spin_unlock_bh(&sta->lock); |
704 | mesh_plink_inc_estab_count(sdata); | 705 | mesh_plink_inc_estab_count(sdata); |
705 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | 706 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); |
@@ -712,7 +713,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
712 | } | 713 | } |
713 | break; | 714 | break; |
714 | 715 | ||
715 | case PLINK_CNF_RCVD: | 716 | case NL80211_PLINK_CNF_RCVD: |
716 | switch (event) { | 717 | switch (event) { |
717 | case OPN_RJCT: | 718 | case OPN_RJCT: |
718 | case CNF_RJCT: | 719 | case CNF_RJCT: |
@@ -721,7 +722,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
721 | if (!reason) | 722 | if (!reason) |
722 | reason = cpu_to_le16(MESH_CLOSE_RCVD); | 723 | reason = cpu_to_le16(MESH_CLOSE_RCVD); |
723 | sta->reason = reason; | 724 | sta->reason = reason; |
724 | sta->plink_state = PLINK_HOLDING; | 725 | sta->plink_state = NL80211_PLINK_HOLDING; |
725 | if (!mod_plink_timer(sta, | 726 | if (!mod_plink_timer(sta, |
726 | dot11MeshHoldingTimeout(sdata))) | 727 | dot11MeshHoldingTimeout(sdata))) |
727 | sta->ignore_plink_timer = true; | 728 | sta->ignore_plink_timer = true; |
@@ -733,7 +734,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
733 | break; | 734 | break; |
734 | case OPN_ACPT: | 735 | case OPN_ACPT: |
735 | del_timer(&sta->plink_timer); | 736 | del_timer(&sta->plink_timer); |
736 | sta->plink_state = PLINK_ESTAB; | 737 | sta->plink_state = NL80211_PLINK_ESTAB; |
737 | spin_unlock_bh(&sta->lock); | 738 | spin_unlock_bh(&sta->lock); |
738 | mesh_plink_inc_estab_count(sdata); | 739 | mesh_plink_inc_estab_count(sdata); |
739 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | 740 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); |
@@ -748,13 +749,13 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
748 | } | 749 | } |
749 | break; | 750 | break; |
750 | 751 | ||
751 | case PLINK_ESTAB: | 752 | case NL80211_PLINK_ESTAB: |
752 | switch (event) { | 753 | switch (event) { |
753 | case CLS_ACPT: | 754 | case CLS_ACPT: |
754 | reason = cpu_to_le16(MESH_CLOSE_RCVD); | 755 | reason = cpu_to_le16(MESH_CLOSE_RCVD); |
755 | sta->reason = reason; | 756 | sta->reason = reason; |
756 | deactivated = __mesh_plink_deactivate(sta); | 757 | deactivated = __mesh_plink_deactivate(sta); |
757 | sta->plink_state = PLINK_HOLDING; | 758 | sta->plink_state = NL80211_PLINK_HOLDING; |
758 | llid = sta->llid; | 759 | llid = sta->llid; |
759 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | 760 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); |
760 | spin_unlock_bh(&sta->lock); | 761 | spin_unlock_bh(&sta->lock); |
@@ -774,7 +775,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
774 | break; | 775 | break; |
775 | } | 776 | } |
776 | break; | 777 | break; |
777 | case PLINK_HOLDING: | 778 | case NL80211_PLINK_HOLDING: |
778 | switch (event) { | 779 | switch (event) { |
779 | case CLS_ACPT: | 780 | case CLS_ACPT: |
780 | if (del_timer(&sta->plink_timer)) | 781 | if (del_timer(&sta->plink_timer)) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a41f234bd486..4f6b2675e41d 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -750,6 +750,8 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
750 | dynamic_ps_enable_work); | 750 | dynamic_ps_enable_work); |
751 | struct ieee80211_sub_if_data *sdata = local->ps_sdata; | 751 | struct ieee80211_sub_if_data *sdata = local->ps_sdata; |
752 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 752 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
753 | unsigned long flags; | ||
754 | int q; | ||
753 | 755 | ||
754 | /* can only happen when PS was just disabled anyway */ | 756 | /* can only happen when PS was just disabled anyway */ |
755 | if (!sdata) | 757 | if (!sdata) |
@@ -758,6 +760,24 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
758 | if (local->hw.conf.flags & IEEE80211_CONF_PS) | 760 | if (local->hw.conf.flags & IEEE80211_CONF_PS) |
759 | return; | 761 | return; |
760 | 762 | ||
763 | /* | ||
764 | * transmission can be stopped by others which leads to | ||
765 | * dynamic_ps_timer expiry. Postpond the ps timer if it | ||
766 | * is not the actual idle state. | ||
767 | */ | ||
768 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
769 | for (q = 0; q < local->hw.queues; q++) { | ||
770 | if (local->queue_stop_reasons[q]) { | ||
771 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, | ||
772 | flags); | ||
773 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
774 | msecs_to_jiffies( | ||
775 | local->hw.conf.dynamic_ps_timeout)); | ||
776 | return; | ||
777 | } | ||
778 | } | ||
779 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
780 | |||
761 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && | 781 | if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) && |
762 | (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { | 782 | (!(ifmgd->flags & IEEE80211_STA_NULLFUNC_ACKED))) { |
763 | netif_tx_stop_all_queues(sdata->dev); | 783 | netif_tx_stop_all_queues(sdata->dev); |
@@ -781,7 +801,7 @@ void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | |||
781 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 801 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
782 | } | 802 | } |
783 | 803 | ||
784 | netif_tx_start_all_queues(sdata->dev); | 804 | netif_tx_wake_all_queues(sdata->dev); |
785 | } | 805 | } |
786 | 806 | ||
787 | void ieee80211_dynamic_ps_timer(unsigned long data) | 807 | void ieee80211_dynamic_ps_timer(unsigned long data) |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index 042461710880..730778a2c90c 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -6,7 +6,7 @@ | |||
6 | #include "driver-ops.h" | 6 | #include "driver-ops.h" |
7 | #include "led.h" | 7 | #include "led.h" |
8 | 8 | ||
9 | int __ieee80211_suspend(struct ieee80211_hw *hw) | 9 | int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) |
10 | { | 10 | { |
11 | struct ieee80211_local *local = hw_to_local(hw); | 11 | struct ieee80211_local *local = hw_to_local(hw); |
12 | struct ieee80211_sub_if_data *sdata; | 12 | struct ieee80211_sub_if_data *sdata; |
@@ -47,6 +47,16 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
47 | cancel_work_sync(&local->dynamic_ps_enable_work); | 47 | cancel_work_sync(&local->dynamic_ps_enable_work); |
48 | del_timer_sync(&local->dynamic_ps_timer); | 48 | del_timer_sync(&local->dynamic_ps_timer); |
49 | 49 | ||
50 | local->wowlan = wowlan && local->open_count; | ||
51 | if (local->wowlan) { | ||
52 | int err = drv_suspend(local, wowlan); | ||
53 | if (err) { | ||
54 | local->quiescing = false; | ||
55 | return err; | ||
56 | } | ||
57 | goto suspend; | ||
58 | } | ||
59 | |||
50 | /* disable keys */ | 60 | /* disable keys */ |
51 | list_for_each_entry(sdata, &local->interfaces, list) | 61 | list_for_each_entry(sdata, &local->interfaces, list) |
52 | ieee80211_disable_keys(sdata); | 62 | ieee80211_disable_keys(sdata); |
@@ -104,6 +114,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw) | |||
104 | if (local->open_count) | 114 | if (local->open_count) |
105 | ieee80211_stop_device(local); | 115 | ieee80211_stop_device(local); |
106 | 116 | ||
117 | suspend: | ||
107 | local->suspended = true; | 118 | local->suspended = true; |
108 | /* need suspended to be visible before quiescing is false */ | 119 | /* need suspended to be visible before quiescing is false */ |
109 | barrier(); | 120 | barrier(); |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index 778c604d7939..8adac67395f7 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -417,8 +417,8 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, | |||
417 | tx_time_single = mr->ack_time + mr->perfect_tx_time; | 417 | tx_time_single = mr->ack_time + mr->perfect_tx_time; |
418 | 418 | ||
419 | /* contention window */ | 419 | /* contention window */ |
420 | tx_time_single += t_slot + min(cw, mp->cw_max); | 420 | tx_time_single += (t_slot * cw) >> 1; |
421 | cw = (cw << 1) | 1; | 421 | cw = min((cw << 1) | 1, mp->cw_max); |
422 | 422 | ||
423 | tx_time += tx_time_single; | 423 | tx_time += tx_time_single; |
424 | tx_time_cts += tx_time_single + mi->sp_ack_dur; | 424 | tx_time_cts += tx_time_single + mi->sp_ack_dur; |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index c06aa3ac6b9d..333b5118be6d 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -464,6 +464,7 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | |||
464 | const struct mcs_group *group; | 464 | const struct mcs_group *group; |
465 | unsigned int tx_time, tx_time_rtscts, tx_time_data; | 465 | unsigned int tx_time, tx_time_rtscts, tx_time_data; |
466 | unsigned int cw = mp->cw_min; | 466 | unsigned int cw = mp->cw_min; |
467 | unsigned int ctime = 0; | ||
467 | unsigned int t_slot = 9; /* FIXME */ | 468 | unsigned int t_slot = 9; /* FIXME */ |
468 | unsigned int ampdu_len = MINSTREL_TRUNC(mi->avg_ampdu_len); | 469 | unsigned int ampdu_len = MINSTREL_TRUNC(mi->avg_ampdu_len); |
469 | 470 | ||
@@ -480,13 +481,27 @@ minstrel_calc_retransmit(struct minstrel_priv *mp, struct minstrel_ht_sta *mi, | |||
480 | 481 | ||
481 | group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; | 482 | group = &minstrel_mcs_groups[index / MCS_GROUP_RATES]; |
482 | tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len; | 483 | tx_time_data = group->duration[index % MCS_GROUP_RATES] * ampdu_len; |
483 | tx_time = 2 * (t_slot + mi->overhead + tx_time_data); | 484 | |
484 | tx_time_rtscts = 2 * (t_slot + mi->overhead_rtscts + tx_time_data); | 485 | /* Contention time for first 2 tries */ |
486 | ctime = (t_slot * cw) >> 1; | ||
487 | cw = min((cw << 1) | 1, mp->cw_max); | ||
488 | ctime += (t_slot * cw) >> 1; | ||
489 | cw = min((cw << 1) | 1, mp->cw_max); | ||
490 | |||
491 | /* Total TX time for data and Contention after first 2 tries */ | ||
492 | tx_time = ctime + 2 * (mi->overhead + tx_time_data); | ||
493 | tx_time_rtscts = ctime + 2 * (mi->overhead_rtscts + tx_time_data); | ||
494 | |||
495 | /* See how many more tries we can fit inside segment size */ | ||
485 | do { | 496 | do { |
486 | cw = (cw << 1) | 1; | 497 | /* Contention time for this try */ |
487 | cw = min(cw, mp->cw_max); | 498 | ctime = (t_slot * cw) >> 1; |
488 | tx_time += cw + t_slot + mi->overhead; | 499 | cw = min((cw << 1) | 1, mp->cw_max); |
489 | tx_time_rtscts += cw + t_slot + mi->overhead_rtscts; | 500 | |
501 | /* Total TX time after this try */ | ||
502 | tx_time += ctime + mi->overhead + tx_time_data; | ||
503 | tx_time_rtscts += ctime + mi->overhead_rtscts + tx_time_data; | ||
504 | |||
490 | if (tx_time_rtscts < mp->segment_size) | 505 | if (tx_time_rtscts < mp->segment_size) |
491 | mr->retry_count_rtscts++; | 506 | mr->retry_count_rtscts++; |
492 | } while ((tx_time < mp->segment_size) && | 507 | } while ((tx_time < mp->segment_size) && |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 13a6697651ad..7fa8c6be7bf0 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -404,11 +404,13 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) | |||
404 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); | 404 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); |
405 | struct sk_buff *skb = rx->skb; | 405 | struct sk_buff *skb = rx->skb; |
406 | 406 | ||
407 | if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN))) | 407 | if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN) && |
408 | !local->sched_scanning)) | ||
408 | return RX_CONTINUE; | 409 | return RX_CONTINUE; |
409 | 410 | ||
410 | if (test_bit(SCAN_HW_SCANNING, &local->scanning) || | 411 | if (test_bit(SCAN_HW_SCANNING, &local->scanning) || |
411 | test_bit(SCAN_SW_SCANNING, &local->scanning)) | 412 | test_bit(SCAN_SW_SCANNING, &local->scanning) || |
413 | local->sched_scanning) | ||
412 | return ieee80211_scan_rx(rx->sdata, skb); | 414 | return ieee80211_scan_rx(rx->sdata, skb); |
413 | 415 | ||
414 | /* scanning finished during invoking of handlers */ | 416 | /* scanning finished during invoking of handlers */ |
@@ -488,15 +490,18 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
488 | * establisment frame, beacon or probe, drop the frame. | 490 | * establisment frame, beacon or probe, drop the frame. |
489 | */ | 491 | */ |
490 | 492 | ||
491 | if (!rx->sta || sta_plink_state(rx->sta) != PLINK_ESTAB) { | 493 | if (!rx->sta || sta_plink_state(rx->sta) != NL80211_PLINK_ESTAB) { |
492 | struct ieee80211_mgmt *mgmt; | 494 | struct ieee80211_mgmt *mgmt; |
493 | 495 | ||
494 | if (!ieee80211_is_mgmt(hdr->frame_control)) | 496 | if (!ieee80211_is_mgmt(hdr->frame_control)) |
495 | return RX_DROP_MONITOR; | 497 | return RX_DROP_MONITOR; |
496 | 498 | ||
497 | if (ieee80211_is_action(hdr->frame_control)) { | 499 | if (ieee80211_is_action(hdr->frame_control)) { |
500 | u8 category; | ||
498 | mgmt = (struct ieee80211_mgmt *)hdr; | 501 | mgmt = (struct ieee80211_mgmt *)hdr; |
499 | if (mgmt->u.action.category != WLAN_CATEGORY_MESH_PLINK) | 502 | category = mgmt->u.action.category; |
503 | if (category != WLAN_CATEGORY_MESH_ACTION && | ||
504 | category != WLAN_CATEGORY_SELF_PROTECTED) | ||
500 | return RX_DROP_MONITOR; | 505 | return RX_DROP_MONITOR; |
501 | return RX_CONTINUE; | 506 | return RX_CONTINUE; |
502 | } | 507 | } |
@@ -1778,7 +1783,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) | |||
1778 | 1783 | ||
1779 | ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, | 1784 | ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, |
1780 | rx->sdata->vif.type, | 1785 | rx->sdata->vif.type, |
1781 | rx->local->hw.extra_tx_headroom); | 1786 | rx->local->hw.extra_tx_headroom, true); |
1782 | 1787 | ||
1783 | while (!skb_queue_empty(&frame_list)) { | 1788 | while (!skb_queue_empty(&frame_list)) { |
1784 | rx->skb = __skb_dequeue(&frame_list); | 1789 | rx->skb = __skb_dequeue(&frame_list); |
@@ -2205,7 +2210,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2205 | goto handled; | 2210 | goto handled; |
2206 | } | 2211 | } |
2207 | break; | 2212 | break; |
2208 | case WLAN_CATEGORY_MESH_PLINK: | 2213 | case WLAN_CATEGORY_MESH_ACTION: |
2209 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | 2214 | if (!ieee80211_vif_is_mesh(&sdata->vif)) |
2210 | break; | 2215 | break; |
2211 | goto queue; | 2216 | goto queue; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 489b6ad200d4..d20046b5d8f4 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/if_arp.h> | 15 | #include <linux/if_arp.h> |
16 | #include <linux/rtnetlink.h> | 16 | #include <linux/rtnetlink.h> |
17 | #include <linux/pm_qos_params.h> | 17 | #include <linux/pm_qos_params.h> |
18 | #include <linux/slab.h> | ||
18 | #include <net/sch_generic.h> | 19 | #include <net/sch_generic.h> |
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
20 | #include <net/mac80211.h> | 21 | #include <net/mac80211.h> |
@@ -170,7 +171,7 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
170 | return RX_CONTINUE; | 171 | return RX_CONTINUE; |
171 | 172 | ||
172 | if (skb->len < 24) | 173 | if (skb->len < 24) |
173 | return RX_DROP_MONITOR; | 174 | return RX_CONTINUE; |
174 | 175 | ||
175 | presp = ieee80211_is_probe_resp(fc); | 176 | presp = ieee80211_is_probe_resp(fc); |
176 | if (presp) { | 177 | if (presp) { |
@@ -850,3 +851,122 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) | |||
850 | } | 851 | } |
851 | mutex_unlock(&local->mtx); | 852 | mutex_unlock(&local->mtx); |
852 | } | 853 | } |
854 | |||
855 | int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | ||
856 | struct cfg80211_sched_scan_request *req) | ||
857 | { | ||
858 | struct ieee80211_local *local = sdata->local; | ||
859 | int ret, i; | ||
860 | |||
861 | mutex_lock(&sdata->local->mtx); | ||
862 | |||
863 | if (local->sched_scanning) { | ||
864 | ret = -EBUSY; | ||
865 | goto out; | ||
866 | } | ||
867 | |||
868 | if (!local->ops->sched_scan_start) { | ||
869 | ret = -ENOTSUPP; | ||
870 | goto out; | ||
871 | } | ||
872 | |||
873 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | ||
874 | local->sched_scan_ies.ie[i] = kzalloc(2 + | ||
875 | IEEE80211_MAX_SSID_LEN + | ||
876 | local->scan_ies_len, | ||
877 | GFP_KERNEL); | ||
878 | if (!local->sched_scan_ies.ie[i]) { | ||
879 | ret = -ENOMEM; | ||
880 | goto out_free; | ||
881 | } | ||
882 | |||
883 | local->sched_scan_ies.len[i] = | ||
884 | ieee80211_build_preq_ies(local, | ||
885 | local->sched_scan_ies.ie[i], | ||
886 | req->ie, req->ie_len, i, | ||
887 | (u32) -1, 0); | ||
888 | } | ||
889 | |||
890 | ret = drv_sched_scan_start(local, sdata, req, | ||
891 | &local->sched_scan_ies); | ||
892 | if (ret == 0) { | ||
893 | local->sched_scanning = true; | ||
894 | goto out; | ||
895 | } | ||
896 | |||
897 | out_free: | ||
898 | while (i > 0) | ||
899 | kfree(local->sched_scan_ies.ie[--i]); | ||
900 | out: | ||
901 | mutex_unlock(&sdata->local->mtx); | ||
902 | return ret; | ||
903 | } | ||
904 | |||
905 | int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) | ||
906 | { | ||
907 | struct ieee80211_local *local = sdata->local; | ||
908 | int ret = 0, i; | ||
909 | |||
910 | mutex_lock(&sdata->local->mtx); | ||
911 | |||
912 | if (!local->ops->sched_scan_stop) { | ||
913 | ret = -ENOTSUPP; | ||
914 | goto out; | ||
915 | } | ||
916 | |||
917 | if (local->sched_scanning) { | ||
918 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) | ||
919 | kfree(local->sched_scan_ies.ie[i]); | ||
920 | |||
921 | drv_sched_scan_stop(local, sdata); | ||
922 | local->sched_scanning = false; | ||
923 | } | ||
924 | out: | ||
925 | mutex_unlock(&sdata->local->mtx); | ||
926 | |||
927 | return ret; | ||
928 | } | ||
929 | |||
930 | void ieee80211_sched_scan_results(struct ieee80211_hw *hw) | ||
931 | { | ||
932 | struct ieee80211_local *local = hw_to_local(hw); | ||
933 | |||
934 | trace_api_sched_scan_results(local); | ||
935 | |||
936 | cfg80211_sched_scan_results(hw->wiphy); | ||
937 | } | ||
938 | EXPORT_SYMBOL(ieee80211_sched_scan_results); | ||
939 | |||
940 | void ieee80211_sched_scan_stopped_work(struct work_struct *work) | ||
941 | { | ||
942 | struct ieee80211_local *local = | ||
943 | container_of(work, struct ieee80211_local, | ||
944 | sched_scan_stopped_work); | ||
945 | int i; | ||
946 | |||
947 | mutex_lock(&local->mtx); | ||
948 | |||
949 | if (!local->sched_scanning) { | ||
950 | mutex_unlock(&local->mtx); | ||
951 | return; | ||
952 | } | ||
953 | |||
954 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) | ||
955 | kfree(local->sched_scan_ies.ie[i]); | ||
956 | |||
957 | local->sched_scanning = false; | ||
958 | |||
959 | mutex_unlock(&local->mtx); | ||
960 | |||
961 | cfg80211_sched_scan_stopped(local->hw.wiphy); | ||
962 | } | ||
963 | |||
964 | void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw) | ||
965 | { | ||
966 | struct ieee80211_local *local = hw_to_local(hw); | ||
967 | |||
968 | trace_api_sched_scan_stopped(local); | ||
969 | |||
970 | ieee80211_queue_work(&local->hw, &local->sched_scan_stopped_work); | ||
971 | } | ||
972 | EXPORT_SYMBOL(ieee80211_sched_scan_stopped); | ||
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d9e6e81ff6b2..b83870bf60fa 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -67,7 +67,8 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
67 | { | 67 | { |
68 | struct sta_info *s; | 68 | struct sta_info *s; |
69 | 69 | ||
70 | s = local->sta_hash[STA_HASH(sta->sta.addr)]; | 70 | s = rcu_dereference_protected(local->sta_hash[STA_HASH(sta->sta.addr)], |
71 | lockdep_is_held(&local->sta_lock)); | ||
71 | if (!s) | 72 | if (!s) |
72 | return -ENOENT; | 73 | return -ENOENT; |
73 | if (s == sta) { | 74 | if (s == sta) { |
@@ -76,9 +77,11 @@ static int sta_info_hash_del(struct ieee80211_local *local, | |||
76 | return 0; | 77 | return 0; |
77 | } | 78 | } |
78 | 79 | ||
79 | while (s->hnext && s->hnext != sta) | 80 | while (rcu_access_pointer(s->hnext) && |
80 | s = s->hnext; | 81 | rcu_access_pointer(s->hnext) != sta) |
81 | if (s->hnext) { | 82 | s = rcu_dereference_protected(s->hnext, |
83 | lockdep_is_held(&local->sta_lock)); | ||
84 | if (rcu_access_pointer(s->hnext)) { | ||
82 | rcu_assign_pointer(s->hnext, sta->hnext); | 85 | rcu_assign_pointer(s->hnext, sta->hnext); |
83 | return 0; | 86 | return 0; |
84 | } | 87 | } |
@@ -274,7 +277,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
274 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ | 277 | #endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ |
275 | 278 | ||
276 | #ifdef CONFIG_MAC80211_MESH | 279 | #ifdef CONFIG_MAC80211_MESH |
277 | sta->plink_state = PLINK_LISTEN; | 280 | sta->plink_state = NL80211_PLINK_LISTEN; |
278 | init_timer(&sta->plink_timer); | 281 | init_timer(&sta->plink_timer); |
279 | #endif | 282 | #endif |
280 | 283 | ||
@@ -652,10 +655,12 @@ static int __must_check __sta_info_destroy(struct sta_info *sta) | |||
652 | if (ret) | 655 | if (ret) |
653 | return ret; | 656 | return ret; |
654 | 657 | ||
658 | mutex_lock(&local->key_mtx); | ||
655 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) | 659 | for (i = 0; i < NUM_DEFAULT_KEYS; i++) |
656 | ieee80211_key_free(local, sta->gtk[i]); | 660 | __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i])); |
657 | if (sta->ptk) | 661 | if (sta->ptk) |
658 | ieee80211_key_free(local, sta->ptk); | 662 | __ieee80211_key_free(key_mtx_dereference(local, sta->ptk)); |
663 | mutex_unlock(&local->key_mtx); | ||
659 | 664 | ||
660 | sta->dead = true; | 665 | sta->dead = true; |
661 | 666 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index aa0adcbf3a93..c6ae8718bd57 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -152,6 +152,7 @@ struct tid_ampdu_rx { | |||
152 | * | 152 | * |
153 | * @tid_rx: aggregation info for Rx per TID -- RCU protected | 153 | * @tid_rx: aggregation info for Rx per TID -- RCU protected |
154 | * @tid_tx: aggregation info for Tx per TID | 154 | * @tid_tx: aggregation info for Tx per TID |
155 | * @tid_start_tx: sessions where start was requested | ||
155 | * @addba_req_num: number of times addBA request has been sent. | 156 | * @addba_req_num: number of times addBA request has been sent. |
156 | * @dialog_token_allocator: dialog token enumerator for each new session; | 157 | * @dialog_token_allocator: dialog token enumerator for each new session; |
157 | * @work: work struct for starting/stopping aggregation | 158 | * @work: work struct for starting/stopping aggregation |
@@ -163,40 +164,18 @@ struct tid_ampdu_rx { | |||
163 | struct sta_ampdu_mlme { | 164 | struct sta_ampdu_mlme { |
164 | struct mutex mtx; | 165 | struct mutex mtx; |
165 | /* rx */ | 166 | /* rx */ |
166 | struct tid_ampdu_rx *tid_rx[STA_TID_NUM]; | 167 | struct tid_ampdu_rx __rcu *tid_rx[STA_TID_NUM]; |
167 | unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)]; | 168 | unsigned long tid_rx_timer_expired[BITS_TO_LONGS(STA_TID_NUM)]; |
168 | /* tx */ | 169 | /* tx */ |
169 | struct work_struct work; | 170 | struct work_struct work; |
170 | struct tid_ampdu_tx *tid_tx[STA_TID_NUM]; | 171 | struct tid_ampdu_tx __rcu *tid_tx[STA_TID_NUM]; |
172 | struct tid_ampdu_tx *tid_start_tx[STA_TID_NUM]; | ||
171 | u8 addba_req_num[STA_TID_NUM]; | 173 | u8 addba_req_num[STA_TID_NUM]; |
172 | u8 dialog_token_allocator; | 174 | u8 dialog_token_allocator; |
173 | }; | 175 | }; |
174 | 176 | ||
175 | 177 | ||
176 | /** | 178 | /** |
177 | * enum plink_state - state of a mesh peer link finite state machine | ||
178 | * | ||
179 | * @PLINK_LISTEN: initial state, considered the implicit state of non existent | ||
180 | * mesh peer links | ||
181 | * @PLINK_OPN_SNT: mesh plink open frame has been sent to this mesh peer | ||
182 | * @PLINK_OPN_RCVD: mesh plink open frame has been received from this mesh peer | ||
183 | * @PLINK_CNF_RCVD: mesh plink confirm frame has been received from this mesh | ||
184 | * peer | ||
185 | * @PLINK_ESTAB: mesh peer link is established | ||
186 | * @PLINK_HOLDING: mesh peer link is being closed or cancelled | ||
187 | * @PLINK_BLOCKED: all frames transmitted from this mesh plink are discarded | ||
188 | */ | ||
189 | enum plink_state { | ||
190 | PLINK_LISTEN, | ||
191 | PLINK_OPN_SNT, | ||
192 | PLINK_OPN_RCVD, | ||
193 | PLINK_CNF_RCVD, | ||
194 | PLINK_ESTAB, | ||
195 | PLINK_HOLDING, | ||
196 | PLINK_BLOCKED | ||
197 | }; | ||
198 | |||
199 | /** | ||
200 | * struct sta_info - STA information | 179 | * struct sta_info - STA information |
201 | * | 180 | * |
202 | * This structure collects information about a station that | 181 | * This structure collects information about a station that |
@@ -264,11 +243,11 @@ enum plink_state { | |||
264 | struct sta_info { | 243 | struct sta_info { |
265 | /* General information, mostly static */ | 244 | /* General information, mostly static */ |
266 | struct list_head list; | 245 | struct list_head list; |
267 | struct sta_info *hnext; | 246 | struct sta_info __rcu *hnext; |
268 | struct ieee80211_local *local; | 247 | struct ieee80211_local *local; |
269 | struct ieee80211_sub_if_data *sdata; | 248 | struct ieee80211_sub_if_data *sdata; |
270 | struct ieee80211_key *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; | 249 | struct ieee80211_key __rcu *gtk[NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS]; |
271 | struct ieee80211_key *ptk; | 250 | struct ieee80211_key __rcu *ptk; |
272 | struct rate_control_ref *rate_ctrl; | 251 | struct rate_control_ref *rate_ctrl; |
273 | void *rate_ctrl_priv; | 252 | void *rate_ctrl_priv; |
274 | spinlock_t lock; | 253 | spinlock_t lock; |
@@ -339,7 +318,7 @@ struct sta_info { | |||
339 | u8 plink_retries; | 318 | u8 plink_retries; |
340 | bool ignore_plink_timer; | 319 | bool ignore_plink_timer; |
341 | bool plink_timer_was_running; | 320 | bool plink_timer_was_running; |
342 | enum plink_state plink_state; | 321 | enum nl80211_plink_state plink_state; |
343 | u32 plink_timeout; | 322 | u32 plink_timeout; |
344 | struct timer_list plink_timer; | 323 | struct timer_list plink_timer; |
345 | #endif | 324 | #endif |
@@ -357,12 +336,12 @@ struct sta_info { | |||
357 | struct ieee80211_sta sta; | 336 | struct ieee80211_sta sta; |
358 | }; | 337 | }; |
359 | 338 | ||
360 | static inline enum plink_state sta_plink_state(struct sta_info *sta) | 339 | static inline enum nl80211_plink_state sta_plink_state(struct sta_info *sta) |
361 | { | 340 | { |
362 | #ifdef CONFIG_MAC80211_MESH | 341 | #ifdef CONFIG_MAC80211_MESH |
363 | return sta->plink_state; | 342 | return sta->plink_state; |
364 | #endif | 343 | #endif |
365 | return PLINK_LISTEN; | 344 | return NL80211_PLINK_LISTEN; |
366 | } | 345 | } |
367 | 346 | ||
368 | static inline void set_sta_flags(struct sta_info *sta, const u32 flags) | 347 | static inline void set_sta_flags(struct sta_info *sta, const u32 flags) |
@@ -421,7 +400,16 @@ static inline u32 get_sta_flags(struct sta_info *sta) | |||
421 | return ret; | 400 | return ret; |
422 | } | 401 | } |
423 | 402 | ||
403 | void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, | ||
404 | struct tid_ampdu_tx *tid_tx); | ||
424 | 405 | ||
406 | static inline struct tid_ampdu_tx * | ||
407 | rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid) | ||
408 | { | ||
409 | return rcu_dereference_protected(sta->ampdu_mlme.tid_tx[tid], | ||
410 | lockdep_is_held(&sta->lock) || | ||
411 | lockdep_is_held(&sta->ampdu_mlme.mtx)); | ||
412 | } | ||
425 | 413 | ||
426 | #define STA_HASH_SIZE 256 | 414 | #define STA_HASH_SIZE 256 |
427 | #define STA_HASH(sta) (sta[5]) | 415 | #define STA_HASH(sta) (sta[5]) |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e3e3aa173af0..6eeaaa2bbafe 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1147,7 +1147,7 @@ static bool ieee80211_tx_prep_agg(struct ieee80211_tx_data *tx, | |||
1147 | * packet pass through because splicing the frames | 1147 | * packet pass through because splicing the frames |
1148 | * back is already done. | 1148 | * back is already done. |
1149 | */ | 1149 | */ |
1150 | tid_tx = tx->sta->ampdu_mlme.tid_tx[tid]; | 1150 | tid_tx = rcu_dereference_protected_tid_tx(tx->sta, tid); |
1151 | 1151 | ||
1152 | if (!tid_tx) { | 1152 | if (!tid_tx) { |
1153 | /* do nothing, let packet pass through */ | 1153 | /* do nothing, let packet pass through */ |
@@ -1751,6 +1751,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1751 | ret = NETDEV_TX_OK; | 1751 | ret = NETDEV_TX_OK; |
1752 | goto fail; | 1752 | goto fail; |
1753 | } | 1753 | } |
1754 | rcu_read_lock(); | ||
1754 | if (!is_multicast_ether_addr(skb->data)) | 1755 | if (!is_multicast_ether_addr(skb->data)) |
1755 | mppath = mpp_path_lookup(skb->data, sdata); | 1756 | mppath = mpp_path_lookup(skb->data, sdata); |
1756 | 1757 | ||
@@ -1765,13 +1766,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1765 | !(mppath && compare_ether_addr(mppath->mpp, skb->data))) { | 1766 | !(mppath && compare_ether_addr(mppath->mpp, skb->data))) { |
1766 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | 1767 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
1767 | skb->data, skb->data + ETH_ALEN); | 1768 | skb->data, skb->data + ETH_ALEN); |
1769 | rcu_read_unlock(); | ||
1768 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, | 1770 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, |
1769 | sdata, NULL, NULL); | 1771 | sdata, NULL, NULL); |
1770 | } else { | 1772 | } else { |
1771 | int is_mesh_mcast = 1; | 1773 | int is_mesh_mcast = 1; |
1772 | const u8 *mesh_da; | 1774 | const u8 *mesh_da; |
1773 | 1775 | ||
1774 | rcu_read_lock(); | ||
1775 | if (is_multicast_ether_addr(skb->data)) | 1776 | if (is_multicast_ether_addr(skb->data)) |
1776 | /* DA TA mSA AE:SA */ | 1777 | /* DA TA mSA AE:SA */ |
1777 | mesh_da = skb->data; | 1778 | mesh_da = skb->data; |
@@ -2534,8 +2535,9 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | |||
2534 | skb_set_network_header(skb, 0); | 2535 | skb_set_network_header(skb, 0); |
2535 | skb_set_transport_header(skb, 0); | 2536 | skb_set_transport_header(skb, 0); |
2536 | 2537 | ||
2537 | /* send all internal mgmt frames on VO */ | 2538 | /* Send all internal mgmt frames on VO. Accordingly set TID to 7. */ |
2538 | skb_set_queue_mapping(skb, 0); | 2539 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); |
2540 | skb->priority = 7; | ||
2539 | 2541 | ||
2540 | /* | 2542 | /* |
2541 | * The other path calling ieee80211_xmit is from the tasklet, | 2543 | * The other path calling ieee80211_xmit is from the tasklet, |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index ef0560a2346a..d3fe2d237485 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1125,9 +1125,27 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1125 | struct sta_info *sta; | 1125 | struct sta_info *sta; |
1126 | int res; | 1126 | int res; |
1127 | 1127 | ||
1128 | #ifdef CONFIG_PM | ||
1128 | if (local->suspended) | 1129 | if (local->suspended) |
1129 | local->resuming = true; | 1130 | local->resuming = true; |
1130 | 1131 | ||
1132 | if (local->wowlan) { | ||
1133 | local->wowlan = false; | ||
1134 | res = drv_resume(local); | ||
1135 | if (res < 0) { | ||
1136 | local->resuming = false; | ||
1137 | return res; | ||
1138 | } | ||
1139 | if (res == 0) | ||
1140 | goto wake_up; | ||
1141 | WARN_ON(res > 1); | ||
1142 | /* | ||
1143 | * res is 1, which means the driver requested | ||
1144 | * to go through a regular reset on wakeup. | ||
1145 | */ | ||
1146 | } | ||
1147 | #endif | ||
1148 | |||
1131 | /* restart hardware */ | 1149 | /* restart hardware */ |
1132 | if (local->open_count) { | 1150 | if (local->open_count) { |
1133 | /* | 1151 | /* |
@@ -1258,6 +1276,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1258 | if (ieee80211_sdata_running(sdata)) | 1276 | if (ieee80211_sdata_running(sdata)) |
1259 | ieee80211_enable_keys(sdata); | 1277 | ieee80211_enable_keys(sdata); |
1260 | 1278 | ||
1279 | wake_up: | ||
1261 | ieee80211_wake_queues_by_reason(hw, | 1280 | ieee80211_wake_queues_by_reason(hw, |
1262 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 1281 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); |
1263 | 1282 | ||
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 0198191b756d..be90640a2774 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
@@ -1024,7 +1024,6 @@ static int rfkill_fop_open(struct inode *inode, struct file *file) | |||
1024 | * start getting events from elsewhere but hold mtx to get | 1024 | * start getting events from elsewhere but hold mtx to get |
1025 | * startup events added first | 1025 | * startup events added first |
1026 | */ | 1026 | */ |
1027 | list_add(&data->list, &rfkill_fds); | ||
1028 | 1027 | ||
1029 | list_for_each_entry(rfkill, &rfkill_list, node) { | 1028 | list_for_each_entry(rfkill, &rfkill_list, node) { |
1030 | ev = kzalloc(sizeof(*ev), GFP_KERNEL); | 1029 | ev = kzalloc(sizeof(*ev), GFP_KERNEL); |
@@ -1033,6 +1032,7 @@ static int rfkill_fop_open(struct inode *inode, struct file *file) | |||
1033 | rfkill_fill_event(&ev->ev, rfkill, RFKILL_OP_ADD); | 1032 | rfkill_fill_event(&ev->ev, rfkill, RFKILL_OP_ADD); |
1034 | list_add_tail(&ev->list, &data->events); | 1033 | list_add_tail(&ev->list, &data->events); |
1035 | } | 1034 | } |
1035 | list_add(&data->list, &rfkill_fds); | ||
1036 | mutex_unlock(&data->mtx); | 1036 | mutex_unlock(&data->mtx); |
1037 | mutex_unlock(&rfkill_global_mutex); | 1037 | mutex_unlock(&rfkill_global_mutex); |
1038 | 1038 | ||
diff --git a/net/wireless/core.c b/net/wireless/core.c index bbf1fa11107a..c22ef3492ee6 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -370,7 +370,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | |||
370 | spin_lock_init(&rdev->bss_lock); | 370 | spin_lock_init(&rdev->bss_lock); |
371 | INIT_LIST_HEAD(&rdev->bss_list); | 371 | INIT_LIST_HEAD(&rdev->bss_list); |
372 | INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done); | 372 | INIT_WORK(&rdev->scan_done_wk, __cfg80211_scan_done); |
373 | 373 | INIT_WORK(&rdev->sched_scan_results_wk, __cfg80211_sched_scan_results); | |
374 | #ifdef CONFIG_CFG80211_WEXT | 374 | #ifdef CONFIG_CFG80211_WEXT |
375 | rdev->wiphy.wext = &cfg80211_wext_handler; | 375 | rdev->wiphy.wext = &cfg80211_wext_handler; |
376 | #endif | 376 | #endif |
@@ -416,6 +416,67 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv) | |||
416 | } | 416 | } |
417 | EXPORT_SYMBOL(wiphy_new); | 417 | EXPORT_SYMBOL(wiphy_new); |
418 | 418 | ||
419 | static int wiphy_verify_combinations(struct wiphy *wiphy) | ||
420 | { | ||
421 | const struct ieee80211_iface_combination *c; | ||
422 | int i, j; | ||
423 | |||
424 | /* If we have combinations enforce them */ | ||
425 | if (wiphy->n_iface_combinations) | ||
426 | wiphy->flags |= WIPHY_FLAG_ENFORCE_COMBINATIONS; | ||
427 | |||
428 | for (i = 0; i < wiphy->n_iface_combinations; i++) { | ||
429 | u32 cnt = 0; | ||
430 | u16 all_iftypes = 0; | ||
431 | |||
432 | c = &wiphy->iface_combinations[i]; | ||
433 | |||
434 | /* Combinations with just one interface aren't real */ | ||
435 | if (WARN_ON(c->max_interfaces < 2)) | ||
436 | return -EINVAL; | ||
437 | |||
438 | /* Need at least one channel */ | ||
439 | if (WARN_ON(!c->num_different_channels)) | ||
440 | return -EINVAL; | ||
441 | |||
442 | if (WARN_ON(!c->n_limits)) | ||
443 | return -EINVAL; | ||
444 | |||
445 | for (j = 0; j < c->n_limits; j++) { | ||
446 | u16 types = c->limits[j].types; | ||
447 | |||
448 | /* | ||
449 | * interface types shouldn't overlap, this is | ||
450 | * used in cfg80211_can_change_interface() | ||
451 | */ | ||
452 | if (WARN_ON(types & all_iftypes)) | ||
453 | return -EINVAL; | ||
454 | all_iftypes |= types; | ||
455 | |||
456 | if (WARN_ON(!c->limits[j].max)) | ||
457 | return -EINVAL; | ||
458 | |||
459 | /* Shouldn't list software iftypes in combinations! */ | ||
460 | if (WARN_ON(wiphy->software_iftypes & types)) | ||
461 | return -EINVAL; | ||
462 | |||
463 | cnt += c->limits[j].max; | ||
464 | /* | ||
465 | * Don't advertise an unsupported type | ||
466 | * in a combination. | ||
467 | */ | ||
468 | if (WARN_ON((wiphy->interface_modes & types) != types)) | ||
469 | return -EINVAL; | ||
470 | } | ||
471 | |||
472 | /* You can't even choose that many! */ | ||
473 | if (WARN_ON(cnt < c->max_interfaces)) | ||
474 | return -EINVAL; | ||
475 | } | ||
476 | |||
477 | return 0; | ||
478 | } | ||
479 | |||
419 | int wiphy_register(struct wiphy *wiphy) | 480 | int wiphy_register(struct wiphy *wiphy) |
420 | { | 481 | { |
421 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | 482 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); |
@@ -444,6 +505,10 @@ int wiphy_register(struct wiphy *wiphy) | |||
444 | if (WARN_ON(ifmodes != wiphy->interface_modes)) | 505 | if (WARN_ON(ifmodes != wiphy->interface_modes)) |
445 | wiphy->interface_modes = ifmodes; | 506 | wiphy->interface_modes = ifmodes; |
446 | 507 | ||
508 | res = wiphy_verify_combinations(wiphy); | ||
509 | if (res) | ||
510 | return res; | ||
511 | |||
447 | /* sanity check supported bands/channels */ | 512 | /* sanity check supported bands/channels */ |
448 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | 513 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { |
449 | sband = wiphy->bands[band]; | 514 | sband = wiphy->bands[band]; |
@@ -493,6 +558,13 @@ int wiphy_register(struct wiphy *wiphy) | |||
493 | return -EINVAL; | 558 | return -EINVAL; |
494 | } | 559 | } |
495 | 560 | ||
561 | if (rdev->wiphy.wowlan.n_patterns) { | ||
562 | if (WARN_ON(!rdev->wiphy.wowlan.pattern_min_len || | ||
563 | rdev->wiphy.wowlan.pattern_min_len > | ||
564 | rdev->wiphy.wowlan.pattern_max_len)) | ||
565 | return -EINVAL; | ||
566 | } | ||
567 | |||
496 | /* check and set up bitrates */ | 568 | /* check and set up bitrates */ |
497 | ieee80211_set_bitrate_flags(wiphy); | 569 | ieee80211_set_bitrate_flags(wiphy); |
498 | 570 | ||
@@ -631,6 +703,7 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev) | |||
631 | mutex_destroy(&rdev->devlist_mtx); | 703 | mutex_destroy(&rdev->devlist_mtx); |
632 | list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) | 704 | list_for_each_entry_safe(scan, tmp, &rdev->bss_list, list) |
633 | cfg80211_put_bss(&scan->pub); | 705 | cfg80211_put_bss(&scan->pub); |
706 | cfg80211_rdev_free_wowlan(rdev); | ||
634 | kfree(rdev); | 707 | kfree(rdev); |
635 | } | 708 | } |
636 | 709 | ||
@@ -664,6 +737,11 @@ static void wdev_cleanup_work(struct work_struct *work) | |||
664 | ___cfg80211_scan_done(rdev, true); | 737 | ___cfg80211_scan_done(rdev, true); |
665 | } | 738 | } |
666 | 739 | ||
740 | if (WARN_ON(rdev->sched_scan_req && | ||
741 | rdev->sched_scan_req->dev == wdev->netdev)) { | ||
742 | __cfg80211_stop_sched_scan(rdev, false); | ||
743 | } | ||
744 | |||
667 | cfg80211_unlock_rdev(rdev); | 745 | cfg80211_unlock_rdev(rdev); |
668 | 746 | ||
669 | mutex_lock(&rdev->devlist_mtx); | 747 | mutex_lock(&rdev->devlist_mtx); |
@@ -685,6 +763,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
685 | struct net_device *dev = ndev; | 763 | struct net_device *dev = ndev; |
686 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 764 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
687 | struct cfg80211_registered_device *rdev; | 765 | struct cfg80211_registered_device *rdev; |
766 | int ret; | ||
688 | 767 | ||
689 | if (!wdev) | 768 | if (!wdev) |
690 | return NOTIFY_DONE; | 769 | return NOTIFY_DONE; |
@@ -751,6 +830,10 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
751 | break; | 830 | break; |
752 | case NL80211_IFTYPE_P2P_CLIENT: | 831 | case NL80211_IFTYPE_P2P_CLIENT: |
753 | case NL80211_IFTYPE_STATION: | 832 | case NL80211_IFTYPE_STATION: |
833 | cfg80211_lock_rdev(rdev); | ||
834 | __cfg80211_stop_sched_scan(rdev, false); | ||
835 | cfg80211_unlock_rdev(rdev); | ||
836 | |||
754 | wdev_lock(wdev); | 837 | wdev_lock(wdev); |
755 | #ifdef CONFIG_CFG80211_WEXT | 838 | #ifdef CONFIG_CFG80211_WEXT |
756 | kfree(wdev->wext.ie); | 839 | kfree(wdev->wext.ie); |
@@ -769,6 +852,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
769 | default: | 852 | default: |
770 | break; | 853 | break; |
771 | } | 854 | } |
855 | wdev->beacon_interval = 0; | ||
772 | break; | 856 | break; |
773 | case NETDEV_DOWN: | 857 | case NETDEV_DOWN: |
774 | dev_hold(dev); | 858 | dev_hold(dev); |
@@ -875,6 +959,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, | |||
875 | return notifier_from_errno(-EOPNOTSUPP); | 959 | return notifier_from_errno(-EOPNOTSUPP); |
876 | if (rfkill_blocked(rdev->rfkill)) | 960 | if (rfkill_blocked(rdev->rfkill)) |
877 | return notifier_from_errno(-ERFKILL); | 961 | return notifier_from_errno(-ERFKILL); |
962 | ret = cfg80211_can_add_interface(rdev, wdev->iftype); | ||
963 | if (ret) | ||
964 | return notifier_from_errno(ret); | ||
878 | break; | 965 | break; |
879 | } | 966 | } |
880 | 967 | ||
diff --git a/net/wireless/core.h b/net/wireless/core.h index 26a0a084e16b..bf0fb40e3c8b 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -60,8 +60,10 @@ struct cfg80211_registered_device { | |||
60 | struct rb_root bss_tree; | 60 | struct rb_root bss_tree; |
61 | u32 bss_generation; | 61 | u32 bss_generation; |
62 | struct cfg80211_scan_request *scan_req; /* protected by RTNL */ | 62 | struct cfg80211_scan_request *scan_req; /* protected by RTNL */ |
63 | struct cfg80211_sched_scan_request *sched_scan_req; | ||
63 | unsigned long suspend_at; | 64 | unsigned long suspend_at; |
64 | struct work_struct scan_done_wk; | 65 | struct work_struct scan_done_wk; |
66 | struct work_struct sched_scan_results_wk; | ||
65 | 67 | ||
66 | #ifdef CONFIG_NL80211_TESTMODE | 68 | #ifdef CONFIG_NL80211_TESTMODE |
67 | struct genl_info *testmode_info; | 69 | struct genl_info *testmode_info; |
@@ -70,6 +72,8 @@ struct cfg80211_registered_device { | |||
70 | struct work_struct conn_work; | 72 | struct work_struct conn_work; |
71 | struct work_struct event_work; | 73 | struct work_struct event_work; |
72 | 74 | ||
75 | struct cfg80211_wowlan *wowlan; | ||
76 | |||
73 | /* must be last because of the way we do wiphy_priv(), | 77 | /* must be last because of the way we do wiphy_priv(), |
74 | * and it should at least be aligned to NETDEV_ALIGN */ | 78 | * and it should at least be aligned to NETDEV_ALIGN */ |
75 | struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN))); | 79 | struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN))); |
@@ -89,6 +93,18 @@ bool wiphy_idx_valid(int wiphy_idx) | |||
89 | return wiphy_idx >= 0; | 93 | return wiphy_idx >= 0; |
90 | } | 94 | } |
91 | 95 | ||
96 | static inline void | ||
97 | cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev) | ||
98 | { | ||
99 | int i; | ||
100 | |||
101 | if (!rdev->wowlan) | ||
102 | return; | ||
103 | for (i = 0; i < rdev->wowlan->n_patterns; i++) | ||
104 | kfree(rdev->wowlan->patterns[i].mask); | ||
105 | kfree(rdev->wowlan->patterns); | ||
106 | kfree(rdev->wowlan); | ||
107 | } | ||
92 | 108 | ||
93 | extern struct workqueue_struct *cfg80211_wq; | 109 | extern struct workqueue_struct *cfg80211_wq; |
94 | extern struct mutex cfg80211_mutex; | 110 | extern struct mutex cfg80211_mutex; |
@@ -397,12 +413,26 @@ void cfg80211_sme_rx_auth(struct net_device *dev, const u8 *buf, size_t len); | |||
397 | void cfg80211_sme_disassoc(struct net_device *dev, int idx); | 413 | void cfg80211_sme_disassoc(struct net_device *dev, int idx); |
398 | void __cfg80211_scan_done(struct work_struct *wk); | 414 | void __cfg80211_scan_done(struct work_struct *wk); |
399 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak); | 415 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak); |
416 | void __cfg80211_sched_scan_results(struct work_struct *wk); | ||
417 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, | ||
418 | bool driver_initiated); | ||
400 | void cfg80211_upload_connect_keys(struct wireless_dev *wdev); | 419 | void cfg80211_upload_connect_keys(struct wireless_dev *wdev); |
401 | int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | 420 | int cfg80211_change_iface(struct cfg80211_registered_device *rdev, |
402 | struct net_device *dev, enum nl80211_iftype ntype, | 421 | struct net_device *dev, enum nl80211_iftype ntype, |
403 | u32 *flags, struct vif_params *params); | 422 | u32 *flags, struct vif_params *params); |
404 | void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); | 423 | void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); |
405 | 424 | ||
425 | int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | ||
426 | struct wireless_dev *wdev, | ||
427 | enum nl80211_iftype iftype); | ||
428 | |||
429 | static inline int | ||
430 | cfg80211_can_add_interface(struct cfg80211_registered_device *rdev, | ||
431 | enum nl80211_iftype iftype) | ||
432 | { | ||
433 | return cfg80211_can_change_interface(rdev, NULL, iftype); | ||
434 | } | ||
435 | |||
406 | struct ieee80211_channel * | 436 | struct ieee80211_channel * |
407 | rdev_freq_to_chan(struct cfg80211_registered_device *rdev, | 437 | rdev_freq_to_chan(struct cfg80211_registered_device *rdev, |
408 | int freq, enum nl80211_channel_type channel_type); | 438 | int freq, enum nl80211_channel_type channel_type); |
@@ -412,6 +442,9 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev, | |||
412 | 442 | ||
413 | u16 cfg80211_calculate_bitrate(struct rate_info *rate); | 443 | u16 cfg80211_calculate_bitrate(struct rate_info *rate); |
414 | 444 | ||
445 | int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | ||
446 | u32 beacon_int); | ||
447 | |||
415 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS | 448 | #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS |
416 | #define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond) | 449 | #define CFG80211_DEV_WARN_ON(cond) WARN_ON(cond) |
417 | #else | 450 | #else |
diff --git a/net/wireless/lib80211_crypt_wep.c b/net/wireless/lib80211_crypt_wep.c index e2e88878ba35..2f265e033ae2 100644 --- a/net/wireless/lib80211_crypt_wep.c +++ b/net/wireless/lib80211_crypt_wep.c | |||
@@ -96,13 +96,12 @@ static int lib80211_wep_build_iv(struct sk_buff *skb, int hdr_len, | |||
96 | u8 *key, int keylen, void *priv) | 96 | u8 *key, int keylen, void *priv) |
97 | { | 97 | { |
98 | struct lib80211_wep_data *wep = priv; | 98 | struct lib80211_wep_data *wep = priv; |
99 | u32 klen, len; | 99 | u32 klen; |
100 | u8 *pos; | 100 | u8 *pos; |
101 | 101 | ||
102 | if (skb_headroom(skb) < 4 || skb->len < hdr_len) | 102 | if (skb_headroom(skb) < 4 || skb->len < hdr_len) |
103 | return -1; | 103 | return -1; |
104 | 104 | ||
105 | len = skb->len - hdr_len; | ||
106 | pos = skb_push(skb, 4); | 105 | pos = skb_push(skb, 4); |
107 | memmove(pos, pos + 4, hdr_len); | 106 | memmove(pos, pos + 4, hdr_len); |
108 | pos += hdr_len; | 107 | pos += hdr_len; |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 16881fea4ce6..493b939970cd 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -963,6 +963,16 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
963 | if (memcmp(mgmt->bssid, dev->dev_addr, ETH_ALEN)) | 963 | if (memcmp(mgmt->bssid, dev->dev_addr, ETH_ALEN)) |
964 | err = -EINVAL; | 964 | err = -EINVAL; |
965 | break; | 965 | break; |
966 | case NL80211_IFTYPE_MESH_POINT: | ||
967 | if (memcmp(mgmt->sa, mgmt->bssid, ETH_ALEN)) { | ||
968 | err = -EINVAL; | ||
969 | break; | ||
970 | } | ||
971 | /* | ||
972 | * check for mesh DA must be done by driver as | ||
973 | * cfg80211 doesn't track the stations | ||
974 | */ | ||
975 | break; | ||
966 | default: | 976 | default: |
967 | err = -EOPNOTSUPP; | 977 | err = -EOPNOTSUPP; |
968 | break; | 978 | break; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 0efa7fd01150..2222ce08ee91 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -173,6 +173,9 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
173 | [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 }, | 173 | [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 }, |
174 | [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG }, | 174 | [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG }, |
175 | [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED }, | 175 | [NL80211_ATTR_KEY_DEFAULT_TYPES] = { .type = NLA_NESTED }, |
176 | [NL80211_ATTR_WOWLAN_TRIGGERS] = { .type = NLA_NESTED }, | ||
177 | [NL80211_ATTR_STA_PLINK_STATE] = { .type = NLA_U8 }, | ||
178 | [NL80211_ATTR_SCHED_SCAN_INTERVAL] = { .type = NLA_U32 }, | ||
176 | }; | 179 | }; |
177 | 180 | ||
178 | /* policy for the key attributes */ | 181 | /* policy for the key attributes */ |
@@ -194,6 +197,15 @@ nl80211_key_default_policy[NUM_NL80211_KEY_DEFAULT_TYPES] = { | |||
194 | [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG }, | 197 | [NL80211_KEY_DEFAULT_TYPE_MULTICAST] = { .type = NLA_FLAG }, |
195 | }; | 198 | }; |
196 | 199 | ||
200 | /* policy for WoWLAN attributes */ | ||
201 | static const struct nla_policy | ||
202 | nl80211_wowlan_policy[NUM_NL80211_WOWLAN_TRIG] = { | ||
203 | [NL80211_WOWLAN_TRIG_ANY] = { .type = NLA_FLAG }, | ||
204 | [NL80211_WOWLAN_TRIG_DISCONNECT] = { .type = NLA_FLAG }, | ||
205 | [NL80211_WOWLAN_TRIG_MAGIC_PKT] = { .type = NLA_FLAG }, | ||
206 | [NL80211_WOWLAN_TRIG_PKT_PATTERN] = { .type = NLA_NESTED }, | ||
207 | }; | ||
208 | |||
197 | /* ifidx get helper */ | 209 | /* ifidx get helper */ |
198 | static int nl80211_get_ifidx(struct netlink_callback *cb) | 210 | static int nl80211_get_ifidx(struct netlink_callback *cb) |
199 | { | 211 | { |
@@ -534,6 +546,7 @@ static int nl80211_key_allowed(struct wireless_dev *wdev) | |||
534 | case NL80211_IFTYPE_AP: | 546 | case NL80211_IFTYPE_AP: |
535 | case NL80211_IFTYPE_AP_VLAN: | 547 | case NL80211_IFTYPE_AP_VLAN: |
536 | case NL80211_IFTYPE_P2P_GO: | 548 | case NL80211_IFTYPE_P2P_GO: |
549 | case NL80211_IFTYPE_MESH_POINT: | ||
537 | break; | 550 | break; |
538 | case NL80211_IFTYPE_ADHOC: | 551 | case NL80211_IFTYPE_ADHOC: |
539 | if (!wdev->current_bss) | 552 | if (!wdev->current_bss) |
@@ -551,6 +564,88 @@ static int nl80211_key_allowed(struct wireless_dev *wdev) | |||
551 | return 0; | 564 | return 0; |
552 | } | 565 | } |
553 | 566 | ||
567 | static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes) | ||
568 | { | ||
569 | struct nlattr *nl_modes = nla_nest_start(msg, attr); | ||
570 | int i; | ||
571 | |||
572 | if (!nl_modes) | ||
573 | goto nla_put_failure; | ||
574 | |||
575 | i = 0; | ||
576 | while (ifmodes) { | ||
577 | if (ifmodes & 1) | ||
578 | NLA_PUT_FLAG(msg, i); | ||
579 | ifmodes >>= 1; | ||
580 | i++; | ||
581 | } | ||
582 | |||
583 | nla_nest_end(msg, nl_modes); | ||
584 | return 0; | ||
585 | |||
586 | nla_put_failure: | ||
587 | return -ENOBUFS; | ||
588 | } | ||
589 | |||
590 | static int nl80211_put_iface_combinations(struct wiphy *wiphy, | ||
591 | struct sk_buff *msg) | ||
592 | { | ||
593 | struct nlattr *nl_combis; | ||
594 | int i, j; | ||
595 | |||
596 | nl_combis = nla_nest_start(msg, | ||
597 | NL80211_ATTR_INTERFACE_COMBINATIONS); | ||
598 | if (!nl_combis) | ||
599 | goto nla_put_failure; | ||
600 | |||
601 | for (i = 0; i < wiphy->n_iface_combinations; i++) { | ||
602 | const struct ieee80211_iface_combination *c; | ||
603 | struct nlattr *nl_combi, *nl_limits; | ||
604 | |||
605 | c = &wiphy->iface_combinations[i]; | ||
606 | |||
607 | nl_combi = nla_nest_start(msg, i + 1); | ||
608 | if (!nl_combi) | ||
609 | goto nla_put_failure; | ||
610 | |||
611 | nl_limits = nla_nest_start(msg, NL80211_IFACE_COMB_LIMITS); | ||
612 | if (!nl_limits) | ||
613 | goto nla_put_failure; | ||
614 | |||
615 | for (j = 0; j < c->n_limits; j++) { | ||
616 | struct nlattr *nl_limit; | ||
617 | |||
618 | nl_limit = nla_nest_start(msg, j + 1); | ||
619 | if (!nl_limit) | ||
620 | goto nla_put_failure; | ||
621 | NLA_PUT_U32(msg, NL80211_IFACE_LIMIT_MAX, | ||
622 | c->limits[j].max); | ||
623 | if (nl80211_put_iftypes(msg, NL80211_IFACE_LIMIT_TYPES, | ||
624 | c->limits[j].types)) | ||
625 | goto nla_put_failure; | ||
626 | nla_nest_end(msg, nl_limit); | ||
627 | } | ||
628 | |||
629 | nla_nest_end(msg, nl_limits); | ||
630 | |||
631 | if (c->beacon_int_infra_match) | ||
632 | NLA_PUT_FLAG(msg, | ||
633 | NL80211_IFACE_COMB_STA_AP_BI_MATCH); | ||
634 | NLA_PUT_U32(msg, NL80211_IFACE_COMB_NUM_CHANNELS, | ||
635 | c->num_different_channels); | ||
636 | NLA_PUT_U32(msg, NL80211_IFACE_COMB_MAXNUM, | ||
637 | c->max_interfaces); | ||
638 | |||
639 | nla_nest_end(msg, nl_combi); | ||
640 | } | ||
641 | |||
642 | nla_nest_end(msg, nl_combis); | ||
643 | |||
644 | return 0; | ||
645 | nla_put_failure: | ||
646 | return -ENOBUFS; | ||
647 | } | ||
648 | |||
554 | static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | 649 | static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, |
555 | struct cfg80211_registered_device *dev) | 650 | struct cfg80211_registered_device *dev) |
556 | { | 651 | { |
@@ -558,13 +653,11 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
558 | struct nlattr *nl_bands, *nl_band; | 653 | struct nlattr *nl_bands, *nl_band; |
559 | struct nlattr *nl_freqs, *nl_freq; | 654 | struct nlattr *nl_freqs, *nl_freq; |
560 | struct nlattr *nl_rates, *nl_rate; | 655 | struct nlattr *nl_rates, *nl_rate; |
561 | struct nlattr *nl_modes; | ||
562 | struct nlattr *nl_cmds; | 656 | struct nlattr *nl_cmds; |
563 | enum ieee80211_band band; | 657 | enum ieee80211_band band; |
564 | struct ieee80211_channel *chan; | 658 | struct ieee80211_channel *chan; |
565 | struct ieee80211_rate *rate; | 659 | struct ieee80211_rate *rate; |
566 | int i; | 660 | int i; |
567 | u16 ifmodes = dev->wiphy.interface_modes; | ||
568 | const struct ieee80211_txrx_stypes *mgmt_stypes = | 661 | const struct ieee80211_txrx_stypes *mgmt_stypes = |
569 | dev->wiphy.mgmt_stypes; | 662 | dev->wiphy.mgmt_stypes; |
570 | 663 | ||
@@ -624,20 +717,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
624 | } | 717 | } |
625 | } | 718 | } |
626 | 719 | ||
627 | nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); | 720 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SUPPORTED_IFTYPES, |
628 | if (!nl_modes) | 721 | dev->wiphy.interface_modes)) |
629 | goto nla_put_failure; | 722 | goto nla_put_failure; |
630 | 723 | ||
631 | i = 0; | ||
632 | while (ifmodes) { | ||
633 | if (ifmodes & 1) | ||
634 | NLA_PUT_FLAG(msg, i); | ||
635 | ifmodes >>= 1; | ||
636 | i++; | ||
637 | } | ||
638 | |||
639 | nla_nest_end(msg, nl_modes); | ||
640 | |||
641 | nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); | 724 | nl_bands = nla_nest_start(msg, NL80211_ATTR_WIPHY_BANDS); |
642 | if (!nl_bands) | 725 | if (!nl_bands) |
643 | goto nla_put_failure; | 726 | goto nla_put_failure; |
@@ -749,6 +832,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
749 | } | 832 | } |
750 | CMD(set_channel, SET_CHANNEL); | 833 | CMD(set_channel, SET_CHANNEL); |
751 | CMD(set_wds_peer, SET_WDS_PEER); | 834 | CMD(set_wds_peer, SET_WDS_PEER); |
835 | if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) | ||
836 | CMD(sched_scan_start, START_SCHED_SCAN); | ||
752 | 837 | ||
753 | #undef CMD | 838 | #undef CMD |
754 | 839 | ||
@@ -821,6 +906,42 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
821 | nla_nest_end(msg, nl_ifs); | 906 | nla_nest_end(msg, nl_ifs); |
822 | } | 907 | } |
823 | 908 | ||
909 | if (dev->wiphy.wowlan.flags || dev->wiphy.wowlan.n_patterns) { | ||
910 | struct nlattr *nl_wowlan; | ||
911 | |||
912 | nl_wowlan = nla_nest_start(msg, | ||
913 | NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED); | ||
914 | if (!nl_wowlan) | ||
915 | goto nla_put_failure; | ||
916 | |||
917 | if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_ANY) | ||
918 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_ANY); | ||
919 | if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_DISCONNECT) | ||
920 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT); | ||
921 | if (dev->wiphy.wowlan.flags & WIPHY_WOWLAN_MAGIC_PKT) | ||
922 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); | ||
923 | if (dev->wiphy.wowlan.n_patterns) { | ||
924 | struct nl80211_wowlan_pattern_support pat = { | ||
925 | .max_patterns = dev->wiphy.wowlan.n_patterns, | ||
926 | .min_pattern_len = | ||
927 | dev->wiphy.wowlan.pattern_min_len, | ||
928 | .max_pattern_len = | ||
929 | dev->wiphy.wowlan.pattern_max_len, | ||
930 | }; | ||
931 | NLA_PUT(msg, NL80211_WOWLAN_TRIG_PKT_PATTERN, | ||
932 | sizeof(pat), &pat); | ||
933 | } | ||
934 | |||
935 | nla_nest_end(msg, nl_wowlan); | ||
936 | } | ||
937 | |||
938 | if (nl80211_put_iftypes(msg, NL80211_ATTR_SOFTWARE_IFTYPES, | ||
939 | dev->wiphy.software_iftypes)) | ||
940 | goto nla_put_failure; | ||
941 | |||
942 | if (nl80211_put_iface_combinations(&dev->wiphy, msg)) | ||
943 | goto nla_put_failure; | ||
944 | |||
824 | return genlmsg_end(msg, hdr); | 945 | return genlmsg_end(msg, hdr); |
825 | 946 | ||
826 | nla_put_failure: | 947 | nla_put_failure: |
@@ -1682,14 +1803,6 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
1682 | if (err) | 1803 | if (err) |
1683 | goto out; | 1804 | goto out; |
1684 | 1805 | ||
1685 | if (!(rdev->wiphy.flags & | ||
1686 | WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS)) { | ||
1687 | if (!key.def_uni || !key.def_multi) { | ||
1688 | err = -EOPNOTSUPP; | ||
1689 | goto out; | ||
1690 | } | ||
1691 | } | ||
1692 | |||
1693 | err = rdev->ops->set_default_key(&rdev->wiphy, dev, key.idx, | 1806 | err = rdev->ops->set_default_key(&rdev->wiphy, dev, key.idx, |
1694 | key.def_uni, key.def_multi); | 1807 | key.def_uni, key.def_multi); |
1695 | 1808 | ||
@@ -1840,8 +1953,9 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1840 | struct beacon_parameters *info); | 1953 | struct beacon_parameters *info); |
1841 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 1954 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
1842 | struct net_device *dev = info->user_ptr[1]; | 1955 | struct net_device *dev = info->user_ptr[1]; |
1956 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
1843 | struct beacon_parameters params; | 1957 | struct beacon_parameters params; |
1844 | int haveinfo = 0; | 1958 | int haveinfo = 0, err; |
1845 | 1959 | ||
1846 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL])) | 1960 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_BEACON_TAIL])) |
1847 | return -EINVAL; | 1961 | return -EINVAL; |
@@ -1850,6 +1964,8 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1850 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | 1964 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
1851 | return -EOPNOTSUPP; | 1965 | return -EOPNOTSUPP; |
1852 | 1966 | ||
1967 | memset(¶ms, 0, sizeof(params)); | ||
1968 | |||
1853 | switch (info->genlhdr->cmd) { | 1969 | switch (info->genlhdr->cmd) { |
1854 | case NL80211_CMD_NEW_BEACON: | 1970 | case NL80211_CMD_NEW_BEACON: |
1855 | /* these are required for NEW_BEACON */ | 1971 | /* these are required for NEW_BEACON */ |
@@ -1858,6 +1974,15 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1858 | !info->attrs[NL80211_ATTR_BEACON_HEAD]) | 1974 | !info->attrs[NL80211_ATTR_BEACON_HEAD]) |
1859 | return -EINVAL; | 1975 | return -EINVAL; |
1860 | 1976 | ||
1977 | params.interval = | ||
1978 | nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); | ||
1979 | params.dtim_period = | ||
1980 | nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]); | ||
1981 | |||
1982 | err = cfg80211_validate_beacon_int(rdev, params.interval); | ||
1983 | if (err) | ||
1984 | return err; | ||
1985 | |||
1861 | call = rdev->ops->add_beacon; | 1986 | call = rdev->ops->add_beacon; |
1862 | break; | 1987 | break; |
1863 | case NL80211_CMD_SET_BEACON: | 1988 | case NL80211_CMD_SET_BEACON: |
@@ -1871,20 +1996,6 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1871 | if (!call) | 1996 | if (!call) |
1872 | return -EOPNOTSUPP; | 1997 | return -EOPNOTSUPP; |
1873 | 1998 | ||
1874 | memset(¶ms, 0, sizeof(params)); | ||
1875 | |||
1876 | if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) { | ||
1877 | params.interval = | ||
1878 | nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]); | ||
1879 | haveinfo = 1; | ||
1880 | } | ||
1881 | |||
1882 | if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) { | ||
1883 | params.dtim_period = | ||
1884 | nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]); | ||
1885 | haveinfo = 1; | ||
1886 | } | ||
1887 | |||
1888 | if (info->attrs[NL80211_ATTR_BEACON_HEAD]) { | 1999 | if (info->attrs[NL80211_ATTR_BEACON_HEAD]) { |
1889 | params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]); | 2000 | params.head = nla_data(info->attrs[NL80211_ATTR_BEACON_HEAD]); |
1890 | params.head_len = | 2001 | params.head_len = |
@@ -1902,13 +2013,18 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1902 | if (!haveinfo) | 2013 | if (!haveinfo) |
1903 | return -EINVAL; | 2014 | return -EINVAL; |
1904 | 2015 | ||
1905 | return call(&rdev->wiphy, dev, ¶ms); | 2016 | err = call(&rdev->wiphy, dev, ¶ms); |
2017 | if (!err && params.interval) | ||
2018 | wdev->beacon_interval = params.interval; | ||
2019 | return err; | ||
1906 | } | 2020 | } |
1907 | 2021 | ||
1908 | static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) | 2022 | static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) |
1909 | { | 2023 | { |
1910 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 2024 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
1911 | struct net_device *dev = info->user_ptr[1]; | 2025 | struct net_device *dev = info->user_ptr[1]; |
2026 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
2027 | int err; | ||
1912 | 2028 | ||
1913 | if (!rdev->ops->del_beacon) | 2029 | if (!rdev->ops->del_beacon) |
1914 | return -EOPNOTSUPP; | 2030 | return -EOPNOTSUPP; |
@@ -1917,7 +2033,10 @@ static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1917 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | 2033 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
1918 | return -EOPNOTSUPP; | 2034 | return -EOPNOTSUPP; |
1919 | 2035 | ||
1920 | return rdev->ops->del_beacon(&rdev->wiphy, dev); | 2036 | err = rdev->ops->del_beacon(&rdev->wiphy, dev); |
2037 | if (!err) | ||
2038 | wdev->beacon_interval = 0; | ||
2039 | return err; | ||
1921 | } | 2040 | } |
1922 | 2041 | ||
1923 | static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { | 2042 | static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { |
@@ -2216,6 +2335,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
2216 | memset(¶ms, 0, sizeof(params)); | 2335 | memset(¶ms, 0, sizeof(params)); |
2217 | 2336 | ||
2218 | params.listen_interval = -1; | 2337 | params.listen_interval = -1; |
2338 | params.plink_state = -1; | ||
2219 | 2339 | ||
2220 | if (info->attrs[NL80211_ATTR_STA_AID]) | 2340 | if (info->attrs[NL80211_ATTR_STA_AID]) |
2221 | return -EINVAL; | 2341 | return -EINVAL; |
@@ -2247,6 +2367,10 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
2247 | params.plink_action = | 2367 | params.plink_action = |
2248 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); | 2368 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); |
2249 | 2369 | ||
2370 | if (info->attrs[NL80211_ATTR_STA_PLINK_STATE]) | ||
2371 | params.plink_state = | ||
2372 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_STATE]); | ||
2373 | |||
2250 | err = get_vlan(info, rdev, ¶ms.vlan); | 2374 | err = get_vlan(info, rdev, ¶ms.vlan); |
2251 | if (err) | 2375 | if (err) |
2252 | goto out; | 2376 | goto out; |
@@ -2286,10 +2410,9 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
2286 | err = -EINVAL; | 2410 | err = -EINVAL; |
2287 | if (params.listen_interval >= 0) | 2411 | if (params.listen_interval >= 0) |
2288 | err = -EINVAL; | 2412 | err = -EINVAL; |
2289 | if (params.supported_rates) | ||
2290 | err = -EINVAL; | ||
2291 | if (params.sta_flags_mask & | 2413 | if (params.sta_flags_mask & |
2292 | ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | | 2414 | ~(BIT(NL80211_STA_FLAG_AUTHENTICATED) | |
2415 | BIT(NL80211_STA_FLAG_MFP) | | ||
2293 | BIT(NL80211_STA_FLAG_AUTHORIZED))) | 2416 | BIT(NL80211_STA_FLAG_AUTHORIZED))) |
2294 | err = -EINVAL; | 2417 | err = -EINVAL; |
2295 | break; | 2418 | break; |
@@ -2840,6 +2963,7 @@ static const struct nla_policy | |||
2840 | [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, | 2963 | [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, |
2841 | [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, | 2964 | [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, |
2842 | .len = IEEE80211_MAX_DATA_LEN }, | 2965 | .len = IEEE80211_MAX_DATA_LEN }, |
2966 | [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG }, | ||
2843 | }; | 2967 | }; |
2844 | 2968 | ||
2845 | static int nl80211_parse_mesh_config(struct genl_info *info, | 2969 | static int nl80211_parse_mesh_config(struct genl_info *info, |
@@ -2949,7 +3073,8 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, | |||
2949 | setup->ie = nla_data(ieattr); | 3073 | setup->ie = nla_data(ieattr); |
2950 | setup->ie_len = nla_len(ieattr); | 3074 | setup->ie_len = nla_len(ieattr); |
2951 | } | 3075 | } |
2952 | setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]); | 3076 | setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]); |
3077 | setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]); | ||
2953 | 3078 | ||
2954 | return 0; | 3079 | return 0; |
2955 | } | 3080 | } |
@@ -3318,6 +3443,188 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
3318 | return err; | 3443 | return err; |
3319 | } | 3444 | } |
3320 | 3445 | ||
3446 | static int nl80211_start_sched_scan(struct sk_buff *skb, | ||
3447 | struct genl_info *info) | ||
3448 | { | ||
3449 | struct cfg80211_sched_scan_request *request; | ||
3450 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
3451 | struct net_device *dev = info->user_ptr[1]; | ||
3452 | struct cfg80211_ssid *ssid; | ||
3453 | struct ieee80211_channel *channel; | ||
3454 | struct nlattr *attr; | ||
3455 | struct wiphy *wiphy; | ||
3456 | int err, tmp, n_ssids = 0, n_channels, i; | ||
3457 | u32 interval; | ||
3458 | enum ieee80211_band band; | ||
3459 | size_t ie_len; | ||
3460 | |||
3461 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || | ||
3462 | !rdev->ops->sched_scan_start) | ||
3463 | return -EOPNOTSUPP; | ||
3464 | |||
3465 | if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) | ||
3466 | return -EINVAL; | ||
3467 | |||
3468 | if (rdev->sched_scan_req) | ||
3469 | return -EINPROGRESS; | ||
3470 | |||
3471 | if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]) | ||
3472 | return -EINVAL; | ||
3473 | |||
3474 | interval = nla_get_u32(info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]); | ||
3475 | if (interval == 0) | ||
3476 | return -EINVAL; | ||
3477 | |||
3478 | wiphy = &rdev->wiphy; | ||
3479 | |||
3480 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { | ||
3481 | n_channels = validate_scan_freqs( | ||
3482 | info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]); | ||
3483 | if (!n_channels) | ||
3484 | return -EINVAL; | ||
3485 | } else { | ||
3486 | n_channels = 0; | ||
3487 | |||
3488 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) | ||
3489 | if (wiphy->bands[band]) | ||
3490 | n_channels += wiphy->bands[band]->n_channels; | ||
3491 | } | ||
3492 | |||
3493 | if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) | ||
3494 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], | ||
3495 | tmp) | ||
3496 | n_ssids++; | ||
3497 | |||
3498 | if (n_ssids > wiphy->max_scan_ssids) | ||
3499 | return -EINVAL; | ||
3500 | |||
3501 | if (info->attrs[NL80211_ATTR_IE]) | ||
3502 | ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | ||
3503 | else | ||
3504 | ie_len = 0; | ||
3505 | |||
3506 | if (ie_len > wiphy->max_scan_ie_len) | ||
3507 | return -EINVAL; | ||
3508 | |||
3509 | request = kzalloc(sizeof(*request) | ||
3510 | + sizeof(*ssid) * n_ssids | ||
3511 | + sizeof(channel) * n_channels | ||
3512 | + ie_len, GFP_KERNEL); | ||
3513 | if (!request) | ||
3514 | return -ENOMEM; | ||
3515 | |||
3516 | if (n_ssids) | ||
3517 | request->ssids = (void *)&request->channels[n_channels]; | ||
3518 | request->n_ssids = n_ssids; | ||
3519 | if (ie_len) { | ||
3520 | if (request->ssids) | ||
3521 | request->ie = (void *)(request->ssids + n_ssids); | ||
3522 | else | ||
3523 | request->ie = (void *)(request->channels + n_channels); | ||
3524 | } | ||
3525 | |||
3526 | i = 0; | ||
3527 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { | ||
3528 | /* user specified, bail out if channel not found */ | ||
3529 | nla_for_each_nested(attr, | ||
3530 | info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], | ||
3531 | tmp) { | ||
3532 | struct ieee80211_channel *chan; | ||
3533 | |||
3534 | chan = ieee80211_get_channel(wiphy, nla_get_u32(attr)); | ||
3535 | |||
3536 | if (!chan) { | ||
3537 | err = -EINVAL; | ||
3538 | goto out_free; | ||
3539 | } | ||
3540 | |||
3541 | /* ignore disabled channels */ | ||
3542 | if (chan->flags & IEEE80211_CHAN_DISABLED) | ||
3543 | continue; | ||
3544 | |||
3545 | request->channels[i] = chan; | ||
3546 | i++; | ||
3547 | } | ||
3548 | } else { | ||
3549 | /* all channels */ | ||
3550 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
3551 | int j; | ||
3552 | if (!wiphy->bands[band]) | ||
3553 | continue; | ||
3554 | for (j = 0; j < wiphy->bands[band]->n_channels; j++) { | ||
3555 | struct ieee80211_channel *chan; | ||
3556 | |||
3557 | chan = &wiphy->bands[band]->channels[j]; | ||
3558 | |||
3559 | if (chan->flags & IEEE80211_CHAN_DISABLED) | ||
3560 | continue; | ||
3561 | |||
3562 | request->channels[i] = chan; | ||
3563 | i++; | ||
3564 | } | ||
3565 | } | ||
3566 | } | ||
3567 | |||
3568 | if (!i) { | ||
3569 | err = -EINVAL; | ||
3570 | goto out_free; | ||
3571 | } | ||
3572 | |||
3573 | request->n_channels = i; | ||
3574 | |||
3575 | i = 0; | ||
3576 | if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) { | ||
3577 | nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], | ||
3578 | tmp) { | ||
3579 | if (request->ssids[i].ssid_len > | ||
3580 | IEEE80211_MAX_SSID_LEN) { | ||
3581 | err = -EINVAL; | ||
3582 | goto out_free; | ||
3583 | } | ||
3584 | memcpy(request->ssids[i].ssid, nla_data(attr), | ||
3585 | nla_len(attr)); | ||
3586 | request->ssids[i].ssid_len = nla_len(attr); | ||
3587 | i++; | ||
3588 | } | ||
3589 | } | ||
3590 | |||
3591 | if (info->attrs[NL80211_ATTR_IE]) { | ||
3592 | request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | ||
3593 | memcpy((void *)request->ie, | ||
3594 | nla_data(info->attrs[NL80211_ATTR_IE]), | ||
3595 | request->ie_len); | ||
3596 | } | ||
3597 | |||
3598 | request->dev = dev; | ||
3599 | request->wiphy = &rdev->wiphy; | ||
3600 | request->interval = interval; | ||
3601 | |||
3602 | err = rdev->ops->sched_scan_start(&rdev->wiphy, dev, request); | ||
3603 | if (!err) { | ||
3604 | rdev->sched_scan_req = request; | ||
3605 | nl80211_send_sched_scan(rdev, dev, | ||
3606 | NL80211_CMD_START_SCHED_SCAN); | ||
3607 | goto out; | ||
3608 | } | ||
3609 | |||
3610 | out_free: | ||
3611 | kfree(request); | ||
3612 | out: | ||
3613 | return err; | ||
3614 | } | ||
3615 | |||
3616 | static int nl80211_stop_sched_scan(struct sk_buff *skb, | ||
3617 | struct genl_info *info) | ||
3618 | { | ||
3619 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
3620 | |||
3621 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || | ||
3622 | !rdev->ops->sched_scan_stop) | ||
3623 | return -EOPNOTSUPP; | ||
3624 | |||
3625 | return __cfg80211_stop_sched_scan(rdev, false); | ||
3626 | } | ||
3627 | |||
3321 | static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, | 3628 | static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags, |
3322 | struct cfg80211_registered_device *rdev, | 3629 | struct cfg80211_registered_device *rdev, |
3323 | struct wireless_dev *wdev, | 3630 | struct wireless_dev *wdev, |
@@ -4816,6 +5123,194 @@ static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info) | |||
4816 | return cfg80211_leave_mesh(rdev, dev); | 5123 | return cfg80211_leave_mesh(rdev, dev); |
4817 | } | 5124 | } |
4818 | 5125 | ||
5126 | static int nl80211_get_wowlan(struct sk_buff *skb, struct genl_info *info) | ||
5127 | { | ||
5128 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
5129 | struct sk_buff *msg; | ||
5130 | void *hdr; | ||
5131 | |||
5132 | if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns) | ||
5133 | return -EOPNOTSUPP; | ||
5134 | |||
5135 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
5136 | if (!msg) | ||
5137 | return -ENOMEM; | ||
5138 | |||
5139 | hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0, | ||
5140 | NL80211_CMD_GET_WOWLAN); | ||
5141 | if (!hdr) | ||
5142 | goto nla_put_failure; | ||
5143 | |||
5144 | if (rdev->wowlan) { | ||
5145 | struct nlattr *nl_wowlan; | ||
5146 | |||
5147 | nl_wowlan = nla_nest_start(msg, NL80211_ATTR_WOWLAN_TRIGGERS); | ||
5148 | if (!nl_wowlan) | ||
5149 | goto nla_put_failure; | ||
5150 | |||
5151 | if (rdev->wowlan->any) | ||
5152 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_ANY); | ||
5153 | if (rdev->wowlan->disconnect) | ||
5154 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_DISCONNECT); | ||
5155 | if (rdev->wowlan->magic_pkt) | ||
5156 | NLA_PUT_FLAG(msg, NL80211_WOWLAN_TRIG_MAGIC_PKT); | ||
5157 | if (rdev->wowlan->n_patterns) { | ||
5158 | struct nlattr *nl_pats, *nl_pat; | ||
5159 | int i, pat_len; | ||
5160 | |||
5161 | nl_pats = nla_nest_start(msg, | ||
5162 | NL80211_WOWLAN_TRIG_PKT_PATTERN); | ||
5163 | if (!nl_pats) | ||
5164 | goto nla_put_failure; | ||
5165 | |||
5166 | for (i = 0; i < rdev->wowlan->n_patterns; i++) { | ||
5167 | nl_pat = nla_nest_start(msg, i + 1); | ||
5168 | if (!nl_pat) | ||
5169 | goto nla_put_failure; | ||
5170 | pat_len = rdev->wowlan->patterns[i].pattern_len; | ||
5171 | NLA_PUT(msg, NL80211_WOWLAN_PKTPAT_MASK, | ||
5172 | DIV_ROUND_UP(pat_len, 8), | ||
5173 | rdev->wowlan->patterns[i].mask); | ||
5174 | NLA_PUT(msg, NL80211_WOWLAN_PKTPAT_PATTERN, | ||
5175 | pat_len, | ||
5176 | rdev->wowlan->patterns[i].pattern); | ||
5177 | nla_nest_end(msg, nl_pat); | ||
5178 | } | ||
5179 | nla_nest_end(msg, nl_pats); | ||
5180 | } | ||
5181 | |||
5182 | nla_nest_end(msg, nl_wowlan); | ||
5183 | } | ||
5184 | |||
5185 | genlmsg_end(msg, hdr); | ||
5186 | return genlmsg_reply(msg, info); | ||
5187 | |||
5188 | nla_put_failure: | ||
5189 | nlmsg_free(msg); | ||
5190 | return -ENOBUFS; | ||
5191 | } | ||
5192 | |||
5193 | static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info) | ||
5194 | { | ||
5195 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
5196 | struct nlattr *tb[NUM_NL80211_WOWLAN_TRIG]; | ||
5197 | struct cfg80211_wowlan no_triggers = {}; | ||
5198 | struct cfg80211_wowlan new_triggers = {}; | ||
5199 | struct wiphy_wowlan_support *wowlan = &rdev->wiphy.wowlan; | ||
5200 | int err, i; | ||
5201 | |||
5202 | if (!rdev->wiphy.wowlan.flags && !rdev->wiphy.wowlan.n_patterns) | ||
5203 | return -EOPNOTSUPP; | ||
5204 | |||
5205 | if (!info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]) | ||
5206 | goto no_triggers; | ||
5207 | |||
5208 | err = nla_parse(tb, MAX_NL80211_WOWLAN_TRIG, | ||
5209 | nla_data(info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]), | ||
5210 | nla_len(info->attrs[NL80211_ATTR_WOWLAN_TRIGGERS]), | ||
5211 | nl80211_wowlan_policy); | ||
5212 | if (err) | ||
5213 | return err; | ||
5214 | |||
5215 | if (tb[NL80211_WOWLAN_TRIG_ANY]) { | ||
5216 | if (!(wowlan->flags & WIPHY_WOWLAN_ANY)) | ||
5217 | return -EINVAL; | ||
5218 | new_triggers.any = true; | ||
5219 | } | ||
5220 | |||
5221 | if (tb[NL80211_WOWLAN_TRIG_DISCONNECT]) { | ||
5222 | if (!(wowlan->flags & WIPHY_WOWLAN_DISCONNECT)) | ||
5223 | return -EINVAL; | ||
5224 | new_triggers.disconnect = true; | ||
5225 | } | ||
5226 | |||
5227 | if (tb[NL80211_WOWLAN_TRIG_MAGIC_PKT]) { | ||
5228 | if (!(wowlan->flags & WIPHY_WOWLAN_MAGIC_PKT)) | ||
5229 | return -EINVAL; | ||
5230 | new_triggers.magic_pkt = true; | ||
5231 | } | ||
5232 | |||
5233 | if (tb[NL80211_WOWLAN_TRIG_PKT_PATTERN]) { | ||
5234 | struct nlattr *pat; | ||
5235 | int n_patterns = 0; | ||
5236 | int rem, pat_len, mask_len; | ||
5237 | struct nlattr *pat_tb[NUM_NL80211_WOWLAN_PKTPAT]; | ||
5238 | |||
5239 | nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], | ||
5240 | rem) | ||
5241 | n_patterns++; | ||
5242 | if (n_patterns > wowlan->n_patterns) | ||
5243 | return -EINVAL; | ||
5244 | |||
5245 | new_triggers.patterns = kcalloc(n_patterns, | ||
5246 | sizeof(new_triggers.patterns[0]), | ||
5247 | GFP_KERNEL); | ||
5248 | if (!new_triggers.patterns) | ||
5249 | return -ENOMEM; | ||
5250 | |||
5251 | new_triggers.n_patterns = n_patterns; | ||
5252 | i = 0; | ||
5253 | |||
5254 | nla_for_each_nested(pat, tb[NL80211_WOWLAN_TRIG_PKT_PATTERN], | ||
5255 | rem) { | ||
5256 | nla_parse(pat_tb, MAX_NL80211_WOWLAN_PKTPAT, | ||
5257 | nla_data(pat), nla_len(pat), NULL); | ||
5258 | err = -EINVAL; | ||
5259 | if (!pat_tb[NL80211_WOWLAN_PKTPAT_MASK] || | ||
5260 | !pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]) | ||
5261 | goto error; | ||
5262 | pat_len = nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]); | ||
5263 | mask_len = DIV_ROUND_UP(pat_len, 8); | ||
5264 | if (nla_len(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]) != | ||
5265 | mask_len) | ||
5266 | goto error; | ||
5267 | if (pat_len > wowlan->pattern_max_len || | ||
5268 | pat_len < wowlan->pattern_min_len) | ||
5269 | goto error; | ||
5270 | |||
5271 | new_triggers.patterns[i].mask = | ||
5272 | kmalloc(mask_len + pat_len, GFP_KERNEL); | ||
5273 | if (!new_triggers.patterns[i].mask) { | ||
5274 | err = -ENOMEM; | ||
5275 | goto error; | ||
5276 | } | ||
5277 | new_triggers.patterns[i].pattern = | ||
5278 | new_triggers.patterns[i].mask + mask_len; | ||
5279 | memcpy(new_triggers.patterns[i].mask, | ||
5280 | nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_MASK]), | ||
5281 | mask_len); | ||
5282 | new_triggers.patterns[i].pattern_len = pat_len; | ||
5283 | memcpy(new_triggers.patterns[i].pattern, | ||
5284 | nla_data(pat_tb[NL80211_WOWLAN_PKTPAT_PATTERN]), | ||
5285 | pat_len); | ||
5286 | i++; | ||
5287 | } | ||
5288 | } | ||
5289 | |||
5290 | if (memcmp(&new_triggers, &no_triggers, sizeof(new_triggers))) { | ||
5291 | struct cfg80211_wowlan *ntrig; | ||
5292 | ntrig = kmemdup(&new_triggers, sizeof(new_triggers), | ||
5293 | GFP_KERNEL); | ||
5294 | if (!ntrig) { | ||
5295 | err = -ENOMEM; | ||
5296 | goto error; | ||
5297 | } | ||
5298 | cfg80211_rdev_free_wowlan(rdev); | ||
5299 | rdev->wowlan = ntrig; | ||
5300 | } else { | ||
5301 | no_triggers: | ||
5302 | cfg80211_rdev_free_wowlan(rdev); | ||
5303 | rdev->wowlan = NULL; | ||
5304 | } | ||
5305 | |||
5306 | return 0; | ||
5307 | error: | ||
5308 | for (i = 0; i < new_triggers.n_patterns; i++) | ||
5309 | kfree(new_triggers.patterns[i].mask); | ||
5310 | kfree(new_triggers.patterns); | ||
5311 | return err; | ||
5312 | } | ||
5313 | |||
4819 | #define NL80211_FLAG_NEED_WIPHY 0x01 | 5314 | #define NL80211_FLAG_NEED_WIPHY 0x01 |
4820 | #define NL80211_FLAG_NEED_NETDEV 0x02 | 5315 | #define NL80211_FLAG_NEED_NETDEV 0x02 |
4821 | #define NL80211_FLAG_NEED_RTNL 0x04 | 5316 | #define NL80211_FLAG_NEED_RTNL 0x04 |
@@ -5100,6 +5595,22 @@ static struct genl_ops nl80211_ops[] = { | |||
5100 | .dumpit = nl80211_dump_scan, | 5595 | .dumpit = nl80211_dump_scan, |
5101 | }, | 5596 | }, |
5102 | { | 5597 | { |
5598 | .cmd = NL80211_CMD_START_SCHED_SCAN, | ||
5599 | .doit = nl80211_start_sched_scan, | ||
5600 | .policy = nl80211_policy, | ||
5601 | .flags = GENL_ADMIN_PERM, | ||
5602 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
5603 | NL80211_FLAG_NEED_RTNL, | ||
5604 | }, | ||
5605 | { | ||
5606 | .cmd = NL80211_CMD_STOP_SCHED_SCAN, | ||
5607 | .doit = nl80211_stop_sched_scan, | ||
5608 | .policy = nl80211_policy, | ||
5609 | .flags = GENL_ADMIN_PERM, | ||
5610 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
5611 | NL80211_FLAG_NEED_RTNL, | ||
5612 | }, | ||
5613 | { | ||
5103 | .cmd = NL80211_CMD_AUTHENTICATE, | 5614 | .cmd = NL80211_CMD_AUTHENTICATE, |
5104 | .doit = nl80211_authenticate, | 5615 | .doit = nl80211_authenticate, |
5105 | .policy = nl80211_policy, | 5616 | .policy = nl80211_policy, |
@@ -5314,6 +5825,22 @@ static struct genl_ops nl80211_ops[] = { | |||
5314 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | 5825 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | |
5315 | NL80211_FLAG_NEED_RTNL, | 5826 | NL80211_FLAG_NEED_RTNL, |
5316 | }, | 5827 | }, |
5828 | { | ||
5829 | .cmd = NL80211_CMD_GET_WOWLAN, | ||
5830 | .doit = nl80211_get_wowlan, | ||
5831 | .policy = nl80211_policy, | ||
5832 | /* can be retrieved by unprivileged users */ | ||
5833 | .internal_flags = NL80211_FLAG_NEED_WIPHY | | ||
5834 | NL80211_FLAG_NEED_RTNL, | ||
5835 | }, | ||
5836 | { | ||
5837 | .cmd = NL80211_CMD_SET_WOWLAN, | ||
5838 | .doit = nl80211_set_wowlan, | ||
5839 | .policy = nl80211_policy, | ||
5840 | .flags = GENL_ADMIN_PERM, | ||
5841 | .internal_flags = NL80211_FLAG_NEED_WIPHY | | ||
5842 | NL80211_FLAG_NEED_RTNL, | ||
5843 | }, | ||
5317 | }; | 5844 | }; |
5318 | 5845 | ||
5319 | static struct genl_multicast_group nl80211_mlme_mcgrp = { | 5846 | static struct genl_multicast_group nl80211_mlme_mcgrp = { |
@@ -5409,6 +5936,28 @@ static int nl80211_send_scan_msg(struct sk_buff *msg, | |||
5409 | return -EMSGSIZE; | 5936 | return -EMSGSIZE; |
5410 | } | 5937 | } |
5411 | 5938 | ||
5939 | static int | ||
5940 | nl80211_send_sched_scan_msg(struct sk_buff *msg, | ||
5941 | struct cfg80211_registered_device *rdev, | ||
5942 | struct net_device *netdev, | ||
5943 | u32 pid, u32 seq, int flags, u32 cmd) | ||
5944 | { | ||
5945 | void *hdr; | ||
5946 | |||
5947 | hdr = nl80211hdr_put(msg, pid, seq, flags, cmd); | ||
5948 | if (!hdr) | ||
5949 | return -1; | ||
5950 | |||
5951 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); | ||
5952 | NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); | ||
5953 | |||
5954 | return genlmsg_end(msg, hdr); | ||
5955 | |||
5956 | nla_put_failure: | ||
5957 | genlmsg_cancel(msg, hdr); | ||
5958 | return -EMSGSIZE; | ||
5959 | } | ||
5960 | |||
5412 | void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, | 5961 | void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, |
5413 | struct net_device *netdev) | 5962 | struct net_device *netdev) |
5414 | { | 5963 | { |
@@ -5466,6 +6015,43 @@ void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | |||
5466 | nl80211_scan_mcgrp.id, GFP_KERNEL); | 6015 | nl80211_scan_mcgrp.id, GFP_KERNEL); |
5467 | } | 6016 | } |
5468 | 6017 | ||
6018 | void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev, | ||
6019 | struct net_device *netdev) | ||
6020 | { | ||
6021 | struct sk_buff *msg; | ||
6022 | |||
6023 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
6024 | if (!msg) | ||
6025 | return; | ||
6026 | |||
6027 | if (nl80211_send_sched_scan_msg(msg, rdev, netdev, 0, 0, 0, | ||
6028 | NL80211_CMD_SCHED_SCAN_RESULTS) < 0) { | ||
6029 | nlmsg_free(msg); | ||
6030 | return; | ||
6031 | } | ||
6032 | |||
6033 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
6034 | nl80211_scan_mcgrp.id, GFP_KERNEL); | ||
6035 | } | ||
6036 | |||
6037 | void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, | ||
6038 | struct net_device *netdev, u32 cmd) | ||
6039 | { | ||
6040 | struct sk_buff *msg; | ||
6041 | |||
6042 | msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | ||
6043 | if (!msg) | ||
6044 | return; | ||
6045 | |||
6046 | if (nl80211_send_sched_scan_msg(msg, rdev, netdev, 0, 0, 0, cmd) < 0) { | ||
6047 | nlmsg_free(msg); | ||
6048 | return; | ||
6049 | } | ||
6050 | |||
6051 | genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, | ||
6052 | nl80211_scan_mcgrp.id, GFP_KERNEL); | ||
6053 | } | ||
6054 | |||
5469 | /* | 6055 | /* |
5470 | * This can happen on global regulatory changes or device specific settings | 6056 | * This can happen on global regulatory changes or device specific settings |
5471 | * based on custom world regulatory domains. | 6057 | * based on custom world regulatory domains. |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index f2af6955a665..2f1bfb87a651 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
@@ -12,6 +12,10 @@ void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | |||
12 | struct net_device *netdev); | 12 | struct net_device *netdev); |
13 | void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | 13 | void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, |
14 | struct net_device *netdev); | 14 | struct net_device *netdev); |
15 | void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, | ||
16 | struct net_device *netdev, u32 cmd); | ||
17 | void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev, | ||
18 | struct net_device *netdev); | ||
15 | void nl80211_send_reg_change_event(struct regulatory_request *request); | 19 | void nl80211_send_reg_change_event(struct regulatory_request *request); |
16 | void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev, | 20 | void nl80211_send_rx_auth(struct cfg80211_registered_device *rdev, |
17 | struct net_device *netdev, | 21 | struct net_device *netdev, |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 1613080a96b9..1ad0f39fe091 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -672,11 +672,9 @@ static int freq_reg_info_regd(struct wiphy *wiphy, | |||
672 | for (i = 0; i < regd->n_reg_rules; i++) { | 672 | for (i = 0; i < regd->n_reg_rules; i++) { |
673 | const struct ieee80211_reg_rule *rr; | 673 | const struct ieee80211_reg_rule *rr; |
674 | const struct ieee80211_freq_range *fr = NULL; | 674 | const struct ieee80211_freq_range *fr = NULL; |
675 | const struct ieee80211_power_rule *pr = NULL; | ||
676 | 675 | ||
677 | rr = ®d->reg_rules[i]; | 676 | rr = ®d->reg_rules[i]; |
678 | fr = &rr->freq_range; | 677 | fr = &rr->freq_range; |
679 | pr = &rr->power_rule; | ||
680 | 678 | ||
681 | /* | 679 | /* |
682 | * We only need to know if one frequency rule was | 680 | * We only need to know if one frequency rule was |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index fbf6f33ae4d0..73a441d237b5 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
@@ -93,6 +93,69 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) | |||
93 | } | 93 | } |
94 | EXPORT_SYMBOL(cfg80211_scan_done); | 94 | EXPORT_SYMBOL(cfg80211_scan_done); |
95 | 95 | ||
96 | void __cfg80211_sched_scan_results(struct work_struct *wk) | ||
97 | { | ||
98 | struct cfg80211_registered_device *rdev; | ||
99 | |||
100 | rdev = container_of(wk, struct cfg80211_registered_device, | ||
101 | sched_scan_results_wk); | ||
102 | |||
103 | cfg80211_lock_rdev(rdev); | ||
104 | |||
105 | /* we don't have sched_scan_req anymore if the scan is stopping */ | ||
106 | if (rdev->sched_scan_req) | ||
107 | nl80211_send_sched_scan_results(rdev, | ||
108 | rdev->sched_scan_req->dev); | ||
109 | |||
110 | cfg80211_unlock_rdev(rdev); | ||
111 | } | ||
112 | |||
113 | void cfg80211_sched_scan_results(struct wiphy *wiphy) | ||
114 | { | ||
115 | /* ignore if we're not scanning */ | ||
116 | if (wiphy_to_dev(wiphy)->sched_scan_req) | ||
117 | queue_work(cfg80211_wq, | ||
118 | &wiphy_to_dev(wiphy)->sched_scan_results_wk); | ||
119 | } | ||
120 | EXPORT_SYMBOL(cfg80211_sched_scan_results); | ||
121 | |||
122 | void cfg80211_sched_scan_stopped(struct wiphy *wiphy) | ||
123 | { | ||
124 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
125 | |||
126 | cfg80211_lock_rdev(rdev); | ||
127 | __cfg80211_stop_sched_scan(rdev, true); | ||
128 | cfg80211_unlock_rdev(rdev); | ||
129 | } | ||
130 | EXPORT_SYMBOL(cfg80211_sched_scan_stopped); | ||
131 | |||
132 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, | ||
133 | bool driver_initiated) | ||
134 | { | ||
135 | int err; | ||
136 | struct net_device *dev; | ||
137 | |||
138 | ASSERT_RDEV_LOCK(rdev); | ||
139 | |||
140 | if (!rdev->sched_scan_req) | ||
141 | return 0; | ||
142 | |||
143 | dev = rdev->sched_scan_req->dev; | ||
144 | |||
145 | if (!driver_initiated) { | ||
146 | err = rdev->ops->sched_scan_stop(&rdev->wiphy, dev); | ||
147 | if (err) | ||
148 | return err; | ||
149 | } | ||
150 | |||
151 | nl80211_send_sched_scan(rdev, dev, NL80211_CMD_SCHED_SCAN_STOPPED); | ||
152 | |||
153 | kfree(rdev->sched_scan_req); | ||
154 | rdev->sched_scan_req = NULL; | ||
155 | |||
156 | return err; | ||
157 | } | ||
158 | |||
96 | static void bss_release(struct kref *ref) | 159 | static void bss_release(struct kref *ref) |
97 | { | 160 | { |
98 | struct cfg80211_internal_bss *bss; | 161 | struct cfg80211_internal_bss *bss; |
@@ -210,7 +273,7 @@ static bool is_mesh(struct cfg80211_bss *a, | |||
210 | { | 273 | { |
211 | const u8 *ie; | 274 | const u8 *ie; |
212 | 275 | ||
213 | if (!is_zero_ether_addr(a->bssid)) | 276 | if (!WLAN_CAPABILITY_IS_MBSS(a->capability)) |
214 | return false; | 277 | return false; |
215 | 278 | ||
216 | ie = cfg80211_find_ie(WLAN_EID_MESH_ID, | 279 | ie = cfg80211_find_ie(WLAN_EID_MESH_ID, |
@@ -248,11 +311,7 @@ static int cmp_bss(struct cfg80211_bss *a, | |||
248 | if (a->channel != b->channel) | 311 | if (a->channel != b->channel) |
249 | return b->channel->center_freq - a->channel->center_freq; | 312 | return b->channel->center_freq - a->channel->center_freq; |
250 | 313 | ||
251 | r = memcmp(a->bssid, b->bssid, ETH_ALEN); | 314 | if (WLAN_CAPABILITY_IS_MBSS(a->capability | b->capability)) { |
252 | if (r) | ||
253 | return r; | ||
254 | |||
255 | if (is_zero_ether_addr(a->bssid)) { | ||
256 | r = cmp_ies(WLAN_EID_MESH_ID, | 315 | r = cmp_ies(WLAN_EID_MESH_ID, |
257 | a->information_elements, | 316 | a->information_elements, |
258 | a->len_information_elements, | 317 | a->len_information_elements, |
@@ -267,6 +326,10 @@ static int cmp_bss(struct cfg80211_bss *a, | |||
267 | b->len_information_elements); | 326 | b->len_information_elements); |
268 | } | 327 | } |
269 | 328 | ||
329 | r = memcmp(a->bssid, b->bssid, ETH_ALEN); | ||
330 | if (r) | ||
331 | return r; | ||
332 | |||
270 | return cmp_ies(WLAN_EID_SSID, | 333 | return cmp_ies(WLAN_EID_SSID, |
271 | a->information_elements, | 334 | a->information_elements, |
272 | a->len_information_elements, | 335 | a->len_information_elements, |
@@ -407,7 +470,7 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
407 | 470 | ||
408 | res->ts = jiffies; | 471 | res->ts = jiffies; |
409 | 472 | ||
410 | if (is_zero_ether_addr(res->pub.bssid)) { | 473 | if (WLAN_CAPABILITY_IS_MBSS(res->pub.capability)) { |
411 | /* must be mesh, verify */ | 474 | /* must be mesh, verify */ |
412 | meshid = cfg80211_find_ie(WLAN_EID_MESH_ID, | 475 | meshid = cfg80211_find_ie(WLAN_EID_MESH_ID, |
413 | res->pub.information_elements, | 476 | res->pub.information_elements, |
diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c index 4294fa22bb2d..c6e4ca6a7d2e 100644 --- a/net/wireless/sysfs.c +++ b/net/wireless/sysfs.c | |||
@@ -93,7 +93,7 @@ static int wiphy_suspend(struct device *dev, pm_message_t state) | |||
93 | 93 | ||
94 | if (rdev->ops->suspend) { | 94 | if (rdev->ops->suspend) { |
95 | rtnl_lock(); | 95 | rtnl_lock(); |
96 | ret = rdev->ops->suspend(&rdev->wiphy); | 96 | ret = rdev->ops->suspend(&rdev->wiphy, rdev->wowlan); |
97 | rtnl_unlock(); | 97 | rtnl_unlock(); |
98 | } | 98 | } |
99 | 99 | ||
diff --git a/net/wireless/util.c b/net/wireless/util.c index 6a750bc6bcfe..f0536d44d43c 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -544,7 +544,8 @@ EXPORT_SYMBOL(ieee80211_data_from_8023); | |||
544 | 544 | ||
545 | void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, | 545 | void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, |
546 | const u8 *addr, enum nl80211_iftype iftype, | 546 | const u8 *addr, enum nl80211_iftype iftype, |
547 | const unsigned int extra_headroom) | 547 | const unsigned int extra_headroom, |
548 | bool has_80211_header) | ||
548 | { | 549 | { |
549 | struct sk_buff *frame = NULL; | 550 | struct sk_buff *frame = NULL; |
550 | u16 ethertype; | 551 | u16 ethertype; |
@@ -553,14 +554,18 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, | |||
553 | int remaining, err; | 554 | int remaining, err; |
554 | u8 dst[ETH_ALEN], src[ETH_ALEN]; | 555 | u8 dst[ETH_ALEN], src[ETH_ALEN]; |
555 | 556 | ||
556 | err = ieee80211_data_to_8023(skb, addr, iftype); | 557 | if (has_80211_header) { |
557 | if (err) | 558 | err = ieee80211_data_to_8023(skb, addr, iftype); |
558 | goto out; | 559 | if (err) |
560 | goto out; | ||
559 | 561 | ||
560 | /* skip the wrapping header */ | 562 | /* skip the wrapping header */ |
561 | eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr)); | 563 | eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr)); |
562 | if (!eth) | 564 | if (!eth) |
563 | goto out; | 565 | goto out; |
566 | } else { | ||
567 | eth = (struct ethhdr *) skb->data; | ||
568 | } | ||
564 | 569 | ||
565 | while (skb != frame) { | 570 | while (skb != frame) { |
566 | u8 padding; | 571 | u8 padding; |
@@ -803,6 +808,11 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
803 | return -EBUSY; | 808 | return -EBUSY; |
804 | 809 | ||
805 | if (ntype != otype) { | 810 | if (ntype != otype) { |
811 | err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, | ||
812 | ntype); | ||
813 | if (err) | ||
814 | return err; | ||
815 | |||
806 | dev->ieee80211_ptr->use_4addr = false; | 816 | dev->ieee80211_ptr->use_4addr = false; |
807 | dev->ieee80211_ptr->mesh_id_up_len = 0; | 817 | dev->ieee80211_ptr->mesh_id_up_len = 0; |
808 | 818 | ||
@@ -896,3 +906,103 @@ u16 cfg80211_calculate_bitrate(struct rate_info *rate) | |||
896 | /* do NOT round down here */ | 906 | /* do NOT round down here */ |
897 | return (bitrate + 50000) / 100000; | 907 | return (bitrate + 50000) / 100000; |
898 | } | 908 | } |
909 | |||
910 | int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev, | ||
911 | u32 beacon_int) | ||
912 | { | ||
913 | struct wireless_dev *wdev; | ||
914 | int res = 0; | ||
915 | |||
916 | if (!beacon_int) | ||
917 | return -EINVAL; | ||
918 | |||
919 | mutex_lock(&rdev->devlist_mtx); | ||
920 | |||
921 | list_for_each_entry(wdev, &rdev->netdev_list, list) { | ||
922 | if (!wdev->beacon_interval) | ||
923 | continue; | ||
924 | if (wdev->beacon_interval != beacon_int) { | ||
925 | res = -EINVAL; | ||
926 | break; | ||
927 | } | ||
928 | } | ||
929 | |||
930 | mutex_unlock(&rdev->devlist_mtx); | ||
931 | |||
932 | return res; | ||
933 | } | ||
934 | |||
935 | int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | ||
936 | struct wireless_dev *wdev, | ||
937 | enum nl80211_iftype iftype) | ||
938 | { | ||
939 | struct wireless_dev *wdev_iter; | ||
940 | int num[NUM_NL80211_IFTYPES]; | ||
941 | int total = 1; | ||
942 | int i, j; | ||
943 | |||
944 | ASSERT_RTNL(); | ||
945 | |||
946 | /* Always allow software iftypes */ | ||
947 | if (rdev->wiphy.software_iftypes & BIT(iftype)) | ||
948 | return 0; | ||
949 | |||
950 | /* | ||
951 | * Drivers will gradually all set this flag, until all | ||
952 | * have it we only enforce for those that set it. | ||
953 | */ | ||
954 | if (!(rdev->wiphy.flags & WIPHY_FLAG_ENFORCE_COMBINATIONS)) | ||
955 | return 0; | ||
956 | |||
957 | memset(num, 0, sizeof(num)); | ||
958 | |||
959 | num[iftype] = 1; | ||
960 | |||
961 | mutex_lock(&rdev->devlist_mtx); | ||
962 | list_for_each_entry(wdev_iter, &rdev->netdev_list, list) { | ||
963 | if (wdev_iter == wdev) | ||
964 | continue; | ||
965 | if (!netif_running(wdev_iter->netdev)) | ||
966 | continue; | ||
967 | |||
968 | if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype)) | ||
969 | continue; | ||
970 | |||
971 | num[wdev_iter->iftype]++; | ||
972 | total++; | ||
973 | } | ||
974 | mutex_unlock(&rdev->devlist_mtx); | ||
975 | |||
976 | for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { | ||
977 | const struct ieee80211_iface_combination *c; | ||
978 | struct ieee80211_iface_limit *limits; | ||
979 | |||
980 | c = &rdev->wiphy.iface_combinations[i]; | ||
981 | |||
982 | limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits, | ||
983 | GFP_KERNEL); | ||
984 | if (!limits) | ||
985 | return -ENOMEM; | ||
986 | if (total > c->max_interfaces) | ||
987 | goto cont; | ||
988 | |||
989 | for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) { | ||
990 | if (rdev->wiphy.software_iftypes & BIT(iftype)) | ||
991 | continue; | ||
992 | for (j = 0; j < c->n_limits; j++) { | ||
993 | if (!(limits[j].types & iftype)) | ||
994 | continue; | ||
995 | if (limits[j].max < num[iftype]) | ||
996 | goto cont; | ||
997 | limits[j].max -= num[iftype]; | ||
998 | } | ||
999 | } | ||
1000 | /* yay, it fits */ | ||
1001 | kfree(limits); | ||
1002 | return 0; | ||
1003 | cont: | ||
1004 | kfree(limits); | ||
1005 | } | ||
1006 | |||
1007 | return -EBUSY; | ||
1008 | } | ||
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 88f3f07205f8..e26e2fb462d4 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c | |||
@@ -702,6 +702,24 @@ static int do_ssb_entry(const char *filename, | |||
702 | return 1; | 702 | return 1; |
703 | } | 703 | } |
704 | 704 | ||
705 | /* Looks like: bcma:mNidNrevNclN. */ | ||
706 | static int do_bcma_entry(const char *filename, | ||
707 | struct bcma_device_id *id, char *alias) | ||
708 | { | ||
709 | id->manuf = TO_NATIVE(id->manuf); | ||
710 | id->id = TO_NATIVE(id->id); | ||
711 | id->rev = TO_NATIVE(id->rev); | ||
712 | id->class = TO_NATIVE(id->class); | ||
713 | |||
714 | strcpy(alias, "bcma:"); | ||
715 | ADD(alias, "m", id->manuf != BCMA_ANY_MANUF, id->manuf); | ||
716 | ADD(alias, "id", id->id != BCMA_ANY_ID, id->id); | ||
717 | ADD(alias, "rev", id->rev != BCMA_ANY_REV, id->rev); | ||
718 | ADD(alias, "cl", id->class != BCMA_ANY_CLASS, id->class); | ||
719 | add_wildcard(alias); | ||
720 | return 1; | ||
721 | } | ||
722 | |||
705 | /* Looks like: virtio:dNvN */ | 723 | /* Looks like: virtio:dNvN */ |
706 | static int do_virtio_entry(const char *filename, struct virtio_device_id *id, | 724 | static int do_virtio_entry(const char *filename, struct virtio_device_id *id, |
707 | char *alias) | 725 | char *alias) |
@@ -968,6 +986,10 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, | |||
968 | do_table(symval, sym->st_size, | 986 | do_table(symval, sym->st_size, |
969 | sizeof(struct ssb_device_id), "ssb", | 987 | sizeof(struct ssb_device_id), "ssb", |
970 | do_ssb_entry, mod); | 988 | do_ssb_entry, mod); |
989 | else if (sym_is(symname, "__mod_bcma_device_table")) | ||
990 | do_table(symval, sym->st_size, | ||
991 | sizeof(struct bcma_device_id), "bcma", | ||
992 | do_bcma_entry, mod); | ||
971 | else if (sym_is(symname, "__mod_virtio_device_table")) | 993 | else if (sym_is(symname, "__mod_virtio_device_table")) |
972 | do_table(symval, sym->st_size, | 994 | do_table(symval, sym->st_size, |
973 | sizeof(struct virtio_device_id), "virtio", | 995 | sizeof(struct virtio_device_id), "virtio", |